Author: ion
Date: Wed Aug 16 22:38:09 2006
New Revision: 23590
URL:
http://svn.reactos.org/svn/reactos?rev=23590&view=rev
Log:
- Add definitions for HCELL_NIL and HCELL_CACHED.
- Add CM_DELAY_DEREF_KCB_ITEM.
- Add CM_CACHED_VALUE_INDEX, CM_CACHED_VALUE.
- Add macros for dealing with cached cells (CMP_GET_CACHED_CELL, CMP_GET_CACHED_DATA,
_INDEX, _VALUE and CMP_IS_CELL_CACHED).
- Implement CmpRemoveFromDelayedClose, CmpDelayDerefKCb, CmpCleanUpKcbValueCache,
CmpCleanUpKcbCacheWithLock.
- Fix return value of CmpAllocateDelayItem.
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/cmkcbncb.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 Wed Aug 16 22:38:09 2006
@@ -73,6 +73,12 @@
#define HBLOCK_SIZE 0x1000
#define HSECTOR_SIZE 0x200
#define HSECTOR_COUNT 8
+
+//
+// Cell Masks
+//
+#define HCELL_NIL 0
+#define HCELL_CACHED 1
//
// CM_KEY_CONTROL_BLOCK Flags
@@ -367,6 +373,15 @@
LIST_ENTRY DelayedLRUList;
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
} CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY;
+
+//
+// Delayed KCB Dereference Entry
+//
+typedef struct _CM_DELAY_DEREF_KCB_ITEM
+{
+ LIST_ENTRY ListEntry;
+ PCM_KEY_CONTROL_BLOCK Kcb;
+} CM_DELAY_DEREF_KCB_ITEM, *PCM_DELAY_DEREF_KCB_ITEM;
//
// Use Count Log and Entry
@@ -521,6 +536,29 @@
} CELL_DATA, *PCELL_DATA;
//
+// Cached Value Index
+//
+typedef struct _CM_CACHED_VALUE_INDEX
+{
+ HCELL_INDEX CellIndex;
+ union
+ {
+ CELL_DATA CellData;
+ ULONG_PTR List[ANYSIZE_ARRAY];
+ } Data;
+} CM_CACHED_VALUE_INDEX, *PCM_CACHED_VALUE_INDEX;
+
+//
+// Cached Value
+//
+typedef struct _CM_CACHED_VALUE
+{
+ USHORT DataCacheType;
+ USHORT ValueKeySize;
+ CM_KEY_VALUE KeyValue;
+} CM_CACHED_VALUE, *PCM_CACHED_VALUE;
+
+//
// Registry Validation Functions
//
BOOLEAN
@@ -531,7 +569,7 @@
);
//
-// Registry Lock
+// Registry Locking Functions
//
BOOLEAN
NTAPI
@@ -540,6 +578,16 @@
);
//
+// KCB Functions
+//
+VOID
+NTAPI
+CmpDereferenceKcbWithLock(
+ IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN BOOLEAN LockHeldExclusively
+);
+
+//
// Global variables accessible from all of Cm
//
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 Wed Aug 16 22:38:09 2006
@@ -19,6 +19,24 @@
GET_HASH_KEY(ConvKey) % CmpHashTableSize
#define GET_HASH_ENTRY(Table, ConvKey) \
(*Table[GET_HASH_INDEX(ConvKey)])
+
+//
+// Returns whether or not the cell is cached
+//
+#define CMP_IS_CELL_CACHED(c) \
+ (((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
+
+//
+// Return data from a cached cell
+//
+#define CMP_GET_CACHED_CELL(c) \
+ (ULONG_PTR)((c) & ~HCELL_CACHED)
+#define CMP_GET_CACHED_DATA(c) \
+ (&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
+#define CMP_GET_CACHED_INDEX(c) \
+ (&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
+#define CMP_GET_CACHED_VALUE(c) \
+ (&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
//
// Makes sure that the registry is locked
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 Wed Aug 16 22:38:09 2006
@@ -29,6 +29,14 @@
ULONG CmpDelayCloseIntervalInSeconds = 5;
KDPC CmpDelayCloseDpc;
KTIMER CmpDelayCloseTimer;
+
+KGUARDED_MUTEX CmpDelayDerefKCBLock;
+BOOLEAN CmpDelayDerefKCBWorkItemActive;
+LIST_ENTRY CmpDelayDerefKCBListHead;
+ULONG CmpDelayDerefKCBIntervalInSeconds = 5;
+KDPC CmpDelayDerefKCBDpc;
+KTIMER CmpDelayDerefKCBTimer;
+
BOOLEAN CmpHoldLazyFlush;
/* FUNCTIONS *****************************************************************/
@@ -281,6 +289,56 @@
}
}
+VOID
+NTAPI
+CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
+{
+ PCM_DELAYED_CLOSE_ENTRY Entry;
+ ULONG NewRefCount, OldRefCount;
+ PAGED_CODE();
+
+ /* Sanity checks */
+ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
+ (CmpTestRegistryLockExclusive() == TRUE));
+ if (Kcb->DelayedCloseIndex == CmpDelayedCloseSize) ASSERT(FALSE);
+
+ /* Get the entry and lock the table */
+ Entry = Kcb->DelayCloseEntry;
+ KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
+
+ /* Remove the entry */
+ RemoveEntryList(&Entry->DelayedLRUList);
+
+ /* Release the lock */
+ KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+
+ /* Free the entry */
+ CmpFreeDelayItem(Entry);
+
+ /* Reduce the number of elements */
+ InterlockedDecrement(&CmpDelayedCloseElements);
+
+ /* Sanity check */
+ if (!Kcb->InDelayClose) ASSERT(FALSE);
+
+ /* Get the old reference count */
+ OldRefCount = Kcb->InDelayClose;
+ ASSERT(OldRefCount == 1);
+
+ /* Set it to 0 */
+ NewRefCount = InterlockedCompareExchange(&Kcb->InDelayClose,
+ 0,
+ OldRefCount);
+ if (NewRefCount != OldRefCount) ASSERT(FALSE);
+
+ /* Remove the link to the entry */
+ Kcb->DelayCloseEntry = NULL;
+
+ /* Set new delay size and remove the delete flag */
+ Kcb->DelayedCloseIndex = CmpDelayedCloseSize;
+ Kcb->Delete = FALSE;
+}
+
BOOLEAN
NTAPI
CmpReferenceKcb(IN PCM_KEY_CONTROL_BLOCK Kcb)
@@ -359,7 +417,7 @@
}
// FIXME: THIS FUNCTION IS PARTIALLY FUCKED
-PCM_DELAYED_CLOSE_ENTRY
+PVOID
NTAPI
CmpAllocateDelayItem(VOID)
{
@@ -408,6 +466,131 @@
/* Release the lock */
KeReleaseGuardedMutex(&CmpDelayAllocBucketLock);
return Entry;
+}
+
+VOID
+NTAPI
+CmpDelayDerefKcb(IN PCM_KEY_CONTROL_BLOCK Kcb)
+{
+ USHORT OldRefCount, NewRefCount;
+ LARGE_INTEGER Timeout;
+ PCM_DELAY_DEREF_KCB_ITEM Entry;
+ PAGED_CODE();
+
+ /* Get the previous reference count */
+ OldRefCount = Kcb->RefCount;
+
+ /* Write the new one */
+ NewRefCount = (USHORT)InterlockedCompareExchange((PLONG)&Kcb->RefCount,
+ OldRefCount - 1,
+ OldRefCount);
+ if (NewRefCount != OldRefCount) return;
+
+ /* Allocate a delay item */
+ Entry = CmpAllocateDelayItem();
+ if (!Entry) return;
+
+ /* Set the KCB */
+ Entry->Kcb = Kcb;
+
+ /* Acquire the delayed deref table lock */
+ KeAcquireGuardedMutex(&CmpDelayDerefKCBLock);
+
+ /* Insert the entry into the list */
+ InsertHeadList(&CmpDelayDerefKCBListHead, &Entry->ListEntry);
+
+ /* Check if we need to enable anything */
+ if (CmpDelayDerefKCBWorkItemActive)
+ {
+ /* Yes, we have no work item, setup the interval */
+ Timeout.QuadPart = CmpDelayDerefKCBIntervalInSeconds * -10000000;
+ KeSetTimer(&CmpDelayDerefKCBTimer, Timeout, &CmpDelayDerefKCBDpc);
+ }
+
+ /* Release the table lock */
+ KeReleaseGuardedMutex(&CmpDelayDerefKCBLock);
+}
+
+VOID
+NTAPI
+CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
+{
+ PULONG_PTR CachedList;
+ ULONG i;
+
+ /* Sanity check */
+ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
+ (CmpTestRegistryLockExclusive() == TRUE));
+
+ /* Check if the value list is cached */
+ if (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
+ {
+ /* Get the cache list */
+ CachedList = (PULONG_PTR)CMP_GET_CACHED_DATA(Kcb->ValueCache.ValueList);
+ for (i = 0; i < Kcb->ValueCache.Count; i++)
+ {
+ /* Check if this cell is cached */
+ if (CMP_IS_CELL_CACHED(CachedList[i]))
+ {
+ /* Free it */
+ ExFreePool((PVOID)CMP_GET_CACHED_CELL(CachedList[i]));
+ }
+ }
+
+ /* Now free the list */
+ ExFreePool((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList));
+ Kcb->ValueCache.ValueList = HCELL_NIL;
+ }
+ else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
+ {
+ /* This is a sym link, check if there's only one reference left */
+ if ((Kcb->ValueCache.RealKcb->RefCount == 1) &&
+ !(Kcb->ValueCache.RealKcb->Delete))
+ {
+ /* Disable delay close for the KCB */
+ Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
+ }
+
+ /* Dereference the KCB */
+ CmpDelayDerefKcb(Kcb->ValueCache.RealKcb);
+ Kcb->ExtFlags &= ~ CM_KCB_SYM_LINK_FOUND;
+ }
+}
+
+VOID
+NTAPI
+CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN BOOLEAN LockHeldExclusively)
+{
+ PCM_KEY_CONTROL_BLOCK Parent;
+ PAGED_CODE();
+
+ /* Sanity checks */
+ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
+ (CmpTestRegistryLockExclusive() == TRUE));
+ ASSERT(Kcb->RefCount == 0);
+
+ /* Cleanup the value cache */
+ CmpCleanUpKcbValueCache(Kcb);
+
+ /* Reference the NCB */
+ CmpDereferenceNcbWithLock(Kcb->NameBlock);
+
+ /* Check if we have an index hint block and free it */
+ if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) ExFreePool(Kcb->IndexHint);
+
+ /* Check if we were already deleted */
+ Parent = Kcb->ParentKcb;
+ if (!Kcb->Delete) CmpFreeKcb(Kcb);
+
+ /* Check if we have a parent */
+ if (Parent)
+ {
+ /* Dereference the parent */
+ LockHeldExclusively ? CmpDereferenceKcbWithLock(Kcb,
+ LockHeldExclusively) :
+ CmpDelayDerefKcb(Kcb);
+ }
}
VOID