ReactOS 0.4.17-dev-684-ga6524ef
work.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for work.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define EX_DELAYED_WORK_THREADS   12
 
#define EX_CRITICAL_WORK_THREADS   8
 
#define EX_DYNAMIC_WORK_THREAD   0x80000000
 
#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT   7
 
#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT   5
 
#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT   4
 

Functions

VOID NTAPI ExpWorkerThreadEntryPoint (IN PVOID Context)
 
VOID NTAPI ExpCreateWorkerThread (WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic)
 
VOID NTAPI ExpDetectWorkerThreadDeadlock (VOID)
 
VOID NTAPI ExpCheckDynamicThreadCount (VOID)
 
VOID NTAPI ExpWorkerThreadBalanceManager (IN PVOID Context)
 
VOID NTAPI ExpInitializeWorkerThreads (VOID)
 
VOID NTAPI ExpSetSwappingKernelApc (IN PKAPC Apc, OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
 
VOID NTAPI ExSwapinWorkerThreads (IN BOOLEAN AllowSwap)
 
VOID NTAPI ExQueueWorkItem (IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
 

Variables

EX_WORK_QUEUE ExWorkerQueue [MaximumWorkQueue]
 
ULONG ExCriticalWorkerThreads
 
ULONG ExDelayedWorkerThreads
 
ULONG ExpAdditionalCriticalWorkerThreads
 
ULONG ExpAdditionalDelayedWorkerThreads
 
BOOLEAN ExpWorkersCanSwap
 
LIST_ENTRY ExpWorkerListHead
 
FAST_MUTEX ExpWorkerSwapinMutex
 
KEVENT ExpThreadSetManagerEvent
 
KEVENT ExpThreadSetManagerShutdownEvent
 
PETHREAD ExpWorkerThreadBalanceManagerPtr
 
PETHREAD ExpLastWorkerThread
 

Macro Definition Documentation

◆ EX_CRITICAL_QUEUE_PRIORITY_INCREMENT

#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT   5

Definition at line 26 of file work.c.

◆ EX_CRITICAL_WORK_THREADS

#define EX_CRITICAL_WORK_THREADS   8

Definition at line 19 of file work.c.

◆ EX_DELAYED_QUEUE_PRIORITY_INCREMENT

#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT   4

Definition at line 27 of file work.c.

◆ EX_DELAYED_WORK_THREADS

#define EX_DELAYED_WORK_THREADS   12

Definition at line 18 of file work.c.

◆ EX_DYNAMIC_WORK_THREAD

#define EX_DYNAMIC_WORK_THREAD   0x80000000

Definition at line 22 of file work.c.

◆ EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT

#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT   7

Definition at line 25 of file work.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file work.c.

Function Documentation

◆ ExpCheckDynamicThreadCount()

VOID NTAPI ExpCheckDynamicThreadCount ( VOID  )

Definition at line 381 of file work.c.

382{
383 ULONG i;
385
386 /* Loop the 3 queues */
387 for (i = 0; i < MaximumWorkQueue; i++)
388 {
389 /* Get the queue */
391
392 /* Check if still need a new thread. See ExQueueWorkItem */
393 if ((Queue->Info.MakeThreadsAsNecessary) &&
394 (!IsListEmpty(&Queue->WorkerQueue.EntryListHead)) &&
395 (Queue->WorkerQueue.CurrentCount <
396 Queue->WorkerQueue.MaximumCount) &&
397 (Queue->DynamicThreadCount < 16))
398 {
399 /* Create a new thread */
400 DPRINT1("EX: Creating new dynamic thread as requested\n");
402 }
403 }
404}
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2231
VOID NTAPI ExpCreateWorkerThread(WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic)
Definition: work.c:249
EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue]
Definition: work.c:30
@ MaximumWorkQueue
Definition: extypes.h:198

Referenced by ExpWorkerThreadBalanceManager().

◆ ExpCreateWorkerThread()

VOID NTAPI ExpCreateWorkerThread ( WORK_QUEUE_TYPE  WorkQueueType,
IN BOOLEAN  Dynamic 
)

Definition at line 249 of file work.c.

251{
257
258 /* Check if this is going to be a dynamic thread */
259 Context = WorkQueueType;
260
261 /* Add the dynamic mask */
262 if (Dynamic) Context |= EX_DYNAMIC_WORK_THREAD;
263
264 /* Create the System Thread */
267 NULL,
268 NULL,
269 NULL,
272 if (!NT_SUCCESS(Status))
273 {
274 /* Well... */
275 DPRINT1("Failed to create worker thread: 0x%08x\n", Status);
276 return;
277 }
278
279 /* If the thread is dynamic */
280 if (Dynamic)
281 {
282 /* Increase the count */
283 InterlockedIncrement(&ExWorkerQueue[WorkQueueType].DynamicThreadCount);
284 }
285
286 /* Set the priority */
287 if (WorkQueueType == DelayedWorkQueue)
288 {
289 /* Priority == 4 */
291 }
292 else if (WorkQueueType == CriticalWorkQueue)
293 {
294 /* Priority == 5 */
296 }
297 else
298 {
299 /* Priority == 7 */
301 }
302
303 /* Get the Thread */
308 (PVOID*)&Thread,
309 NULL);
310
311 /* Set the Priority */
313
314 /* Dereference and close handle */
317}
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
LONG KPRIORITY
Definition: compat.h:803
#define UlongToPtr(u)
Definition: config.h:106
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:24
#define KernelMode
Definition: asm.h:38
HANDLE hThread
Definition: wizard.c:28
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1340
POBJECT_TYPE PsThreadType
Definition: thread.c:20
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3406
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
_In_ PVOID Context
Definition: storport.h:2269
KTHREAD Tcb
Definition: pstypes.h:1198
LONG NTAPI KeSetBasePriorityThread(IN PKTHREAD Thread, IN LONG Increment)
Definition: thrdobj.c:1157
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:655
#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT
Definition: work.c:27
#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:25
VOID NTAPI ExpWorkerThreadEntryPoint(IN PVOID Context)
Definition: work.c:77
#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:26
#define EX_DYNAMIC_WORK_THREAD
Definition: work.c:22
@ DelayedWorkQueue
Definition: extypes.h:190
@ CriticalWorkQueue
Definition: extypes.h:189
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by ExpCheckDynamicThreadCount(), ExpDetectWorkerThreadDeadlock(), and ExpInitializeWorkerThreads().

