test: yield.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# yield.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1996  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     yield.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the function to yield execution for one quantum
    00012     to any other runnable thread.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 15-Mar-1996
    00017
    00018 Environment:
    00019
    00020     Kernel mode only.
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026 #include "ki.h"
    00027
    00028 NTSTATUS
    00029 NtYieldExecution (
    00030     VOID
    00031     )
    00032
    00033 /*++
    00034
    00035 Routine Description:
    00036
    00037     This function yields execution to any ready thread for up to one
    00038     quantum.
    00039
    00040 Arguments:
    00041
    00042     None.
    00043
    00044 Return Value:
    00045
    00046     None.
    00047
    00048 --*/
    00049
    00050 {
    00051
    00052     KIRQL OldIrql;
    00053     PRKPRCB Prcb;
    00054     KPRIORITY Priority;
    00055     NTSTATUS Status;
    00056     PRKTHREAD Thread;
    00057
    00058     //
    00059     // If any other threads are ready, then attempt to yield execution.
    00060     //
    00061
    00062     Status = STATUS_NO_YIELD_PERFORMED;
    00063     if (KiReadySummary != 0) {
    00064
    00065         //
    00066         // If a thread has not already been selected for execution, then
    00067         // attempt to select another thread for execution.
    00068         //
    00069
    00070         Thread = KeGetCurrentThread();
    00071         KiLockDispatcherDatabase(&Thread->WaitIrql);
    00072         Prcb = KeGetCurrentPrcb();
    00073         if (Prcb->NextThread == NULL) {
    00074             Prcb->NextThread = KiFindReadyThread(Thread->NextProcessor, 1);
    00075         }
    00076
    00077         //
    00078         // If a new thread has been selected for execution, then switch
    00079         // immediately to the selected thread.
    00080         //
    00081
    00082         if (Prcb->NextThread != NULL) {
    00083
    00084             //
    00085             // Give the current thread a new quantum, simulate a quantum
    00086             // end, insert the current thread in the appropriate ready list,
    00087             // and switch context to selected thread.
    00088             //
    00089
    00090             Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
    00091             Thread->State = Ready;
    00092             Priority = Thread->Priority;
    00093             if (Priority < LOW_REALTIME_PRIORITY) {
    00094                 Priority = Priority - Thread->PriorityDecrement - 1;
    00095                 if (Priority < Thread->BasePriority) {
    00096                     Priority = Thread->BasePriority;
    00097                 }
    00098
    00099                 Thread->PriorityDecrement = 0;
    00100
    00101             }
    00102
    00103             Thread->Priority = (SCHAR)Priority;
    00104
    00105             InsertTailList(&KiDispatcherReadyListHead[Priority],
    00106                            &Thread->WaitListEntry);
    00107
    00108             SetMember(Priority, KiReadySummary);
    00109             KiSwapThread();
    00110             Status = STATUS_SUCCESS;
    00111
    00112         } else {
    00113             KiUnlockDispatcherDatabase(Thread->WaitIrql);
    00114         }
    00115     }
    00116
    00117     return Status;
    00118 }