diff --git a/NTOSKRNL/CC/cclazywriter.cpp b/NTOSKRNL/CC/cclazywriter.cpp index dbdc4ad..47a4f3f 100644 --- a/NTOSKRNL/CC/cclazywriter.cpp +++ b/NTOSKRNL/CC/cclazywriter.cpp @@ -13,9 +13,142 @@ extern "C" -/*Internal Function*/ +BOOLEAN +FASTCALL +CcIsLazyWriteScanQueued( + _In_ ULONG ReasonForFlush + ) +{ + switch (ReasonForFlush) + { + case 0: + return false; -/* Directives for Extra Write Behind Threads here */ + case 1: + case 2: + case 16: + if (LazyWriter.PendingLowMemoryScan || + LazyWriter.PendingPowerScan || + LazyWriter.PendingCoalescingFlushScan) + { + return true; + } + return false; + + case 4: + if (LazyWriter.PendingPeriodicScan || + LazyWriter.PendingTeardownScan) + { + return true; + } + return false; + + case 8: + return (BOOLEAN)LazyWriter.PendingTeardownScan; + + default: + return false; + } +} + +VOID +NTAPI +CcQueueLazyWriteScanThread( + _In_ PVOID NULL_PARAM + ) +{ + UNREFERENCED_PARAMETER(NULL_PARAM); + + ULONG Reason = 0; + BOOLEAN NeedAdjustment; + NTSTATUS Status; + KIRQL OldIrql; + PWORK_QUEUE_ENTRY WorkQueueEntry; + PVOID WaitObjects[5]; + + WaitObjects[0] = &CcLowMemoryEvent; + WaitObjects[1] = &CcPowerEvent; + WaitObjects[2] = &CcPeriodicEvent; + WaitObjects[3] = &CcWaitingForTeardownEvent; + WaitObjects[4] = &CcCoalescingFlushEvent; + + for (;;) + { + NeedAdjustment = false; + + Status = KeWaitForMultipleObjects( + 5, + WaitObjects, + WaitAny, + WrFreePage, + KernelMode, + false, + NULL, + WaitBlockArray); + + switch (Status) + { + case STATUS_WAIT_0: + Reason = 1; + NeedAdjustment = true; + break; + + case STATUS_WAIT_1: + Reason = 2; + break; + + case STATUS_WAIT_2: + Reason = 4; + break; + + case STATUS_WAIT_3: + Reason = 8; + break; + + case STATUS_WAIT_4: + Reason = 16; + break; + + default: + continue; + } + + if (CcNumberOfExternalCaches && !IsListEmpty(&CcExternalCacheList)) + { + CcNotifyExternalCaches(Reason); + } + + CcAdjustWriteBehindThreadPoolIfNeeded(NeedAdjustment); + + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + + if (CcIsLazyWriteScanQueued(Reason)) + { + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + continue; + } + + CcSetLazyWriteScanQueued(Reason, true); + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + + if (!NT_SUCCESS(CcAllocateWorkQueueEntry(&WorkQueueEntry))) + { + KSPIN_LOCK_QUEUE_NUMBER queueNumber = LockQueueMasterLock; + SpinLockGuard guard(queueNumber); + LazyWriter.ScanActive = false; + CcSetLazyWriteScanQueued(Reason, false); + } + else + { + WorkQueueEntry->Function = 3; + WorkQueueEntry->Parameters.Notification.Reason = Reason; + + CcPostWorkQueue( + WorkQueueEntry, + (Reason != 8) ? &CcRegularWorkQueue : &CcFastTeardownWorkQueue); + } + } +} VOID NTAPI