◆ ExpDetectWorkerThreadDeadlock()

VOID NTAPI ExpDetectWorkerThreadDeadlock ( VOID  )

Definition at line 336 of file work.c.

337{
338 ULONG i;
340
341 /* Loop the 3 queues */
342 for (i = 0; i < MaximumWorkQueue; i++)
343 {
344 /* Get the queue */
346 ASSERT(Queue->DynamicThreadCount <= 16);
347
348 /* Check if stuff is on the queue that still is unprocessed */
349 if ((Queue->QueueDepthLastPass) &&
350 (Queue->WorkItemsProcessed == Queue->WorkItemsProcessedLastPass) &&
351 (Queue->DynamicThreadCount < 16))
352 {
353 /* Stuff is still on the queue and nobody did anything about it */
354 DPRINT1("EX: Work Queue Deadlock detected: %lu\n", i);
356 DPRINT1("Dynamic threads queued %d\n", Queue->DynamicThreadCount);
357 }
358
359 /* Update our data */
360 Queue->WorkItemsProcessedLastPass = Queue->WorkItemsProcessed;
361 Queue->QueueDepthLastPass = KeReadStateQueue(&Queue->WorkerQueue);
362 }
363}
#define ASSERT(a)
Definition: mode.c:44
LONG NTAPI KeReadStateQueue(IN PKQUEUE Queue)
Definition: queue.c:226

Referenced by ExpWorkerThreadBalanceManager().

◆ ExpInitializeWorkerThreads()

VOID NTAPI ExpInitializeWorkerThreads ( VOID  )

Definition at line 521 of file work.c.

