ReactOS  0.4.13-dev-563-g0561610
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 
19 NTAPI
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,
31  Function,
32  Parameter,
33  ThreadHandle,
34  NULL);
35 }
36 
38 NTAPI
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 
51 typedef struct _RTLP_IOWORKERTHREAD
52 {
57 
58 typedef struct _RTLP_WORKITEM
59 {
65 
77 
78 #define IsThreadPoolInitialized() (*((volatile LONG*)&ThreadPoolInitialized) == 1)
79 
80 static 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 
122 Finish:
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 
145 static NTSTATUS
147 {
149 
152  TRUE,
153  TokenHandle);
155  {
156  *TokenHandle = NULL;
158  }
159 
160  return Status;
161 }
162 
163 static 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 
192 static VOID
193 NTAPI
197 {
199  BOOLEAN Impersonated = FALSE;
200  RTLP_WORKITEM WorkItem = *(volatile RTLP_WORKITEM *)SystemArgument2;
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 
221  _SEH2_TRY
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 
250  if (WorkItem.Flags & WT_EXECUTELONGFUNCTION)
251  {
253  }
254 }
255 
256 
257 static NTSTATUS
259 {
261 
263 
264  if (WorkItem->Flags & WT_EXECUTELONGFUNCTION)
265  {
267  }
268 
269  if (WorkItem->Flags & WT_EXECUTEINPERSISTENTTHREAD)
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 
306 static VOID
307 NTAPI
311 {
313  BOOLEAN Impersonated = FALSE;
314  PRTLP_IOWORKERTHREAD IoThread = (PRTLP_IOWORKERTHREAD)NormalContext;
315  RTLP_WORKITEM WorkItem = *(volatile RTLP_WORKITEM *)SystemArgument2;
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 
338  _SEH2_TRY
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 */
365  if (WorkItem.Flags & WT_EXECUTELONGFUNCTION)
366  {
368  if (NT_SUCCESS(Status))
369  {
370  IoThread->Flags &= ~WT_EXECUTELONGFUNCTION;
372  }
373  }
374 
375  /* update the requests counter */
377 
378  if (WorkItem.Flags & WT_EXECUTELONGFUNCTION)
379  {
381  }
382 }
383 
384 static NTSTATUS
386 {
387  PLIST_ENTRY CurrentEntry;
388  PRTLP_IOWORKERTHREAD IoThread = NULL;
390 
391  if (WorkItem->Flags & WT_EXECUTEINPERSISTENTIOTHREAD)
392  {
393  if (PersistentIoThread != NULL)
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 */
402  CurrentEntry = ThreadPoolIOWorkerThreadsList.Flink;
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 */
433  CurrentEntry = ThreadPoolIOWorkerThreadsList.Flink;
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 */
444  if ((WorkItem->Flags & WT_EXECUTELONGFUNCTION) && !(IoThread->Flags & WT_EXECUTEINPERSISTENTIOTHREAD))
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 */
457  if (ThreadPoolIOWorkerThreads == 0)
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 */
466  CurrentEntry = ThreadPoolIOWorkerThreadsList.Flink;
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 
516 static BOOLEAN
518 {
520  ULONG IoPending;
521  BOOLEAN CreatedHandle = FALSE;
522  BOOLEAN IsIoPending = TRUE;
523 
524  if (ThreadHandle == NULL)
525  {
527  NtCurrentThread(),
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 
559 static ULONG
560 NTAPI
562 {
565  BOOLEAN Terminate;
567 
569  {
570  /* Oops, too many worker threads... */
571  goto InitFailed;
572  }
573 
574  /* Get a thread handle to ourselves */
576  NtCurrentThread(),
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 
586 InitFailed:
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 
611 Wait:
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 
676 static ULONG
677 NTAPI
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,
711  &IoStatusBlock,
712  &Timeout);
713 
714  if (Status == STATUS_SUCCESS)
715  {
716  TimeoutCount = 0;
717 
718  _SEH2_TRY
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  */
777 NTSTATUS
778 NTAPI
781  IN ULONG Flags)
782 {
783  LONG FreeWorkers;
785  PRTLP_WORKITEM WorkItem;
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 */
856  Status = RtlpQueueIoWorkerThread(WorkItem);
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 */
883  Status = RtlpQueueWorkerThread(WorkItem);
884  }
885  }
886 
888  }
889 
890  if (!NT_SUCCESS(Status))
891  {
892  if (WorkItem->TokenHandle != NULL)
893  {
894  NtClose(WorkItem->TokenHandle);
895  }
896 
897 Cleanup:
898  RtlFreeHeap(RtlGetProcessHeap(),
899  0,
900  WorkItem);
901  }
902 
903  return Status;
904 }
905 
906 /*
907  * @unimplemented
908  */
909 NTSTATUS
910 NTAPI
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 
933  &IoStatusBlock,
934  &FileCompletionInfo,
935  sizeof(FileCompletionInfo),
937 
938  return Status;
939 }
940 
941 /*
942  * @implemented
943  */
944 NTSTATUS
945 NTAPI
947  IN PRTL_EXIT_POOL_THREAD ExitPoolThread)
948 {
949  RtlpStartThreadFunc = StartPoolThread;
950  RtlpExitThreadFunc = ExitPoolThread;
951  return STATUS_SUCCESS;
952 }
#define IN
Definition: typedefs.h:38
#define MAX_WORKERTHREADS
Definition: workitem.c:48
static NTSTATUS RtlpGetImpersonationToken(OUT PHANDLE TokenHandle)
Definition: workitem.c:146
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:72
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
#define IO_COMPLETION_ALL_ACCESS
Definition: file.c:72
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define WT_EXECUTEINUITHREAD
Definition: winnt_old.h:1073
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:87
NTSTATUS NTAPI RtlSetThreadPoolStartFunc(IN PRTL_START_POOL_THREAD StartPoolThread, IN PRTL_EXIT_POOL_THREAD ExitPoolThread)
Definition: workitem.c:946
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
PVOID Context
Definition: workitem.c:61
NTSTATUS RtlpInitializeTimerThread(VOID)
Definition: timerqueue.c:27
#define STATUS_CANT_OPEN_ANONYMOUS
Definition: ntstatus.h:388
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define NtCurrentThread()
struct _RTLP_WORKITEM * PRTLP_WORKITEM
#define WT_EXECUTEINIOTHREAD
Definition: winnt_old.h:1072
static LONG ThreadPoolWorkerThreadsLongRequests
Definition: workitem.c:73
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define InterlockedCompareExchange
Definition: interlocked.h:104
struct _ThreadInfo ThreadInfo
#define TOKEN_IMPERSONATE
Definition: setypes.h:873
#define WT_TRANSFER_IMPERSONATION
Definition: winnt_old.h:1080
struct _RTLP_IOWORKERTHREAD * PRTLP_IOWORKERTHREAD
_In_ PVOID Parameter
Definition: ldrtypes.h:240
#define InsertTailList(ListHead, Entry)
LIST_ENTRY ListEntry
Definition: workitem.c:53
NTSTATUS NTAPI NtQueueApcThread(IN HANDLE ThreadHandle, IN PKNORMAL_ROUTINE ApcRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: state.c:500
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define WT_EXECUTEINPERSISTENTTHREAD
Definition: winnt_old.h:1079
_SEH2_TRY
Definition: create.c:4250
ULONG(NTAPI * PTHREAD_START_ROUTINE)(PVOID Parameter)
Definition: rtltypes.h:562
static NTSTATUS RtlpQueueIoWorkerThread(IN OUT PRTLP_WORKITEM WorkItem)
Definition: workitem.c:385
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
HANDLE FileHandle
Definition: stats.c:38
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
static LONG ThreadPoolIOWorkerThreads
Definition: workitem.c:74
struct _RTLP_IOWORKERTHREAD RTLP_IOWORKERTHREAD
#define DUPLICATE_SAME_ACCESS
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:684
long LONG
Definition: pedump.c:60
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
HANDLE TimerThreadHandle
Definition: timerqueue.c:24
#define WORKERTHREAD_CREATION_THRESHOLD
Definition: workitem.c:49
#define IsThreadPoolInitialized()
Definition: workitem.c:78
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2014
void * PVOID
Definition: retypes.h:9
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
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
Definition: wait.c:879
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
NTSTATUS NTAPI RtlSetIoCompletionCallback(IN HANDLE FileHandle, IN PIO_APC_ROUTINE Callback, IN ULONG Flags)
Definition: workitem.c:911
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define WT_EXECUTELONGFUNCTION
Definition: winnt_old.h:1076
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
static LIST_ENTRY ThreadPoolIOWorkerThreadsList
Definition: workitem.c:69
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI RtlpStartThread(IN PTHREAD_START_ROUTINE Function, IN PVOID Parameter, OUT PHANDLE ThreadHandle)
Definition: workitem.c:20
#define WT_EXECUTEINPERSISTENTIOTHREAD
Definition: queuetest.c:12
static LONG ThreadPoolWorkerThreadsRequests
Definition: workitem.c:72
static VOID NTAPI RtlpExecuteIoWorkItem(IN OUT PVOID NormalContext, IN OUT PVOID SystemArgument1, IN OUT PVOID SystemArgument2)
Definition: workitem.c:308
static ULONG NTAPI RtlpIoWorkerThreadProc(IN PVOID Parameter)
Definition: workitem.c:561
#define STATUS_NO_TOKEN
Definition: ntstatus.h:346
NTSTATUS NTAPI NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, IN PVOID CompletionKey, IN PVOID CompletionContext, IN NTSTATUS CompletionStatus, IN ULONG CompletionInformation)
Definition: iocomp.c:568
NTSTATUS NTAPI RtlpExitThread(IN NTSTATUS ExitStatus)
Definition: workitem.c:39
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:719
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static LONG ThreadPoolIOWorkerThreadsRequests
Definition: workitem.c:75
static PRTLP_IOWORKERTHREAD PersistentIoThread
Definition: workitem.c:68
static NTSTATUS RtlpStartWorkerThread(PTHREAD_START_ROUTINE StartRoutine)
Definition: workitem.c:164
#define InterlockedDecrement
Definition: armddk.h:52
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
NTSTATUS NTAPI RtlQueueWorkItem(IN WORKERCALLBACKFUNC Function, IN PVOID Context OPTIONAL, IN ULONG Flags)
Definition: workitem.c:779
Definition: typedefs.h:117
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)
static const WCHAR Cleanup[]
Definition: register.c:80
static LONG ThreadPoolWorkerThreads
Definition: workitem.c:71
#define InterlockedExchange
Definition: armddk.h:54
HANDLE TokenHandle
Definition: workitem.c:63
Status
Definition: gdiplustypes.h:24
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
struct _RTLP_WORKITEM RTLP_WORKITEM
_SEH2_END
Definition: create.c:4424
static ULONG Timeout
Definition: ping.c:61
#define InterlockedIncrement
Definition: armddk.h:53
PRTL_EXIT_POOL_THREAD RtlpExitThreadFunc
Definition: workitem.c:46
static NTSTATUS RtlpQueueWorkerThread(IN OUT PRTLP_WORKITEM WorkItem)
Definition: workitem.c:258
PRTL_START_POOL_THREAD RtlpStartThreadFunc
Definition: workitem.c:45
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
_In_ NTSTATUS ExitStatus
Definition: psfuncs.h:861
static NTSTATUS RtlpInitializeThreadPool(VOID)
Definition: workitem.c:81
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static LONG ThreadPoolIOWorkerThreadsLongRequests
Definition: workitem.c:76
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:444
#define DPRINT1
Definition: precomp.h:8
NTSTATUS NTAPI NtOpenThreadToken(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle)
Definition: token.c:3858
VOID(NTAPI * WORKERCALLBACKFUNC)(_In_ PVOID Context)
Definition: rtltypes.h:509
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:3407
ULONG Flags
Definition: workitem.c:62
#define OUT
Definition: typedefs.h:39
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG NumberOfConcurrentThreads)
Definition: iocomp.c:253
static BOOLEAN RtlpIsIoPending(IN HANDLE ThreadHandle OPTIONAL)
Definition: workitem.c:517
static LONG ThreadPoolInitialized
Definition: workitem.c:66
static HANDLE ThreadPoolCompletionPort
Definition: workitem.c:70
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:632
WORKERCALLBACKFUNC Function
Definition: workitem.c:60
static RTL_CRITICAL_SECTION ThreadPoolLock
Definition: workitem.c:67
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
return STATUS_SUCCESS
Definition: btrfs.c:2777
signed int * PLONG
Definition: retypes.h:5
LPFNPSPCALLBACK Callback
Definition: desk.c:111
static VOID NTAPI RtlpExecuteWorkItem(IN OUT PVOID NormalContext, IN OUT PVOID SystemArgument1, IN OUT PVOID SystemArgument2)
Definition: workitem.c:194
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:3042
NTSTATUS(NTAPI * PRTL_EXIT_POOL_THREAD)(_In_ NTSTATUS ExitStatus)
Definition: rtltypes.h:583
static ULONG NTAPI RtlpWorkerThreadProc(IN PVOID Parameter)
Definition: workitem.c:678
IN BOOLEAN Wait
Definition: fatprocs.h:1529
NTSTATUS(NTAPI * PRTL_START_POOL_THREAD)(_In_ PTHREAD_START_ROUTINE Function, _In_ PVOID Parameter, _Out_ PHANDLE ThreadHandle)
Definition: rtltypes.h:576
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68