ReactOS 0.4.15-dev-7842-g558ab78
lazywrite.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for lazywrite.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID CcPostWorkQueue (IN PWORK_QUEUE_ENTRY WorkItem, IN PLIST_ENTRY WorkQueue)
 
VOID NTAPI CcScanDpc (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
VOID CcWriteBehind (VOID)
 
VOID CcLazyWriteScan (VOID)
 
VOID CcScheduleLazyWriteScan (IN BOOLEAN NoDelay)
 
VOID NTAPI CcWorkerThread (IN PVOID Parameter)
 
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity (VOID)
 

Variables

ULONG CcLazyWritePages = 0
 
ULONG CcLazyWriteIos = 0
 
LAZY_WRITER LazyWriter
 
NPAGED_LOOKASIDE_LIST CcTwilightLookasideList
 
LIST_ENTRY CcExpressWorkQueue
 
LIST_ENTRY CcRegularWorkQueue
 
LIST_ENTRY CcIdleWorkerThreadList
 
LIST_ENTRY CcPostTickWorkQueue
 
BOOLEAN CcQueueThrottle = FALSE
 
ULONG CcNumberActiveWorkerThreads = 0
 
LARGE_INTEGER CcFirstDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*3000*1000*10)
 
LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10)
 
LARGE_INTEGER CcNoDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0)
 
ULONG CcNumberWorkerThreads
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file lazywrite.c.

Function Documentation

◆ CcLazyWriteScan()

VOID CcLazyWriteScan ( VOID  )

Definition at line 146 of file lazywrite.c.

147{
150 PLIST_ENTRY ListEntry;
151 LIST_ENTRY ToPost;
153
154 /* Do we have entries to queue after we're done? */
155 InitializeListHead(&ToPost);
158 {
160 {
162 WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks);
163 InsertTailList(&ToPost, &WorkItem->WorkQueueLinks);
164 }
166 }
168
169 /* Our target is one-eighth of the dirty pages */
171 if (Target != 0)
172 {
173 /* There is stuff to flush, schedule a write-behind operation */
174
175 /* Allocate a work item */
176 WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
177 if (WorkItem != NULL)
178 {
179 WorkItem->Function = WriteBehind;
181 }
182 }
183
184 /* Post items that were due for end of run */
185 while (!IsListEmpty(&ToPost))
186 {
187 ListEntry = RemoveHeadList(&ToPost);
188 WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks);
190 }
191
192 /* If we have deferred writes, try them now! */
194 {
196 /* Reschedule immediately a lazy writer run
197 * Keep us active to have short idle delay
198 */
200 }
201 else
202 {
203 /* We're no longer active */
207 }
208}
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
NPAGED_LOOKASIDE_LIST CcTwilightLookasideList
Definition: lazywrite.c:38
LIST_ENTRY CcRegularWorkQueue
Definition: lazywrite.c:40
VOID CcPostWorkQueue(IN PWORK_QUEUE_ENTRY WorkItem, IN PLIST_ENTRY WorkQueue)
Definition: lazywrite.c:53
VOID CcScheduleLazyWriteScan(IN BOOLEAN NoDelay)
Definition: lazywrite.c:210
LIST_ENTRY CcPostTickWorkQueue
Definition: lazywrite.c:42
LAZY_WRITER LazyWriter
Definition: lazywrite.c:37
VOID CcPostDeferredWrites(VOID)
Definition: copy.c:73
LIST_ENTRY CcDeferredWrites
Definition: view.c:57
ULONG CcTotalDirtyPages
Definition: view.c:56
@ WriteBehind
Definition: cc.h:279
BOOLEAN OtherWork
Definition: cc.h:247
BOOLEAN ScanActive
Definition: cc.h:246
Definition: typedefs.h:120
Definition: cc.h:252
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ LockQueueMasterLock
Definition: ketypes.h:663

Referenced by CcWorkerThread().