522{
523 ULONG WorkQueueType;
524 ULONG CriticalThreads, DelayedThreads;
525 HANDLE ThreadHandle;
527 ULONG i;
529
530 /* Setup the stack swap support */
534
535 /* Default the number of worker threads to be created */
536 DelayedThreads = EX_DELAYED_WORK_THREADS;
537 CriticalThreads = EX_CRITICAL_WORK_THREADS;
538
539 /*
540 * Get an additional number of worker threads from the Registry
541 * but make sure to NOT exceed the limit of 100. Windows XP
542 * and Server 2003 systems have a limit of 16, later versions
543 * of Windows like 7 and 8.1 have a limit of 100.
544 */
549
550 /* Calculate final count */
551 DelayedThreads += ExpAdditionalDelayedWorkerThreads;
552 CriticalThreads += ExpAdditionalCriticalWorkerThreads;
553
554 /* Initialize the Array */
555 for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++)
556 {
557 /* Clear the structure and initialize the queue */
558 RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
559 KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
560 }
561
562 /* Dynamic threads are only used for the critical queue */
564
565 /* Initialize the balance set manager events */
569 FALSE);
570
571 /* Create the built-in worker threads for the critical queue */
572 for (i = 0; i < CriticalThreads; i++)
573 {
574 /* Create the thread */
577 }
578
579 /* Create the built-in worker threads for the delayed queue */
580 for (i = 0; i < DelayedThreads; i++)
581 {
582 /* Create the thread */
585 }
586
587 /* Create the built-in worker thread for the hypercritical queue */
589
590 /* Create the balance set manager thread */
591 Status = PsCreateSystemThread(&ThreadHandle,
593 NULL,
594 0,
595 NULL,
597 NULL);
598 if (!NT_SUCCESS(Status))
599 {
600 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
601 }
602
603 /* Get a pointer to it for the shutdown process */
604 ObReferenceObjectByHandle(ThreadHandle,
606 NULL,
608 (PVOID*)&Thread,
609 NULL);
611
612 /* Close the handle and return */
613 ObCloseHandle(ThreadHandle, KernelMode);
614}
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define FALSE
Definition: types.h:117
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define min(a, b)
Definition: monoChain.cc:55
@ NotificationEvent
@ SynchronizationEvent
VOID NTAPI KeInitializeQueue(IN PKQUEUE Queue, IN ULONG Count OPTIONAL)
Definition: queue.c:148
ULONG MakeThreadsAsNecessary
Definition: extypes.h:571
EX_QUEUE_WORKER_INFO Info
Definition: extypes.h:583
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context)
Definition: work.c:426
ULONG ExCriticalWorkerThreads
Definition: work.c:33
KEVENT ExpThreadSetManagerEvent
Definition: work.c:44
PETHREAD ExpWorkerThreadBalanceManagerPtr
Definition: work.c:48
BOOLEAN ExpWorkersCanSwap
Definition: work.c:39
ULONG ExDelayedWorkerThreads
Definition: work.c:34
ULONG ExpAdditionalCriticalWorkerThreads
Definition: work.c:35
#define EX_DELAYED_WORK_THREADS
Definition: work.c:18
#define EX_CRITICAL_WORK_THREADS
Definition: work.c:19
KEVENT ExpThreadSetManagerShutdownEvent
Definition: work.c:45
ULONG ExpAdditionalDelayedWorkerThreads
Definition: work.c:36
FAST_MUTEX ExpWorkerSwapinMutex
Definition: work.c:41
LIST_ENTRY ExpWorkerListHead
Definition: work.c:40
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
@ HyperCriticalWorkQueue
Definition: extypes.h:191

Referenced by ExpInitSystemPhase1().

◆ ExpSetSwappingKernelApc()

VOID NTAPI ExpSetSwappingKernelApc ( IN PKAPC  Apc,
OUT PKNORMAL_ROUTINE NormalRoutine,
IN OUT PVOID NormalContext,
IN OUT PVOID SystemArgument1,
IN OUT PVOID SystemArgument2 
)

Definition at line 618 of file work.c.

