Windows2000/private/ntos/rtl/threads.h

446 lines
19 KiB
C

/*++
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:
These routines are statically linked in the caller's executable and
are callable in only from user mode. They make use of Nt system services.
Revision History:
Aug-19 lokeshs - modifications to thread pool apis.
*/
//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; //ksl
#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
ULONG Period ; // In Milliseconds. Used for periodic timers.
LIST_ENTRY TimersToFireList;//placed in this list if the timer is fired
} ;
} ;
HANDLE CompletionEvent ; // Event signalled when the timer is finally deleted
#if DBG1
ULONG DbgId; //ksl
ULONG ThreadId ;
ULONG ThreadId2 ;
#endif
} RTLP_GENERIC_TIMER, *PRTLP_GENERIC_TIMER ;
#if DBG1
ULONG NextTimerDbgId;
ULONG NextWaitDbgId;
#endif
// Structurs 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.
#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 not being waited upon
ULONG NumActiveWaits ; // Total number of waits.
HANDLE ActiveWaitArray[64] ;// Array used for waiting
PRTLP_WAIT ActiveWaitPointers[64] ;// 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
RTLP_TIMER TimerBlocks[63] ;// All the timers required for wait timeouts - max of 63 since wait[0]
// is used for NT timer object
LIST_ENTRY FreeTimerBlocks ;// List of Free Blocks
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 ;
} RTLP_WORK, *PRTLP_WORK ;
// Structure used for storing events
typedef struct _RTLP_EVENT {
LIST_ENTRY List ;
HANDLE Handle ;
} RTLP_EVENT, *PRTLP_EVENT ;
// Globals used by the thread pool
ULONG StartedTPInitialization ; // Used for Initializing ThreadPool
ULONG CompletedTPInitialization;// Used to check if ThreadPool is initialized
ULONG StartedWorkerInitialization ; // Used for Worker thread startup synchronization
ULONG CompletedWorkerInitialization ; // Used to check if Worker thread pool is initialized
ULONG StartedWaitInitialization ; // Used for Wait thread startup synchronization
ULONG CompletedWaitInitialization ; // Used to check if Wait thread pool is initialized
ULONG StartedTimerInitialization ; // Used by Timer thread startup synchronization
ULONG CompletedTimerInitialization ; // Used for to check if Timer thread is initialized
ULONG StartedEventCacheInitialization ; // Used for initializing event cache
ULONG CompletedEventCacheInitialization;// Used for initializing event cache
HANDLE TimerThreadHandle ; // Holds the timer thread handle
ULONG TimerThreadId ; // Used to check if current thread is a timer thread
ULONG NumIOWorkerThreads ; // Count of IO Worker Threads alive
ULONG NumWorkerThreads ; // Count of Worker Threads alive
ULONG NumMinWorkerThreads ; // Min worker threads should be alive: 1 if ioCompletion used, else 0
ULONG NumIOWorkRequests ; // Count of IO Work Requests pending
ULONG NumLongIOWorkRequests ; // IO Worker threads executing long worker functions
ULONG NumWorkRequests ; // Count of Work Requests pending.
ULONG NumLongWorkRequests ; // Worker threads executing long worker functions
ULONG NumExecutingWorkerThreads ; // Worker threads currently executing worker functions
ULONG TotalExecutedWorkRequests ; // Total worker requests that were picked up
ULONG OldTotalExecutedWorkRequests ; // Total worker requests since last timeout.
HANDLE WorkerThreadTimerQueue ; // Timer queue used by worker threads
ULONG WorkerThreadTimerQueueInit ; // Initialization of the above timer queue
HANDLE WorkerThreadTimer ; // Timer used by worker threads
ULONG NumUnusedEvents ; // Count of Unused events in the cache
ULONG LastThreadCreationTickCount ; // Tick count at which the last thread was created
LIST_ENTRY IOWorkerThreads ; // List of IOWorkerThreads
PRTLP_IOWORKER_TCB PersistentIOTCB ; // ptr to TCB of persistest IO worker thread
HANDLE WorkerCompletionPort ; // Completion port used for queuing tasks to Worker threads
LIST_ENTRY WaitThreads ; // List of all wait threads created
LIST_ENTRY EventCache ; // Events used for synchronization
LIST_ENTRY TimerQueues ; // All timer queues are linked in this list
HANDLE TimerHandle ; // Holds handle of NT Timer used by the Timer Thread
ULONG NumTimerQueues ; // Number of timer queues
RTL_CRITICAL_SECTION WorkerCriticalSection ; // Exclusion used by worker threads
RTL_CRITICAL_SECTION WaitCriticalSection ; // Exclusion used by wait threads
RTL_CRITICAL_SECTION TimerCriticalSection ; // Exclusion used by timer threads
RTL_CRITICAL_SECTION EventCacheCriticalSection ;// Exclusion used for handle allocation
RTLP_START_THREAD RtlpStartThread ;
PRTLP_START_THREAD RtlpStartThreadFunc = RtlpStartThread ;
RTLP_EXIT_THREAD RtlpExitThread ;
PRTLP_EXIT_THREAD RtlpExitThreadFunc = RtlpExitThread ;
#if DBG1
PVOID CallbackFn1, CallbackFn2, Context1, Context2 ;
#endif
// defines used in the thread pool
#define THREAD_CREATION_DAMPING_TIME1 1000 // In Milliseconds. Time between starting successive threads.
#define THREAD_CREATION_DAMPING_TIME2 5000 // 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 MAX_WORKER_THREADS 1000 // Max effective worker threads
#define INFINITE_TIME (ULONG)~0 // In milliseconds
#define RTLP_MAX_TIMERS 0x00080000 // 524288 timers per process
#define MAX_UNUSED_EVENTS 40
// 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 (!(volatile ULONG) 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) { \
\
RtlCopyMemory (&(ThreadCB)->ActiveWaitArray[DstIndex], \
&(ThreadCB)->ActiveWaitArray[SrcIndex], \
sizeof (HANDLE) * (Count)) ; \
\
RtlCopyMemory (&(ThreadCB)->ActiveWaitPointers[DstIndex],\
&(ThreadCB)->ActiveWaitPointers[SrcIndex],\
sizeof (HANDLE) * (Count)) ; \
}
LARGE_INTEGER Last64BitTickCount ;
LARGE_INTEGER Resync64BitTickCount ;
LARGE_INTEGER Firing64BitTickCount ;
#define RtlpGetResync64BitTickCount() Resync64BitTickCount.QuadPart
#define RtlpSetFiring64BitTickCount(Timeout) \
Firing64BitTickCount.QuadPart = (Timeout)
// signature for timer and wait entries
#define SET_SIGNATURE(ptr) (ptr)->State |= 0xfedc0000
#define CHECK_SIGNATURE(ptr) ASSERT( ((ptr)->State & 0xffff0000) == 0xfedc0000 )
#define SET_DEL_SIGNATURE(ptr) ((ptr)->State |= 0xfedcb000)
#define CHECK_DEL_SIGNATURE(ptr) ASSERT( (((ptr)->State & 0xffff0000) == 0xfedc0000) \
&& ( ! ((ptr)->State & 0x0000f000)) )
#define CLEAR_SIGNATURE(ptr) ((ptr)->State = ((ptr)->State & 0x0000ffff) | 0xcdef0000)
#define SET_DEL_TIMERQ_SIGNATURE(ptr) ((ptr)->State |= 0x00000a00)
// debug prints
#define DPRN0 (DPRN & 0x1)
#define DPRN1 (DPRN & 0x2)
#define DPRN2 (DPRN & 0x4)
#define DPRN3 (DPRN & 0x8)
#define DPRN4 (DPRN & 0x10)
// Prototypes for thread pool private functions
NTSTATUS RtlpInitializeWorkerThreadPool () ;
NTSTATUS RtlpInitializeWaitThreadPool () ;
NTSTATUS RtlpInitializeTimerThreadPool () ;
NTSTATUS RtlpStartThread (IN PUSER_THREAD_START_ROUTINE Function, OUT HANDLE *ThreadHandle) ;
LONG RtlpWaitThread (IN PVOID WaitHandle) ;
LONG RtlpWorkerThread (PVOID NotUsed) ;
LONG RtlpIOWorkerThread (PVOID NotUsed) ;
LONG RtlpTimerThread (PVOID NotUsed) ;
VOID RtlpAddTimerQueue (PVOID Queue) ;
VOID RtlpAddTimer (PRTLP_TIMER Timer) ;
VOID RtlpResetTimer (HANDLE TimerHandle, ULONG DueTime, PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB) ;
VOID RtlpFireTimersAndReorder (PRTLP_TIMER_QUEUE Queue, ULONG *NewFiringTime, PLIST_ENTRY TimersToFireList) ;
VOID RtlpFireTimers (PLIST_ENTRY TimersToFireList) ;
VOID RtlpInsertTimersIntoDeltaList (PLIST_ENTRY NewTimerList, PLIST_ENTRY DeltaTimerList, ULONG TimeRemaining, ULONG *NewFiringTime) ;
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) ;
VOID RtlpAddWait (PRTLP_WAIT Wait) ;
NTSTATUS RtlpDeregisterWait (PRTLP_WAIT Wait, HANDLE PartialCompletionEvent, PULONG StatusPtr) ;
NTSTATUS RtlpDeactivateWait (PRTLP_WAIT Wait) ;
VOID RtlpDeleteWait (PRTLP_WAIT Wait) ;
VOID RtlpProcessWaitCompletion (PRTLP_WAIT Wait, ULONG ArrayIndex) ;
VOID RtlpProcessTimeouts (PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB) ;
ULONG RtlpGetTimeRemaining (HANDLE TimerHandle) ;
VOID RtlpServiceTimer (PVOID NotUsedArg, ULONG NotUsedLowTimer, LONG NotUsedHighTimer) ;
ULONG RtlpGetQueueRelativeTime (PRTLP_TIMER_QUEUE Queue) ;
VOID RtlpCancelTimer (PRTLP_TIMER TimerToCancel) ;
VOID RtlpCancelTimerEx (PRTLP_TIMER Timer, BOOLEAN DeletingQueue) ;
VOID RtlpDeactivateTimer (PRTLP_TIMER_QUEUE Queue, PRTLP_TIMER Timer) ;
NTSTATUS RtlpDeleteTimerQueue (PRTLP_TIMER_QUEUE Queue) ;
VOID RtlpDeleteTimerQueueComplete (PRTLP_TIMER_QUEUE Queue) ;
LONGLONG Rtlp64BitTickCount() ;
NTSTATUS RtlpFindWaitThread (PRTLP_WAIT_THREAD_CONTROL_BLOCK *ThreadCB) ;
VOID RtlpExecuteIOWorkItem (PVOID Function, PVOID Context, PVOID NotUsed) ;
VOID RtlpExecuteLongIOWorkItem (PVOID Function, PVOID Context, PVOID NotUsed) ;
NTSTATUS RtlpQueueIOWorkerRequest (WORKERCALLBACKFUNC Function, PVOID Context, ULONG Flags) ;
NTSTATUS RtlpStartWorkerThread () ;
NTSTATUS RtlpStartIOWorkerThread () ;
VOID RtlpWorkerThreadTimerCallback(PVOID Context, BOOLEAN NotUsed) ;
NTSTATUS RtlpQueueWorkerRequest (WORKERCALLBACKFUNC Function, PVOID Context, ULONG Flags) ;
#define THREAD_TYPE_WORKER 1
#define THREAD_TYPE_IO_WORKER 2
BOOLEAN RtlpDoWeNeedNewWorkerThread (ULONG ThreadType) ;
VOID RtlpUpdateTimer (PRTLP_TIMER Timer, PRTLP_TIMER UpdatedTimer) ;
VOID RtlpDeleteTimer (PRTLP_TIMER Timer) ;
PRTLP_EVENT RtlpGetWaitEvent (VOID) ;
VOID RtlpFreeWaitEvent (PRTLP_EVENT Event) ;
VOID RtlpInitializeEventCache (VOID) ;
VOID RtlpFreeWaitEvent (PRTLP_EVENT Event) ;
PRTLP_EVENT RtlpGetWaitEvent (VOID) ;
VOID RtlpDeleteWaitAPC (PRTLP_WAIT_THREAD_CONTROL_BLOCK ThreadCB, PRTLP_WAIT Wait, HANDLE Handle) ;
VOID RtlpDoNothing (PVOID NotUsed1, PVOID NotUsed2, PVOID NotUsed3) ;
VOID RtlpExecuteWorkerRequest (NTSTATUS Status, PVOID Context, PVOID ActualFunction) ;
NTSTATUS RtlpInitializeTPHeap () ;
NTSTATUS RtlpWaitForEvent (HANDLE Event, HANDLE ThreadHandle) ;
VOID RtlpThreadCleanup () ;
VOID RtlpWorkerThreadCleanup (NTSTATUS Status, PVOID NotUsed, PVOID NotUsed2) ;
PVOID RtlpForceAllocateTPHeap(ULONG dwSize, ULONG dwFlags);
VOID RtlpWorkerThreadInitializeTimers(PVOID Context);
NTSYSAPI NTSTATUS NTAPI RtlThreadPoolCleanup (ULONG Flags) ;
#define STATE_REGISTERED 0x0001//to make sure that a wait is not deleted before being registered
//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
#define STATE_DELETE 0x0004//when deregister wait is called(RefCount may be >0)
#define STATE_DONTFIRE 0x0008//set when cancel timer called. The APC will clean it up.
#define STATE_ONE_SHOT_FIRED 0x0010//set when one shot timer fired.