◆ CcPostWorkQueue()

VOID CcPostWorkQueue ( IN PWORK_QUEUE_ENTRY  WorkItem,
IN PLIST_ENTRY  WorkQueue 
)

Definition at line 53 of file lazywrite.c.

56{
58 PWORK_QUEUE_ITEM ThreadToSpawn;
59
60 /* First of all, insert the item in the queue */
62 InsertTailList(WorkQueue, &WorkItem->WorkQueueLinks);
63
64 /* Now, define whether we have to spawn a new work thread
65 * We will spawn a new one if:
66 * - There's no throttle in action
67 * - There's still at least one idle thread
68 */
69 ThreadToSpawn = NULL;
71 {
72 PLIST_ENTRY ListEntry;
73
74 /* Get the idle thread */
76 ThreadToSpawn = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ITEM, List);
77
78 /* We're going to have one more! */
80 }
81
83
84 /* If we have a thread to spawn, do it! */
85 if (ThreadToSpawn != NULL)
86 {
87 /* We NULLify it to be consistent with initialization */
88 ThreadToSpawn->List.Flink = NULL;
89 ExQueueWorkItem(ThreadToSpawn, CriticalWorkQueue);
90 }
91}
ULONG CcNumberActiveWorkerThreads
Definition: lazywrite.c:44
LIST_ENTRY CcIdleWorkerThreadList
Definition: lazywrite.c:41
BOOLEAN CcQueueThrottle
Definition: lazywrite.c:43
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY List
Definition: extypes.h:203
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
LIST_ENTRY WorkQueue
Definition: workqueue.c:16
@ CriticalWorkQueue
Definition: extypes.h:189
@ LockQueueWorkQueueLock
Definition: ketypes.h:666

Referenced by CcLazyWriteScan(), CcScanDpc(), and CcScheduleReadAhead().

◆ CcScanDpc()

VOID NTAPI CcScanDpc ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 95 of file lazywrite.c.

100{
102
103 /* Allocate a work item */
104 WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
105 if (WorkItem == NULL)
106 {
108 return;
109 }
110
111 /* And post it, it will be for lazy write */
112 WorkItem->Function = LazyScan;
114}
@ LazyScan
Definition: cc.h:280

Referenced by CcInitializeCacheManager().

◆ CcScheduleLazyWriteScan()

VOID CcScheduleLazyWriteScan ( IN BOOLEAN  NoDelay)

Definition at line 210 of file lazywrite.c.

212{
213 /* If no delay, immediately start lazy writer,
214 * no matter it was already started
215 */
216 if (NoDelay)
217 {
220 }
221 /* Otherwise, if it's not running, just wait three seconds to start it */
222 else if (!LazyWriter.ScanActive)
223 {
226 }
227 /* Finally, already running, so queue for the next second */
228 else
229 {
231 }
232}
#define TRUE
Definition: types.h:120
LARGE_INTEGER CcFirstDelay
Definition: lazywrite.c:45
LARGE_INTEGER CcIdleDelay
Definition: lazywrite.c:46
LARGE_INTEGER CcNoDelay
Definition: lazywrite.c:47
KDPC ScanDpc
Definition: cc.h:244
KTIMER ScanTimer
Definition: cc.h:245
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281

Referenced by CcCanIWrite(), CcDeferWrite(), CcLazyWriteScan(), CcRosMarkDirtyVacb(), and CcWaitForCurrentLazyWriterActivity().

◆ CcWaitForCurrentLazyWriterActivity()

NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity ( VOID  )

Definition at line 377 of file lazywrite.c.