623{
624 PBOOLEAN AllowSwap;
626
627 /* Make sure it's an active worker */
628 if (PsGetCurrentThread()->ActiveExWorker)
629 {
630 /* Read the setting from the context flag */
631 AllowSwap = (PBOOLEAN)NormalContext;
632 KeSetKernelStackSwapEnable(*AllowSwap);
633 }
634
635 /* Let caller know that we're done */
637}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PKEVENT
Definition: env_spec_w32.h:70
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
BOOLEAN NTAPI KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
Definition: thrdobj.c:988
unsigned char * PBOOLEAN
Definition: typedefs.h:53
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:756

Referenced by ExSwapinWorkerThreads().

◆ ExpWorkerThreadBalanceManager()

VOID NTAPI ExpWorkerThreadBalanceManager ( IN PVOID  Context)

Definition at line 426 of file work.c.

427{
431 PVOID WaitEvents[3];
432 PAGED_CODE();
434
435 /* Raise our priority above all other worker threads */
438
439 /* Setup the timer */
441 Timeout.QuadPart = Int32x32To64(-1, 10000000);
442
443 /* We'll wait on the periodic timer and also the emergency event */
444 WaitEvents[0] = &Timer;
445 WaitEvents[1] = &ExpThreadSetManagerEvent;
446 WaitEvents[2] = &ExpThreadSetManagerShutdownEvent;
447
448 /* Start wait loop */
449 for (;;)
450 {
451 /* Wait for the timer */
454 WaitEvents,
455 WaitAny,
456 Executive,
458 FALSE,
459 NULL,
460 NULL);
461 if (Status == 0)
462 {
463 /* Our timer expired. Check for deadlocks */
465 }
466 else if (Status == 1)
467 {
468 /* Someone notified us, verify if we should create a new thread */
470 }
471 else if (Status == 2)
472 {
473 /* We are shutting down. Cancel the timer */
474 DPRINT1("System shutdown\n");
476
477 /* Make sure we have a final thread */
479
480 /* Wait for it */
482 Executive,
484 FALSE,
485 NULL);
486
487 /* Dereference it and kill us */
490 }
491
492 /*
493 * If WinDBG wants to attach or kill a user-mode process, and/or
494 * page-in an address region, queue a debugger worker thread.
495 */
497 {
501 }
502 }
503}
#define PAGED_CODE()
WINKD_WORKER_STATE ExpDebuggerWork
Definition: dbgctrl.c:25
VOID NTAPI ExpDebuggerWorker(_In_ PVOID Context)
Definition: dbgctrl.c:52
WORK_QUEUE_ITEM ExpDebuggerWorkItem
Definition: dbgctrl.c:20
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
@ WinKdWorkerStart
Definition: ex.h:63
@ WinKdWorkerInitialized
Definition: ex.h:64
#define KeGetCurrentThread
Definition: hal.h:55
#define Int32x32To64(a, b)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ WaitAny
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:586
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1164
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:981
static ULONG Timeout
Definition: ping.c:61
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:282
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
VOID NTAPI ExpCheckDynamicThreadCount(VOID)
Definition: work.c:381
PETHREAD ExpLastWorkerThread
Definition: work.c:49
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:727
VOID NTAPI ExpDetectWorkerThreadDeadlock(VOID)
Definition: work.c:336
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ Executive
Definition: ketypes.h:467

Referenced by ExpInitializeWorkerThreads().

◆ ExpWorkerThreadEntryPoint()

VOID NTAPI ExpWorkerThreadEntryPoint ( IN PVOID  Context)

Definition at line 77 of file work.c.

