nt!KeWaitForMultipleObjects函数分析之一个例子ExpWorkerThreadBalanceManager
第一部分:
1: kd> dt kTHREAD 8999c8a0
+0x02c State : 0x2 ''
+0x054 WaitBlockList : 0x8999c940 _KWAIT_BLOCK
第一个_KWAIT_BLOCK:
1: kd> dx -id 0,0,899a2278 -r1 ((CSRSRV!_KWAIT_BLOCK *)0x8999c940)
((CSRSRV!_KWAIT_BLOCK *)0x8999c940) : 0x8999c940 [Type: _KWAIT_BLOCK *]
[+0x000] WaitListEntry [Type: _LIST_ENTRY]
[+0x008] Thread : 0x8999c8a0 [Type: _KTHREAD *]
[+0x00c] Object : 0xf78fad78 [Type: void *]
[+0x010] NextWaitBlock : 0x8999c958 [Type: _KWAIT_BLOCK *]
[+0x014] WaitKey : 0x0 [Type: unsigned short]
[+0x016] WaitType : 0x1 [Type: unsigned short]
第二个_KWAIT_BLOCK:
1: kd> dx -id 0,0,899a2278 -r1 ((CSRSRV!_KWAIT_BLOCK *)0x8999c958)
((CSRSRV!_KWAIT_BLOCK *)0x8999c958) : 0x8999c958 [Type: _KWAIT_BLOCK *]
[+0x000] WaitListEntry [Type: _LIST_ENTRY]
[+0x008] Thread : 0x8999c8a0 [Type: _KTHREAD *]
[+0x00c] Object : 0x80bf5c60 [Type: void *] //80bf5c60 nt!ExpThreadSetManagerEvent = struct _KEVENT
[+0x010] NextWaitBlock : 0x8999c970 [Type: _KWAIT_BLOCK *]
[+0x014] WaitKey : 0x1 [Type: unsigned short]
[+0x016] WaitType : 0x1 [Type: unsigned short]
1: kd> x nt!ExpThreadSetManagerEvent
80bf5c60 nt!ExpThreadSetManagerEvent = struct _KEVENT
第三个_KWAIT_BLOCK:
1: kd> dx -id 0,0,899a2278 -r1 ((CSRSRV!_KWAIT_BLOCK *)0x8999c970)
((CSRSRV!_KWAIT_BLOCK *)0x8999c970) : 0x8999c970 [Type: _KWAIT_BLOCK *]
[+0x000] WaitListEntry [Type: _LIST_ENTRY]
[+0x008] Thread : 0x8999c8a0 [Type: _KTHREAD *]
[+0x00c] Object : 0x80bf5c50 [Type: void *] //80bf5c50 nt!ExpThreadSetManagerShutdownEvent = struct _KEVENT
[+0x010] NextWaitBlock : 0x8999c940 [Type: _KWAIT_BLOCK *] //返回到 NextWaitBlock : 0x8999c940结束
[+0x014] WaitKey : 0x2 [Type: unsigned short]
[+0x016] WaitType : 0x1 [Type: unsigned short]
1: kd> x nt!ExpThreadSetManagerShutdownEvent
80bf5c50 nt!ExpThreadSetManagerShutdownEvent = struct _KEVENT
第二部分:
1: kd> dt ktimer 0xf78fad78 //Object : 0xf78fad78
CSRSRV!KTIMER
+0x000 Header : _DISPATCHER_HEADER
+0x010 DueTime : _ULARGE_INTEGER 0x00002707`bbe04df6
+0x018 TimerListEntry : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x020 Dpc : (null)
+0x024 Period : 0n0
1: kd> dx -id 0,0,899a2278 -r1 (*((CSRSRV!_DISPATCHER_HEADER *)0xf78fad78))
(*((CSRSRV!_DISPATCHER_HEADER *)0xf78fad78)) [Type: _DISPATCHER_HEADER]
[+0x000] Type : 0x8 [Type: unsigned char]
[+0x001] Absolute : 0x0 [Type: unsigned char]
[+0x002] Size : 0xa [Type: unsigned char]
[+0x003] Inserted : 0x0 [Type: unsigned char]
[+0x003] DebugActive : 0x0 [Type: unsigned char]
[+0x000] Lock : 655368 [Type: long]
[+0x004] SignalState : 1 [Type: long] //定时器到期SignalState : 1
[+0x008] WaitListHead [Type: _LIST_ENTRY]
DueTime.QuadPart = - THREAD_SET_INTERVAL;
#define THREAD_SET_INTERVAL (1 * 1000 * 1000 * 10)
1: kd> dt kevent 0x80bf5c60 80bf5c60 nt!ExpThreadSetManagerEvent = struct _KEVENT
CSRSRV!KEVENT
+0x000 Header : _DISPATCHER_HEADER
1: kd> dx -id 0,0,899a2278 -r1 (*((CSRSRV!_DISPATCHER_HEADER *)0x80bf5c60))
(*((CSRSRV!_DISPATCHER_HEADER *)0x80bf5c60)) [Type: _DISPATCHER_HEADER]
[+0x000] Type : 0x1 [Type: unsigned char]
[+0x001] Absolute : 0x0 [Type: unsigned char]
[+0x002] Size : 0x4 [Type: unsigned char]
[+0x003] Inserted : 0x0 [Type: unsigned char]
[+0x003] DebugActive : 0x0 [Type: unsigned char]
[+0x000] Lock : 262145 [Type: long]
[+0x004] SignalState : 0 [Type: long]
[+0x008] WaitListHead [Type: _LIST_ENTRY]
1: kd> dt kevent 0x80bf5c50 //80bf5c50 nt!ExpThreadSetManagerShutdownEvent = struct _KEVENT
CSRSRV!KEVENT
+0x000 Header : _DISPATCHER_HEADER
1: kd> dx -id 0,0,899a2278 -r1 (*((CSRSRV!_DISPATCHER_HEADER *)0x80bf5c50))
(*((CSRSRV!_DISPATCHER_HEADER *)0x80bf5c50)) [Type: _DISPATCHER_HEADER]
[+0x000] Type : 0x1 [Type: unsigned char]
[+0x001] Absolute : 0x0 [Type: unsigned char]
[+0x002] Size : 0x4 [Type: unsigned char]
[+0x003] Inserted : 0x0 [Type: unsigned char]
[+0x003] DebugActive : 0x0 [Type: unsigned char]
[+0x000] Lock : 262145 [Type: long]
[+0x004] SignalState : 0 [Type: long]
[+0x008] WaitListHead [Type: _LIST_ENTRY]
第三部分:
VOID
ExpWorkerThreadBalanceManager (
IN PVOID StartContext
)
{
KTIMER PeriodTimer;
LARGE_INTEGER DueTime;
PVOID WaitObjects[MaximumBalanceObject];
NTSTATUS Status;
PAGED_CODE();
UNREFERENCED_PARAMETER (StartContext);
//
// Raise the thread priority to just higher than the priority of the
// critical work queue.
//
KeSetBasePriorityThread (KeGetCurrentThread(),
CRITICAL_WORK_QUEUE_PRIORITY + 1);
//
// Initialize the periodic timer and set the manager period.
//
KeInitializeTimer (&PeriodTimer);
DueTime.QuadPart = - THREAD_SET_INTERVAL;
//
// Initialize the wait object array.
//
WaitObjects[TimerExpiration] = (PVOID)&PeriodTimer;
WaitObjects[ThreadSetManagerEvent] = (PVOID)&ExpThreadSetManagerEvent;
WaitObjects[ShutdownEvent] = (PVOID)&ExpThreadSetManagerShutdownEvent;
//
// Loop forever processing events.
//
while (TRUE) {
//
// Set the timer to expire at the next periodic interval.
//
KeSetTimer (&PeriodTimer, DueTime, NULL);
//
// Wake up when the timer expires or the set manager event is
// signalled.
//
Status = KeWaitForMultipleObjects (MaximumBalanceObject,
WaitObjects,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL);
switch (Status) {
case TimerExpiration:
//
// Periodic timer expiration - go see if any work queues
// are deadlocked.
//
ExpDetectWorkerThreadDeadlock ();
break;
case ThreadSetManagerEvent:
//
// Someone has asked us to check some metrics to determine
// whether we should create another worker thread.
//
ExpCheckDynamicThreadCount ();
break;
case ShutdownEvent:
//
// Time to exit...
//
KeCancelTimer (&PeriodTimer);
ASSERT (ExpLastWorkerThread);
//
// Wait for the last worker thread to terminate
//
KeWaitForSingleObject (ExpLastWorkerThread,
Executive,
KernelMode,
FALSE,
NULL);
ObDereferenceObject (ExpLastWorkerThread);
PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN);
break;
}
//
// Special debugger support.
//
// This checks if special debugging routines need to be run on the
// behalf of the debugger.
//
if (ExpDebuggerWork == 1) {
ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL);
ExpDebuggerWork = 2;
ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue);
}
}
}
第四部分:case TimerExpiration:分支
#define STATUS_KERNEL_APC 0x100
//
// Define balance set wait object types.
//
typedef enum _BALANCE_OBJECT {
TimerExpiration,
ThreadSetManagerEvent,
ShutdownEvent,
MaximumBalanceObject
} BALANCE_OBJECT;
switch (Status) {
case TimerExpiration:
//
// Periodic timer expiration - go see if any work queues
// are deadlocked.
//
ExpDetectWorkerThreadDeadlock ();
break;
第五部分:ExpDetectWorkerThreadDeadlock
//
// Worker Thread
//
typedef enum _WORK_QUEUE_TYPE {
CriticalWorkQueue,
DelayedWorkQueue,
HyperCriticalWorkQueue,
MaximumWorkQueue
} WORK_QUEUE_TYPE;
1: kd> x nt!ExWorkerQueue
80bf5c80 nt!ExWorkerQueue = struct _EX_WORK_QUEUE [3]
80bf5c80 nt!ExWorkerQueue = struct _EX_WORK_QUEUE []
1: kd> dx -r1 (*((ntkrnlmp!_EX_WORK_QUEUE (*)[3])0x80bf5c80))
(*((ntkrnlmp!_EX_WORK_QUEUE (*)[3])0x80bf5c80)) [Type: _EX_WORK_QUEUE [3]]
[0] [Type: _EX_WORK_QUEUE]
[1] [Type: _EX_WORK_QUEUE]
[2] [Type: _EX_WORK_QUEUE]
1: kd> dx -r1 (*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5c80))
(*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5c80)) [Type: _EX_WORK_QUEUE]
[+0x000] WorkerQueue [Type: _KQUEUE]
[+0x028] DynamicThreadCount : 0x0 [Type: unsigned long]
[+0x02c] WorkItemsProcessed : 0x240 [Type: unsigned long]
[+0x030] WorkItemsProcessedLastPass : 0x23f [Type: unsigned long]
[+0x034] QueueDepthLastPass : 0x0 [Type: unsigned long]
[+0x038] Info [Type: EX_QUEUE_WORKER_INFO]
1: kd> dx -r1 (*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5cbc))
(*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5cbc)) [Type: _EX_WORK_QUEUE]
[+0x000] WorkerQueue [Type: _KQUEUE]
[+0x028] DynamicThreadCount : 0x0 [Type: unsigned long]
[+0x02c] WorkItemsProcessed : 0x16c [Type: unsigned long]
[+0x030] WorkItemsProcessedLastPass : 0x16a [Type: unsigned long]
[+0x034] QueueDepthLastPass : 0x0 [Type: unsigned long]
[+0x038] Info [Type: EX_QUEUE_WORKER_INFO]
1: kd> dx -r1 (*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5cf8))
(*((ntkrnlmp!_EX_WORK_QUEUE *)0x80bf5cf8)) [Type: _EX_WORK_QUEUE]
[+0x000] WorkerQueue [Type: _KQUEUE]
[+0x028] DynamicThreadCount : 0x0 [Type: unsigned long]
[+0x02c] WorkItemsProcessed : 0x7a [Type: unsigned long]
[+0x030] WorkItemsProcessedLastPass : 0x79 [Type: unsigned long]
[+0x034] QueueDepthLastPass : 0x0 [Type: unsigned long]
[+0x038] Info [Type: EX_QUEUE_WORKER_INFO]