ReactOS  0.4.15-dev-1392-g3014417
work.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Kernel
4  * FILE: ntoskrnl/ex/work.c
5  * PURPOSE: Manage system work queues and worker threads
6  * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* DATA **********************************************************************/
16 
17 /* Number of worker threads for each Queue */
18 #define EX_HYPERCRITICAL_WORK_THREADS 1
19 #define EX_DELAYED_WORK_THREADS 3
20 #define EX_CRITICAL_WORK_THREADS 5
21 
22 /* Magic flag for dynamic worker threads */
23 #define EX_DYNAMIC_WORK_THREAD 0x80000000
24 
25 /* Worker thread priority increments (added to base priority) */
26 #define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT 7
27 #define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT 5
28 #define EX_DELAYED_QUEUE_PRIORITY_INCREMENT 4
29 
30 /* The actual worker queue array */
32 
33 /* Accounting of the total threads and registry hacked threads */
38 
39 /* Future support for stack swapping worker threads */
43 
44 /* The worker balance set manager events */
47 
48 /* Thread pointers for future worker thread shutdown support */
51 
52 /* PRIVATE FUNCTIONS *********************************************************/
53 
54 /*++
55  * @name ExpWorkerThreadEntryPoint
56  *
57  * The ExpWorkerThreadEntryPoint routine is the entrypoint for any new
58  * worker thread created by teh system.
59  *
60  * @param Context
61  * Contains the work queue type masked with a flag specifing whether the
62  * thread is dynamic or not.
63  *
64  * @return None.
65  *
66  * @remarks A dynamic thread can timeout after 10 minutes of waiting on a queue
67  * while a static thread will never timeout.
68  *
69  * Worker threads must return at IRQL == PASSIVE_LEVEL, must not have
70  * active impersonation info, and must not have disabled APCs.
71  *
72  * NB: We will re-enable APCs for broken threads but all other cases
73  * will generate a bugcheck.
74  *
75  *--*/
76 VOID
77 NTAPI
79 {
81  PLIST_ENTRY QueueEntry;
82  WORK_QUEUE_TYPE WorkQueueType;
85  PLARGE_INTEGER TimeoutPointer = NULL;
87  KPROCESSOR_MODE WaitMode;
88  EX_QUEUE_WORKER_INFO OldValue, NewValue;
89 
90  /* Check if this is a dyamic thread */
92  {
93  /* It is, which means we will eventually time out after 10 minutes */
94  Timeout.QuadPart = Int32x32To64(10, -10000000 * 60);
95  TimeoutPointer = &Timeout;
96  }
97 
98  /* Get Queue Type and Worker Queue */
99  WorkQueueType = (WORK_QUEUE_TYPE)((ULONG_PTR)Context &
101  WorkQueue = &ExWorkerQueue[WorkQueueType];
102 
103  /* Select the wait mode */
104  WaitMode = (UCHAR)WorkQueue->Info.WaitMode;
105 
106  /* Nobody should have initialized this yet, do it now */
108  if (WaitMode == UserMode) Thread->ExWorkerCanWaitUser = TRUE;
109 
110  /* If we shouldn't swap, disable that feature */
112 
113  /* Set the worker flags */
114  do
115  {
116  /* Check if the queue is being disabled */
117  if (WorkQueue->Info.QueueDisabled)
118  {
119  /* Re-enable stack swapping and kill us */
122  }
123 
124  /* Increase the worker count */
125  OldValue = WorkQueue->Info;
126  NewValue = OldValue;
127  NewValue.WorkerCount++;
128  }
130  *(PLONG)&NewValue,
131  *(PLONG)&OldValue) != *(PLONG)&OldValue);
132 
133  /* Success, you are now officially a worker thread! */
135 
136  /* Loop forever */
137 ProcessLoop:
138  for (;;)
139  {
140  /* Wait for something to happen on the queue */
141  QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue,
142  WaitMode,
143  TimeoutPointer);
144 
145  /* Check if we timed out and quit this loop in that case */
146  if ((NTSTATUS)(ULONG_PTR)QueueEntry == STATUS_TIMEOUT) break;
147 
148  /* Increment Processed Work Items */
149  InterlockedIncrement((PLONG)&WorkQueue->WorkItemsProcessed);
150 
151  /* Get the Work Item */
153 
154  /* Make sure nobody is trying to play smart with us */
155  ASSERT((ULONG_PTR)WorkItem->WorkerRoutine > MmUserProbeAddress);
156 
157  /* Call the Worker Routine */
158  WorkItem->WorkerRoutine(WorkItem->Parameter);
159 
160  /* Make sure APCs are not disabled */
161  if (Thread->Tcb.CombinedApcDisable != 0)
162  {
163  /* We're nice and do it behind your back */
164  DPRINT1("Warning: Broken Worker Thread: %p %p %p came back "
165  "with APCs disabled!\n",
166  WorkItem->WorkerRoutine,
167  WorkItem->Parameter,
168  WorkItem);
171  }
172 
173  /* Make sure it returned at right IRQL */
175  {
176  /* It didn't, bugcheck! */
177  KeBugCheckEx(WORKER_THREAD_RETURNED_AT_BAD_IRQL,
178  (ULONG_PTR)WorkItem->WorkerRoutine,
180  (ULONG_PTR)WorkItem->Parameter,
182  }
183 
184  /* Make sure it returned with Impersionation Disabled */
186  {
187  /* It didn't, bugcheck! */
188  KeBugCheckEx(IMPERSONATING_WORKER_THREAD,
189  (ULONG_PTR)WorkItem->WorkerRoutine,
190  (ULONG_PTR)WorkItem->Parameter,
192  0);
193  }
194  }
195 
196  /* This is a dynamic thread. Terminate it unless IRPs are pending */
197  if (!IsListEmpty(&Thread->IrpList)) goto ProcessLoop;
198 
199  /* Don't terminate it if the queue is disabled either */
200  if (WorkQueue->Info.QueueDisabled) goto ProcessLoop;
201 
202  /* Set the worker flags */
203  do
204  {
205  /* Decrease the worker count */
206  OldValue = WorkQueue->Info;
207  NewValue = OldValue;
208  NewValue.WorkerCount--;
209  }
211  *(PLONG)&NewValue,
212  *(PLONG)&OldValue) != *(PLONG)&OldValue);
213 
214  /* Decrement dynamic thread count */
215  InterlockedDecrement(&WorkQueue->DynamicThreadCount);
216 
217  /* We're not a worker thread anymore */
219 
220  /* Re-enable the stack swap */
222  return;
223 }
224 
225 /*++
226  * @name ExpCreateWorkerThread
227  *
228  * The ExpCreateWorkerThread routine creates a new worker thread for the
229  * specified queue.
230  *
231  * @param QueueType
232  * Type of the queue to use for this thread. Valid values are:
233  * - DelayedWorkQueue
234  * - CriticalWorkQueue
235  * - HyperCriticalWorkQueue
236  *
237  * @param Dynamic
238  * Specifies whether or not this thread is a dynamic thread.
239  *
240  * @return None.
241  *
242  * @remarks HyperCritical work threads run at priority 7; Critical work threads
243  * run at priority 5, and delayed work threads run at priority 4.
244  *
245  * This, worker threads cannot pre-empty a normal user-mode thread.
246  *
247  *--*/
248 VOID
249 NTAPI
251  IN BOOLEAN Dynamic)
252 {
254  HANDLE hThread;
255  ULONG Context;
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 
273  /* If the thread is dynamic */
274  if (Dynamic)
275  {
276  /* Increase the count */
277  InterlockedIncrement(&ExWorkerQueue[WorkQueueType].DynamicThreadCount);
278  }
279 
280  /* Set the priority */
281  if (WorkQueueType == DelayedWorkQueue)
282  {
283  /* Priority == 4 */
285  }
286  else if (WorkQueueType == CriticalWorkQueue)
287  {
288  /* Priority == 5 */
290  }
291  else
292  {
293  /* Priority == 7 */
295  }
296 
297  /* Get the Thread */
300  PsThreadType,
301  KernelMode,
302  (PVOID*)&Thread,
303  NULL);
304 
305  /* Set the Priority */
307 
308  /* Dereference and close handle */
311 }
312 
313 /*++
314  * @name ExpDetectWorkerThreadDeadlock
315  *
316  * The ExpDetectWorkerThreadDeadlock routine checks every queue and creates
317  * a dynamic thread if the queue seems to be deadlocked.
318  *
319  * @param None
320  *
321  * @return None.
322  *
323  * @remarks The algorithm for deciding if a new thread must be created is based
324  * on whether the queue has processed no new items in the last second,
325  * and new items are still enqueued.
326  *
327  *--*/
328 VOID
329 NTAPI
331 {
332  ULONG i;
334 
335  /* Loop the 3 queues */
336  for (i = 0; i < MaximumWorkQueue; i++)
337  {
338  /* Get the queue */
339  Queue = &ExWorkerQueue[i];
340  ASSERT(Queue->DynamicThreadCount <= 16);
341 
342  /* Check if stuff is on the queue that still is unprocessed */
343  if ((Queue->QueueDepthLastPass) &&
344  (Queue->WorkItemsProcessed == Queue->WorkItemsProcessedLastPass) &&
345  (Queue->DynamicThreadCount < 16))
346  {
347  /* Stuff is still on the queue and nobody did anything about it */
348  DPRINT1("EX: Work Queue Deadlock detected: %lu\n", i);
350  DPRINT1("Dynamic threads queued %d\n", Queue->DynamicThreadCount);
351  }
352 
353  /* Update our data */
354  Queue->WorkItemsProcessedLastPass = Queue->WorkItemsProcessed;
355  Queue->QueueDepthLastPass = KeReadStateQueue(&Queue->WorkerQueue);
356  }
357 }
358 
359 /*++
360  * @name ExpCheckDynamicThreadCount
361  *
362  * The ExpCheckDynamicThreadCount routine checks every queue and creates
363  * a dynamic thread if the queue requires one.
364  *
365  * @param None
366  *
367  * @return None.
368  *
369  * @remarks The algorithm for deciding if a new thread must be created is
370  * documented in the ExQueueWorkItem routine.
371  *
372  *--*/
373 VOID
374 NTAPI
376 {
377  ULONG i;
379 
380  /* Loop the 3 queues */
381  for (i = 0; i < MaximumWorkQueue; i++)
382  {
383  /* Get the queue */
384  Queue = &ExWorkerQueue[i];
385 
386  /* Check if still need a new thread. See ExQueueWorkItem */
387  if ((Queue->Info.MakeThreadsAsNecessary) &&
388  (!IsListEmpty(&Queue->WorkerQueue.EntryListHead)) &&
389  (Queue->WorkerQueue.CurrentCount <
390  Queue->WorkerQueue.MaximumCount) &&
391  (Queue->DynamicThreadCount < 16))
392  {
393  /* Create a new thread */
394  DPRINT1("EX: Creating new dynamic thread as requested\n");
396  }
397  }
398 }
399 
400 /*++
401  * @name ExpWorkerThreadBalanceManager
402  *
403  * The ExpWorkerThreadBalanceManager routine is the entrypoint for the
404  * worker thread balance set manager.
405  *
406  * @param Context
407  * Unused.
408  *
409  * @return None.
410  *
411  * @remarks The worker thread balance set manager listens every second, but can
412  * also be woken up by an event when a new thread is needed, or by the
413  * special shutdown event. This thread runs at priority 7.
414  *
415  * This routine must run at IRQL == PASSIVE_LEVEL.
416  *
417  *--*/
418 VOID
419 NTAPI
421 {
422  KTIMER Timer;
425  PVOID WaitEvents[3];
426  PAGED_CODE();
428 
429  /* Raise our priority above all other worker threads */
432 
433  /* Setup the timer */
435  Timeout.QuadPart = Int32x32To64(-1, 10000000);
436 
437  /* We'll wait on the periodic timer and also the emergency event */
438  WaitEvents[0] = &Timer;
439  WaitEvents[1] = &ExpThreadSetManagerEvent;
440  WaitEvents[2] = &ExpThreadSetManagerShutdownEvent;
441 
442  /* Start wait loop */
443  for (;;)
444  {
445  /* Wait for the timer */
448  WaitEvents,
449  WaitAny,
450  Executive,
451  KernelMode,
452  FALSE,
453  NULL,
454  NULL);
455  if (Status == 0)
456  {
457  /* Our timer expired. Check for deadlocks */
459  }
460  else if (Status == 1)
461  {
462  /* Someone notified us, verify if we should create a new thread */
464  }
465  else if (Status == 2)
466  {
467  /* We are shutting down. Cancel the timer */
468  DPRINT1("System shutdown\n");
470 
471  /* Make sure we have a final thread */
473 
474  /* Wait for it */
476  Executive,
477  KernelMode,
478  FALSE,
479  NULL);
480 
481  /* Dereference it and kill us */
484  }
485 
486  /*
487  * If WinDBG wants to attach or kill a user-mode process, and/or
488  * page-in an address region, queue a debugger worker thread.
489  */
491  {
495  }
496  }
497 }
498 
499 /*++
500  * @name ExpInitializeWorkerThreads
501  *
502  * The ExpInitializeWorkerThreads routine initializes worker thread and
503  * work queue support.
504  *
505  * @param None.
506  *
507  * @return None.
508  *
509  * @remarks This routine is only called once during system initialization.
510  *
511  *--*/
512 CODE_SEG("INIT")
513 VOID
514 NTAPI
516 {
517  ULONG WorkQueueType;
518  ULONG CriticalThreads, DelayedThreads;
519  HANDLE ThreadHandle;
521  ULONG i;
522 
523  /* Setup the stack swap support */
527 
528  /* Set the number of critical and delayed threads. We shouldn't hardcode */
529  DelayedThreads = EX_DELAYED_WORK_THREADS;
530  CriticalThreads = EX_CRITICAL_WORK_THREADS;
531 
532  /* Protect against greedy registry modifications */
537 
538  /* Calculate final count */
539  DelayedThreads += ExpAdditionalDelayedWorkerThreads;
540  CriticalThreads += ExpAdditionalCriticalWorkerThreads;
541 
542  /* Initialize the Array */
543  for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++)
544  {
545  /* Clear the structure and initialize the queue */
546  RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
547  KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
548  }
549 
550  /* Dynamic threads are only used for the critical queue */
552 
553  /* Initialize the balance set manager events */
557  FALSE);
558 
559  /* Create the built-in worker threads for the critical queue */
560  for (i = 0; i < CriticalThreads; i++)
561  {
562  /* Create the thread */
565  }
566 
567  /* Create the built-in worker threads for the delayed queue */
568  for (i = 0; i < DelayedThreads; i++)
569  {
570  /* Create the thread */
573  }
574 
575  /* Create the built-in worker thread for the hypercritical queue */
577 
578  /* Create the balance set manager thread */
579  PsCreateSystemThread(&ThreadHandle,
581  NULL,
582  0,
583  NULL,
585  NULL);
586 
587  /* Get a pointer to it for the shutdown process */
588  ObReferenceObjectByHandle(ThreadHandle,
590  NULL,
591  KernelMode,
592  (PVOID*)&Thread,
593  NULL);
595 
596  /* Close the handle and return */
597  ObCloseHandle(ThreadHandle, KernelMode);
598 }
599 
600 VOID
601 NTAPI
603  OUT PKNORMAL_ROUTINE *NormalRoutine,
604  IN OUT PVOID *NormalContext,
607 {
608  PBOOLEAN AllowSwap;
610 
611  /* Make sure it's an active worker */
612  if (PsGetCurrentThread()->ActiveExWorker)
613  {
614  /* Read the setting from the context flag */
615  AllowSwap = (PBOOLEAN)NormalContext;
616  KeSetKernelStackSwapEnable(*AllowSwap);
617  }
618 
619  /* Let caller know that we're done */
620  KeSetEvent(Event, 0, FALSE);
621 }
622 
623 VOID
624 NTAPI
626 {
627  KEVENT Event;
628  PETHREAD CurrentThread = PsGetCurrentThread(), Thread;
630  KAPC Apc;
631  PAGED_CODE();
632 
633  /* Initialize an event so we know when we're done */
635 
636  /* Lock this routine */
638 
639  /* New threads cannot swap anymore */
640  ExpWorkersCanSwap = AllowSwap;
641 
642  /* Loop all threads in the system process */
644  while (Thread)
645  {
646  /* Skip threads with explicit permission to do this */
647  if (Thread->ExWorkerCanWaitUser) goto Next;
648 
649  /* Check if we reached ourselves */
650  if (Thread == CurrentThread)
651  {
652  /* Do it inline */
653  KeSetKernelStackSwapEnable(AllowSwap);
654  }
655  else
656  {
657  /* Queue an APC */
658  KeInitializeApc(&Apc,
659  &Thread->Tcb,
662  NULL,
663  NULL,
664  KernelMode,
665  &AllowSwap);
666  if (KeInsertQueueApc(&Apc, &Event, NULL, 3))
667  {
668  /* Wait for the APC to run */
671  }
672  }
673 
674  /* Next thread */
675 Next:
677  }
678 
679  /* Release the lock */
681 }
682 
683 /* PUBLIC FUNCTIONS **********************************************************/
684 
685 /*++
686  * @name ExQueueWorkItem
687  * @implemented NT4
688  *
689  * The ExQueueWorkItem routine acquires rundown protection for
690  * the specified descriptor.
691  *
692  * @param WorkItem
693  * Pointer to an initialized Work Queue Item structure. This structure
694  * must be located in nonpaged pool memory.
695  *
696  * @param QueueType
697  * Type of the queue to use for this item. Can be one of the following:
698  * - DelayedWorkQueue
699  * - CriticalWorkQueue
700  * - HyperCriticalWorkQueue
701  *
702  * @return None.
703  *
704  * @remarks This routine is obsolete. Use IoQueueWorkItem instead.
705  *
706  * Callers of this routine must be running at IRQL <= DISPATCH_LEVEL.
707  *
708  *--*/
709 VOID
710 NTAPI
713 {
716  ASSERT(WorkItem->List.Flink == NULL);
717 
718  /* Don't try to trick us */
719  if ((ULONG_PTR)WorkItem->WorkerRoutine < MmUserProbeAddress)
720  {
721  /* Bugcheck the system */
722  KeBugCheckEx(WORKER_INVALID,
723  1,
725  (ULONG_PTR)WorkItem->WorkerRoutine,
726  0);
727  }
728 
729  /* Insert the Queue */
730  KeInsertQueue(&WorkQueue->WorkerQueue, &WorkItem->List);
731  ASSERT(!WorkQueue->Info.QueueDisabled);
732 
733  /*
734  * Check if we need a new thread. Our decision is as follows:
735  * - This queue type must support Dynamic Threads (duh!)
736  * - It actually has to have unprocessed items
737  * - We have CPUs which could be handling another thread
738  * - We haven't abused our usage of dynamic threads.
739  */
740  if ((WorkQueue->Info.MakeThreadsAsNecessary) &&
741  (!IsListEmpty(&WorkQueue->WorkerQueue.EntryListHead)) &&
742  (WorkQueue->WorkerQueue.CurrentCount <
743  WorkQueue->WorkerQueue.MaximumCount) &&
744  (WorkQueue->DynamicThreadCount < 16))
745  {
746  /* Let the balance manager know about it */
747  DPRINT1("Requesting a new thread. CurrentCount: %lu. MaxCount: %lu\n",
748  WorkQueue->WorkerQueue.CurrentCount,
749  WorkQueue->WorkerQueue.MaximumCount);
751  }
752 }
753 
754 /* EOF */
ULONG MmUserProbeAddress
Definition: init.c:50
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
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
#define EX_DYNAMIC_WORK_THREAD
Definition: work.c:23
#define IN
Definition: typedefs.h:39
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
struct _KEVENT * PKEVENT
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:711
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
VOID NTAPI ExSwapinWorkerThreads(IN BOOLEAN AllowSwap)
Definition: work.c:625
VOID NTAPI ExpCreateWorkerThread(WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic)
Definition: work.c:250
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG CombinedApcDisable
Definition: ketypes.h:1815
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
KEVENT ExpThreadSetManagerShutdownEvent
Definition: work.c:46
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2221
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1337
LONG NTSTATUS
Definition: precomp.h:26
KTHREAD Tcb
Definition: pstypes.h:1045
#define InterlockedCompareExchange
Definition: interlocked.h:104
LONG NTAPI KeSetBasePriorityThread(IN PKTHREAD Thread, IN LONG Increment)
Definition: thrdobj.c:1184
PETHREAD ExpWorkerThreadBalanceManagerPtr
Definition: work.c:49
VOID NTAPI ExpWorkerThreadEntryPoint(IN PVOID Context)
Definition: work.c:78
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
LONG KPRIORITY
Definition: compat.h:662
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
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:496
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
VOID NTAPI ExpDetectWorkerThreadDeadlock(VOID)
Definition: work.c:330
LIST_ENTRY WorkQueue
Definition: workqueue.c:20
#define EX_CRITICAL_WORK_THREADS
Definition: work.c:20
ULONG ActiveExWorker
Definition: pstypes.h:1142
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:450
unsigned char BOOLEAN
LONG NTAPI KeReadStateQueue(IN PKQUEUE Queue)
Definition: queue.c:226
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
VOID NTAPI ExpInitializeWorkerThreads(VOID)
Definition: work.c:515
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define UlongToPtr(u)
Definition: config.h:106
PETHREAD ExpLastWorkerThread
Definition: work.c:50
Status
Definition: gdiplustypes.h:24
FAST_MUTEX
Definition: extypes.h:17
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
WORK_QUEUE_ITEM ExpDebuggerWorkItem
Definition: dbgctrl.c:20
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
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:602
#define ASSERT(a)
Definition: mode.c:45
LIST_ENTRY ExpWorkerListHead
Definition: work.c:41
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
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
ULONG ActiveImpersonationInfo
Definition: pstypes.h:1123
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
enum _WORK_QUEUE_TYPE WORK_QUEUE_TYPE
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:651
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define InterlockedDecrement
Definition: armddk.h:52
PLIST_ENTRY NTAPI KeRemoveQueue(IN PKQUEUE Queue, IN KPROCESSOR_MODE WaitMode, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: queue.c:238
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:26
Definition: ketypes.h:535
Definition: typedefs.h:119
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
VOID NTAPI ExpCheckDynamicThreadCount(VOID)
Definition: work.c:375
#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT
Definition: work.c:28
_Must_inspect_result_ _In_ PWDF_TIMER_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFTIMER * Timer
Definition: wdftimer.h:153
KEVENT ExpThreadSetManagerEvent
Definition: work.c:45
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
FAST_MUTEX ExpWorkerSwapinMutex
Definition: work.c:42
VOID NTAPI ExpDebuggerWorker(IN PVOID Context)
Definition: dbgctrl.c:52
#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:27
static ULONG Timeout
Definition: ping.c:61
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
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
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue]
Definition: work.c:31
#define EX_DELAYED_WORK_THREADS
Definition: work.c:19
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
LONG NTAPI KeInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry)
Definition: queue.c:198
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
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
ULONG ExDelayedWorkerThreads
Definition: work.c:35
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
HANDLE hThread
Definition: wizard.c:27
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost)
Definition: apc.c:735
ULONG MakeThreadsAsNecessary
Definition: extypes.h:400
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI KeInitializeQueue(IN PKQUEUE Queue, IN ULONG Count OPTIONAL)
Definition: queue.c:148
ULONG ExpAdditionalCriticalWorkerThreads
Definition: work.c:36
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
struct tagContext Context
Definition: acpixf.h:1034
WINKD_WORKER_STATE ExpDebuggerWork
Definition: dbgctrl.c:25
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
ULONG ExCriticalWorkerThreads
Definition: work.c:34
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BOOLEAN ExpWorkersCanSwap
Definition: work.c:40
ULONG ExWorkerCanWaitUser
Definition: pstypes.h:1143
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:674
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
#define KeGetCurrentThread
Definition: hal.h:44
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
signed int * PLONG
Definition: retypes.h:5
LIST_ENTRY IrpList
Definition: pstypes.h:1086
EX_QUEUE_WORKER_INFO Info
Definition: extypes.h:412
ULONG ExpAdditionalDelayedWorkerThreads
Definition: work.c:37
#define Int32x32To64(a, b)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context)
Definition: work.c:420
_Must_inspect_result_ _In_ PFLT_CALLBACK_DATA _In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE _In_ WORK_QUEUE_TYPE QueueType
Definition: fltkernel.h:1977
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:855
BOOLEAN NTAPI KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
Definition: thrdobj.c:997
#define PAGED_CODE()