[CMAKE]
[reactos.git] / ntoskrnl / config / cmdelay.c
index 4f71aec..58ac9a6 100644 (file)
@@ -15,7 +15,6 @@
 /* GLOBALS *******************************************************************/
 
 WORK_QUEUE_ITEM CmpDelayDerefKCBWorkItem;
-LIST_ENTRY CmpFreeDelayItemsListHead;
 
 ULONG CmpDelayedCloseSize = 2048;
 ULONG CmpDelayedCloseElements;
@@ -54,17 +53,139 @@ VOID
 NTAPI
 CmpDelayCloseWorker(IN PVOID Context)
 {
+    PCM_DELAYED_CLOSE_ENTRY ListEntry;
+    ULONG i, ConvKey;
     PAGED_CODE();
 
     /* Sanity check */
     ASSERT(CmpDelayCloseWorkItemActive);
 
-    /* FIXME: TODO */
-    ASSERT(FALSE);
+    /* Lock the registry */
+    CmpLockRegistry();
+
+    /* Acquire the delayed close table lock */
+    KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
+
+    /* Iterate */
+    for (i = 0; i < (CmpDelayedCloseSize >> 2); i++)
+    {
+        /* Break out of the loop if there is nothing to process */
+        if (CmpDelayedCloseElements <= CmpDelayedCloseSize) break;
+
+        /* Sanity check */
+        ASSERT(!IsListEmpty(&CmpDelayedLRUListHead));
+
+        /* Get the entry */
+        ListEntry = CONTAINING_RECORD(CmpDelayedLRUListHead.Blink,
+                                      CM_DELAYED_CLOSE_ENTRY,
+                                      DelayedLRUList);
+
+        /* Save the ConvKey value of the KCB */
+        ConvKey = ListEntry->KeyControlBlock->ConvKey;
+
+        /* Release the delayed close table lock */
+        KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+
+        /* Acquire the KCB lock */
+        CmpAcquireKcbLockExclusiveByKey(ConvKey);
+
+        /* Reacquire the delayed close table lock */
+        KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
+
+        /* Get the entry */
+        ListEntry = CONTAINING_RECORD(CmpDelayedLRUListHead.Blink,
+                                      CM_DELAYED_CLOSE_ENTRY,
+                                      DelayedLRUList);
+
+        /* Is the entry we have still the first one? */
+        if (CmpDelayedCloseElements <= CmpDelayedCloseSize)
+        {
+            /* No, someone already inserted an entry there */
+            CmpReleaseKcbLockByKey(ConvKey);
+            break;
+        }
+
+        /* Is it a different entry? */
+        if (ConvKey != ListEntry->KeyControlBlock->ConvKey)
+        {
+            /* Release the delayed close table lock */
+            KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+
+            /* Release the KCB lock */
+            CmpReleaseKcbLockByKey(ConvKey);
+
+            /* Reacquire the delayed close table lock */
+            KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
+
+            /* Iterate again */
+            continue;
+        }
+
+        /* Remove it from the end of the list */
+        ListEntry =
+            (PCM_DELAYED_CLOSE_ENTRY)RemoveTailList(&CmpDelayedLRUListHead);
+
+        /* Get the containing entry */
+        ListEntry = CONTAINING_RECORD(ListEntry,
+                                      CM_DELAYED_CLOSE_ENTRY,
+                                      DelayedLRUList);
+
+        /* Process the entry */
+        if ((ListEntry->KeyControlBlock->RefCount) ||
+            (ListEntry->KeyControlBlock->DelayedCloseIndex))
+        {
+            /* Add it to the beginning of the list */
+            InsertHeadList(&CmpDelayedLRUListHead, &ListEntry->DelayedLRUList);
+
+            /* Release the delayed close table lock */
+            KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+        }
+        else
+        {
+            /* Release the delayed close table lock */
+            KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+
+            /* Zero out the DelayCloseEntry pointer */
+            ListEntry->KeyControlBlock->DelayCloseEntry = NULL;
+
+            /* Cleanup the KCB cache */
+            CmpCleanUpKcbCacheWithLock(ListEntry->KeyControlBlock, FALSE);
+
+            /* Free the delay item */
+            CmpFreeDelayItem(ListEntry);
+
+            /* Decrement delayed close elements count */
+            InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
+        }
+
+        /* Release the KCB lock */
+        CmpReleaseKcbLockByKey(ConvKey);
+
+        /* Reacquire the delayed close table lock */
+        KeAcquireGuardedMutex(&CmpDelayedCloseTableLock);
+    }
+
+    if (CmpDelayedCloseElements <= CmpDelayedCloseSize)
+    {
+        /* We're not active anymore */
+        CmpDelayCloseWorkItemActive = FALSE;
+    }
+    else
+    {
+        /* We didn't process all things, so reschedule for the next time */
+        CmpArmDelayedCloseTimer();
+    }
+
+    /* Release the delayed close table lock */
+    KeReleaseGuardedMutex(&CmpDelayedCloseTableLock);
+
+    /* Unlock the registry */
+    CmpUnlockRegistry();
 }
 
 VOID
 NTAPI
+INIT_FUNCTION
 CmpInitializeDelayedCloseTable(VOID)
 {
     
@@ -139,6 +260,7 @@ CmpDelayDerefKCBWorker(IN PVOID Context)
 
 VOID
 NTAPI
+INIT_FUNCTION
 CmpInitDelayDerefKCBEngine(VOID)
 {
     /* Initialize lock and list */
@@ -163,6 +285,8 @@ CmpDelayDerefKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
     LARGE_INTEGER Timeout;
     PCM_DELAY_DEREF_KCB_ITEM Entry;
     PAGED_CODE();
+    CMTRACE(CM_REFERENCE_DEBUG,
+            "%s - Dereferencing KCB: %p\n", __FUNCTION__, Kcb);
 
     /* Get the previous reference count */
     OldRefCount = *(PLONG)&Kcb->RefCount;