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 }