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