379{
381 KEVENT WaitEvent;
383
384 /* Allocate a work item */
385 WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
386 if (WorkItem == NULL)
387 {
389 }
390
391 /* We want lazy writer to set our event */
392 WorkItem->Function = SetDone;
394 WorkItem->Parameters.Event.Event = &WaitEvent;
395
396 /* Use the post tick queue */
398 InsertTailList(&CcPostTickWorkQueue, &WorkItem->WorkQueueLinks);
399
400 /* Inform the lazy writer it will have to handle the post tick queue */
402 /* And if it's not running, queue a lazy writer run
403 * And start it NOW, we want the response now
404 */
406 {
408 }
409
411
412 /* And now, wait until lazy writer replies */
413 return KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL);
414}
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
@ SetDone
Definition: cc.h:281
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ Executive
Definition: ketypes.h:415

◆ CcWorkerThread()

VOID NTAPI CcWorkerThread ( IN PVOID  Parameter)

Definition at line 236 of file lazywrite.c.

238{
240 BOOLEAN DropThrottle, WritePerformed;
242#if DBG
244#endif
245
246 /* Get back our thread item */
247 Item = Parameter;
248 /* And by default, don't touch throttle */
249 DropThrottle = FALSE;
250 /* No write performed */
251 WritePerformed = FALSE;
252
253#if DBG
254 /* Top level IRP should be clean when started
255 * Save it to catch buggy drivers (or bugs!)
256 */
258 if (TopLevel != NULL)
259 {
260 DPRINT1("(%p) TopLevel IRP for this thread: %p\n", PsGetCurrentThread(), TopLevel);
261 }
262#endif
263
264 /* Loop till we have jobs */
265 while (TRUE)
266 {
268
269 /* Lock queues */
271
272 /* If we have to touch throttle, reset it now! */
273 if (DropThrottle)
274 {
276 DropThrottle = FALSE;
277 }
278
279 /* Check first if we have read ahead to do */
281 {
282 /* If not, check regular queue */
284 {
285 break;
286 }
287 else
288 {
290 }
291 }
292 else
293 {
295 }
296
297 /* Get our work item, if someone is waiting for us to finish
298 * and we're not the only thread in queue
299 * then, quit running to let the others do
300 * and throttle so that noone starts till current activity is over
301 */
302 if (WorkItem->Function == SetDone && CcNumberActiveWorkerThreads > 1)
303 {
305 break;
306 }
307
308 /* Otherwise, remove current entry */
309 RemoveEntryList(&WorkItem->WorkQueueLinks);
311
312 /* And handle it */
313 switch (WorkItem->Function)
314 {
315 case ReadAhead:
316 CcPerformReadAhead(WorkItem->Parameters.Read.FileObject);
317 break;
318
319 case WriteBehind:
320 PsGetCurrentThread()->MemoryMaker = 1;
322 PsGetCurrentThread()->MemoryMaker = 0;
323 WritePerformed = TRUE;
324 break;
325
326 case LazyScan:
328 break;
329
330 case SetDone:
331 KeSetEvent(WorkItem->Parameters.Event.Event, IO_NO_INCREMENT, FALSE);
332 DropThrottle = TRUE;
333 break;
334
335 default:
336 DPRINT1("Ignored item: %p (%d)\n", WorkItem, WorkItem->Function);
337 break;
338 }
339
340 /* And release the item */
341 ExFreeToNPagedLookasideList(&CcTwilightLookasideList, WorkItem);
342 }
343
344 /* Our thread is available again */
346 /* One less worker */
349
350 /* If there are pending write openations and we have at least 20 dirty pages */
352 {
353 /* And if we performed a write operation previously, then
354 * stress the system a bit and reschedule a scan to find
355 * stuff to write
356 */
357 if (WritePerformed)
358 {
360 }
361 }
362
363#if DBG
364 /* Top level shouldn't have changed */
365 if (TopLevel != IoGetTopLevelIrp())
366 {
367 DPRINT1("(%p) Mismatching TopLevel: %p, %p\n", PsGetCurrentThread(), TopLevel, IoGetTopLevelIrp());
368 }
369#endif
370}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
VOID CcWriteBehind(VOID)
Definition: lazywrite.c:117
LIST_ENTRY CcExpressWorkQueue
Definition: lazywrite.c:39
VOID CcLazyWriteScan(VOID)
Definition: lazywrite.c:146
VOID CcPerformReadAhead(IN PFILE_OBJECT FileObject)
Definition: copy.c:130
@ ReadAhead
Definition: cc.h:278
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
_In_ WDFCOLLECTION _In_ WDFOBJECT Item
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