78{
81 WORK_QUEUE_TYPE WorkQueueType;
84 PLARGE_INTEGER TimeoutPointer = NULL;
86 KPROCESSOR_MODE WaitMode;
87 EX_QUEUE_WORKER_INFO OldValue, NewValue;
88
89 /* Check if this is a dyamic thread */
91 {
92 /* It is, which means we will eventually time out after 10 minutes */
93 Timeout.QuadPart = Int32x32To64(10, -10000000 * 60);
94 TimeoutPointer = &Timeout;
95 }
96
97 /* Get Queue Type and Worker Queue */
98 WorkQueueType = (WORK_QUEUE_TYPE)((ULONG_PTR)Context &
99 ~EX_DYNAMIC_WORK_THREAD);
100 WorkQueue = &ExWorkerQueue[WorkQueueType];
101
102 /* Select the wait mode */
103 WaitMode = (UCHAR)WorkQueue->Info.WaitMode;
104
105 /* Nobody should have initialized this yet, do it now */
107 if (WaitMode == UserMode) Thread->ExWorkerCanWaitUser = TRUE;
108
109 /* If we shouldn't swap, disable that feature */
111
112 /* Set the worker flags */
113 do
114 {
115 /* Check if the queue is being disabled */
116 if (WorkQueue->Info.QueueDisabled)
117 {
118 /* Re-enable stack swapping and kill us */
121 }
122
123 /* Increase the worker count */
124 OldValue = WorkQueue->Info;
125 NewValue = OldValue;
126 NewValue.WorkerCount++;
127 }
129 *(PLONG)&NewValue,
130 *(PLONG)&OldValue) != *(PLONG)&OldValue);
131
132 /* Success, you are now officially a worker thread! */
134
135 /* Loop forever */
136ProcessLoop:
137 for (;;)
138 {
139 /* Wait for something to happen on the queue */
140 QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue,
141 WaitMode,
142 TimeoutPointer);
143
144 /* Check if we timed out and quit this loop in that case */
146
147 /* Increment Processed Work Items */
148 InterlockedIncrement((PLONG)&WorkQueue->WorkItemsProcessed);
149
150 /* Get the Work Item */
152
153 /* Make sure nobody is trying to play smart with us */
154 ASSERT((ULONG_PTR)WorkItem->WorkerRoutine > MmUserProbeAddress);
155
156 /* Call the Worker Routine */
157 WorkItem->WorkerRoutine(WorkItem->Parameter);
158
159 /* Make sure APCs are not disabled */
160 if (Thread->Tcb.CombinedApcDisable != 0)
161 {
162 /* We're nice and do it behind your back */
163 DPRINT1("Warning: Broken Worker Thread: %p %p %p came back "
164 "with APCs disabled!\n",
165 WorkItem->WorkerRoutine,
166 WorkItem->Parameter,
167 WorkItem);
170 }
171
172 /* Make sure it returned at right IRQL */
174 {
175 /* It didn't, bugcheck! */
176 KeBugCheckEx(WORKER_THREAD_RETURNED_AT_BAD_IRQL,
177 (ULONG_PTR)WorkItem->WorkerRoutine,
179 (ULONG_PTR)WorkItem->Parameter,
181 }
182
183 /* Make sure it returned with Impersionation Disabled */
185 {
186 /* It didn't, bugcheck! */
187 KeBugCheckEx(IMPERSONATING_WORKER_THREAD,
188 (ULONG_PTR)WorkItem->WorkerRoutine,
189 (ULONG_PTR)WorkItem->Parameter,
191 0);
192 }
193 }
194
195 /* This is a dynamic thread. Terminate it unless IRPs are pending */
196 if (!IsListEmpty(&Thread->IrpList)) goto ProcessLoop;
197
198 /* Don't terminate it if the queue is disabled either */
199 if (WorkQueue->Info.QueueDisabled) goto ProcessLoop;
200
201 /* Set the worker flags */
202 do
203 {
204 /* Decrease the worker count */
205 OldValue = WorkQueue->Info;
206 NewValue = OldValue;
207 NewValue.WorkerCount--;
208 }
210 *(PLONG)&NewValue,
211 *(PLONG)&OldValue) != *(PLONG)&OldValue);
212
213 /* Decrement dynamic thread count */
214 InterlockedDecrement(&WorkQueue->DynamicThreadCount);
215
216 /* We're not a worker thread anymore */
218
219 /* Re-enable the stack swap */
221 return;
222}
#define InterlockedDecrement
Definition: armddk.h:52
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define UserMode
Definition: asm.h:39
PLIST_ENTRY NTAPI KeRemoveQueue(IN PKQUEUE Queue, IN KPROCESSOR_MODE WaitMode, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: queue.c:238
ULONG MmUserProbeAddress
Definition: init.c:50
_In_ PREQUEST_QUEUE_ENTRY QueueEntry
Definition: scsi.c:1054
ULONG ExWorkerCanWaitUser
Definition: pstypes.h:1296
LIST_ENTRY IrpList
Definition: pstypes.h:1239
ULONG ActiveExWorker
Definition: pstypes.h:1295
ULONG ActiveImpersonationInfo
Definition: pstypes.h:1276
ULONG CombinedApcDisable
Definition: ketypes.h:2030
Definition: typedefs.h:120
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t ULONG_PTR
Definition: typedefs.h:65
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
LIST_ENTRY WorkQueue
Definition: workqueue.c:16
_Enum_is_bitflag_ enum _WORK_QUEUE_TYPE WORK_QUEUE_TYPE
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7

Referenced by ExpCreateWorkerThread().

◆ ExQueueWorkItem()

VOID NTAPI ExQueueWorkItem ( IN PWORK_QUEUE_ITEM  WorkItem,
IN WORK_QUEUE_TYPE  QueueType 
)

Definition at line 727 of file work.c.

729{
732 ASSERT(WorkItem->List.Flink == NULL);
733
734 /* Don't try to trick us */
735 if ((ULONG_PTR)WorkItem->WorkerRoutine < MmUserProbeAddress)
736 {
737 /* Bugcheck the system */
738 KeBugCheckEx(WORKER_INVALID,
739 1,
741 (ULONG_PTR)WorkItem->WorkerRoutine,
742 0);
743 }
744
745 /* Insert the Queue */
746 KeInsertQueue(&WorkQueue->WorkerQueue, &WorkItem->List);
747 ASSERT(!WorkQueue->Info.QueueDisabled);
748
749 /*
750 * Check if we need a new thread. Our decision is as follows:
751 * - This queue type must support Dynamic Threads (duh!)
752 * - It actually has to have unprocessed items
753 * - We have CPUs which could be handling another thread
754 * - We haven't abused our usage of dynamic threads.
755 */
756 if ((WorkQueue->Info.MakeThreadsAsNecessary) &&
757 (!IsListEmpty(&WorkQueue->WorkerQueue.EntryListHead)) &&
758 (WorkQueue->WorkerQueue.CurrentCount <
759 WorkQueue->WorkerQueue.MaximumCount) &&
760 (WorkQueue->DynamicThreadCount < 16))
761 {
762 /* Let the balance manager know about it */
763 DPRINT1("Requesting a new thread. CurrentCount: %lu. MaxCount: %lu\n",
764 WorkQueue->WorkerQueue.CurrentCount,
765 WorkQueue->WorkerQueue.MaximumCount);
767 }
768}
_Must_inspect_result_ _In_ PFLT_CALLBACK_DATA _In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE _In_ WORK_QUEUE_TYPE QueueType
Definition: fltkernel.h:1978
LONG NTAPI KeInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry)
Definition: queue.c:198

