Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengate.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ke/gate.c 00005 * PURPOSE: Implements the Gate Dispatcher Object 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* FUNCTIONS ****************************************************************/ 00016 00017 VOID 00018 FASTCALL 00019 KeInitializeGate(IN PKGATE Gate) 00020 { 00021 /* Initialize the Dispatcher Header */ 00022 Gate->Header.Type = GateObject; 00023 Gate->Header.Signalling = FALSE; 00024 Gate->Header.Size = sizeof(KGATE) / sizeof(ULONG); 00025 Gate->Header.SignalState = 0; 00026 InitializeListHead(&(Gate->Header.WaitListHead)); 00027 } 00028 00029 VOID 00030 FASTCALL 00031 KeWaitForGate(IN PKGATE Gate, 00032 IN KWAIT_REASON WaitReason, 00033 IN KPROCESSOR_MODE WaitMode) 00034 { 00035 KLOCK_QUEUE_HANDLE ApcLock; 00036 PKTHREAD Thread = KeGetCurrentThread(); 00037 PKWAIT_BLOCK GateWaitBlock; 00038 LONG_PTR Status; 00039 PKQUEUE Queue; 00040 ASSERT_GATE(Gate); 00041 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); 00042 00043 /* Start wait loop */ 00044 do 00045 { 00046 /* Acquire the APC lock */ 00047 KiAcquireApcLock(Thread, &ApcLock); 00048 00049 /* Check if a kernel APC is pending and we're below APC_LEVEL */ 00050 if ((Thread->ApcState.KernelApcPending) && 00051 !(Thread->SpecialApcDisable) && 00052 (ApcLock.OldIrql < APC_LEVEL)) 00053 { 00054 /* Release the lock, this will fire the APC */ 00055 KiReleaseApcLock(&ApcLock); 00056 } 00057 else 00058 { 00059 /* Check if we have a queue and lock the dispatcher if so */ 00060 Queue = Thread->Queue; 00061 if (Queue) KiAcquireDispatcherLockAtDpcLevel(); 00062 00063 /* Lock the thread */ 00064 KiAcquireThreadLock(Thread); 00065 00066 /* Lock the gate */ 00067 KiAcquireDispatcherObject(&Gate->Header); 00068 00069 /* Check if it's already signaled */ 00070 if (Gate->Header.SignalState) 00071 { 00072 /* Unsignal it */ 00073 Gate->Header.SignalState = 0; 00074 00075 /* Release the gate and thread locks */ 00076 KiReleaseDispatcherObject(&Gate->Header); 00077 KiReleaseThreadLock(Thread); 00078 00079 /* Release the gate lock */ 00080 if (Queue) KiReleaseDispatcherLockFromDpcLevel(); 00081 00082 /* Release the APC lock and return */ 00083 KiReleaseApcLock(&ApcLock); 00084 break; 00085 } 00086 00087 /* Setup a Wait Block */ 00088 GateWaitBlock = &Thread->WaitBlock[0]; 00089 GateWaitBlock->Object = (PVOID)Gate; 00090 GateWaitBlock->Thread = Thread; 00091 00092 /* Set the Thread Wait Data */ 00093 Thread->WaitMode = WaitMode; 00094 Thread->WaitReason = WaitReason; 00095 Thread->WaitIrql = ApcLock.OldIrql; 00096 Thread->State = GateWait; 00097 Thread->GateObject = Gate; 00098 00099 /* Insert into the Wait List */ 00100 InsertTailList(&Gate->Header.WaitListHead, 00101 &GateWaitBlock->WaitListEntry); 00102 00103 /* Release the gate lock */ 00104 KiReleaseDispatcherObject(&Gate->Header); 00105 00106 /* Set swap busy */ 00107 KiSetThreadSwapBusy(Thread); 00108 00109 /* Release the thread lock */ 00110 KiReleaseThreadLock(Thread); 00111 00112 /* Check if we had a queue */ 00113 if (Queue) 00114 { 00115 /* Wake it up */ 00116 KiActivateWaiterQueue(Queue); 00117 00118 /* Release the dispatcher lock */ 00119 KiReleaseDispatcherLockFromDpcLevel(); 00120 } 00121 00122 /* Release the APC lock but stay at DPC level */ 00123 KiReleaseApcLockFromDpcLevel(&ApcLock); 00124 00125 /* Find a new thread to run */ 00126 Status = KiSwapThread(Thread, KeGetCurrentPrcb()); 00127 00128 /* Make sure we weren't executing an APC */ 00129 if (Status == STATUS_SUCCESS) return; 00130 } 00131 } while (TRUE); 00132 } 00133 00134 VOID 00135 FASTCALL 00136 KeSignalGateBoostPriority(IN PKGATE Gate) 00137 { 00138 PKTHREAD WaitThread; 00139 PKWAIT_BLOCK WaitBlock; 00140 KIRQL OldIrql; 00141 ASSERT_GATE(Gate); 00142 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); 00143 00144 /* Start entry loop */ 00145 for (;;) 00146 { 00147 /* Raise to synch level */ 00148 OldIrql = KeRaiseIrqlToSynchLevel(); 00149 00150 /* Lock the gate */ 00151 KiAcquireDispatcherObject(&Gate->Header); 00152 00153 /* Make sure we're not already signaled or that the list is empty */ 00154 if (Gate->Header.SignalState) break; 00155 00156 /* Check if our wait list is empty */ 00157 if (IsListEmpty(&Gate->Header.WaitListHead)) 00158 { 00159 /* It is, so signal the event */ 00160 Gate->Header.SignalState = 1; 00161 break; 00162 } 00163 else 00164 { 00165 /* Get WaitBlock */ 00166 WaitBlock = CONTAINING_RECORD(Gate->Header.WaitListHead.Flink, 00167 KWAIT_BLOCK, 00168 WaitListEntry); 00169 00170 /* Get the Associated thread */ 00171 WaitThread = WaitBlock->Thread; 00172 00173 /* Check to see if the waiting thread is locked */ 00174 if (KiTryThreadLock(WaitThread)) 00175 { 00176 /* Unlock the gate */ 00177 KiReleaseDispatcherObject(&Gate->Header); 00178 00179 /* Lower IRQL and loop again */ 00180 KeLowerIrql(OldIrql); 00181 continue; 00182 } 00183 00184 /* Remove it */ 00185 RemoveEntryList(&WaitBlock->WaitListEntry); 00186 00187 /* Clear wait status */ 00188 WaitThread->WaitStatus = STATUS_SUCCESS; 00189 00190 /* Set state and CPU */ 00191 WaitThread->State = DeferredReady; 00192 WaitThread->DeferredProcessor = KeGetCurrentPrcb()->Number; 00193 00194 /* Release the gate lock */ 00195 KiReleaseDispatcherObject(&Gate->Header); 00196 00197 /* Release the thread lock */ 00198 KiReleaseThreadLock(WaitThread); 00199 00200 /* FIXME: Boosting */ 00201 00202 /* Check if we have a queue */ 00203 if (WaitThread->Queue) 00204 { 00205 /* Acquire the dispatcher lock */ 00206 KiAcquireDispatcherLockAtDpcLevel(); 00207 00208 /* Check if we still have one */ 00209 if (WaitThread->Queue) 00210 { 00211 /* Increment active threads */ 00212 WaitThread->Queue->CurrentCount++; 00213 } 00214 00215 /* Release lock */ 00216 KiReleaseDispatcherLockFromDpcLevel(); 00217 } 00218 00219 /* Make the thread ready */ 00220 KiReadyThread(WaitThread); 00221 00222 /* Exit the dispatcher */ 00223 KiExitDispatcher(OldIrql); 00224 return; 00225 } 00226 } 00227 00228 /* If we got here, then there's no rescheduling. */ 00229 KiReleaseDispatcherObject(&Gate->Header); 00230 KeLowerIrql(OldIrql); 00231 } 00232 00233 /* EOF */ Generated on Sat May 26 2012 04:36:19 for ReactOS by
1.7.6.1
|