Referenced by CcInitializeCacheManager().

◆ CcWriteBehind()

VOID CcWriteBehind ( VOID  )

Definition at line 117 of file lazywrite.c.

118{
120
122 if (Target != 0)
123 {
124 /* Flush! */
125 DPRINT("Lazy writer starting (%d)\n", Target);
127
128 /* And update stats */
131 DPRINT("Lazy writer done (%d)\n", Count);
132 }
133
134 /* Make sure we're not throttling writes after this */
136 {
137 /* Break if we can't even find one to free */
139 {
140 break;
141 }
142 }
143}
ULONG CcLazyWritePages
Definition: lazywrite.c:20
ULONG CcLazyWriteIos
Definition: lazywrite.c:21
int Count
Definition: noreturn.cpp:7
BOOLEAN CcRosFreeOneUnusedVacb(VOID)
Definition: view.c:720
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:308
ULONG MmThrottleTop
Definition: mminit.c:396
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
#define DPRINT
Definition: sndvol32.h:71

Referenced by CcWorkerThread().

Variable Documentation

◆ CcExpressWorkQueue

LIST_ENTRY CcExpressWorkQueue

Definition at line 39 of file lazywrite.c.

Referenced by CcInitializeCacheManager(), CcScheduleReadAhead(), and CcWorkerThread().

◆ CcFirstDelay

LARGE_INTEGER CcFirstDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*3000*1000*10)

Definition at line 45 of file lazywrite.c.

Referenced by CcScheduleLazyWriteScan().

◆ CcIdleDelay

LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10)

Definition at line 46 of file lazywrite.c.

Referenced by CcCanIWrite(), and CcScheduleLazyWriteScan().

◆ CcIdleWorkerThreadList

LIST_ENTRY CcIdleWorkerThreadList

Definition at line 41 of file lazywrite.c.

Referenced by CcInitializeCacheManager(), CcPostWorkQueue(), and CcWorkerThread().

◆ CcLazyWriteIos

ULONG CcLazyWriteIos = 0

Definition at line 21 of file lazywrite.c.

Referenced by CcWriteBehind(), and QSI_DEF().

◆ CcLazyWritePages

ULONG CcLazyWritePages = 0

Definition at line 20 of file lazywrite.c.

Referenced by CcWriteBehind(), and QSI_DEF().

◆ CcNoDelay

Definition at line 47 of file lazywrite.c.

Referenced by CcScheduleLazyWriteScan().

◆ CcNumberActiveWorkerThreads

ULONG CcNumberActiveWorkerThreads = 0

Definition at line 44 of file lazywrite.c.

Referenced by CcPostWorkQueue(), and CcWorkerThread().

◆ CcNumberWorkerThreads

ULONG CcNumberWorkerThreads

Definition at line 48 of file lazywrite.c.

Referenced by CcInitializeCacheManager().

◆ CcPostTickWorkQueue

LIST_ENTRY CcPostTickWorkQueue

◆ CcQueueThrottle

BOOLEAN CcQueueThrottle = FALSE

Definition at line 43 of file lazywrite.c.

Referenced by CcPostWorkQueue(), and CcWorkerThread().

◆ CcRegularWorkQueue

LIST_ENTRY CcRegularWorkQueue

Definition at line 40 of file lazywrite.c.

Referenced by CcInitializeCacheManager(), CcLazyWriteScan(), CcScanDpc(), and CcWorkerThread().

◆ CcTwilightLookasideList

◆ LazyWriter