Referenced by _Function_class_(), _IRQL_requires_max_(), add_thread_job(), CcpDereferenceCache(), CcPostWorkQueue(), CcScheduleReadAhead(), CdAddToWorkque(), CompBattMonitorIrpComplete(), CTEScheduleEvent(), DriverEntry(), ExpWorkerThreadBalanceManager(), Ext2FloppyFlushDpc(), Ext2QueueCloseRequest(), Ext2QueueRequest(), FatAddToWorkque(), FatCleanVolumeDpc(), FatDeferredFlushDpc(), FatPagingFileErrorHandler(), FltpFastIoDetachDevice(), ForwardedIoCompletionRoutine(), HalAllocateAdapterChannel(), IopDoLoadUnloadDriver(), IopLogDpcRoutine(), IoQueueWorkItem(), IoReportTargetDeviceChangeAsynchronous(), IoWriteErrorLogEntry(), KdpTimeSlipDpcRoutine(), KsGenerateEvent(), KsInstallBusEnumInterface(), KspBusDpcRoutine(), KsQueueWorkItem(), KsRemoveBusEnumInterface(), NdisScheduleWorkItem(), NtfsQueueRequest(), NtSetSystemPowerState(), ObpDeferObjectDeletion(), PiQueueDeviceAction(), PostOnlineNotification(), RxAddToWorkque(), SendOnlineNotificationWorker(), UDFPostRequest(), UDFQueueDelayedClose(), UDFStartEjectWaiter(), UDFVVerify(), USBPORT_TimerDpc(), USBSTOR_QueueWorkItem(), USBSTOR_TimerRoutine(), and VfatQueueRequest().

