Author: fireball Date: Sun Oct 28 21:20:48 2007 New Revision: 29933
URL: http://svn.reactos.org/svn/reactos?rev=29933&view=rev Log: - Fix code that tried to get a KCB from the alloc page. - Fix code that wasn't using CM_DELAY_ALLOC for delay allocation entries, but was using CM_DELAYED_CLOSE_ENTRY instead. - Fix definition of CM_DELAYED_CLOSE_ENTRY. - Fill out the CmpMachineHiveList. - Fix various callers of list-entry functions which were sending inverted parameters (entry instead of head) - Implement CmpInitializeDelayedCloseTable to do some work that CmpInitializeCache used to do. - Implement new locking macro: CmpConvertKcbSharedToExclusive and use it. - Rename more functions to their real names, expanding "Kcb" to "KeyControlBlock" when necessary. - CmpInitializeCache: Calculate size based on hash table entries, not pointers to key hashes. The locks need to be initialized, not the whole structure zeroed out. - CmpFreeKeyControlBlock: Fix code that gets the KCB and removes it from the list -- it was missing. - CmpReferenceKeyControlBlock: * Use DelayedCloseIndex instead of "Delete". * Do not add + 1 to InterlockedIncrement's result - CmpDelayDerefKeyControlBlock: * Insert the entry at the tail, not the head. * Check if the worker is inactive, not if it's acvice. * Remove the KCB before freeing it. * Use DelayedCloseIndex, not delete. - CmpAllocateKeyControlBlock/CmpAllocateDelayItem: * Simplify and fix list lookup. * Simplify algorithm with a goto. - CmpDereferenceKeyControlBlockWithLock: * Make it actually decrement the reference count. * Use Delete flag instead of PrivateAlloc flag.
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/cmdata.c branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c branches/alex-cm-branch/reactos/ntoskrnl/cm/cmkcbncb.c branches/alex-cm-branch/reactos/ntoskrnl/cm/cmutil.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 Sun Oct 28 21:20:48 2007 @@ -338,6 +338,15 @@ ULONG Reserved; PVOID AllocPage; } CM_ALLOC_PAGE, *PCM_ALLOC_PAGE; + +// +// Allocation Page Entry +// +typedef struct _CM_DELAY_ALLOC +{ + LIST_ENTRY ListEntry; + PCM_KEY_CONTROL_BLOCK Kcb; +} CM_DELAY_ALLOC, *PCM_DELAY_ALLOC;
// // Delayed Close Entry @@ -574,7 +583,6 @@ { PWCHAR FileName; PWCHAR BaseName; - PWCHAR RegRootName; PCMHIVE CmHive; ULONG HHiveFlags; ULONG CmHiveFlags; @@ -582,7 +590,6 @@ BOOLEAN ThreadFinished; BOOLEAN ThreadStarted; BOOLEAN Allocate; - BOOLEAN WinPERequired; } HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
// @@ -853,8 +860,6 @@ IN PSECURITY_DESCRIPTOR SecurityDescriptor );
-/* NOTE: This function declaration is currently duplicated in both */ -/* cm/cm.h and config/cm.h. TODO: Pick one single place to declare it. */ NTSTATUS NTAPI CmpOpenHiveFiles( @@ -919,7 +924,7 @@
VOID NTAPI -CmpDereferenceKcbWithLock( +CmpDereferenceKeyControlBlockWithLock( IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively ); @@ -1285,7 +1290,7 @@ extern ULONG CmpConfigurationAreaSize; extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData; extern UNICODE_STRING CmTypeName[]; -extern HIVE_LIST_ENTRY CmpMachineHiveList[5]; +extern HIVE_LIST_ENTRY CmpMachineHiveList[]; extern UNICODE_STRING CmSymbolicLinkValueName; extern UNICODE_STRING CmpSystemStartOptions; extern UNICODE_STRING CmpLoadOptions;
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 Sun Oct 28 21:20:48 2007 @@ -200,6 +200,18 @@ }
// +// Converts a KCB lock +// +FORCEINLINE +VOID +CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k) +{ + ASSERT(CmpIsKcbLockedExclusive(k) == FALSE); + CmpReleaseKcbLock(k); + CmpAcquireKcbLockExclusive(k); +} + +// // Exclusively acquires an NCB // #define CmpAcquireNcbLockExclusive(n) \
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmdata.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmdata.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmdata.c Sun Oct 28 21:20:48 2007 @@ -38,7 +38,30 @@
EX_PUSH_LOCK CmpHiveListHeadLock, CmpLoadHiveLock;
-HIVE_LIST_ENTRY CmpMachineHiveList[5]; +HIVE_LIST_ENTRY CmpMachineHiveList[] = +{ + { + L"HARDWARE", L"MACHINE\", NULL, HIVE_VOLATILE, 0, NULL, FALSE, FALSE, FALSE + }, + { + L"SECURITY", L"MACHINE\", NULL, 0, 0, NULL, FALSE, FALSE, FALSE + }, + { + L"SOFTWARE", L"MACHINE\", NULL, 0, 0, NULL, FALSE, FALSE, FALSE + }, + { + L"SYSTEM", L"MACHINE\", NULL, 0, 0, NULL, FALSE, FALSE, FALSE + }, + { + L"DEFAULT", L"USER\.DEFAULT", NULL, 0, 1, NULL, FALSE, FALSE, FALSE + }, + { + L"SAM", L"MACHINE\", NULL, HIVE_NOLAZYFLUSH, 0, NULL, FALSE, FALSE, FALSE + }, + { + NULL, NULL, 0, 0, 0, NULL, FALSE, FALSE, FALSE + } +};
UNICODE_STRING CmSymbolicLinkValueName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c Sun Oct 28 21:20:48 2007 @@ -31,8 +31,6 @@ BOOLEAN CmSelfHeal, CmpSelfHeal; KGUARDED_MUTEX CmpSelfHealQueueLock; LIST_ENTRY CmpSelfHealQueueListHead; - -HIVE_LIST_ENTRY CmpMachineHiveList[];
EX_PUSH_LOCK CmpLoadHiveLock;
@@ -335,8 +333,8 @@ ValueName.Length);
Quickie: - /* Free the buffers */ - RtlFreeUnicodeString(&ValueName); + /* Free the buffers */ + RtlFreeUnicodeString(&ValueName);
/* Close the key and return */ NtClose(KeyHandle);
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 Sun Oct 28 21:20:48 2007 @@ -71,39 +71,72 @@ ASSERT(CmpDelayCloseWorkItemActive);
/* FIXME: TODO */ -} - -VOID -NTAPI -CmpInitializeCache(VOID) -{ - ULONG Length; - - /* Calculate length for the table */ - Length = CmpHashTableSize * sizeof(PCM_KEY_HASH); - - /* Allocate it */ - CmpCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); - if (!CmpCacheTable) KeBugCheck(CONFIG_INITIALIZATION_FAILED); - RtlZeroMemory(CmpCacheTable, Length); - - /* Calculate length for the name cache */ - Length = CmpHashTableSize * sizeof(PCM_NAME_HASH); - - /* Now allocate the name cache table */ - CmpNameCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); - if (!CmpCacheTable) KeBugCheck(CONFIG_INITIALIZATION_FAILED); - RtlZeroMemory(CmpNameCacheTable, Length); + ASSERT(FALSE); +} + +VOID +NTAPI +CmpInitializeDelayedCloseTable(VOID) +{
/* Setup the delayed close lock */ KeInitializeGuardedMutex(&CmpDelayedCloseTableLock);
/* Setup the work item */ ExInitializeWorkItem(&CmpDelayCloseWorkItem, CmpDelayCloseWorker, NULL); + + /* Setup the list head */ + InitializeListHead(&CmpDelayedLRUListHead);
/* Setup the DPC and its timer */ KeInitializeDpc(&CmpDelayCloseDpc, CmpDelayCloseDpcRoutine, NULL); KeInitializeTimer(&CmpDelayCloseTimer); +} + +VOID +NTAPI +CmpInitializeCache(VOID) +{ + ULONG Length, i; + + /* Calculate length for the table */ + Length = CmpHashTableSize * sizeof(CM_KEY_HASH_TABLE_ENTRY); + + /* Allocate it */ + CmpCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); + if (!CmpCacheTable) + { + /* Take the system down */ + KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 1, 0, 0); + } + + /* Initialize the locks */ + for (i = 0;i < CmpHashTableSize; i++) + { + /* Setup the pushlock */ + ExInitializePushLock((PULONG_PTR)&CmpCacheTable[i].Lock); + } + + /* Calculate length for the name cache */ + Length = CmpHashTableSize * sizeof(CM_NAME_HASH_TABLE_ENTRY); + + /* Now allocate the name cache table */ + CmpNameCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); + if (!CmpNameCacheTable) + { + /* Take the system down */ + KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 3, 0, 0); + } + + /* Initialize the locks */ + for (i = 0;i < CmpHashTableSize; i++) + { + /* Setup the pushlock */ + ExInitializePushLock((PULONG_PTR)&CmpNameCacheTable[i].Lock); + } + + /* Setup the delayed close table */ + CmpInitializeDelayedCloseTable(); }
VOID @@ -153,6 +186,7 @@ ASSERT(CmpDelayDerefKCBWorkItemActive);
/* FIXME: TODO */ + ASSERT(FALSE); }
VOID @@ -340,7 +374,7 @@
VOID NTAPI -CmpRemoveKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) +CmpRemoveKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb) { /* Make sure that the registry and KCB are utterly locked */ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || @@ -352,7 +386,7 @@
VOID NTAPI -CmpFreeKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) +CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb) { ULONG i; PCM_ALLOC_PAGE AllocPage; @@ -367,43 +401,47 @@ { /* Free it from the pool */ ExFreePool(Kcb); - } - else - { - /* Acquire the private allocation lock */ - KeAcquireGuardedMutex(&CmpAllocBucketLock); - - /* Sanity check on lock ownership */ - ASSERT((GET_HASH_ENTRY(CmpCacheTable, Kcb->ConvKey).Owner == - KeGetCurrentThread()) || - (CmpTestRegistryLockExclusive() == TRUE)); - - /* Remove us from the list */ - RemoveEntryList(&CmpFreeKCBListHead); - - /* Get the allocation page */ - AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)Kcb & 0xFFFFF000); - - /* Sanity check */ - ASSERT(AllocPage->FreeCount != CM_KCBS_PER_PAGE); - - /* Increase free count */ - if (++AllocPage->FreeCount == CM_KCBS_PER_PAGE) - { - /* Loop all the entries */ - for (i = CM_KCBS_PER_PAGE; i; i--) - { - /* Remove the entry - RemoveEntryList(& */ - } - - /* Free the page */ - ExFreePool(AllocPage); - } - - /* Release the lock */ - KeReleaseGuardedMutex(&CmpAllocBucketLock); - } + return; + } + + /* Acquire the private allocation lock */ + KeAcquireGuardedMutex(&CmpAllocBucketLock); + + /* Sanity check on lock ownership */ + ASSERT((GET_HASH_ENTRY(CmpCacheTable, Kcb->ConvKey).Owner == + KeGetCurrentThread()) || + (CmpTestRegistryLockExclusive() == TRUE)); + + /* Add us to the free list */ + InsertTailList(&CmpFreeKCBListHead, &Kcb->FreeListEntry); + + /* Get the allocation page */ + AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)Kcb & 0xFFFFF000); + + /* Sanity check */ + ASSERT(AllocPage->FreeCount != CM_KCBS_PER_PAGE); + + /* Increase free count */ + if (++AllocPage->FreeCount == CM_KCBS_PER_PAGE) + { + /* Loop all the entries */ + for (i = CM_KCBS_PER_PAGE; i; i--) + { + /* Get the KCB */ + Kcb = (PVOID)((ULONG_PTR)AllocPage + + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + + i * sizeof(CM_KEY_CONTROL_BLOCK)); + + /* Remove the entry */ + RemoveEntryList(&Kcb->FreeListEntry); + } + + /* Free the page */ + ExFreePool(AllocPage); + } + + /* Release the lock */ + KeReleaseGuardedMutex(&CmpAllocBucketLock); }
VOID @@ -455,6 +493,7 @@
/* Get the entry and lock the table */ Entry = Kcb->DelayCloseEntry; + ASSERT(Entry); KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
/* Remove the entry */ @@ -487,12 +526,11 @@
/* Set new delay size and remove the delete flag */ Kcb->DelayedCloseIndex = CmpDelayedCloseSize; - Kcb->Delete = FALSE; }
BOOLEAN NTAPI -CmpReferenceKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) +CmpReferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb) { /* Check if this is the KCB's first reference */ if (Kcb->RefCount == 0) @@ -503,36 +541,36 @@ /* Convert it to exclusive */ if (!CmpTryToConvertKcbSharedToExclusive(Kcb)) { - /* Set the delete flag */ - Kcb->Delete = TRUE; + /* Set the delayed close index so that we can be ignored */ + Kcb->DelayedCloseIndex = 1;
/* Increase the reference count while we release the lock */ InterlockedIncrement((PLONG)&Kcb->RefCount); - - /* Sanity check, KCB should still be shared */ - ASSERT(CmpIsKcbLockedExclusive(Kcb) == FALSE); - - /* Release the current lock */ - CmpReleaseKcbLock(Kcb); - - /* Now acquire the lock in exclusive mode */ - CmpAcquireKcbLockExclusive(Kcb); + + /* Go from shared to exclusive */ + CmpConvertKcbSharedToExclusive(Kcb);
/* Decrement the reference count; the lock is now held again */ InterlockedDecrement((PLONG)&Kcb->RefCount); - - /* Sanity check */ - ASSERT((Kcb->DelayedCloseIndex == CmpDelayedCloseSize) || - (Kcb->DelayedCloseIndex == 0)); - - /* Remove the delete flag */ - Kcb->Delete = FALSE; + + /* Check if we still control the index */ + if (Kcb->DelayedCloseIndex == 1) + { + /* Reset it */ + Kcb->DelayedCloseIndex = 0; + } + else + { + /* Sanity check */ + ASSERT((Kcb->DelayedCloseIndex == CmpDelayedCloseSize) || + (Kcb->DelayedCloseIndex == 0)); + } } } }
/* Increase the reference count */ - if ((InterlockedIncrement((PLONG)&Kcb->RefCount) + 1) == 0) + if (InterlockedIncrement((PLONG)&Kcb->RefCount) == 0) { /* We've overflown to 64K references, bail out */ InterlockedDecrement((PLONG)&Kcb->RefCount); @@ -548,14 +586,8 @@ /* Convert it to exclusive */ if (!CmpTryToConvertKcbSharedToExclusive(Kcb)) { - /* Sanity check, KCB should still be shared */ - ASSERT(CmpIsKcbLockedExclusive(Kcb) == FALSE); - - /* Release the current lock */ - CmpReleaseKcbLock(Kcb); - - /* Now acquire the lock in exclusive mode */ - CmpAcquireKcbLockExclusive(Kcb); + /* Go from shared to exclusive */ + CmpConvertKcbSharedToExclusive(Kcb); } }
@@ -569,7 +601,7 @@
VOID NTAPI -CmpDelayDerefKcb(IN PCM_KEY_CONTROL_BLOCK Kcb) +CmpDelayDerefKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb) { USHORT OldRefCount, NewRefCount; LARGE_INTEGER Timeout; @@ -596,10 +628,10 @@ KeAcquireGuardedMutex(&CmpDelayDerefKCBLock);
/* Insert the entry into the list */ - InsertHeadList(&CmpDelayDerefKCBListHead, &Entry->ListEntry); + InsertTailList(&CmpDelayDerefKCBListHead, &Entry->ListEntry);
/* Check if we need to enable anything */ - if (CmpDelayDerefKCBWorkItemActive) + if (!CmpDelayDerefKCBWorkItemActive) { /* Yes, we have no work item, setup the interval */ Timeout.QuadPart = CmpDelayDerefKCBIntervalInSeconds * -10000000; @@ -651,7 +683,7 @@ }
/* Dereference the KCB */ - CmpDelayDerefKcb(Kcb->ValueCache.RealKcb); + CmpDelayDerefKeyControlBlock(Kcb->ValueCache.RealKcb); Kcb->ExtFlags &= ~ CM_KCB_SYM_LINK_FOUND; } } @@ -680,15 +712,18 @@
/* Check if we were already deleted */ Parent = Kcb->ParentKcb; - if (!Kcb->Delete) CmpFreeKcb(Kcb); + if (!Kcb->Delete) CmpRemoveKeyControlBlock(Kcb); + + /* Free the KCB as well */ + CmpFreeKeyControlBlock(Kcb);
/* Check if we have a parent */ if (Parent) { /* Dereference the parent */ - LockHeldExclusively ? CmpDereferenceKcbWithLock(Kcb, - LockHeldExclusively) : - CmpDelayDerefKcb(Kcb); + LockHeldExclusively ? + CmpDereferenceKeyControlBlockWithLock(Kcb,LockHeldExclusively) : + CmpDelayDerefKeyControlBlock(Kcb); } }
@@ -748,8 +783,8 @@ OldRefCount); if (NewRefCount != OldRefCount) ASSERT(FALSE);
- /* Remove the delete flag */ - Kcb->Delete = FALSE; + /* Reset the delayed close index */ + Kcb->DelayedCloseIndex = 0;
/* Set up the close entry */ Kcb->DelayCloseEntry = Entry; @@ -778,9 +813,9 @@
PCM_KEY_CONTROL_BLOCK NTAPI -CmpAllocateKcb(VOID) -{ - PLIST_ENTRY ListHead, NextEntry; +CmpAllocateKeyControlBlock(VOID) +{ + PLIST_ENTRY NextEntry; PCM_KEY_CONTROL_BLOCK CurrentKcb; PCM_ALLOC_PAGE AllocPage; ULONG i; @@ -792,13 +827,12 @@ /* They are, acquire the bucket lock */ KeAcquireGuardedMutex(&CmpAllocBucketLock);
- /* Loop the free KCB list */ - ListHead = &CmpFreeKCBListHead; - NextEntry = ListHead->Flink; - while (NextEntry != ListHead) + /* See if there's something on the free KCB list */ +SearchKcbList: + if (!IsListEmpty(&CmpFreeKCBListHead)) { /* Remove the entry */ - RemoveEntryList(NextEntry); + NextEntry = RemoveHeadList(&CmpFreeKCBListHead);
/* Get the KCB */ CurrentKcb = CONTAINING_RECORD(NextEntry, @@ -833,39 +867,20 @@ for (i = 0; i < CM_KCBS_PER_PAGE; i++) { /* Get this entry */ - CurrentKcb = (PCM_KEY_CONTROL_BLOCK)(AllocPage + 1); + CurrentKcb = (PVOID)((ULONG_PTR)AllocPage + + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + + i * sizeof(CM_KEY_CONTROL_BLOCK));
/* Set it up */ CurrentKcb->PrivateAlloc = TRUE; CurrentKcb->DelayCloseEntry = NULL; - InsertHeadList(&CurrentKcb->FreeListEntry, - &CmpFreeKCBListHead); - } - - /* Get the KCB */ - CurrentKcb = CONTAINING_RECORD(NextEntry, - CM_KEY_CONTROL_BLOCK, - FreeListEntry); - - /* Get the allocation page */ - AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)CurrentKcb & 0xFFFFF000); - - /* Decrease the free count */ - ASSERT(AllocPage->FreeCount != 0); - AllocPage->FreeCount--; - - /* Make sure this KCB is privately allocated */ - ASSERT(CurrentKcb->PrivateAlloc == 1); - - /* Release the allocation lock */ - KeReleaseGuardedMutex(&CmpAllocBucketLock); - - /* Return the KCB */ - return CurrentKcb; - } - - /* Release the lock */ - KeReleaseGuardedMutex(&CmpAllocBucketLock); + InsertHeadList(&CmpFreeKCBListHead, + &CurrentKcb->FreeListEntry); + } + + /* Now go back and search the list */ + goto SearchKcbList; + } }
/* Allocate a KCB only */ @@ -885,33 +900,37 @@
VOID NTAPI -CmpDereferenceKcbWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, - IN BOOLEAN LockHeldExclusively) +CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN LockHeldExclusively) { /* Sanity check */ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || (CmpTestRegistryLockExclusive() == TRUE));
- /* Check if we should do a direct delete */ - if (((CmpHoldLazyFlush) && - !(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) && - !(Kcb->Flags & KEY_SYM_LINK)) || - (Kcb->ExtFlags & CM_KCB_NO_DELAY_CLOSE) || - (Kcb->PrivateAlloc)) - { - /* Clean up the KCB*/ - CmpCleanUpKcbCacheWithLock(Kcb, LockHeldExclusively); - } - else - { - /* Otherwise, use delayed close */ - CmpAddToDelayedClose(Kcb, LockHeldExclusively); - } -} - -VOID -NTAPI -CmpInitializeKcbKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb) + /* Check if this is the last reference */ + if (InterlockedDecrement((PLONG)&Kcb->RefCount) == 0) + { + /* Check if we should do a direct delete */ + if (((CmpHoldLazyFlush) && + !(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) && + !(Kcb->Flags & KEY_SYM_LINK)) || + (Kcb->ExtFlags & CM_KCB_NO_DELAY_CLOSE) || + (Kcb->Delete)) + { + /* Clean up the KCB*/ + CmpCleanUpKcbCacheWithLock(Kcb, LockHeldExclusively); + } + else + { + /* Otherwise, use delayed close */ + CmpAddToDelayedClose(Kcb, LockHeldExclusively); + } + } +} + +VOID +NTAPI +InitializeKCBKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb) { /* Initialize the list */ InitializeListHead(&Kcb->KeyBodyListHead); @@ -939,6 +958,7 @@ PWCHAR p;
/* Make sure we own this hive */ + ASSERT(FALSE); if (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()) return NULL;
/* Check if this is a fake KCB */ @@ -977,11 +997,11 @@ }
/* Allocate the KCB */ - Kcb = CmpAllocateKcb(); + Kcb = CmpAllocateKeyControlBlock(); if (!Kcb) return NULL;
/* Initailize the key list */ - CmpInitializeKcbKeyBodyList(Kcb); + InitializeKCBKeyBodyList(Kcb);
/* Set it up */ Kcb->Delete = FALSE; @@ -1007,9 +1027,9 @@ ASSERT(!FoundKcb->Delete);
/* Free the one we allocated and reference this one */ - CmpFreeKcb(Kcb); + CmpFreeKeyControlBlock(Kcb); Kcb = FoundKcb; - if (!CmpReferenceKcb(Kcb)) + if (!CmpReferenceKeyControlBlock(Kcb)) { /* We got too many handles */ ASSERT(Kcb->RefCount + 1 != 0); @@ -1054,7 +1074,8 @@ if (Parent) { /* Reference the parent */ - if (((Parent->TotalLevels + 1) < 512) && (CmpReferenceKcb(Parent))) + if (((Parent->TotalLevels + 1) < 512) && + (CmpReferenceKeyControlBlock(Parent))) { /* Link it */ Kcb->ParentKcb = Parent; @@ -1063,8 +1084,8 @@ else { /* Remove the KCB and free it */ - CmpRemoveKcb(Kcb); - CmpFreeKcb(Kcb); + CmpRemoveKeyControlBlock(Kcb); + CmpFreeKeyControlBlock(Kcb); Kcb = NULL; } } @@ -1103,11 +1124,11 @@ else { /* Dereference the KCB */ - CmpDereferenceKcbWithLock(Parent, FALSE); + CmpDereferenceKeyControlBlockWithLock(Parent, FALSE);
/* Remove the KCB and free it */ - CmpRemoveKcb(Kcb); - CmpFreeKcb(Kcb); + CmpRemoveKeyControlBlock(Kcb); + CmpFreeKeyControlBlock(Kcb); Kcb = NULL; } }
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmutil.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmutil.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmutil.c Sun Oct 28 21:20:48 2007 @@ -55,7 +55,7 @@ NTAPI CmpAllocateDelayItem(VOID) { - PCM_DELAYED_CLOSE_ENTRY Entry; + PCM_DELAY_ALLOC Entry; PCM_ALLOC_PAGE AllocPage; ULONG i; PLIST_ENTRY NextEntry; @@ -63,70 +63,69 @@
/* Lock the allocation buckets */ KeAcquireGuardedMutex(&CmpDelayAllocBucketLock); - while (TRUE) + + /* Look for an item on the free list */ +SearchList: + if (!IsListEmpty(&CmpFreeDelayItemsListHead)) { /* Get the current entry in the list */ - NextEntry = CmpFreeDelayItemsListHead.Flink; - - /* Check if we need to allocate an entry */ - if (((NextEntry) && (CmpFreeDelayItemsListHead.Blink) && - IsListEmpty(&CmpFreeDelayItemsListHead)) || - (!(NextEntry) && !(CmpFreeDelayItemsListHead.Blink))) + NextEntry = RemoveHeadList(&CmpFreeDelayItemsListHead); + + /* Grab the item */ + Entry = CONTAINING_RECORD(NextEntry, CM_DELAY_ALLOC, ListEntry); + + /* Clear the list */ + Entry->ListEntry.Flink = Entry->ListEntry.Blink = NULL; + + /* Grab the alloc page */ + AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)Entry & 0xFFFFF000); + + /* Decrease free entries */ + ASSERT(AllocPage->FreeCount != 0); + AllocPage->FreeCount--; + + /* Release the lock */ + KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); + return Entry; + } + + /* Allocate an allocation page */ + AllocPage = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_CM); + if (AllocPage) + { + /* Set default entries */ + AllocPage->FreeCount = CM_DELAYS_PER_PAGE; + + /* Loop each entry */ + for (i = 0; i < CM_DELAYS_PER_PAGE; i++) { - /* Allocate an allocation page */ - AllocPage = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_CM); - if (AllocPage) - { - /* Set default entries */ - AllocPage->FreeCount = CM_DELAYS_PER_PAGE; - - /* Loop each entry */ - for (i = 0; i < CM_DELAYS_PER_PAGE; i++) - { - /* Get this entry and link it */ - Entry = (PCM_DELAYED_CLOSE_ENTRY)(&AllocPage[i]); - InsertHeadList(&Entry->DelayedLRUList, - &CmpFreeDelayItemsListHead); - - /* Clear the KCB pointer */ - Entry->KeyControlBlock = NULL; - } - } - else - { - /* Release the lock */ - KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); - return NULL; - } + /* Get this entry and link it */ + Entry = (PVOID)((ULONG_PTR)AllocPage + + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + + i * sizeof(CM_DELAY_ALLOC)); + InsertTailList(&CmpFreeDelayItemsListHead, + &Entry->ListEntry); + + /* Clear the KCB pointer */ + Entry->Kcb = NULL; } } - - /* Set the next item in the list */ - CmpFreeDelayItemsListHead.Flink = NextEntry->Flink; - NextEntry->Flink->Blink = &CmpFreeDelayItemsListHead; - NextEntry->Blink = NULL; - - /* Get the entry and the alloc page */ - Entry = CONTAINING_RECORD(NextEntry, - CM_DELAYED_CLOSE_ENTRY, - DelayedLRUList); - AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)Entry & 0xFFFFF000); - - /* Decrease free entries */ - ASSERT(AllocPage->FreeCount != 0); - AllocPage->FreeCount--; - - /* Release the lock */ - KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); - return Entry; + else + { + /* Release the lock */ + KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); + return NULL; + } + + /* Do the search again */ + goto SearchList; }
VOID NTAPI CmpFreeDelayItem(PVOID Entry) { - PCM_DELAYED_CLOSE_ENTRY AllocEntry = (PCM_DELAYED_CLOSE_ENTRY)Entry; - PCM_DELAYED_CLOSE_ENTRY *AllocTable; + PCM_DELAY_ALLOC AllocEntry = (PCM_DELAY_ALLOC)Entry; PCM_ALLOC_PAGE AllocPage; ULONG i; PAGED_CODE(); @@ -135,7 +134,7 @@ KeAcquireGuardedMutex(&CmpDelayAllocBucketLock);
/* Add the entry at the end */ - InsertTailList(&CmpFreeDelayItemsListHead, &AllocEntry->DelayedLRUList); + InsertTailList(&CmpFreeDelayItemsListHead, &AllocEntry->ListEntry);
/* Get the alloc page */ AllocPage = (PCM_ALLOC_PAGE)((ULONG_PTR)Entry & 0xFFFFF000); @@ -145,12 +144,13 @@ if (++AllocPage->FreeCount == CM_DELAYS_PER_PAGE) { /* Page is totally free now, loop each entry */ - AllocTable = (PCM_DELAYED_CLOSE_ENTRY*)&AllocPage->AllocPage; - for (i = CM_DELAYS_PER_PAGE; i; i--) + for (i = 0; i < CM_DELAYS_PER_PAGE; i++) { /* Get the entry and unlink it */ - AllocEntry = AllocTable[i]; - RemoveEntryList(&AllocEntry->DelayedLRUList); + AllocEntry = (PVOID)((ULONG_PTR)AllocPage + + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + + i * sizeof(CM_DELAY_ALLOC)); + RemoveEntryList(&AllocEntry->ListEntry); }
/* Now free the page */