From 4475d4786b69593e3c7f5619ddba0f9d612a5fd7 Mon Sep 17 00:00:00 2001 From: Mike Nordell Date: Tue, 16 Oct 2007 05:08:45 +0000 Subject: [PATCH] Debugging helper functions added, to verify hive list integrity. Grab hive lock for insertion in EnlistKeyBodyWithKCB. Some comments added. svn path=/trunk/; revision=29619 --- reactos/ntoskrnl/cm/registry.c | 70 +++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 5ef47f0c604..7dfaa851e3e 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -38,7 +38,7 @@ ERESOURCE CmpRegistryLock; 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 @@ extern FAST_MUTEX CmiCallbackLock; /* 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 @@ CmiWorkerThread(PVOID Param) 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 @@ CmiWorkerThread(PVOID Param) 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 @@ CmiWorkerThread(PVOID Param) } 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 @@ CmpRosGetHardwareHive(OUT PULONG Length) 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