◆ ExSwapinWorkerThreads()

VOID NTAPI ExSwapinWorkerThreads ( IN BOOLEAN  AllowSwap)

Definition at line 641 of file work.c.

642{
644 PETHREAD CurrentThread = PsGetCurrentThread(), Thread;
646 KAPC Apc;
647 PAGED_CODE();
648
649 /* Initialize an event so we know when we're done */
651
652 /* Lock this routine */
654
655 /* New threads cannot swap anymore */
656 ExpWorkersCanSwap = AllowSwap;
657
658 /* Loop all threads in the system process */
660 while (Thread)
661 {
662 /* Skip threads with explicit permission to do this */
664
665 /* Check if we reached ourselves */
666 if (Thread == CurrentThread)
667 {
668 /* Do it inline */
670 }
671 else
672 {
673 /* Queue an APC */
674 KeInitializeApc(&Apc,
675 &Thread->Tcb,
678 NULL,
679 NULL,
681 &AllowSwap);
682 if (KeInsertQueueApc(&Apc, &Event, NULL, 3))
683 {
684 /* Wait for the APC to run */
687 }
688 }
689
690 /* Next thread */
691Next:
693 }
694
695 /* Release the lock */
697}
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
@ InsertApcEnvironment
Definition: ketypes.h:914
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost)
Definition: apc.c:735
VOID NTAPI KeInitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT TargetEnvironment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE Mode, IN PVOID Context)
Definition: apc.c:651
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
Definition: ketypes.h:615
VOID NTAPI ExpSetSwappingKernelApc(IN PKAPC Apc, OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
Definition: work.c:618

Referenced by NtSetSystemPowerState().

Variable Documentation

◆ ExCriticalWorkerThreads

ULONG ExCriticalWorkerThreads

Definition at line 33 of file work.c.

Referenced by CcInitializeCacheManager(), and ExpInitializeWorkerThreads().

◆ ExDelayedWorkerThreads

ULONG ExDelayedWorkerThreads

Definition at line 34 of file work.c.

Referenced by ExpInitializeWorkerThreads().

◆ ExpAdditionalCriticalWorkerThreads

ULONG ExpAdditionalCriticalWorkerThreads

Definition at line 35 of file work.c.

Referenced by ExpInitializeWorkerThreads().

◆ ExpAdditionalDelayedWorkerThreads

ULONG ExpAdditionalDelayedWorkerThreads

Definition at line 36 of file work.c.

Referenced by ExpInitializeWorkerThreads().

◆ ExpLastWorkerThread

PETHREAD ExpLastWorkerThread

Definition at line 49 of file work.c.

Referenced by ExpWorkerThreadBalanceManager().

◆ ExpThreadSetManagerEvent

KEVENT ExpThreadSetManagerEvent

◆ ExpThreadSetManagerShutdownEvent

KEVENT ExpThreadSetManagerShutdownEvent

Definition at line 45 of file work.c.

Referenced by ExpInitializeWorkerThreads(), and ExpWorkerThreadBalanceManager().

◆ ExpWorkerListHead

LIST_ENTRY ExpWorkerListHead

Definition at line 40 of file work.c.

Referenced by ExpInitializeWorkerThreads().

◆ ExpWorkersCanSwap

BOOLEAN ExpWorkersCanSwap

◆ ExpWorkerSwapinMutex

FAST_MUTEX ExpWorkerSwapinMutex

Definition at line 41 of file work.c.

Referenced by ExpInitializeWorkerThreads(), and ExSwapinWorkerThreads().

◆ ExpWorkerThreadBalanceManagerPtr

PETHREAD ExpWorkerThreadBalanceManagerPtr

Definition at line 48 of file work.c.

Referenced by ExpInitializeWorkerThreads().

◆ ExWorkerQueue