ReactOS 0.4.17-dev-684-ga6524ef
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 Delayed and Critical queues */
18#define EX_DELAYED_WORK_THREADS 12
19#define EX_CRITICAL_WORK_THREADS 8
20
21/* Magic flag for dynamic worker threads */
22#define EX_DYNAMIC_WORK_THREAD 0x80000000
23
24/* Worker thread priority increments (added to base priority) */
25#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT 7
26#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT 5
27#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT 4
28
29/* The actual worker queue array */
31
32/* Accounting of the total threads and registry hacked threads */
37
38/* Future support for stack swapping worker threads */
42
43/* The worker balance set manager events */
46
47/* Thread pointers for future worker thread shutdown support */
50
51/* PRIVATE FUNCTIONS *********************************************************/
52
53/*++
54 * @name ExpWorkerThreadEntryPoint
55 *
56 * The ExpWorkerThreadEntryPoint routine is the entrypoint for any new
57 * worker thread created by teh system.
58 *
59 * @param Context
60 * Contains the work queue type masked with a flag specifing whether the
61 * thread is dynamic or not.
62 *
63 * @return None.
64 *
65 * @remarks A dynamic thread can timeout after 10 minutes of waiting on a queue
66 * while a static thread will never timeout.
67 *
68 * Worker threads must return at IRQL == PASSIVE_LEVEL, must not have
69 * active impersonation info, and must not have disabled APCs.
70 *
71 * NB: We will re-enable APCs for broken threads but all other cases
72 * will generate a bugcheck.
73 *
74 *--*/
75VOID
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}
223
224/*++
225 * @name ExpCreateWorkerThread
226 *
227 * The ExpCreateWorkerThread routine creates a new worker thread for the
228 * specified queue.
229 *
230 * @param QueueType
231 * Type of the queue to use for this thread. Valid values are:
232 * - DelayedWorkQueue
233 * - CriticalWorkQueue
234 * - HyperCriticalWorkQueue
235 *
236 * @param Dynamic
237 * Specifies whether or not this thread is a dynamic thread.
238 *
239 * @return None.
240 *
241 * @remarks HyperCritical work threads run at priority 7; Critical work threads
242 * run at priority 5, and delayed work threads run at priority 4.
243 *
244 * This, worker threads cannot pre-empty a normal user-mode thread.
245 *
246 *--*/
247VOID
248NTAPI
250 IN BOOLEAN Dynamic)
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}
318
319/*++
320 * @name ExpDetectWorkerThreadDeadlock
321 *
322 * The ExpDetectWorkerThreadDeadlock routine checks every queue and creates
323 * a dynamic thread if the queue seems to be deadlocked.
324 *
325 * @param None
326 *
327 * @return None.
328 *
329 * @remarks The algorithm for deciding if a new thread must be created is based
330 * on whether the queue has processed no new items in the last second,
331 * and new items are still enqueued.
332 *
333 *--*/
334VOID
335NTAPI
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}
364
365/*++
366 * @name ExpCheckDynamicThreadCount
367 *
368 * The ExpCheckDynamicThreadCount routine checks every queue and creates
369 * a dynamic thread if the queue requires one.
370 *
371 * @param None
372 *
373 * @return None.
374 *
375 * @remarks The algorithm for deciding if a new thread must be created is
376 * documented in the ExQueueWorkItem routine.
377 *
378 *--*/
379VOID
380NTAPI
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}
405
406/*++
407 * @name ExpWorkerThreadBalanceManager
408 *
409 * The ExpWorkerThreadBalanceManager routine is the entrypoint for the
410 * worker thread balance set manager.
411 *
412 * @param Context
413 * Unused.
414 *
415 * @return None.
416 *
417 * @remarks The worker thread balance set manager listens every second, but can
418 * also be woken up by an event when a new thread is needed, or by the
419 * special shutdown event. This thread runs at priority 7.
420 *
421 * This routine must run at IRQL == PASSIVE_LEVEL.
422 *
423 *--*/
424VOID
425NTAPI
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}
504
505/*++
506 * @name ExpInitializeWorkerThreads
507 *
508 * The ExpInitializeWorkerThreads routine initializes worker thread and
509 * work queue support.
510 *
511 * @param None.
512 *
513 * @return None.
514 *
515 * @remarks This routine is only called once during system initialization.
516 *
517 *--*/
518CODE_SEG("INIT")
519VOID
520NTAPI
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}
615
616VOID
617NTAPI
619 OUT PKNORMAL_ROUTINE *NormalRoutine,
620 IN OUT PVOID *NormalContext,
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}
638
639VOID
640NTAPI
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}
698
699/* PUBLIC FUNCTIONS **********************************************************/
700
701/*++
702 * @name ExQueueWorkItem
703 * @implemented NT4
704 *
705 * The ExQueueWorkItem routine acquires rundown protection for
706 * the specified descriptor.
707 *
708 * @param WorkItem
709 * Pointer to an initialized Work Queue Item structure. This structure
710 * must be located in nonpaged pool memory.
711 *
712 * @param QueueType
713 * Type of the queue to use for this item. Can be one of the following:
714 * - DelayedWorkQueue
715 * - CriticalWorkQueue
716 * - HyperCriticalWorkQueue
717 *
718 * @return None.
719 *
720 * @remarks This routine is obsolete. Use IoQueueWorkItem instead.
721 *
722 * Callers of this routine must be running at IRQL <= DISPATCH_LEVEL.
723 *
724 *--*/
725VOID
726NTAPI
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}
769
770/* EOF */
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
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 STATUS_TIMEOUT
Definition: d3dkmdt.h:49
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 NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
LONG KPRIORITY
Definition: compat.h:803
#define UlongToPtr(u)
Definition: config.h:106
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#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 PKEVENT
Definition: env_spec_w32.h:70
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
@ WinKdWorkerStart
Definition: ex.h:63
@ WinKdWorkerInitialized
Definition: ex.h:64
_Must_inspect_result_ _In_ PFLT_CALLBACK_DATA _In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE _In_ WORK_QUEUE_TYPE QueueType
Definition: fltkernel.h:1978
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:24
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
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define KeGetCurrentThread
Definition: hal.h:55
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
@ InsertApcEnvironment
Definition: ketypes.h:914
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:888
HANDLE hThread
Definition: wizard.c:28
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1340
#define Int32x32To64(a, b)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ NotificationEvent
@ SynchronizationEvent
@ WaitAny
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
LONG NTAPI KeReadStateQueue(IN PKQUEUE Queue)
Definition: queue.c:226
LONG NTAPI KeInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry)
Definition: queue.c:198
VOID NTAPI KeInitializeQueue(IN PKQUEUE Queue, IN ULONG Count OPTIONAL)
Definition: queue.c:148
PLIST_ENTRY NTAPI KeRemoveQueue(IN PKQUEUE Queue, IN KPROCESSOR_MODE WaitMode, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: queue.c:238
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 MmUserProbeAddress
Definition: init.c:50
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1164
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
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:981
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
static ULONG Timeout
Definition: ping.c:61
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
_In_ PREQUEST_QUEUE_ENTRY QueueEntry
Definition: scsi.c:1054
_In_ PVOID Context
Definition: storport.h:2269
KTHREAD Tcb
Definition: pstypes.h:1198
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 MakeThreadsAsNecessary
Definition: extypes.h:571
EX_QUEUE_WORKER_INFO Info
Definition: extypes.h:583
Definition: ketypes.h:615
ULONG CombinedApcDisable
Definition: ketypes.h:2030
Definition: typedefs.h:120
LONG NTAPI KeSetBasePriorityThread(IN PKTHREAD Thread, IN LONG Increment)
Definition: thrdobj.c:1157
BOOLEAN NTAPI KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
Definition: thrdobj.c:988
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
unsigned char UCHAR
Definition: typedefs.h:53
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2231
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:655
_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
#define EX_DELAYED_QUEUE_PRIORITY_INCREMENT
Definition: work.c:27
#define EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:25
VOID NTAPI ExpCheckDynamicThreadCount(VOID)
Definition: work.c:381
VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context)
Definition: work.c:426
PETHREAD ExpLastWorkerThread
Definition: work.c:49
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
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:727
VOID NTAPI ExpWorkerThreadEntryPoint(IN PVOID Context)
Definition: work.c:77
#define EX_CRITICAL_QUEUE_PRIORITY_INCREMENT
Definition: work.c:26
VOID NTAPI ExpCreateWorkerThread(WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic)
Definition: work.c:249
#define EX_DELAYED_WORK_THREADS
Definition: work.c:18
#define EX_CRITICAL_WORK_THREADS
Definition: work.c:19
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
KEVENT ExpThreadSetManagerShutdownEvent
Definition: work.c:45
VOID NTAPI ExpDetectWorkerThreadDeadlock(VOID)
Definition: work.c:336
VOID NTAPI ExSwapinWorkerThreads(IN BOOLEAN AllowSwap)
Definition: work.c:641
ULONG ExpAdditionalDelayedWorkerThreads
Definition: work.c:36
VOID NTAPI ExpInitializeWorkerThreads(VOID)
Definition: work.c:521
#define EX_DYNAMIC_WORK_THREAD
Definition: work.c:22
FAST_MUTEX ExpWorkerSwapinMutex
Definition: work.c:41
EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue]
Definition: work.c:30
LIST_ENTRY ExpWorkerListHead
Definition: work.c:40
LIST_ENTRY WorkQueue
Definition: workqueue.c:16
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
@ DelayedWorkQueue
Definition: extypes.h:190
@ CriticalWorkQueue
Definition: extypes.h:189
@ HyperCriticalWorkQueue
Definition: extypes.h:191
@ MaximumWorkQueue
Definition: extypes.h:198
_Enum_is_bitflag_ enum _WORK_QUEUE_TYPE WORK_QUEUE_TYPE
@ Executive
Definition: ketypes.h:467
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:756
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:757
#define ObDereferenceObject
Definition: obfuncs.h:203