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