KeWaitForMultipleObjects函数分析之逻辑结构

KeWaitForMultipleObjects函数分析之逻辑结构

KeWaitForMultipleObjects

do {

//

// Test to determine if a kernel APC is pending.

//

// If a kernel APC is pending, the special APC disable count is zero,

// and the previous IRQL was less than APC_LEVEL, then a kernel APC

// was queued by another processor just after IRQL was raised to

// DISPATCH_LEVEL, but before the dispatcher database was locked.

//

// N.B. that this can only happen in a multiprocessor system.

//

第一章:

if (Thread->ApcState.KernelApcPending &&

第一章:第0部分:

} else {

第一章:第一部分:

//

// Construct wait blocks and check to determine if the wait is

// already satisfied. If the wait is satisfied, then perform

// wait completion and return. Else put current thread in a wait

// state if an explicit timeout value of zero is not specified.

//

Index = 0;
if (WaitType == WaitAny) {

do {

//

// Test if wait can be satisfied immediately.

//测试是否能立即满足条件,如果立即满足,则退出函数。

Index += 1;

} while(Index < Count);

} else {

do {

//

// Test if wait can be satisfied.

//测试是否能立即满足条件,如果立即满足,则退出函数。

Index += 1;

} while(Index < Count);

//

// If all objects have been scanned, then satisfy the wait.

//

if (Index == Count) {

WaitBlock = &WaitBlockArray[0];

do {

Objectx = (PKMUTANT)WaitBlock->Object;

KiWaitSatisfyAny(Objectx, Thread);

WaitBlock = WaitBlock->NextWaitBlock;

} while (WaitBlock != &WaitBlockArray[0]);

WaitStatus = (NTSTATUS)Thread->WaitStatus;

goto NoWait;

}
} //if (WaitType == WaitAny) { 结束

第一章:第二部分:

第二部分A:

//

// Test for alert pending.

//

TestForAlertPending(Alertable);

//

// Check to determine if a timeout value is specified.

//

if (ARGUMENT_PRESENT(Timeout)) {

//

// If the timeout value is zero, then return immediately without

// waiting.

//

if (Timeout->QuadPart == 0) {

WaitStatus = (NTSTATUS)(STATUS_TIMEOUT);

goto NoWait;

}

}

第二部分B:

//

// Insert wait blocks in object wait lists.

//

WaitBlock = &WaitBlockArray[0];

do {

Objectx = (PKMUTANT)WaitBlock->Object;

InsertTailList(&Objectx->Header.WaitListHead, &WaitBlock->WaitListEntry);

WaitBlock = WaitBlock->NextWaitBlock;

} while (WaitBlock != &WaitBlockArray[0]);

第二部分C:

//

// If the current thread is processing a queue entry, then attempt

// to activate another thread that is blocked on the queue object.

//

Queue = Thread->Queue;

if (Queue != NULL) {

KiActivateWaiterQueue(Queue);

}

第二部分D:

//

// Set the thread wait parameters, set the thread dispatcher state

// to Waiting, and insert the thread in the wait list.

//

CurrentPrcb = KeGetCurrentPrcb();

Thread->State = Waiting;

if (StackSwappable != FALSE) {

InsertTailList(&CurrentPrcb->WaitListHead, &Thread->WaitListEntry);

}

第二部分E:

//

// Set swap busy for the current thread, unlock the dispatcher

// database, and switch to a new thread.

//

// Control is returned at the original IRQL.

//

ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);

KiSetContextSwapBusy(Thread);

KiUnlockDispatcherDatabaseFromSynchLevel();
WaitStatus = (NTSTATUS)KiSwapThread(Thread, CurrentPrcb);

第二部分F: KiSwapThread函数返回了,说明满足了条件,可以返回了。 return WaitStatus;

//

// If the thread was not awakened to deliver a kernel mode APC,

// then return the wait status.

//

if (WaitStatus != STATUS_KERNEL_APC) {

return WaitStatus;

}

if (ARGUMENT_PRESENT(Timeout)) {

//

// Reduce the amount of time remaining before timeout occurs.

//

Timeout = KiComputeWaitInterval(OriginalTime,

&DueTime,

&NewTime);

}

} //if (Thread->ApcState.KernelApcPending && 结束

第二章:

//

// Raise IRQL to SYNCH level, initialize the thread local variables,

// and lock the dispatcher database.

//

WaitStart:

Thread->WaitIrql = KeRaiseIrqlToSynchLevel();

InitializeWaitMultiple();

KiLockDispatcherDatabaseAtSynchLevel();

} while (TRUE);