Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

557 lines
16 KiB

  1. /*++
  2. Copyright (c) 1989-1998 Microsoft Corporation
  3. Module Name:
  4. threads.h
  5. Abstract:
  6. This module is the header file for thread pools. Thread pools can be used for
  7. one time execution of tasks, for waits and for one shot or periodic timers.
  8. Author:
  9. Gurdeep Singh Pall (gurdeep) Nov 13, 1997
  10. Environment:
  11. The thread pool routines are statically linked in the caller's
  12. executable and are callable only from user mode. They make use of
  13. Nt system services.
  14. Revision History:
  15. Aug-19 lokeshs - modifications to thread pool apis.
  16. Rob Earhart (earhart) September 29, 2000
  17. Moved globals to threads.c
  18. Split up thread pools to seperate modules
  19. Moved module-specific interfaces to modules
  20. --*/
  21. //todo remove below
  22. #define DBG1 1
  23. // Structures used by the Thread pool
  24. // Timer structures
  25. // Timer Queues and Timer entries both use RTLP_GENERIC_TIMER structure below.
  26. // Timer Queues are linked using List.
  27. // Timers are attached to the Timer Queue using TimerList
  28. // Timers are linked to each other using List
  29. #define RTLP_TIMER RTLP_GENERIC_TIMER
  30. #define PRTLP_TIMER PRTLP_GENERIC_TIMER
  31. #define RTLP_TIMER_QUEUE RTLP_GENERIC_TIMER
  32. #define PRTLP_TIMER_QUEUE PRTLP_GENERIC_TIMER
  33. struct _RTLP_WAIT ;
  34. typedef struct _RTLP_GENERIC_TIMER {
  35. LIST_ENTRY List ; // All Timers and Queues are linked using this.
  36. ULONG DeltaFiringTime ; // Time difference in Milliseconds from the TIMER entry
  37. // just before this entry
  38. union {
  39. ULONG RefCount ; // Timer RefCount
  40. ULONG * RefCountPtr ; // Pointer to Wait->Refcount
  41. } ; // keeps count of async callbacks still executing
  42. ULONG State ; // State of timer: CREATED, DELETE, ACTIVE. DONT_FIRE
  43. union {
  44. // Used for Timer Queues
  45. struct {
  46. LIST_ENTRY TimerList ; // Timers Hanging off of the queue
  47. LIST_ENTRY UncancelledTimerList ;// List of one shot timers not cancelled
  48. // not used for wait timers
  49. #if DBG1
  50. ULONG NextDbgId;
  51. #endif
  52. } ;
  53. // Used for Timers
  54. struct {
  55. struct _RTLP_GENERIC_TIMER *Queue ;// Queue to which this timer belongs
  56. struct _RTLP_WAIT *Wait ; // Pointer to Wait event if timer is part of waits. else NULL
  57. ULONG Flags ; // Flags indicating special treatment for this timer
  58. PVOID Function ; // Function to call when timer fires
  59. PVOID Context ; // Context to pass to function when timer fires
  60. PACTIVATION_CONTEXT ActivationContext; // Activation context to activate around callbacks to Function
  61. ULONG Period ; // In Milliseconds. Used for periodic timers.
  62. LIST_ENTRY TimersToFireList;//placed in this list if the timer is fired
  63. HANDLE ImpersonationToken; // Token to use for callouts
  64. } ;
  65. } ;
  66. HANDLE CompletionEvent ; // Event signalled when the timer is finally deleted
  67. #if DBG1
  68. ULONG DbgId;
  69. ULONG ThreadId ;
  70. ULONG ThreadId2 ;
  71. #endif
  72. } RTLP_GENERIC_TIMER, *PRTLP_GENERIC_TIMER ;
  73. // Structures used by Wait Threads
  74. // Wait structure
  75. typedef struct _RTLP_WAIT {
  76. struct _RTLP_WAIT_THREAD_CONTROL_BLOCK *ThreadCB ;
  77. HANDLE WaitHandle ; // Object to wait on
  78. ULONG State ; // REGISTERED, ACTIVE,DELETE state flags
  79. ULONG RefCount ; // initially set to 1. When 0, then ready to be deleted
  80. HANDLE CompletionEvent ;
  81. struct _RTLP_GENERIC_TIMER *Timer ; // For timeouts on the wait
  82. ULONG Flags ; // Flags indicating special treatment for this wait
  83. PVOID Function ; // Function to call when wait completes
  84. PVOID Context ; // Context to pass to function
  85. ULONG Timeout ; // In Milliseconds.
  86. PACTIVATION_CONTEXT ActivationContext; // Activation context to activate around calls out to function
  87. HANDLE ImpersonationToken; // Token to use for callouts
  88. #if DBG1
  89. ULONG DbgId ;
  90. ULONG ThreadId ;
  91. ULONG ThreadId2 ;
  92. #endif
  93. } RTLP_WAIT, *PRTLP_WAIT ;
  94. // Wait Thread Control Block
  95. typedef struct _RTLP_WAIT_THREAD_CONTROL_BLOCK {
  96. LIST_ENTRY WaitThreadsList ;// List of all the thread control blocks
  97. HANDLE ThreadHandle ; // Handle for this thread
  98. ULONG ThreadId ; // Used to check if callback is in WaitThread
  99. ULONG NumWaits ; // Number of active waits + handles pending waits
  100. ULONG NumActiveWaits ; // Number of active waits (reflects ActiveWaitArray)
  101. ULONG NumRegisteredWaits ; // Number of waits that are registered
  102. HANDLE ActiveWaitArray[MAXIMUM_WAIT_OBJECTS] ;// Array used for waiting
  103. PRTLP_WAIT ActiveWaitPointers[MAXIMUM_WAIT_OBJECTS] ;// Array of pointers to active Wait blocks.
  104. HANDLE TimerHandle ; // Handle to the NT timer used for timeouts
  105. RTLP_TIMER_QUEUE TimerQueue;// Queue in which all timers are kept
  106. LARGE_INTEGER Current64BitTickCount ;
  107. LONGLONG Firing64BitTickCount ;
  108. RTL_CRITICAL_SECTION WaitThreadCriticalSection ;
  109. // Used for addition and deletion of waits
  110. } RTLP_WAIT_THREAD_CONTROL_BLOCK, *PRTLP_WAIT_THREAD_CONTROL_BLOCK ;
  111. // Structure used for attaching all I/O worker threads
  112. typedef struct _RTLP_IOWORKER_TCB {
  113. LIST_ENTRY List ; // List of IO Worker threads
  114. HANDLE ThreadHandle ; // Handle of this thread
  115. ULONG Flags ; // WT_EXECUTEINPERSISTENTIOTHREAD
  116. BOOLEAN LongFunctionFlag ;// Is the thread currently executing long fn
  117. } RTLP_IOWORKER_TCB, *PRTLP_IOWORKER_TCB ;
  118. typedef struct _RTLP_WAITWORKER {
  119. union {
  120. PRTLP_WAIT Wait ;
  121. PRTLP_TIMER Timer ;
  122. } ;
  123. BOOLEAN WaitThreadCallback ; //callback queued by Wait thread or Timer thread
  124. BOOLEAN TimerCondition ;//true if fired because wait timed out.
  125. } RTLP_ASYNC_CALLBACK, * PRTLP_ASYNC_CALLBACK ;
  126. // structure used for calling worker function
  127. typedef struct _RTLP_WORK {
  128. WORKERCALLBACKFUNC Function ;
  129. ULONG Flags ;
  130. PACTIVATION_CONTEXT ActivationContext;
  131. HANDLE ImpersonationToken;
  132. } RTLP_WORK, *PRTLP_WORK ;
  133. // Structure used for storing events
  134. typedef struct _RTLP_EVENT {
  135. SINGLE_LIST_ENTRY Link ;
  136. HANDLE Handle ;
  137. } RTLP_EVENT, *PRTLP_EVENT ;
  138. // Defines used in the thread pool
  139. #define THREAD_CREATION_DAMPING_TIME1 1000 // In Milliseconds. Time between starting successive threads.
  140. #define THREAD_CREATION_DAMPING_TIME2 15000 // In Milliseconds. Time between starting successive threads.
  141. #define THREAD_TERMINATION_DAMPING_TIME 10000 // In Milliseconds. Time between stopping successive threads.
  142. #define NEW_THREAD_THRESHOLD 7 // Number of requests outstanding before we start a new thread
  143. #define NEW_THREAD_THRESHOLD2 14
  144. #define MAX_WORKER_THREADS 1000 // Max effective worker threads
  145. #define INFINITE_TIME (ULONG)~0 // In milliseconds
  146. #define PSEUDO_INFINITE_TIME 0x80000000 // In milliseconds
  147. #define RTLP_MAX_TIMERS 0x00080000 // 524288 timers per process
  148. #define MAX_UNUSED_EVENTS 40
  149. #define NEEDS_IO_THREAD(Flags) (Flags & (WT_EXECUTEINIOTHREAD \
  150. | WT_EXECUTEINUITHREAD \
  151. | WT_EXECUTEINPERSISTENTIOTHREAD))
  152. // Macros
  153. #define ONE_MILLISECOND_TIMEOUT(TimeOut) { \
  154. TimeOut.LowPart = 0xffffd8f0 ; \
  155. TimeOut.HighPart = 0xffffffff ; \
  156. }
  157. #define HUNDRED_MILLISECOND_TIMEOUT(TimeOut) { \
  158. TimeOut.LowPart = 0xfff0bdc0 ; \
  159. TimeOut.HighPart = 0xffffffff ; \
  160. }
  161. #define ONE_SECOND_TIMEOUT(TimeOut) { \
  162. TimeOut.LowPart = 0xff676980 ; \
  163. TimeOut.HighPart = 0xffffffff ; \
  164. }
  165. #define USE_PROCESS_HEAP 1
  166. #define RtlpFreeTPHeap(Ptr) \
  167. RtlFreeHeap( RtlProcessHeap(), 0, (Ptr) )
  168. #define RtlpAllocateTPHeap(Size, Flags) \
  169. RtlAllocateHeap( RtlProcessHeap(), (Flags), (Size) )
  170. // used to allocate Wait thread
  171. #define ACQUIRE_GLOBAL_WAIT_LOCK() \
  172. RtlEnterCriticalSection (&WaitCriticalSection)
  173. #define RELEASE_GLOBAL_WAIT_LOCK() \
  174. RtlLeaveCriticalSection(&WaitCriticalSection)
  175. // taken before a timer/queue is deleted and when the timers
  176. // are being fired. Used to assure that no timers will be fired later.
  177. #define ACQUIRE_GLOBAL_TIMER_LOCK() \
  178. RtlEnterCriticalSection (&TimerCriticalSection)
  179. #define RELEASE_GLOBAL_TIMER_LOCK() \
  180. RtlLeaveCriticalSection(&TimerCriticalSection)
  181. // used in RtlpThreadPoolCleanup to find if a component is initialized
  182. #define IS_COMPONENT_INITIALIZED(StartedVariable, CompletedVariable, Flag) \
  183. {\
  184. LARGE_INTEGER TimeOut ; \
  185. Flag = FALSE ; \
  186. \
  187. if ( StartedVariable ) { \
  188. \
  189. if ( !CompletedVariable ) { \
  190. \
  191. ONE_MILLISECOND_TIMEOUT(TimeOut) ; \
  192. \
  193. while (!*((ULONG volatile *)&CompletedVariable)) \
  194. NtDelayExecution (FALSE, &TimeOut) ; \
  195. \
  196. if (CompletedVariable == 1) \
  197. Flag = TRUE ; \
  198. \
  199. } else { \
  200. Flag = TRUE ; \
  201. } \
  202. } \
  203. }
  204. // macro used to set dbg function/context
  205. #define DBG_SET_FUNCTION(Fn, Context) { \
  206. CallbackFn1 = CallbackFn2 ; \
  207. CallbackFn2 = (Fn) ; \
  208. Context1 = Context2 ; \
  209. Context2 = (Context ) ; \
  210. }
  211. // used to move the wait array
  212. /*
  213. VOID
  214. RtlpShiftWaitArray(
  215. PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB ThreadCB,
  216. ULONG SrcIndex,
  217. ULONG DstIndex,
  218. ULONG Count
  219. )
  220. */
  221. #define RtlpShiftWaitArray(ThreadCB, SrcIndex, DstIndex, Count) { \
  222. \
  223. RtlMoveMemory (&(ThreadCB)->ActiveWaitArray[DstIndex], \
  224. &(ThreadCB)->ActiveWaitArray[SrcIndex], \
  225. sizeof (HANDLE) * (Count)) ; \
  226. \
  227. RtlMoveMemory (&(ThreadCB)->ActiveWaitPointers[DstIndex],\
  228. &(ThreadCB)->ActiveWaitPointers[SrcIndex],\
  229. sizeof (HANDLE) * (Count)) ; \
  230. }
  231. // signature for timer and wait entries
  232. #define SET_WAIT_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0100)
  233. #define SET_TIMER_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0200)
  234. #define SET_TIMER_QUEUE_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0300)
  235. #define IS_WAIT_SIGNATURE(ptr) (((ptr)->State & 0x00000f00) == 0x00000100)
  236. #define IS_TIMER_SIGNATURE(ptr) (((ptr)->State & 0x00000f00) == 0x00000200)
  237. #define CHECK_SIGNATURE(ptr) ASSERTMSG( InvalidSignatureMsg, \
  238. ((ptr)->State & 0xffff0000) == 0xfedc0000 )
  239. #define SET_DEL_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0x0000b000)
  240. #define CHECK_DEL_SIGNATURE(ptr) ASSERTMSG( InvalidDelSignatureMsg, \
  241. (((ptr)->State & 0xffff0000) == 0xfedc0000) \
  242. && ( ! ((ptr)->State & 0x0000f000)) )
  243. #define IS_DEL_SIGNATURE_SET(ptr) ((ptr)->State & 0x0000f000)
  244. #define CLEAR_SIGNATURE(ptr) RtlInterlockedSetClearBits(&(ptr)->State, \
  245. 0xcdef0000, \
  246. 0xfedc0000 & ~(0xcdef0000))
  247. #define SET_DEL_TIMERQ_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0x00000a00)
  248. // debug prints
  249. #define RTLP_THREADPOOL_ERROR_MASK (0x01 | DPFLTR_MASK)
  250. #define RTLP_THREADPOOL_WARNING_MASK (0x02 | DPFLTR_MASK)
  251. #define RTLP_THREADPOOL_INFO_MASK (0x04 | DPFLTR_MASK)
  252. #define RTLP_THREADPOOL_TRACE_MASK (0x08 | DPFLTR_MASK)
  253. #define RTLP_THREADPOOL_VERBOSE_MASK (0x10 | DPFLTR_MASK)
  254. #if DBG
  255. extern CHAR InvalidSignatureMsg[];
  256. extern CHAR InvalidDelSignatureMsg[];
  257. #endif
  258. extern ULONG MaxThreads;
  259. extern BOOLEAN LdrpShutdownInProgress;
  260. NTSTATUS
  261. NTAPI
  262. RtlpStartThreadpoolThread(
  263. PUSER_THREAD_START_ROUTINE Function,
  264. PVOID Parameter,
  265. HANDLE *ThreadHandleReturn
  266. );
  267. extern PRTLP_EXIT_THREAD RtlpExitThreadFunc;
  268. #if DBG1
  269. extern PVOID CallbackFn1, CallbackFn2, Context1, Context2 ;
  270. #endif
  271. // Timer globals needed by worker
  272. extern ULONG StartedTimerInitialization ; // Used by Timer thread startup synchronization
  273. extern ULONG CompletedTimerInitialization ; // Used for to check if Timer thread is initialized
  274. extern HANDLE TimerThreadHandle;
  275. VOID
  276. RtlpAsyncWaitCallbackCompletion(
  277. IN PVOID Context
  278. );
  279. NTSTATUS
  280. RtlpInitializeTimerThreadPool (
  281. ) ;
  282. NTSTATUS
  283. RtlpTimerCleanup(
  284. VOID
  285. );
  286. NTSYSAPI
  287. NTSTATUS
  288. NTAPI
  289. RtlpWaitCleanup(
  290. VOID
  291. );
  292. NTSYSAPI
  293. NTSTATUS
  294. NTAPI
  295. RtlpWorkerCleanup(
  296. VOID
  297. );
  298. NTSYSAPI
  299. VOID
  300. NTAPI
  301. RtlpThreadCleanup (
  302. VOID
  303. );
  304. VOID
  305. RtlpResetTimer (
  306. HANDLE TimerHandle,
  307. ULONG DueTime,
  308. PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB
  309. ) ;
  310. BOOLEAN
  311. RtlpInsertInDeltaList (
  312. PLIST_ENTRY DeltaList,
  313. PRTLP_GENERIC_TIMER NewTimer,
  314. ULONG TimeRemaining,
  315. ULONG *NewFiringTime
  316. ) ;
  317. BOOLEAN
  318. RtlpRemoveFromDeltaList (
  319. PLIST_ENTRY DeltaList,
  320. PRTLP_GENERIC_TIMER Timer,
  321. ULONG TimeRemaining,
  322. ULONG* NewFiringTime
  323. ) ;
  324. BOOLEAN
  325. RtlpReOrderDeltaList (
  326. PLIST_ENTRY DeltaList,
  327. PRTLP_GENERIC_TIMER Timer,
  328. ULONG TimeRemaining,
  329. ULONG* NewFiringTime,
  330. ULONG ChangedFiringTime
  331. ) ;
  332. NTSTATUS
  333. RtlpDeactivateWait (
  334. PRTLP_WAIT Wait,
  335. BOOLEAN OkayToFreeTheTimer
  336. ) ;
  337. VOID
  338. RtlpDeleteWait (
  339. PRTLP_WAIT Wait
  340. ) ;
  341. VOID
  342. RtlpProcessTimeouts (
  343. PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB
  344. ) ;
  345. ULONG
  346. RtlpGetTimeRemaining (
  347. HANDLE TimerHandle
  348. ) ;
  349. #define THREAD_TYPE_WORKER 1
  350. #define THREAD_TYPE_IO_WORKER 2
  351. VOID
  352. RtlpDeleteTimer (
  353. PRTLP_TIMER Timer
  354. ) ;
  355. PRTLP_EVENT
  356. RtlpGetWaitEvent (
  357. VOID
  358. ) ;
  359. VOID
  360. RtlpFreeWaitEvent (
  361. PRTLP_EVENT Event
  362. ) ;
  363. VOID
  364. RtlpDoNothing (
  365. PVOID NotUsed1,
  366. PVOID NotUsed2,
  367. PVOID NotUsed3
  368. ) ;
  369. VOID
  370. RtlpExecuteWorkerRequest (
  371. NTSTATUS Status,
  372. PVOID Context,
  373. PVOID ActualFunction
  374. ) ;
  375. NTSTATUS
  376. RtlpWaitForEvent (
  377. HANDLE Event,
  378. HANDLE ThreadHandle
  379. ) ;
  380. NTSYSAPI
  381. NTSTATUS
  382. NTAPI
  383. RtlThreadPoolCleanup (
  384. ULONG Flags
  385. ) ;
  386. VOID
  387. RtlpWaitOrTimerCallout(WAITORTIMERCALLBACKFUNC Function,
  388. PVOID Context,
  389. BOOLEAN TimedOut,
  390. PACTIVATION_CONTEXT ActivationContext,
  391. HANDLE ImpersonationToken);
  392. VOID
  393. RtlpApcCallout(APC_CALLBACK_FUNCTION Function,
  394. NTSTATUS Status,
  395. PVOID Context1,
  396. PVOID Context2);
  397. VOID
  398. RtlpWorkerCallout(WORKERCALLBACKFUNC Function,
  399. PVOID Context,
  400. PACTIVATION_CONTEXT ActivationContext,
  401. HANDLE ImpersonationToken);
  402. // Waits and timers may specify that their callbacks must execute
  403. // within worker threads of various types. This can cause a problem
  404. // if those worker threads are unavailable. RtlpAcquireWorker
  405. // guarantees that at least one worker thread of the appropriate type
  406. // will be available to handle callbacks until a matching call to
  407. // RtlpReleaseWorker is made.
  408. NTSTATUS
  409. RtlpAcquireWorker(ULONG Flags);
  410. VOID
  411. RtlpReleaseWorker(ULONG Flags);
  412. //to make sure that a wait is not deleted before being registered
  413. #define STATE_REGISTERED 0x0001
  414. //set when wait registered. Removed when one shot wait fired.
  415. //when deregisterWait called, tells whether to be removed from ActiveArray
  416. //If timer active, then have to remove it from delta list and reset the timer.
  417. #define STATE_ACTIVE 0x0002
  418. //when deregister wait is called(RefCount may be >0)
  419. #define STATE_DELETE 0x0004
  420. //set when cancel timer called. The APC will clean it up.
  421. #define STATE_DONTFIRE 0x0008
  422. //set when one shot timer fired.
  423. #define STATE_ONE_SHOT_FIRED 0x0010