|
|
/*++
Copyright (c) 1998-2002 Microsoft Corporation
Module Name:
thrdpool.h
Abstract:
This module contains public declarations for the thread pool package.
Author:
Keith Moore (keithmo) 10-Jun-1998
Revision History:
--*/
#ifndef _THRDPOOL_H_
#define _THRDPOOL_H_
//
// Pointer to a thread pool worker function.
//
typedef union _UL_WORK_ITEM *PUL_WORK_ITEM;
typedef VOID (*PUL_WORK_ROUTINE)( IN PUL_WORK_ITEM pWorkItem );
//
// A work item. A work item may only appear on the work queue once.
//
typedef union _UL_WORK_ITEM { DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) ULONGLONG Alignment;
struct { SLIST_ENTRY QueueListEntry; // Next pointer
PUL_WORK_ROUTINE pWorkRoutine; // Callback routine
};
} UL_WORK_ITEM, *PUL_WORK_ITEM;
//
// We have to be sure that the DriverContext (PVOID [4]) in the IRP is
// big enough to hold both the process pointer and a UL_WORK_ITEM.
//
C_ASSERT(FIELD_OFFSET(UL_WORK_ITEM, pWorkRoutine) <= (4 - 2) * sizeof(PVOID));
//
// Public functions.
//
NTSTATUS UlInitializeThreadPool( IN USHORT ThreadsPerCpu );
VOID UlTerminateThreadPool( VOID );
//
// One-time initialization of a UL_WORK_ITEM. Note that UlpThreadPoolWorker
// will reinitialize the workitem just before calling pWorkRoutine(), so
// this only needs to be done when the UL_WORK_ITEM (or enclosing struct)
// is first created. We need this so that we can check that a workitem is
// not being queued when it is already on the queue---a catastrophic error.
//
#if DBG
// Use non-zero values to ensure that item is properly initialized
// and not just zero by coincidence
# define WORK_ITEM_INIT_LIST_ENTRY ((PSLIST_ENTRY) 0xda7a)
# define WORK_ITEM_INIT_ROUTINE ((PUL_WORK_ROUTINE) 0xc0de)
#else
// Use zero for efficiency
# define WORK_ITEM_INIT_LIST_ENTRY NULL
# define WORK_ITEM_INIT_ROUTINE NULL
#endif
__inline VOID UlInitializeWorkItem( IN PUL_WORK_ITEM pWorkItem) { pWorkItem->QueueListEntry.Next = WORK_ITEM_INIT_LIST_ENTRY; pWorkItem->pWorkRoutine = WORK_ITEM_INIT_ROUTINE; }
__inline BOOLEAN UlIsInitializedWorkItem( IN PUL_WORK_ITEM pWorkItem) { return (BOOLEAN)(WORK_ITEM_INIT_LIST_ENTRY == pWorkItem->QueueListEntry.Next && WORK_ITEM_INIT_ROUTINE == pWorkItem->pWorkRoutine); }
VOID UlQueueWorkItem( IN PUL_WORK_ITEM pWorkItem, IN PUL_WORK_ROUTINE pWorkRoutine, IN PCSTR pFileName, IN USHORT LineNumber );
#define UL_QUEUE_WORK_ITEM( pWorkItem, pWorkRoutine ) \
UlQueueWorkItem( \ pWorkItem, \ pWorkRoutine, \ __FILE__, (USHORT) __LINE__ \ )
//
// Store a WORK_ITEM inside IRP::Tail.Overlay.DriverContext (array of 4 PVOIDs)
// Ensure that it's correctly aligned for the platform
//
#ifdef _WIN64
// DriverContext[1] is 16-byte aligned
C_ASSERT(((1 * sizeof(PVOID) + FIELD_OFFSET(IRP, Tail.Overlay.DriverContext)) & (MEMORY_ALLOCATION_ALIGNMENT - 1) ) == 0);
#define UL_PROCESS_FROM_IRP( _irp ) \
(*(PEPROCESS*)&((_irp)->Tail.Overlay.DriverContext[0]))
#define UL_MDL_FROM_IRP( _irp ) \
(*(PMDL*)&((_irp)->Tail.Overlay.DriverContext[0]))
#define UL_WORK_ITEM_FROM_IRP( _irp ) \
(PUL_WORK_ITEM)&((_irp)->Tail.Overlay.DriverContext[1])
#define UL_WORK_ITEM_TO_IRP( _workItem ) \
CONTAINING_RECORD( (_workItem), IRP, Tail.Overlay.DriverContext[1])
#else // !_WIN64
// DriverContext[0] is 8-byte aligned
C_ASSERT(((0 * sizeof(PVOID) + FIELD_OFFSET(IRP, Tail.Overlay.DriverContext)) & (MEMORY_ALLOCATION_ALIGNMENT - 1) ) == 0);
#define UL_PROCESS_FROM_IRP( _irp ) \
(*(PEPROCESS*)&((_irp)->Tail.Overlay.DriverContext[3]))
#define UL_MDL_FROM_IRP( _irp ) \
(*(PMDL*)&((_irp)->Tail.Overlay.DriverContext[3]))
#define UL_WORK_ITEM_FROM_IRP( _irp ) \
(PUL_WORK_ITEM)&((_irp)->Tail.Overlay.DriverContext[0])
#define UL_WORK_ITEM_TO_IRP( _workItem ) \
CONTAINING_RECORD( (_workItem), IRP, Tail.Overlay.DriverContext[0])
#endif // !_WIN64
VOID UlQueueSyncItem( IN PUL_WORK_ITEM pWorkItem, IN PUL_WORK_ROUTINE pWorkRoutine, IN PCSTR pFileName, IN USHORT LineNumber );
#define UL_QUEUE_SYNC_ITEM( pWorkItem, pWorkRoutine ) \
UlQueueSyncItem( \ pWorkItem, \ pWorkRoutine, \ __FILE__, __LINE__ \ )
VOID UlQueueWaitItem( IN PUL_WORK_ITEM pWorkItem, IN PUL_WORK_ROUTINE pWorkRoutine, IN PCSTR pFileName, IN USHORT LineNumber );
#define UL_QUEUE_WAIT_ITEM( pWorkItem, pWorkRoutine ) \
UlQueueWaitItem( \ pWorkItem, \ pWorkRoutine, \ __FILE__, __LINE__ \ )
VOID UlQueueHighPriorityItem( IN PUL_WORK_ITEM pWorkItem, IN PUL_WORK_ROUTINE pWorkRoutine, IN PCSTR pFileName, IN USHORT LineNumber );
#define UL_QUEUE_HIGH_PRIORITY_ITEM( pWorkItem, pWorkRoutine ) \
UlQueueHighPriorityItem( \ pWorkItem, \ pWorkRoutine, \ __FILE__, __LINE__ \ )
VOID UlCallPassive( IN PUL_WORK_ITEM pWorkItem, IN PUL_WORK_ROUTINE pWorkRoutine, IN PCSTR pFileName, IN USHORT LineNumber );
#define UL_CALL_PASSIVE( pWorkItem, pWorkRoutine ) \
UlCallPassive( \ pWorkItem, \ pWorkRoutine, \ __FILE__, __LINE__ \ )
PETHREAD UlQueryIrpThread( VOID );
#endif // _THRDPOOL_H_
|