Debugging helper functions added, to verify hive list integrity. Grab hive lock for...
authorMike Nordell <tamlin@algonet.se>
Tue, 16 Oct 2007 05:08:45 +0000 (05:08 +0000)
committerMike Nordell <tamlin@algonet.se>
Tue, 16 Oct 2007 05:08:45 +0000 (05:08 +0000)
svn path=/trunk/; revision=29619

reactos/ntoskrnl/cm/registry.c

index 5ef47f0..7dfaa85 100644 (file)
@@ -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