Author: mnordell Date: Tue Oct 16 09:08:45 2007 New Revision: 29619
URL: http://svn.reactos.org/svn/reactos?rev=29619&view=rev Log: Debugging helper functions added, to verify hive list integrity. Grab hive lock for insertion in EnlistKeyBodyWithKCB. Some comments added.
Modified: trunk/reactos/ntoskrnl/cm/registry.c
Modified: trunk/reactos/ntoskrnl/cm/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/registry.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/cm/registry.c (original) +++ trunk/reactos/ntoskrnl/cm/registry.c Tue Oct 16 09:08:45 2007 @@ -38,7 +38,7 @@ KTIMER CmiWorkerTimer; LIST_ENTRY CmiKeyObjectListHead; LIST_ENTRY CmiConnectedHiveList; -ULONG CmiTimer = 0; +ULONG CmiTimer = 0; /* gets incremented every 5 seconds (CmiWorkerTimer) */
volatile BOOLEAN CmiHiveSyncEnabled = FALSE; volatile BOOLEAN CmiHiveSyncPending = FALSE; @@ -57,6 +57,60 @@
/* FUNCTIONS ****************************************************************/
+/* Debugging helper functions: */ +/* CmiVerifyHiveListIntegrity */ +/* CmiVerifyHiveListIntegrityWhileLocked */ +/* These functions are normally unused. However, should any of the asserts */ +/* checking for registry loops in CmiWorkerThread start to trigger, it is */ +/* recommended to add liberal amounts of calls to this function throughout */ +/* suspect code. This function is due to its iterative nature not intended */ +/* to be called during normal circumstances, but as a debugging aid. */ +static +VOID +NTAPI +CmipVerifyHiveListIntegrity(BOOLEAN IsLocked) +{ + PLIST_ENTRY CurrentEntry; + if (!IsLocked) + { + /* Acquire hive lock */ + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE); + } + + if (IsListEmpty(&CmiKeyObjectListHead)) + { + ASSERT(CmiKeyObjectListHead.Blink == CmiKeyObjectListHead.Flink); + } + /* walk the list both forwards and backwards */ + CurrentEntry = CmiKeyObjectListHead.Flink; + while (CurrentEntry != &CmiKeyObjectListHead) + { + ASSERT(CurrentEntry->Blink != CurrentEntry); + ASSERT(CurrentEntry->Flink != CurrentEntry); + CurrentEntry = CurrentEntry->Flink; + } + + CurrentEntry = CmiKeyObjectListHead.Blink; + while (CurrentEntry != &CmiKeyObjectListHead) + { + ASSERT(CurrentEntry->Blink != CurrentEntry); + ASSERT(CurrentEntry->Flink != CurrentEntry); + CurrentEntry = CurrentEntry->Blink; + } + + if (!IsLocked) + { + ExReleaseResourceLite(&CmpRegistryLock); + KeLeaveCriticalRegion(); + } +} + +VOID NTAPI CmiVerifyHiveListIntegrity() { CmipVerifyHiveListIntegrity(FALSE); } +VOID NTAPI CmiVerifyHiveListIntegrityWhileLocked() { CmipVerifyHiveListIntegrity(TRUE); } + + + VOID NTAPI CmiWorkerThread(PVOID Param) @@ -64,7 +118,9 @@ NTSTATUS Status; PLIST_ENTRY CurrentEntry; PKEY_OBJECT CurrentKey; - ULONG Count; + ULONG Count; /* how many objects have been dereferenced each pass */ + + /* Loop forever, getting woken up every 5 seconds by CmiWorkerTimer */
while (1) { @@ -96,6 +152,7 @@ if (1 == ObGetObjectPointerCount(CurrentKey) && !(CurrentKey->Flags & KO_MARKED_FOR_DELETE)) { + /* PointerCount is 1, and it's not marked for delete */ ObDereferenceObject(CurrentKey); if (CurrentEntry == CmiKeyObjectListHead.Blink) { @@ -107,6 +164,7 @@ } else { + /* PointerCount was not 1, or it was marked for delete */ if (CurrentEntry == CurrentEntry->Blink) { DPRINT("Registry loop detected! Crashing\n"); @@ -166,13 +224,21 @@ return (PVOID)((MdBlock->BasePage << PAGE_SHIFT) | KSEG0_BASE); }
+/* Precondition: Must not hold the hive lock CmpRegistryLock */ VOID NTAPI EnlistKeyBodyWithKCB(IN PKEY_OBJECT KeyObject, IN ULONG Flags) { + /* Acquire hive lock */ + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE); + /* Insert it into the global list (we don't have KCBs here) */ InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry); + + ExReleaseResourceLite(&CmpRegistryLock); + KeLeaveCriticalRegion(); }
NTSTATUS