Author: ion Date: Wed Aug 16 22:38:09 2006 New Revision: 23590
URL: http://svn.reactos.org/svn/reactos?rev=23590&view=rev Log: - Add definitions for HCELL_NIL and HCELL_CACHED. - Add CM_DELAY_DEREF_KCB_ITEM. - Add CM_CACHED_VALUE_INDEX, CM_CACHED_VALUE. - Add macros for dealing with cached cells (CMP_GET_CACHED_CELL, CMP_GET_CACHED_DATA, _INDEX, _VALUE and CMP_IS_CELL_CACHED). - Implement CmpRemoveFromDelayedClose, CmpDelayDerefKCb, CmpCleanUpKcbValueCache, CmpCleanUpKcbCacheWithLock. - Fix return value of CmpAllocateDelayItem.
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h Wed Aug 16 22:38:09 2006 @@ -73,6 +73,12 @@ #define HBLOCK_SIZE 0x1000 #define HSECTOR_SIZE 0x200 #define HSECTOR_COUNT 8 + +// +// Cell Masks +// +#define HCELL_NIL 0 +#define HCELL_CACHED 1
// // CM_KEY_CONTROL_BLOCK Flags @@ -367,6 +373,15 @@ LIST_ENTRY DelayedLRUList; PCM_KEY_CONTROL_BLOCK KeyControlBlock; } CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY; + +// +// Delayed KCB Dereference Entry +// +typedef struct _CM_DELAY_DEREF_KCB_ITEM +{ + LIST_ENTRY ListEntry; + PCM_KEY_CONTROL_BLOCK Kcb; +} CM_DELAY_DEREF_KCB_ITEM, *PCM_DELAY_DEREF_KCB_ITEM;
// // Use Count Log and Entry @@ -521,6 +536,29 @@ } CELL_DATA, *PCELL_DATA;
// +// Cached Value Index +// +typedef struct _CM_CACHED_VALUE_INDEX +{ + HCELL_INDEX CellIndex; + union + { + CELL_DATA CellData; + ULONG_PTR List[ANYSIZE_ARRAY]; + } Data; +} CM_CACHED_VALUE_INDEX, *PCM_CACHED_VALUE_INDEX; + +// +// Cached Value +// +typedef struct _CM_CACHED_VALUE +{ + USHORT DataCacheType; + USHORT ValueKeySize; + CM_KEY_VALUE KeyValue; +} CM_CACHED_VALUE, *PCM_CACHED_VALUE; + +// // Registry Validation Functions // BOOLEAN @@ -531,7 +569,7 @@ );
// -// Registry Lock +// Registry Locking Functions // BOOLEAN NTAPI @@ -540,6 +578,16 @@ );
// +// KCB Functions +// +VOID +NTAPI +CmpDereferenceKcbWithLock( + IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN LockHeldExclusively +); + +// // Global variables accessible from all of Cm //
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cm_x.h Wed Aug 16 22:38:09 2006 @@ -19,6 +19,24 @@ GET_HASH_KEY(ConvKey) % CmpHashTableSize #define GET_HASH_ENTRY(Table, ConvKey) \ (*Table[GET_HASH_INDEX(ConvKey)]) + +// +// Returns whether or not the cell is cached +// +#define CMP_IS_CELL_CACHED(c) \ + (((c) & HCELL_CACHED) && ((c) != HCELL_NIL)) + +// +// Return data from a cached cell +// +#define CMP_GET_CACHED_CELL(c) \ + (ULONG_PTR)((c) & ~HCELL_CACHED) +#define CMP_GET_CACHED_DATA(c) \ + (&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData)) +#define CMP_GET_CACHED_INDEX(c) \ + (&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex)) +#define CMP_GET_CACHED_VALUE(c) \ + (&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
// // Makes sure that the registry is locked
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c Wed Aug 16 22:38:09 2006 @@ -29,6 +29,14 @@ ULONG CmpDelayCloseIntervalInSeconds = 5; KDPC CmpDelayCloseDpc; KTIMER CmpDelayCloseTimer; + +KGUARDED_MUTEX CmpDelayDerefKCBLock; +BOOLEAN CmpDelayDerefKCBWorkItemActive; +LIST_ENTRY CmpDelayDerefKCBListHead; +ULONG CmpDelayDerefKCBIntervalInSeconds = 5; +KDPC CmpDelayDerefKCBDpc; +KTIMER CmpDelayDerefKCBTimer; + BOOLEAN CmpHoldLazyFlush;
/* FUNCTIONS *****************************************************************/ @@ -281,6 +289,56 @@ } }
+VOID +NTAPI +CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb) +{ + PCM_DELAYED_CLOSE_ENTRY Entry; + ULONG NewRefCount, OldRefCount; + PAGED_CODE(); + + /* Sanity checks */ + ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || + (CmpTestRegistryLockExclusive() == TRUE)); + if (Kcb->DelayedCloseIndex == CmpDelayedCloseSize) ASSERT(FALSE); + + /* Get the entry and lock the table */ + Entry = Kcb->DelayCloseEntry; + KeAcquireGuardedMutex(&CmpDelayedCloseTableLock); + + /* Remove the entry */ + RemoveEntryList(&Entry->DelayedLRUList); + + /* Release the lock */ + KeReleaseGuardedMutex(&CmpDelayedCloseTableLock); + + /* Free the entry */ + CmpFreeDelayItem(Entry); + + /* Reduce the number of elements */ + InterlockedDecrement(&CmpDelayedCloseElements); + + /* Sanity check */ + if (!Kcb->InDelayClose) ASSERT(FALSE); + + /* Get the old reference count */ + OldRefCount = Kcb->InDelayClose; + ASSERT(OldRefCount == 1); + + /* Set it to 0 */ + NewRefCount = InterlockedCompareExchange(&Kcb->InDelayClose, + 0, + OldRefCount); + if (NewRefCount != OldRefCount) ASSERT(FALSE); + + /* Remove the link to the entry */ + Kcb->DelayCloseEntry = NULL; + + /* Set new delay size and remove the delete flag */ + Kcb->DelayedCloseIndex = CmpDelayedCloseSize; + Kcb->Delete = FALSE; +} + BOOLEAN NTAPI CmpReferenceKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) @@ -359,7 +417,7 @@ }
// FIXME: THIS FUNCTION IS PARTIALLY FUCKED -PCM_DELAYED_CLOSE_ENTRY +PVOID NTAPI CmpAllocateDelayItem(VOID) { @@ -408,6 +466,131 @@ /* Release the lock */ KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); return Entry; +} + +VOID +NTAPI +CmpDelayDerefKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) +{ + USHORT OldRefCount, NewRefCount; + LARGE_INTEGER Timeout; + PCM_DELAY_DEREF_KCB_ITEM Entry; + PAGED_CODE(); + + /* Get the previous reference count */ + OldRefCount = Kcb->RefCount; + + /* Write the new one */ + NewRefCount = (USHORT)InterlockedCompareExchange((PLONG)&Kcb->RefCount, + OldRefCount - 1, + OldRefCount); + if (NewRefCount != OldRefCount) return; + + /* Allocate a delay item */ + Entry = CmpAllocateDelayItem(); + if (!Entry) return; + + /* Set the KCB */ + Entry->Kcb = Kcb; + + /* Acquire the delayed deref table lock */ + KeAcquireGuardedMutex(&CmpDelayDerefKCBLock); + + /* Insert the entry into the list */ + InsertHeadList(&CmpDelayDerefKCBListHead, &Entry->ListEntry); + + /* Check if we need to enable anything */ + if (CmpDelayDerefKCBWorkItemActive) + { + /* Yes, we have no work item, setup the interval */ + Timeout.QuadPart = CmpDelayDerefKCBIntervalInSeconds * -10000000; + KeSetTimer(&CmpDelayDerefKCBTimer, Timeout, &CmpDelayDerefKCBDpc); + } + + /* Release the table lock */ + KeReleaseGuardedMutex(&CmpDelayDerefKCBLock); +} + +VOID +NTAPI +CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb) +{ + PULONG_PTR CachedList; + ULONG i; + + /* Sanity check */ + ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || + (CmpTestRegistryLockExclusive() == TRUE)); + + /* Check if the value list is cached */ + if (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)) + { + /* Get the cache list */ + CachedList = (PULONG_PTR)CMP_GET_CACHED_DATA(Kcb->ValueCache.ValueList); + for (i = 0; i < Kcb->ValueCache.Count; i++) + { + /* Check if this cell is cached */ + if (CMP_IS_CELL_CACHED(CachedList[i])) + { + /* Free it */ + ExFreePool((PVOID)CMP_GET_CACHED_CELL(CachedList[i])); + } + } + + /* Now free the list */ + ExFreePool((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList)); + Kcb->ValueCache.ValueList = HCELL_NIL; + } + else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) + { + /* This is a sym link, check if there's only one reference left */ + if ((Kcb->ValueCache.RealKcb->RefCount == 1) && + !(Kcb->ValueCache.RealKcb->Delete)) + { + /* Disable delay close for the KCB */ + Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE; + } + + /* Dereference the KCB */ + CmpDelayDerefKcb(Kcb->ValueCache.RealKcb); + Kcb->ExtFlags &= ~ CM_KCB_SYM_LINK_FOUND; + } +} + +VOID +NTAPI +CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN LockHeldExclusively) +{ + PCM_KEY_CONTROL_BLOCK Parent; + PAGED_CODE(); + + /* Sanity checks */ + ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || + (CmpTestRegistryLockExclusive() == TRUE)); + ASSERT(Kcb->RefCount == 0); + + /* Cleanup the value cache */ + CmpCleanUpKcbValueCache(Kcb); + + /* Reference the NCB */ + CmpDereferenceNcbWithLock(Kcb->NameBlock); + + /* Check if we have an index hint block and free it */ + if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) ExFreePool(Kcb->IndexHint); + + /* Check if we were already deleted */ + Parent = Kcb->ParentKcb; + if (!Kcb->Delete) CmpFreeKcb(Kcb); + + /* Check if we have a parent */ + if (Parent) + { + /* Dereference the parent */ + LockHeldExclusively ? CmpDereferenceKcbWithLock(Kcb, + LockHeldExclusively) : + CmpDelayDerefKcb(Kcb); + } }
VOID