ReactOS 0.4.16-dev-117-g38f21f9
gate.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/gate.c
5 * PURPOSE: Implements the Gate Dispatcher Object
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* FUNCTIONS ****************************************************************/
16
17VOID
20{
21 /* Initialize the Dispatcher Header */
22 Gate->Header.Type = GateObject;
23 Gate->Header.Signalling = FALSE;
24 Gate->Header.Size = sizeof(KGATE) / sizeof(ULONG);
25 Gate->Header.SignalState = 0;
26 InitializeListHead(&(Gate->Header.WaitListHead));
27}
28
29VOID
32 IN KWAIT_REASON WaitReason,
33 IN KPROCESSOR_MODE WaitMode)
34{
35 KLOCK_QUEUE_HANDLE ApcLock;
37 PKWAIT_BLOCK GateWaitBlock;
40 ASSERT_GATE(Gate);
42
43 /* Start wait loop */
44 do
45 {
46 /* Acquire the APC lock */
48
49 /* Check if a kernel APC is pending and we're below APC_LEVEL */
50 if ((Thread->ApcState.KernelApcPending) &&
51 !(Thread->SpecialApcDisable) &&
52 (ApcLock.OldIrql < APC_LEVEL))
53 {
54 /* Release the lock, this will fire the APC */
55 KiReleaseApcLock(&ApcLock);
56 }
57 else
58 {
59 /* Check if we have a queue and lock the dispatcher if so */
60 Queue = Thread->Queue;
62
63 /* Lock the thread */
65
66 /* Lock the gate */
67 KiAcquireDispatcherObject(&Gate->Header);
68
69 /* Check if it's already signaled */
70 if (Gate->Header.SignalState)
71 {
72 /* Unsignal it */
73 Gate->Header.SignalState = 0;
74
75 /* Release the gate and thread locks */
76 KiReleaseDispatcherObject(&Gate->Header);
78
79 /* Release the gate lock */
81
82 /* Release the APC lock and return */
83 KiReleaseApcLock(&ApcLock);
84 break;
85 }
86
87 /* Setup a Wait Block */
88 GateWaitBlock = &Thread->WaitBlock[0];
89 GateWaitBlock->Object = (PVOID)Gate;
90 GateWaitBlock->Thread = Thread;
91
92 /* Set the Thread Wait Data */
93 Thread->WaitMode = WaitMode;
94 Thread->WaitReason = WaitReason;
95 Thread->WaitIrql = ApcLock.OldIrql;
96 Thread->State = GateWait;
97 Thread->GateObject = Gate;
98
99 /* Insert into the Wait List */
100 InsertTailList(&Gate->Header.WaitListHead,
101 &GateWaitBlock->WaitListEntry);
102
103 /* Release the gate lock */
104 KiReleaseDispatcherObject(&Gate->Header);
105
106 /* Set swap busy */
108
109 /* Release the thread lock */
111
112 /* Check if we had a queue */
113 if (Queue)
114 {
115 /* Wake it up */
117
118 /* Release the dispatcher lock */
120 }
121
122 /* Release the APC lock but stay at DPC level */
124
125 /* Find a new thread to run */
127
128 /* Make sure we weren't executing an APC */
129 if (Status == STATUS_SUCCESS) return;
130 }
131 } while (TRUE);
132}
133
134VOID
137{
138 PKTHREAD WaitThread;
139 PKWAIT_BLOCK WaitBlock;
141 ASSERT_GATE(Gate);
143
144 /* Start entry loop */
145 for (;;)
146 {
147 /* Raise to synch level */
149
150 /* Lock the gate */
151 KiAcquireDispatcherObject(&Gate->Header);
152
153 /* Make sure we're not already signaled or that the list is empty */
154 if (Gate->Header.SignalState) break;
155
156 /* Check if our wait list is empty */
157 if (IsListEmpty(&Gate->Header.WaitListHead))
158 {
159 /* It is, so signal the event */
160 Gate->Header.SignalState = 1;
161 break;
162 }
163 else
164 {
165 /* Get WaitBlock */
166 WaitBlock = CONTAINING_RECORD(Gate->Header.WaitListHead.Flink,
168 WaitListEntry);
169
170 /* Get the Associated thread */
171 WaitThread = WaitBlock->Thread;
172
173 /* Check to see if the waiting thread is locked */
174 if (KiTryThreadLock(WaitThread))
175 {
176 /* Unlock the gate */
177 KiReleaseDispatcherObject(&Gate->Header);
178
179 /* Lower IRQL and loop again */
181 continue;
182 }
183
184 /* Remove it */
185 RemoveEntryList(&WaitBlock->WaitListEntry);
186
187 /* Clear wait status */
188 WaitThread->WaitStatus = STATUS_SUCCESS;
189
190 /* Set state and CPU */
191 WaitThread->State = DeferredReady;
192 WaitThread->DeferredProcessor = KeGetCurrentPrcb()->Number;
193
194 /* Release the gate lock */
195 KiReleaseDispatcherObject(&Gate->Header);
196
197 /* Release the thread lock */
198 KiReleaseThreadLock(WaitThread);
199
200 /* FIXME: Boosting */
201
202 /* Check if we have a queue */
203 if (WaitThread->Queue)
204 {
205 /* Acquire the dispatcher lock */
207
208 /* Check if we still have one */
209 if (WaitThread->Queue)
210 {
211 /* Increment active threads */
212 WaitThread->Queue->CurrentCount++;
213 }
214
215 /* Release lock */
217 }
218
219 /* Make the thread ready */
220 KiReadyThread(WaitThread);
221
222 /* Exit the dispatcher */
224 return;
225 }
226 }
227
228 /* If we got here, then there's no rescheduling. */
229 KiReleaseDispatcherObject(&Gate->Header);
231}
232
233/* EOF */
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL KeSignalGateBoostPriority(IN PKGATE Gate)
Definition: gate.c:136
VOID FASTCALL KeWaitForGate(IN PKGATE Gate, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode)
Definition: gate.c:31
VOID FASTCALL KeInitializeGate(IN PKGATE Gate)
Definition: gate.c:19
Status
Definition: gdiplustypes.h:25
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156
#define KeGetCurrentThread
Definition: hal.h:55
FORCEINLINE VOID KiAcquireApcLockRaiseToSynch(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:607
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:210
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:240
FORCEINLINE VOID KiReleaseDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:142
FORCEINLINE VOID KiAcquireDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:132
FORCEINLINE VOID KiReleaseDispatcherLockFromSynchLevel(VOID)
Definition: ke_x.h:174
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:250
FORCEINLINE VOID KiAcquireDispatcherLockAtSynchLevel(VOID)
Definition: ke_x.h:165
FORCEINLINE VOID KiReleaseApcLockFromSynchLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:643
FORCEINLINE VOID KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:635
FORCEINLINE BOOLEAN KiTryThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:260
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
@ GateObject
Definition: ketypes.h:413
@ GateWait
Definition: ketypes.h:397
@ DeferredReady
Definition: ketypes.h:395
#define FASTCALL
Definition: nt_native.h:50
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:429
LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: thrdschd.c:355
VOID FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue)
Definition: queue.c:24
VOID FASTCALL KiExitDispatcher(KIRQL OldIrql)
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
#define STATUS_SUCCESS
Definition: shellext.h:65
volatile ULONG CurrentCount
Definition: ketypes.h:1418
PKQUEUE Queue
Definition: ketypes.h:1806
volatile INT_PTR WaitStatus
Definition: ketypes.h:1799
ULONG DeferredProcessor
Definition: ketypes.h:1906
volatile UCHAR State
Definition: ketypes.h:1789
struct _KTHREAD * Thread
Definition: ketypes.h:465
PVOID Object
Definition: ketypes.h:468
LIST_ENTRY WaitListEntry
Definition: ketypes.h:456
void * PVOID
Definition: typedefs.h:50
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2225
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
struct _KGATE KGATE
#define ASSERT_GATE(Object)
enum _KWAIT_REASON KWAIT_REASON