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.
 
 
 
 
 
 

132 lines
3.0 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
yield.c
Abstract:
This module implements the function to yield execution for one quantum
to any other runnable thread.
Author:
David N. Cutler (davec) 15-Mar-1996
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
NTSTATUS
NtYieldExecution (
VOID
)
/*++
Routine Description:
This function yields execution to any ready thread for up to one
quantum.
Arguments:
None.
Return Value:
None.
--*/
{
KIRQL OldIrql;
PKTHREAD NewThread;
PRKPRCB Prcb;
NTSTATUS Status;
PKTHREAD Thread;
//
// If any other threads are ready, then attempt to yield execution.
//
Status = STATUS_NO_YIELD_PERFORMED;
Thread = KeGetCurrentThread();
OldIrql = KeRaiseIrqlToSynchLevel();
Prcb = KeGetCurrentPrcb();
if (Prcb->ReadySummary != 0) {
//
// Acquire the thread lock and the PRCB lock.
//
// If a thread has not already been selected for execution, then
// attempt to select another thread for execution.
//
KiAcquireThreadLock(Thread);
KiAcquirePrcbLock(Prcb);
if (Prcb->NextThread == NULL) {
Prcb->NextThread = KiSelectReadyThread(1, Prcb);
}
//
// If a new thread has been selected for execution, then switch
// immediately to the selected thread.
//
if ((NewThread = Prcb->NextThread) != NULL) {
Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
//
// Compute the new thread priority.
//
// N.B. The new priority will never be greater than the previous
// priority.
//
Thread->Priority = KiComputeNewPriority(Thread, 1);
//
// Release the thread lock, set swap busy for the old thread,
// set the next thread to NULL, set the current thread to the
// new thread, set the new thread state to running, set the
// wait reason, queue the old running thread, and release the
// PRCB lock, and swp context to the new thread.
//
KiReleaseThreadLock(Thread);
KiSetContextSwapBusy(Thread);
Prcb->NextThread = NULL;
Prcb->CurrentThread = NewThread;
NewThread->State = Running;
Thread->WaitReason = WrYieldExecution;
KxQueueReadyThread(Thread, Prcb);
Thread->WaitIrql = APC_LEVEL;
ASSERT(OldIrql <= DISPATCH_LEVEL);
KiSwapContext(Thread, NewThread);
Status = STATUS_SUCCESS;
} else {
KiReleasePrcbLock(Prcb);
KiReleaseThreadLock(Thread);
}
}
//
// Lower IRQL to its previous level and return.
//
KeLowerIrql(OldIrql);
return Status;
}