ReactOS 0.4.15-dev-7842-g558ab78
workitem.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Work Item implementation
5 * FILE: lib/rtl/workitem.c
6 * PROGRAMMER:
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <rtl.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* FUNCTIONS ***************************************************************/
17
22 OUT PHANDLE ThreadHandle)
23{
24 /* Create a native worker thread -- used for SMSS, CSRSS, etc... */
26 NULL,
27 TRUE,
28 0,
29 0,
30 0,
33 ThreadHandle,
34 NULL);
35}
36
40{
41 /* Kill a native worker thread -- used for SMSS, CSRSS, etc... */
43}
44
47
48#define MAX_WORKERTHREADS 0x100
49#define WORKERTHREAD_CREATION_THRESHOLD 0x5
50
52{
57
58typedef struct _RTLP_WORKITEM
59{
65
77
78#define IsThreadPoolInitialized() (*((volatile LONG*)&ThreadPoolInitialized) == 1)
79
80static NTSTATUS
82{
84 LONG InitStatus;
85
86 do
87 {
89 2,
90 0);
91 if (InitStatus == 0)
92 {
93 /* We're the first thread to initialize the thread pool */
94
96
98
105
106 /* Initialize the lock */
108 if (!NT_SUCCESS(Status))
109 goto Finish;
110
111 /* Create the complection port */
114 NULL,
115 0);
116 if (!NT_SUCCESS(Status))
117 {
119 goto Finish;
120 }
121
122Finish:
123 /* Initialization done */
125 1);
126 break;
127 }
128 else if (InitStatus == 2)
129 {
131
132 /* Another thread is currently initializing the thread pool!
133 Poll after a short period of time to see if the initialization
134 was completed */
135
136 Timeout.QuadPart = -10000000LL; /* Wait for a second */
138 &Timeout);
139 }
140 } while (InitStatus != 1);
141
142 return Status;
143}
144
145static NTSTATUS
147{
149
152 TRUE,
155 {
156 *TokenHandle = NULL;
158 }
159
160 return Status;
161}
162
163static NTSTATUS
165{
167 HANDLE ThreadHandle;
169 volatile LONG WorkerInitialized = 0;
170
171 Timeout.QuadPart = -10000LL; /* Wait for 100ms */
172
173 /* Start the thread */
174 Status = RtlpStartThreadFunc(StartRoutine, (PVOID)&WorkerInitialized, &ThreadHandle);
175 if (NT_SUCCESS(Status))
176 {
177 NtResumeThread(ThreadHandle, NULL);
178
179 /* Poll until the thread got a chance to initialize */
180 while (WorkerInitialized == 0)
181 {
183 &Timeout);
184 }
185
186 NtClose(ThreadHandle);
187 }
188
189 return Status;
190}
191
192static VOID
193NTAPI
197{
199 BOOLEAN Impersonated = FALSE;
201
202 RtlFreeHeap(RtlGetProcessHeap(),
203 0,
205
206 if (WorkItem.TokenHandle != NULL)
207 {
210 &WorkItem.TokenHandle,
211 sizeof(HANDLE));
212
213 NtClose(WorkItem.TokenHandle);
214
215 if (NT_SUCCESS(Status))
216 {
217 Impersonated = TRUE;
218 }
219 }
220
222 {
223 DPRINT("RtlpExecuteWorkItem: Function: 0x%p Context: 0x%p ImpersonationToken: 0x%p\n", WorkItem.Function, WorkItem.Context, WorkItem.TokenHandle);
224
225 /* Execute the function */
226 WorkItem.Function(WorkItem.Context);
227 }
229 {
230 DPRINT1("Exception 0x%x while executing IO work item 0x%p\n", _SEH2_GetExceptionCode(), WorkItem.Function);
231 }
232 _SEH2_END;
233
234 if (Impersonated)
235 {
236 WorkItem.TokenHandle = NULL;
239 &WorkItem.TokenHandle,
240 sizeof(HANDLE));
241 if (!NT_SUCCESS(Status))
242 {
243 DPRINT1("Failed to revert worker thread to self!!! Status: 0x%x\n", Status);
244 }
245 }
246
247 /* update the requests counter */
249
251 {
253 }
254}
255
256
257static NTSTATUS
259{
261
263
264 if (WorkItem->Flags & WT_EXECUTELONGFUNCTION)
265 {
267 }
268
270 {
272
273 if (NT_SUCCESS(Status))
274 {
275 /* Queue an APC in the timer thread */
278 NULL,
279 NULL,
280 WorkItem);
281 }
282 }
283 else
284 {
285 /* Queue an IO completion message */
288 WorkItem,
290 0);
291 }
292
293 if (!NT_SUCCESS(Status))
294 {
296
297 if (WorkItem->Flags & WT_EXECUTELONGFUNCTION)
298 {
300 }
301 }
302
303 return Status;
304}
305
306static VOID
307NTAPI
311{
313 BOOLEAN Impersonated = FALSE;
314 PRTLP_IOWORKERTHREAD IoThread = (PRTLP_IOWORKERTHREAD)NormalContext;
316
317 ASSERT(IoThread != NULL);
318
319 RtlFreeHeap(RtlGetProcessHeap(),
320 0,
322
323 if (WorkItem.TokenHandle != NULL)
324 {
327 &WorkItem.TokenHandle,
328 sizeof(HANDLE));
329
330 NtClose(WorkItem.TokenHandle);
331
332 if (NT_SUCCESS(Status))
333 {
334 Impersonated = TRUE;
335 }
336 }
337
339 {
340 DPRINT("RtlpExecuteIoWorkItem: Function: 0x%p Context: 0x%p ImpersonationToken: 0x%p\n", WorkItem.Function, WorkItem.Context, WorkItem.TokenHandle);
341
342 /* Execute the function */
343 WorkItem.Function(WorkItem.Context);
344 }
346 {
347 DPRINT1("Exception 0x%x while executing IO work item 0x%p\n", _SEH2_GetExceptionCode(), WorkItem.Function);
348 }
349 _SEH2_END;
350
351 if (Impersonated)
352 {
353 WorkItem.TokenHandle = NULL;
356 &WorkItem.TokenHandle,
357 sizeof(HANDLE));
358 if (!NT_SUCCESS(Status))
359 {
360 DPRINT1("Failed to revert worker thread to self!!! Status: 0x%x\n", Status);
361 }
362 }
363
364 /* remove the long function flag */
366 {
368 if (NT_SUCCESS(Status))
369 {
370 IoThread->Flags &= ~WT_EXECUTELONGFUNCTION;
372 }
373 }
374
375 /* update the requests counter */
377
379 {
381 }
382}
383
384static NTSTATUS
386{
387 PLIST_ENTRY CurrentEntry;
388 PRTLP_IOWORKERTHREAD IoThread = NULL;
390
392 {
394 {
395 /* We already have a persistent IO worker thread */
396 IoThread = PersistentIoThread;
397 }
398 else
399 {
400 /* We're not aware of any persistent IO worker thread. Search for a unused
401 worker thread that doesn't have a long function queued */
403 while (CurrentEntry != &ThreadPoolIOWorkerThreadsList)
404 {
405 IoThread = CONTAINING_RECORD(CurrentEntry,
407 ListEntry);
408
409 if (!(IoThread->Flags & WT_EXECUTELONGFUNCTION))
410 break;
411
412 CurrentEntry = CurrentEntry->Flink;
413 }
414
415 if (CurrentEntry != &ThreadPoolIOWorkerThreadsList)
416 {
417 /* Found a worker thread we can use. */
418 ASSERT(IoThread != NULL);
419
421 PersistentIoThread = IoThread;
422 }
423 else
424 {
425 DPRINT1("Failed to find a worker thread for the persistent IO thread!\n");
426 return STATUS_NO_MEMORY;
427 }
428 }
429 }
430 else
431 {
432 /* Find a worker thread that is not currently executing a long function */
434 while (CurrentEntry != &ThreadPoolIOWorkerThreadsList)
435 {
436 IoThread = CONTAINING_RECORD(CurrentEntry,
438 ListEntry);
439
440 if (!(IoThread->Flags & WT_EXECUTELONGFUNCTION))
441 {
442 /* if we're trying to queue a long function then make sure we're not dealing
443 with the persistent thread */
445 {
446 /* found a candidate */
447 break;
448 }
449 }
450
451 CurrentEntry = CurrentEntry->Flink;
452 }
453
454 if (CurrentEntry == &ThreadPoolIOWorkerThreadsList)
455 {
456 /* Couldn't find an appropriate thread, see if we can use the persistent thread (if it exists) for now */
458 {
459 DPRINT1("Failed to find a worker thread for the work item 0x%p!\n", WorkItem);
461 return STATUS_NO_MEMORY;
462 }
463 else
464 {
465 /* pick the first worker thread */
467 IoThread = CONTAINING_RECORD(CurrentEntry,
469 ListEntry);
470
471 /* Since this might be the persistent worker thread, don't run as a
472 long function */
473 WorkItem->Flags &= ~WT_EXECUTELONGFUNCTION;
474 }
475 }
476
477 /* Move the picked thread to the end of the list. Since we're always searching
478 from the beginning, this improves distribution of work items */
479 RemoveEntryList(&IoThread->ListEntry);
481 &IoThread->ListEntry);
482 }
483
484 ASSERT(IoThread != NULL);
485
487
488 if (WorkItem->Flags & WT_EXECUTELONGFUNCTION)
489 {
490 /* We're about to queue a long function, mark the thread */
491 IoThread->Flags |= WT_EXECUTELONGFUNCTION;
492
494 }
495
496 /* It's time to queue the work item */
499 IoThread,
500 NULL,
501 WorkItem);
502 if (!NT_SUCCESS(Status))
503 {
504 DPRINT1("Failed to queue APC for work item 0x%p\n", WorkItem->Function);
506
507 if (WorkItem->Flags & WT_EXECUTELONGFUNCTION)
508 {
510 }
511 }
512
513 return Status;
514}
515
516static BOOLEAN
518{
520 ULONG IoPending;
521 BOOLEAN CreatedHandle = FALSE;
522 BOOLEAN IsIoPending = TRUE;
523
524 if (ThreadHandle == NULL)
525 {
529 &ThreadHandle,
530 0,
531 0,
533 if (!NT_SUCCESS(Status))
534 {
535 return IsIoPending;
536 }
537
538 CreatedHandle = TRUE;
539 }
540
541 Status = NtQueryInformationThread(ThreadHandle,
543 &IoPending,
544 sizeof(IoPending),
545 NULL);
546 if (NT_SUCCESS(Status) && IoPending == 0)
547 {
548 IsIoPending = FALSE;
549 }
550
551 if (CreatedHandle)
552 {
553 NtClose(ThreadHandle);
554 }
555
556 return IsIoPending;
557}
558
559static ULONG
560NTAPI
562{
565 BOOLEAN Terminate;
567
569 {
570 /* Oops, too many worker threads... */
571 goto InitFailed;
572 }
573
574 /* Get a thread handle to ourselves */
578 (PHANDLE)&ThreadInfo.ThreadHandle,
579 0,
580 0,
582 if (!NT_SUCCESS(Status))
583 {
584 DPRINT1("Failed to create handle to own thread! Status: 0x%x\n", Status);
585
586InitFailed:
588
589 /* Signal initialization completion */
591 1);
592
594 return 0;
595 }
596
597 ThreadInfo.Flags = 0;
598
599 /* Insert the thread into the list */
601 (PLIST_ENTRY)&ThreadInfo.ListEntry);
602
603 /* Signal initialization completion */
605 1);
606
607 for (;;)
608 {
609 Timeout.QuadPart = -50000000LL; /* Wait for 5 seconds by default */
610
611Wait:
612 do
613 {
614 /* Perform an alertable wait, the work items are going to be executed as APCs */
616 &Timeout);
617
618 /* Loop as long as we executed an APC */
619 } while (Status != STATUS_SUCCESS);
620
621 /* We timed out, let's see if we're allowed to terminate */
622 Terminate = FALSE;
623
625 if (NT_SUCCESS(Status))
626 {
628 {
629 /* This thread is supposed to be persistent. Don't terminate! */
631
632 Timeout.QuadPart = -0x7FFFFFFFFFFFFFFFLL;
633 goto Wait;
634 }
635
636 /* FIXME - figure out an effective method to determine if it's appropriate to
637 lower the number of threads. For now let's always terminate if there's
638 at least one thread and no queued items. */
640 (*((volatile LONG*)&ThreadPoolIOWorkerThreadsRequests) == 0);
641
642 if (Terminate)
643 {
644 /* Prevent termination as long as IO is pending */
645 Terminate = !RtlpIsIoPending(ThreadInfo.ThreadHandle);
646 }
647
648 if (Terminate)
649 {
650 /* Rundown the thread and unlink it from the list */
653 }
654
656
657 if (Terminate)
658 {
659 /* Break the infinite loop and terminate */
661 break;
662 }
663 }
664 else
665 {
666 DPRINT1("Failed to acquire the thread pool lock!!! Status: 0x%x\n", Status);
667 break;
668 }
669 }
670
671 NtClose(ThreadInfo.ThreadHandle);
673 return 0;
674}
675
676static ULONG
677NTAPI
679{
681 BOOLEAN Terminate;
684 ULONG TimeoutCount = 0;
687
689 {
690 /* Signal initialization completion */
692 1);
693
694 /* Oops, too many worker threads... */
696 return 0;
697 }
698
699 /* Signal initialization completion */
701 1);
702
703 for (;;)
704 {
705 Timeout.QuadPart = -50000000LL; /* Wait for 5 seconds by default */
706
707 /* Dequeue a completion message */
709 (PVOID*)&ApcRoutine,
712 &Timeout);
713
714 if (Status == STATUS_SUCCESS)
715 {
716 TimeoutCount = 0;
717
719 {
720 /* Call the APC routine */
724 }
726 {
727 (void)0;
728 }
729 _SEH2_END;
730 }
731 else
732 {
733 Terminate = FALSE;
734
736 continue;
737
738 /* FIXME - this should be optimized, check if there's requests, etc */
739
740 if (Status == STATUS_TIMEOUT)
741 {
742 /* FIXME - we might want to optimize this */
743 if (TimeoutCount++ > 2 &&
745 {
746 Terminate = TRUE;
747 }
748 }
749 else
750 Terminate = TRUE;
751
753
754 if (Terminate)
755 {
756 /* Prevent termination as long as IO is pending */
757 Terminate = !RtlpIsIoPending(NULL);
758 }
759
760 if (Terminate)
761 {
764 break;
765 }
766 }
767 }
768
770 return 0;
771
772}
773
774/*
775 * @implemented
776 */
778NTAPI
781 IN ULONG Flags)
782{
783 LONG FreeWorkers;
786
787 DPRINT("RtlQueueWorkItem(0x%p, 0x%p, 0x%x)\n", Function, Context, Flags);
788
789 /* Initialize the thread pool if not already initialized */
791 {
793
794 if (!NT_SUCCESS(Status))
795 return Status;
796 }
797
798 /* Allocate a work item */
799 WorkItem = RtlAllocateHeap(RtlGetProcessHeap(),
800 0,
801 sizeof(RTLP_WORKITEM));
802 if (WorkItem == NULL)
803 return STATUS_NO_MEMORY;
804
805 WorkItem->Function = Function;
806 WorkItem->Context = Context;
807 WorkItem->Flags = Flags;
808
810 {
812
813 if (!NT_SUCCESS(Status))
814 {
815 DPRINT1("Failed to get impersonation token! Status: 0x%x\n", Status);
816 goto Cleanup;
817 }
818 }
819 else
820 WorkItem->TokenHandle = NULL;
821
823 if (NT_SUCCESS(Status))
824 {
826 {
827 /* FIXME - We should optimize the algorithm used to determine whether to grow the thread pool! */
828
830
833 {
834 /* We shouldn't queue a long function into the persistent IO thread */
835 FreeWorkers--;
836 }
837
838 /* See if it's a good idea to grow the pool */
841 {
842 /* Grow the thread pool */
844
845 if (!NT_SUCCESS(Status) && *((volatile LONG*)&ThreadPoolIOWorkerThreads) != 0)
846 {
847 /* We failed to create the thread, but there's at least one there so
848 we can at least queue the request */
850 }
851 }
852
853 if (NT_SUCCESS(Status))
854 {
855 /* Queue a IO worker thread */
857 }
858 }
859 else
860 {
861 /* FIXME - We should optimize the algorithm used to determine whether to grow the thread pool! */
862
864
865 /* See if it's a good idea to grow the pool */
868 {
869 /* Grow the thread pool */
871
872 if (!NT_SUCCESS(Status) && *((volatile LONG*)&ThreadPoolWorkerThreads) != 0)
873 {
874 /* We failed to create the thread, but there's at least one there so
875 we can at least queue the request */
877 }
878 }
879
880 if (NT_SUCCESS(Status))
881 {
882 /* Queue a normal worker thread */
884 }
885 }
886
888 }
889
890 if (!NT_SUCCESS(Status))
891 {
892 if (WorkItem->TokenHandle != NULL)
893 {
894 NtClose(WorkItem->TokenHandle);
895 }
896
897Cleanup:
898 RtlFreeHeap(RtlGetProcessHeap(),
899 0,
900 WorkItem);
901 }
902
903 return Status;
904}
905
906/*
907 * @unimplemented
908 */
910NTAPI
913 IN ULONG Flags)
914{
916 FILE_COMPLETION_INFORMATION FileCompletionInfo;
918
919 DPRINT("RtlSetIoCompletionCallback(0x%p, 0x%p, 0x%x)\n", FileHandle, Callback, Flags);
920
921 /* Initialize the thread pool if not already initialized */
923 {
925 if (!NT_SUCCESS(Status))
926 return Status;
927 }
928
929 FileCompletionInfo.Port = ThreadPoolCompletionPort;
930 FileCompletionInfo.Key = (PVOID)Callback;
931
934 &FileCompletionInfo,
935 sizeof(FileCompletionInfo),
937
938 return Status;
939}
940
941/*
942 * @implemented
943 */
945NTAPI
947 IN PRTL_EXIT_POOL_THREAD ExitPoolThread)
948{
949 RtlpStartThreadFunc = StartPoolThread;
950 RtlpExitThreadFunc = ExitPoolThread;
951 return STATUS_SUCCESS;
952}
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
#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:32
@ ThreadImpersonationToken
Definition: compat.h:940
@ ThreadIsIoPending
Definition: compat.h:951
static const WCHAR Cleanup[]
Definition: register.c:80
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FileCompletionInformation
Definition: from_kernel.h:91
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define InterlockedCompareExchange
Definition: interlocked.h:104
NTSTATUS NTAPI NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, IN PVOID CompletionKey, IN PVOID CompletionContext, IN NTSTATUS CompletionStatus, IN ULONG CompletionInformation)
Definition: iocomp.c:569
NTSTATUS NTAPI NtRemoveIoCompletion(IN HANDLE IoCompletionHandle, OUT PVOID *KeyContext, OUT PVOID *ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: iocomp.c:445
NTSTATUS NTAPI NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG NumberOfConcurrentThreads)
Definition: iocomp.c:253
struct _ThreadInfo ThreadInfo
#define ASSERT(a)
Definition: mode.c:44
#define IO_COMPLETION_ALL_ACCESS
Definition: file.c:72
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:726
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:744
_In_ NTSTATUS ExitStatus
Definition: psfuncs.h:867
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:726
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSTATUS(NTAPI * PRTL_START_POOL_THREAD)(_In_ PTHREAD_START_ROUTINE Function, _In_ PVOID Parameter, _Out_ PHANDLE ThreadHandle)
Definition: rtltypes.h:580
NTSTATUS(NTAPI * PRTL_EXIT_POOL_THREAD)(_In_ NTSTATUS ExitStatus)
Definition: rtltypes.h:587
ULONG(NTAPI * PTHREAD_START_ROUTINE)(PVOID Parameter)
Definition: rtltypes.h:566
VOID(NTAPI * WORKERCALLBACKFUNC)(_In_ PVOID Context)
Definition: rtltypes.h:513
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1279
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
Definition: wait.c:876
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2018
NTSTATUS NTAPI NtQueueApcThread(IN HANDLE ThreadHandle, IN PKNORMAL_ROUTINE ApcRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: state.c:600
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
NTSTATUS NTAPI NtOpenThreadToken(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _Out_ PHANDLE TokenHandle)
Opens a token that is tied to a thread handle.
Definition: token.c:2474
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_CANT_OPEN_ANONYMOUS
Definition: ntstatus.h:402
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3410
long LONG
Definition: pedump.c:60
static ULONG Timeout
Definition: ping.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define WT_EXECUTEINPERSISTENTIOTHREAD
Definition: queuetest.c:12
HANDLE TimerThreadHandle
Definition: timerqueue.c:24
NTSTATUS RtlpInitializeTimerThread(VOID)
Definition: timerqueue.c:27
static NTSTATUS RtlpInitializeThreadPool(VOID)
Definition: workitem.c:81
static NTSTATUS RtlpGetImpersonationToken(OUT PHANDLE TokenHandle)
Definition: workitem.c:146
#define WORKERTHREAD_CREATION_THRESHOLD
Definition: workitem.c:49
static HANDLE ThreadPoolCompletionPort
Definition: workitem.c:70
static LONG ThreadPoolWorkerThreads
Definition: workitem.c:71
struct _RTLP_IOWORKERTHREAD * PRTLP_IOWORKERTHREAD
static LONG ThreadPoolWorkerThreadsLongRequests
Definition: workitem.c:73
NTSTATUS NTAPI RtlQueueWorkItem(IN WORKERCALLBACKFUNC Function, IN PVOID Context OPTIONAL, IN ULONG Flags)
Definition: workitem.c:779
#define MAX_WORKERTHREADS
Definition: workitem.c:48
static BOOLEAN RtlpIsIoPending(IN HANDLE ThreadHandle OPTIONAL)
Definition: workitem.c:517
static ULONG NTAPI RtlpWorkerThreadProc(IN PVOID Parameter)
Definition: workitem.c:678
static LIST_ENTRY ThreadPoolIOWorkerThreadsList
Definition: workitem.c:69
NTSTATUS NTAPI RtlSetThreadPoolStartFunc(IN PRTL_START_POOL_THREAD StartPoolThread, IN PRTL_EXIT_POOL_THREAD ExitPoolThread)
Definition: workitem.c:946
struct _RTLP_WORKITEM * PRTLP_WORKITEM
static PRTLP_IOWORKERTHREAD PersistentIoThread
Definition: workitem.c:68
NTSTATUS NTAPI RtlSetIoCompletionCallback(IN HANDLE FileHandle, IN PIO_APC_ROUTINE Callback, IN ULONG Flags)
Definition: workitem.c:911
static LONG ThreadPoolIOWorkerThreadsLongRequests
Definition: workitem.c:76
#define IsThreadPoolInitialized()
Definition: workitem.c:78
static ULONG NTAPI RtlpIoWorkerThreadProc(IN PVOID Parameter)
Definition: workitem.c:561
NTSTATUS NTAPI RtlpStartThread(IN PTHREAD_START_ROUTINE Function, IN PVOID Parameter, OUT PHANDLE ThreadHandle)
Definition: workitem.c:20
static NTSTATUS RtlpStartWorkerThread(PTHREAD_START_ROUTINE StartRoutine)
Definition: workitem.c:164
static LONG ThreadPoolInitialized
Definition: workitem.c:66
struct _RTLP_WORKITEM RTLP_WORKITEM
static LONG ThreadPoolWorkerThreadsRequests
Definition: workitem.c:72
static RTL_CRITICAL_SECTION ThreadPoolLock
Definition: workitem.c:67
static NTSTATUS RtlpQueueIoWorkerThread(IN OUT PRTLP_WORKITEM WorkItem)
Definition: workitem.c:385
PRTL_EXIT_POOL_THREAD RtlpExitThreadFunc
Definition: workitem.c:46
static VOID NTAPI RtlpExecuteIoWorkItem(IN OUT PVOID NormalContext, IN OUT PVOID SystemArgument1, IN OUT PVOID SystemArgument2)
Definition: workitem.c:308
struct _RTLP_IOWORKERTHREAD RTLP_IOWORKERTHREAD
static VOID NTAPI RtlpExecuteWorkItem(IN OUT PVOID NormalContext, IN OUT PVOID SystemArgument1, IN OUT PVOID SystemArgument2)
Definition: workitem.c:194
static NTSTATUS RtlpQueueWorkerThread(IN OUT PRTLP_WORKITEM WorkItem)
Definition: workitem.c:258
PRTL_START_POOL_THREAD RtlpStartThreadFunc
Definition: workitem.c:45
static LONG ThreadPoolIOWorkerThreads
Definition: workitem.c:74
NTSTATUS NTAPI RtlpExitThread(IN NTSTATUS ExitStatus)
Definition: workitem.c:39
static LONG ThreadPoolIOWorkerThreadsRequests
Definition: workitem.c:75
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY ListEntry
Definition: workitem.c:53
ULONG Flags
Definition: workitem.c:62
HANDLE TokenHandle
Definition: workitem.c:63
WORKERCALLBACKFUNC Function
Definition: workitem.c:60
PVOID Context
Definition: workitem.c:61
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#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
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
#define WT_TRANSFER_IMPERSONATION
Definition: winnt_old.h:1047
#define WT_EXECUTEINPERSISTENTTHREAD
Definition: winnt_old.h:1046
#define WT_EXECUTEINIOTHREAD
Definition: winnt_old.h:1039
#define WT_EXECUTELONGFUNCTION
Definition: winnt_old.h:1043
#define WT_EXECUTEINUITHREAD
Definition: winnt_old.h:1040
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
#define DUPLICATE_SAME_ACCESS
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:91
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
#define TOKEN_IMPERSONATE
Definition: setypes.h:927
#define NtCurrentThread()