ReactOS 0.4.15-dev-5865-g640e228
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 136 of file lazywrite.c.

137{
140 PLIST_ENTRY ListEntry;
141 LIST_ENTRY ToPost;
143
144 /* Do we have entries to queue after we're done? */
145 InitializeListHead(&ToPost);
148 {
150 {
152 WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks);
153 InsertTailList(&ToPost, &WorkItem->WorkQueueLinks);
154 }
156 }
158
159 /* Our target is one-eighth of the dirty pages */
161 if (Target != 0)
162 {
163 /* There is stuff to flush, schedule a write-behind operation */
164
165 /* Allocate a work item */
166 WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
167 if (WorkItem != NULL)
168 {
169 WorkItem->Function = WriteBehind;
171 }
172 }
173
174 /* Post items that were due for end of run */
175 while (!IsListEmpty(&ToPost))
176 {
177 ListEntry = RemoveHeadList(&ToPost);
178 WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks);
180 }
181
182 /* If we have deferred writes, try them now! */
184 {
186 /* Reschedule immediately a lazy writer run
187 * Keep us active to have short idle delay
188 */
190 }
191 else
192 {
193 /* We're no longer active */
197 }
198}
#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:200
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:792
@ LockQueueMasterLock
Definition: ketypes.h:651

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:654

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 200 of file lazywrite.c.

202{
203 /* If no delay, immediately start lazy writer,
204 * no matter it was already started
205 */
206 if (NoDelay)
207 {
210 }
211 /* Otherwise, if it's not running, just wait three seconds to start it */
212 else if (!LazyWriter.ScanActive)
213 {
216 }
217 /* Finally, already running, so queue for the next second */
218 else
219 {
221 }
222}
#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 367 of file lazywrite.c.

369{
371 KEVENT WaitEvent;
373
374 /* Allocate a work item */
375 WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
376 if (WorkItem == NULL)
377 {
379 }
380
381 /* We want lazy writer to set our event */
382 WorkItem->Function = SetDone;
384 WorkItem->Parameters.Event.Event = &WaitEvent;
385
386 /* Use the post tick queue */
388 InsertTailList(&CcPostTickWorkQueue, &WorkItem->WorkQueueLinks);
389
390 /* Inform the lazy writer it will have to handle the post tick queue */
392 /* And if it's not running, queue a lazy writer run
393 * And start it NOW, we want the response now
394 */
396 {
398 }
399
401
402 /* And now, wait until lazy writer replies */
403 return KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL);
404}
#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:403

◆ CcWorkerThread()

VOID NTAPI CcWorkerThread ( IN PVOID  Parameter)

Definition at line 226 of file lazywrite.c.

228{
230 BOOLEAN DropThrottle, WritePerformed;
232#if DBG
234#endif
235
236 /* Get back our thread item */
237 Item = Parameter;
238 /* And by default, don't touch throttle */
239 DropThrottle = FALSE;
240 /* No write performed */
241 WritePerformed = FALSE;
242
243#if DBG
244 /* Top level IRP should be clean when started
245 * Save it to catch buggy drivers (or bugs!)
246 */
248 if (TopLevel != NULL)
249 {
250 DPRINT1("(%p) TopLevel IRP for this thread: %p\n", PsGetCurrentThread(), TopLevel);
251 }
252#endif
253
254 /* Loop till we have jobs */
255 while (TRUE)
256 {
258
259 /* Lock queues */
261
262 /* If we have to touch throttle, reset it now! */
263 if (DropThrottle)
264 {
266 DropThrottle = FALSE;
267 }
268
269 /* Check first if we have read ahead to do */
271 {
272 /* If not, check regular queue */
274 {
275 break;
276 }
277 else
278 {
280 }
281 }
282 else
283 {
285 }
286
287 /* Get our work item, if someone is waiting for us to finish
288 * and we're not the only thread in queue
289 * then, quit running to let the others do
290 * and throttle so that noone starts till current activity is over
291 */
292 if (WorkItem->Function == SetDone && CcNumberActiveWorkerThreads > 1)
293 {
295 break;
296 }
297
298 /* Otherwise, remove current entry */
299 RemoveEntryList(&WorkItem->WorkQueueLinks);
301
302 /* And handle it */
303 switch (WorkItem->Function)
304 {
305 case ReadAhead:
306 CcPerformReadAhead(WorkItem->Parameters.Read.FileObject);
307 break;
308
309 case WriteBehind:
310 PsGetCurrentThread()->MemoryMaker = 1;
312 PsGetCurrentThread()->MemoryMaker = 0;
313 WritePerformed = TRUE;
314 break;
315
316 case LazyScan:
318 break;
319
320 case SetDone:
321 KeSetEvent(WorkItem->Parameters.Event.Event, IO_NO_INCREMENT, FALSE);
322 DropThrottle = TRUE;
323 break;
324
325 default:
326 DPRINT1("Ignored item: %p (%d)\n", WorkItem, WorkItem->Function);
327 break;
328 }
329
330 /* And release the item */
331 ExFreeToNPagedLookasideList(&CcTwilightLookasideList, WorkItem);
332 }
333
334 /* Our thread is available again */
336 /* One less worker */
339
340 /* If there are pending write openations and we have at least 20 dirty pages */
342 {
343 /* And if we performed a write operation previously, then
344 * stress the system a bit and reschedule a scan to find
345 * stuff to write
346 */
347 if (WritePerformed)
348 {
350 }
351 }
352
353#if DBG
354 /* Top level shouldn't have changed */
355 if (TopLevel != IoGetTopLevelIrp())
356 {
357 DPRINT1("(%p) Mismatching TopLevel: %p, %p\n", PsGetCurrentThread(), TopLevel, IoGetTopLevelIrp());
358 }
359#endif
360}
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:136
_In_ PVOID Parameter
Definition: ldrtypes.h:241
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

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}
ULONG CcLazyWritePages
Definition: lazywrite.c:20
ULONG CcLazyWriteIos
Definition: lazywrite.c:21
int Count
Definition: noreturn.cpp:7
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:305
#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