|
|
/*++
Copyright (c) 1989-1998 Microsoft Corporation
Module Name:
threads.h
Abstract:
This module is the header file for thread pools. Thread pools can be used for one time execution of tasks, for waits and for one shot or periodic timers.
Author:
Gurdeep Singh Pall (gurdeep) Nov 13, 1997
Environment:
The thread pool routines are statically linked in the caller's executable and are callable only from user mode. They make use of Nt system services.
Revision History:
Aug-19 lokeshs - modifications to thread pool apis. Rob Earhart (earhart) September 29, 2000 Moved globals to threads.c Split up thread pools to seperate modules Moved module-specific interfaces to modules
--*/
//todo remove below
#define DBG1 1
// Structures used by the Thread pool
// Timer structures
// Timer Queues and Timer entries both use RTLP_GENERIC_TIMER structure below.
// Timer Queues are linked using List.
// Timers are attached to the Timer Queue using TimerList
// Timers are linked to each other using List
#define RTLP_TIMER RTLP_GENERIC_TIMER
#define PRTLP_TIMER PRTLP_GENERIC_TIMER
#define RTLP_TIMER_QUEUE RTLP_GENERIC_TIMER
#define PRTLP_TIMER_QUEUE PRTLP_GENERIC_TIMER
struct _RTLP_WAIT ;
typedef struct _RTLP_GENERIC_TIMER {
LIST_ENTRY List ; // All Timers and Queues are linked using this.
ULONG DeltaFiringTime ; // Time difference in Milliseconds from the TIMER entry
// just before this entry
union { ULONG RefCount ; // Timer RefCount
ULONG * RefCountPtr ; // Pointer to Wait->Refcount
} ; // keeps count of async callbacks still executing
ULONG State ; // State of timer: CREATED, DELETE, ACTIVE. DONT_FIRE
union {
// Used for Timer Queues
struct {
LIST_ENTRY TimerList ; // Timers Hanging off of the queue
LIST_ENTRY UncancelledTimerList ;// List of one shot timers not cancelled
// not used for wait timers
#if DBG1
ULONG NextDbgId; #endif
} ;
// Used for Timers
struct { struct _RTLP_GENERIC_TIMER *Queue ;// Queue to which this timer belongs
struct _RTLP_WAIT *Wait ; // Pointer to Wait event if timer is part of waits. else NULL
ULONG Flags ; // Flags indicating special treatment for this timer
PVOID Function ; // Function to call when timer fires
PVOID Context ; // Context to pass to function when timer fires
PACTIVATION_CONTEXT ActivationContext; // Activation context to activate around callbacks to Function
ULONG Period ; // In Milliseconds. Used for periodic timers.
LIST_ENTRY TimersToFireList;//placed in this list if the timer is fired
HANDLE ImpersonationToken; // Token to use for callouts
} ; } ;
HANDLE CompletionEvent ; // Event signalled when the timer is finally deleted
#if DBG1
ULONG DbgId; ULONG ThreadId ; ULONG ThreadId2 ; #endif
} RTLP_GENERIC_TIMER, *PRTLP_GENERIC_TIMER ;
// Structures used by Wait Threads
// Wait structure
typedef struct _RTLP_WAIT { struct _RTLP_WAIT_THREAD_CONTROL_BLOCK *ThreadCB ; HANDLE WaitHandle ; // Object to wait on
ULONG State ; // REGISTERED, ACTIVE,DELETE state flags
ULONG RefCount ; // initially set to 1. When 0, then ready to be deleted
HANDLE CompletionEvent ; struct _RTLP_GENERIC_TIMER *Timer ; // For timeouts on the wait
ULONG Flags ; // Flags indicating special treatment for this wait
PVOID Function ; // Function to call when wait completes
PVOID Context ; // Context to pass to function
ULONG Timeout ; // In Milliseconds.
PACTIVATION_CONTEXT ActivationContext; // Activation context to activate around calls out to function
HANDLE ImpersonationToken; // Token to use for callouts
#if DBG1
ULONG DbgId ; ULONG ThreadId ; ULONG ThreadId2 ; #endif
} RTLP_WAIT, *PRTLP_WAIT ;
// Wait Thread Control Block
typedef struct _RTLP_WAIT_THREAD_CONTROL_BLOCK {
LIST_ENTRY WaitThreadsList ;// List of all the thread control blocks
HANDLE ThreadHandle ; // Handle for this thread
ULONG ThreadId ; // Used to check if callback is in WaitThread
ULONG NumWaits ; // Number of active waits + handles pending waits
ULONG NumActiveWaits ; // Number of active waits (reflects ActiveWaitArray)
ULONG NumRegisteredWaits ; // Number of waits that are registered
HANDLE ActiveWaitArray[MAXIMUM_WAIT_OBJECTS] ;// Array used for waiting
PRTLP_WAIT ActiveWaitPointers[MAXIMUM_WAIT_OBJECTS] ;// Array of pointers to active Wait blocks.
HANDLE TimerHandle ; // Handle to the NT timer used for timeouts
RTLP_TIMER_QUEUE TimerQueue;// Queue in which all timers are kept
LARGE_INTEGER Current64BitTickCount ; LONGLONG Firing64BitTickCount ; RTL_CRITICAL_SECTION WaitThreadCriticalSection ; // Used for addition and deletion of waits
} RTLP_WAIT_THREAD_CONTROL_BLOCK, *PRTLP_WAIT_THREAD_CONTROL_BLOCK ;
// Structure used for attaching all I/O worker threads
typedef struct _RTLP_IOWORKER_TCB {
LIST_ENTRY List ; // List of IO Worker threads
HANDLE ThreadHandle ; // Handle of this thread
ULONG Flags ; // WT_EXECUTEINPERSISTENTIOTHREAD
BOOLEAN LongFunctionFlag ;// Is the thread currently executing long fn
} RTLP_IOWORKER_TCB, *PRTLP_IOWORKER_TCB ;
typedef struct _RTLP_WAITWORKER { union { PRTLP_WAIT Wait ; PRTLP_TIMER Timer ; } ; BOOLEAN WaitThreadCallback ; //callback queued by Wait thread or Timer thread
BOOLEAN TimerCondition ;//true if fired because wait timed out.
} RTLP_ASYNC_CALLBACK, * PRTLP_ASYNC_CALLBACK ;
// structure used for calling worker function
typedef struct _RTLP_WORK {
WORKERCALLBACKFUNC Function ; ULONG Flags ; PACTIVATION_CONTEXT ActivationContext; HANDLE ImpersonationToken; } RTLP_WORK, *PRTLP_WORK ;
// Structure used for storing events
typedef struct _RTLP_EVENT {
SINGLE_LIST_ENTRY Link ; HANDLE Handle ; } RTLP_EVENT, *PRTLP_EVENT ;
// Defines used in the thread pool
#define THREAD_CREATION_DAMPING_TIME1 1000 // In Milliseconds. Time between starting successive threads.
#define THREAD_CREATION_DAMPING_TIME2 15000 // In Milliseconds. Time between starting successive threads.
#define THREAD_TERMINATION_DAMPING_TIME 10000 // In Milliseconds. Time between stopping successive threads.
#define NEW_THREAD_THRESHOLD 7 // Number of requests outstanding before we start a new thread
#define NEW_THREAD_THRESHOLD2 14
#define MAX_WORKER_THREADS 1000 // Max effective worker threads
#define INFINITE_TIME (ULONG)~0 // In milliseconds
#define PSEUDO_INFINITE_TIME 0x80000000 // In milliseconds
#define RTLP_MAX_TIMERS 0x00080000 // 524288 timers per process
#define MAX_UNUSED_EVENTS 40
#define NEEDS_IO_THREAD(Flags) (Flags & (WT_EXECUTEINIOTHREAD \
| WT_EXECUTEINUITHREAD \ | WT_EXECUTEINPERSISTENTIOTHREAD))
// Macros
#define ONE_MILLISECOND_TIMEOUT(TimeOut) { \
TimeOut.LowPart = 0xffffd8f0 ; \ TimeOut.HighPart = 0xffffffff ; \ }
#define HUNDRED_MILLISECOND_TIMEOUT(TimeOut) { \
TimeOut.LowPart = 0xfff0bdc0 ; \ TimeOut.HighPart = 0xffffffff ; \ }
#define ONE_SECOND_TIMEOUT(TimeOut) { \
TimeOut.LowPart = 0xff676980 ; \ TimeOut.HighPart = 0xffffffff ; \ }
#define USE_PROCESS_HEAP 1
#define RtlpFreeTPHeap(Ptr) \
RtlFreeHeap( RtlProcessHeap(), 0, (Ptr) )
#define RtlpAllocateTPHeap(Size, Flags) \
RtlAllocateHeap( RtlProcessHeap(), (Flags), (Size) )
// used to allocate Wait thread
#define ACQUIRE_GLOBAL_WAIT_LOCK() \
RtlEnterCriticalSection (&WaitCriticalSection)
#define RELEASE_GLOBAL_WAIT_LOCK() \
RtlLeaveCriticalSection(&WaitCriticalSection)
// taken before a timer/queue is deleted and when the timers
// are being fired. Used to assure that no timers will be fired later.
#define ACQUIRE_GLOBAL_TIMER_LOCK() \
RtlEnterCriticalSection (&TimerCriticalSection)
#define RELEASE_GLOBAL_TIMER_LOCK() \
RtlLeaveCriticalSection(&TimerCriticalSection)
// used in RtlpThreadPoolCleanup to find if a component is initialized
#define IS_COMPONENT_INITIALIZED(StartedVariable, CompletedVariable, Flag) \
{\ LARGE_INTEGER TimeOut ; \ Flag = FALSE ; \ \ if ( StartedVariable ) { \ \ if ( !CompletedVariable ) { \ \ ONE_MILLISECOND_TIMEOUT(TimeOut) ; \ \ while (!*((ULONG volatile *)&CompletedVariable)) \ NtDelayExecution (FALSE, &TimeOut) ; \ \ if (CompletedVariable == 1) \ Flag = TRUE ; \ \ } else { \ Flag = TRUE ; \ } \ } \ }
// macro used to set dbg function/context
#define DBG_SET_FUNCTION(Fn, Context) { \
CallbackFn1 = CallbackFn2 ; \ CallbackFn2 = (Fn) ; \ Context1 = Context2 ; \ Context2 = (Context ) ; \ }
// used to move the wait array
/*
VOID RtlpShiftWaitArray( PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB ThreadCB, ULONG SrcIndex, ULONG DstIndex, ULONG Count ) */ #define RtlpShiftWaitArray(ThreadCB, SrcIndex, DstIndex, Count) { \
\ RtlMoveMemory (&(ThreadCB)->ActiveWaitArray[DstIndex], \ &(ThreadCB)->ActiveWaitArray[SrcIndex], \ sizeof (HANDLE) * (Count)) ; \ \ RtlMoveMemory (&(ThreadCB)->ActiveWaitPointers[DstIndex],\ &(ThreadCB)->ActiveWaitPointers[SrcIndex],\ sizeof (HANDLE) * (Count)) ; \ }
// signature for timer and wait entries
#define SET_WAIT_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0100)
#define SET_TIMER_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0200)
#define SET_TIMER_QUEUE_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0xfedc0300)
#define IS_WAIT_SIGNATURE(ptr) (((ptr)->State & 0x00000f00) == 0x00000100)
#define IS_TIMER_SIGNATURE(ptr) (((ptr)->State & 0x00000f00) == 0x00000200)
#define CHECK_SIGNATURE(ptr) ASSERTMSG( InvalidSignatureMsg, \
((ptr)->State & 0xffff0000) == 0xfedc0000 ) #define SET_DEL_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0x0000b000)
#define CHECK_DEL_SIGNATURE(ptr) ASSERTMSG( InvalidDelSignatureMsg, \
(((ptr)->State & 0xffff0000) == 0xfedc0000) \ && ( ! ((ptr)->State & 0x0000f000)) ) #define IS_DEL_SIGNATURE_SET(ptr) ((ptr)->State & 0x0000f000)
#define CLEAR_SIGNATURE(ptr) RtlInterlockedSetClearBits(&(ptr)->State, \
0xcdef0000, \ 0xfedc0000 & ~(0xcdef0000)) #define SET_DEL_TIMERQ_SIGNATURE(ptr) RtlInterlockedSetBitsDiscardReturn(&(ptr)->State, 0x00000a00)
// debug prints
#define RTLP_THREADPOOL_ERROR_MASK (0x01 | DPFLTR_MASK)
#define RTLP_THREADPOOL_WARNING_MASK (0x02 | DPFLTR_MASK)
#define RTLP_THREADPOOL_INFO_MASK (0x04 | DPFLTR_MASK)
#define RTLP_THREADPOOL_TRACE_MASK (0x08 | DPFLTR_MASK)
#define RTLP_THREADPOOL_VERBOSE_MASK (0x10 | DPFLTR_MASK)
#if DBG
extern CHAR InvalidSignatureMsg[]; extern CHAR InvalidDelSignatureMsg[]; #endif
extern ULONG MaxThreads;
extern BOOLEAN LdrpShutdownInProgress;
NTSTATUS NTAPI RtlpStartThreadpoolThread( PUSER_THREAD_START_ROUTINE Function, PVOID Parameter, HANDLE *ThreadHandleReturn );
extern PRTLP_EXIT_THREAD RtlpExitThreadFunc;
#if DBG1
extern PVOID CallbackFn1, CallbackFn2, Context1, Context2 ; #endif
// Timer globals needed by worker
extern ULONG StartedTimerInitialization ; // Used by Timer thread startup synchronization
extern ULONG CompletedTimerInitialization ; // Used for to check if Timer thread is initialized
extern HANDLE TimerThreadHandle;
VOID RtlpAsyncWaitCallbackCompletion( IN PVOID Context );
NTSTATUS RtlpInitializeTimerThreadPool ( ) ;
NTSTATUS RtlpTimerCleanup( VOID );
NTSYSAPI NTSTATUS NTAPI RtlpWaitCleanup( VOID );
NTSYSAPI NTSTATUS NTAPI RtlpWorkerCleanup( VOID );
NTSYSAPI VOID NTAPI RtlpThreadCleanup ( VOID );
VOID RtlpResetTimer ( HANDLE TimerHandle, ULONG DueTime, PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB ) ;
BOOLEAN RtlpInsertInDeltaList ( PLIST_ENTRY DeltaList, PRTLP_GENERIC_TIMER NewTimer, ULONG TimeRemaining, ULONG *NewFiringTime ) ;
BOOLEAN RtlpRemoveFromDeltaList ( PLIST_ENTRY DeltaList, PRTLP_GENERIC_TIMER Timer, ULONG TimeRemaining, ULONG* NewFiringTime ) ;
BOOLEAN RtlpReOrderDeltaList ( PLIST_ENTRY DeltaList, PRTLP_GENERIC_TIMER Timer, ULONG TimeRemaining, ULONG* NewFiringTime, ULONG ChangedFiringTime ) ;
NTSTATUS RtlpDeactivateWait ( PRTLP_WAIT Wait, BOOLEAN OkayToFreeTheTimer ) ;
VOID RtlpDeleteWait ( PRTLP_WAIT Wait ) ;
VOID RtlpProcessTimeouts ( PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB ) ;
ULONG RtlpGetTimeRemaining ( HANDLE TimerHandle ) ;
#define THREAD_TYPE_WORKER 1
#define THREAD_TYPE_IO_WORKER 2
VOID RtlpDeleteTimer ( PRTLP_TIMER Timer ) ;
PRTLP_EVENT RtlpGetWaitEvent ( VOID ) ;
VOID RtlpFreeWaitEvent ( PRTLP_EVENT Event ) ;
VOID RtlpDoNothing ( PVOID NotUsed1, PVOID NotUsed2, PVOID NotUsed3 ) ;
VOID RtlpExecuteWorkerRequest ( NTSTATUS Status, PVOID Context, PVOID ActualFunction ) ;
NTSTATUS RtlpWaitForEvent ( HANDLE Event, HANDLE ThreadHandle ) ;
NTSYSAPI NTSTATUS NTAPI RtlThreadPoolCleanup ( ULONG Flags ) ;
VOID RtlpWaitOrTimerCallout(WAITORTIMERCALLBACKFUNC Function, PVOID Context, BOOLEAN TimedOut, PACTIVATION_CONTEXT ActivationContext, HANDLE ImpersonationToken);
VOID RtlpApcCallout(APC_CALLBACK_FUNCTION Function, NTSTATUS Status, PVOID Context1, PVOID Context2);
VOID RtlpWorkerCallout(WORKERCALLBACKFUNC Function, PVOID Context, PACTIVATION_CONTEXT ActivationContext, HANDLE ImpersonationToken);
// Waits and timers may specify that their callbacks must execute
// within worker threads of various types. This can cause a problem
// if those worker threads are unavailable. RtlpAcquireWorker
// guarantees that at least one worker thread of the appropriate type
// will be available to handle callbacks until a matching call to
// RtlpReleaseWorker is made.
NTSTATUS RtlpAcquireWorker(ULONG Flags);
VOID RtlpReleaseWorker(ULONG Flags);
//to make sure that a wait is not deleted before being registered
#define STATE_REGISTERED 0x0001
//set when wait registered. Removed when one shot wait fired.
//when deregisterWait called, tells whether to be removed from ActiveArray
//If timer active, then have to remove it from delta list and reset the timer.
#define STATE_ACTIVE 0x0002
//when deregister wait is called(RefCount may be >0)
#define STATE_DELETE 0x0004
//set when cancel timer called. The APC will clean it up.
#define STATE_DONTFIRE 0x0008
//set when one shot timer fired.
#define STATE_ONE_SHOT_FIRED 0x0010
|