Leaked source code of windows server 2003
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.
 
 
 
 
 
 

336 lines
6.6 KiB

/*++
Copyright (c) 1998-2002 Microsoft Corporation
Module Name:
thrdpoolp.h
Abstract:
This module contains private declarations for the thread pool package.
Author:
Keith Moore (KeithMo) 10-Jun-1998
Revision History:
Chun Ye (ChunYe) Spring 2001
George V. Reilly (GeorgeRe) Summer 2001
--*/
#ifndef _THRDPOOLP_H_
#define _THRDPOOLP_H_
//
// CODEWORK: Build a new kind of tracelog for threadpool. Reftrace is
// inadequate.
//
// Special threads
enum {
WaitThreadPool,
HighPriorityThreadPool,
MaxThreadPools // must be last
};
//
// Various states that a thread pool worker thread can be in
//
typedef enum {
ThreadPoolCreated = 1,
ThreadPoolInit,
ThreadPoolFlush,
ThreadPoolSearchOther,
ThreadPoolBlock,
ThreadPoolReverseList,
ThreadPoolExecute,
ThreadPoolException,
ThreadPoolTerminated,
} UL_THREAD_POOL_STATE;
typedef struct _UL_THREAD_POOL *PUL_THREAD_POOL;
//
// Thread tracker object. One of these objects is created for each
// thread in the pool. These are useful for (among other things)
// debugging.
//
typedef struct _UL_THREAD_TRACKER
{
//
// Links onto the per-thread-pool list.
//
LIST_ENTRY ThreadListEntry;
//
// Back pointer to owning threadpool
//
PUL_THREAD_POOL pThreadPool;
//
// The thread.
//
PETHREAD pThread;
//
// The thread handle returned from PsCreateSystemThread.
//
HANDLE ThreadHandle;
//
// List of worker items currently being processed in inner loop
// and length of that list
//
SLIST_ENTRY CurrentListHead;
ULONG ListLength;
//
// Current state of the thread
//
UL_THREAD_POOL_STATE State;
//
// Current workitem and current workroutine
//
PUL_WORK_ROUTINE pWorkRoutine;
PUL_WORK_ITEM pWorkItem;
//
// Statistics
// Average queue length (at time of flush) = SumQueueLength / QueueFlushes
//
ULONGLONG Executions;
ULONGLONG SumQueueLengths;
ULONG QueueFlushes;
ULONG MaxQueueLength;
} UL_THREAD_TRACKER, *PUL_THREAD_TRACKER;
//
// The thread pool object.
//
typedef struct _UL_THREAD_POOL
{
//
// List of unprocessed worker items on this thread pool.
//
SLIST_HEADER WorkQueueSList;
//
// An event used to wakeup the thread from blocking state.
//
KEVENT WorkQueueEvent;
//
// List of threads.
//
LIST_ENTRY ThreadListHead;
//
// Pointer to the special thread designated as the IRP thread. The
// IRP thread is the first pool thread created and the last one to
// die. It is also the target for all asynchronous IRPs.
//
PETHREAD pIrpThread;
//
// A very infrequently used spinlock.
//
UL_SPIN_LOCK ThreadSpinLock;
//
// The number of threads we created for this pool.
//
UCHAR ThreadCount;
//
// Flag used to indicate that this pool has been successfully
// initialized.
//
BOOLEAN Initialized;
//
// Target CPU for this pool. The worker threads use this to set
// their hard affinity.
//
UCHAR ThreadCpu;
//
// Regular worker threads can pull workitems from
// other regular queues on other processors.
//
BOOLEAN LookOnOtherQueues;
} UL_THREAD_POOL, *PUL_THREAD_POOL;
//
// Necessary to ensure our array of UL_THREAD_POOL structures is
// cache aligned.
//
typedef union _UL_ALIGNED_THREAD_POOL
{
UL_THREAD_POOL ThreadPool;
UCHAR CacheAlignment[(sizeof(UL_THREAD_POOL) + UL_CACHE_LINE - 1)
& ~(UL_CACHE_LINE - 1)];
} UL_ALIGNED_THREAD_POOL;
//
// Inline function to validate that a UL_WORK_ITEM has been properly
// initialized. Bugcheck if it's not.
//
__inline
VOID
UlpValidateWorkItem(
IN PUL_WORK_ITEM pWorkItem,
IN PCSTR pFileName,
IN USHORT LineNumber
)
{
if (! UlIsInitializedWorkItem(pWorkItem))
{
ASSERT(! "Uninitialized workitem");
//
// If the workitem was not properly zeroed, then chances are that
// it's already on a work queue. If we were to requeue the work item,
// it would corrupt the work queue. Better to fail hard now, while
// there's some hope of figuring out what went wrong, than let it
// crash mysteriously later.
//
UlBugCheckEx(
HTTP_SYS_BUGCHECK_WORKITEM,
(ULONG_PTR) pWorkItem,
(ULONG_PTR) pFileName,
(ULONG_PTR) LineNumber
);
}
} // UlpValidateWorkItem
//
// Inline function to queue a preinitialized UL_WORK_ITEM.
//
__inline
VOID
QUEUE_UL_WORK_ITEM(
PUL_THREAD_POOL pThreadPool,
IN PUL_WORK_ITEM pWorkItem
)
{
if (NULL == InterlockedPushEntrySList(
&pThreadPool->WorkQueueSList,
&pWorkItem->QueueListEntry
))
{
//
// If the work queue was empty when we added this item,
// set the event to wake the thread up
//
KeSetEvent(
&pThreadPool->WorkQueueEvent,
0,
FALSE
);
}
}
//
// Private prototypes.
//
NTSTATUS
UlpCreatePoolThread(
IN PUL_THREAD_POOL pThreadPool
);
VOID
UlpThreadPoolWorker(
IN PVOID Context
);
VOID
UlpInitThreadTracker(
IN PUL_THREAD_POOL pThreadPool,
IN PETHREAD pThread,
IN PUL_THREAD_TRACKER pThreadTracker
);
VOID
UlpDestroyThreadTracker(
IN PUL_THREAD_TRACKER pThreadTracker
);
PUL_THREAD_TRACKER
UlpPopThreadTracker(
IN PUL_THREAD_POOL pThreadPool
);
VOID
UlpKillThreadWorker(
IN PUL_WORK_ITEM pWorkItem
);
//
// Private globals.
//
extern DECLSPEC_ALIGN(UL_CACHE_LINE)
UL_ALIGNED_THREAD_POOL g_UlThreadPool[];
#define CURRENT_THREAD_POOL() \
&g_UlThreadPool[KeGetCurrentProcessorNumber()].ThreadPool
#define CURRENT_SYNC_THREAD_POOL() \
&g_UlThreadPool[g_UlNumberOfProcessors + KeGetCurrentProcessorNumber()].ThreadPool
#define WAIT_THREAD_POOL() \
&g_UlThreadPool[(g_UlNumberOfProcessors * 2) + WaitThreadPool].ThreadPool
#define HIGH_PRIORITY_THREAD_POOL() \
&g_UlThreadPool[(g_UlNumberOfProcessors * 2) + HighPriorityThreadPool].ThreadPool
extern PUL_WORK_ITEM g_pKillerWorkItems;
#endif // _THRDPOOLP_H_