ReactOS  r76032
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 
17 VOID
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 
29 VOID
32  IN KWAIT_REASON WaitReason,
33  IN KPROCESSOR_MODE WaitMode)
34 {
35  KLOCK_QUEUE_HANDLE ApcLock;
37  PKWAIT_BLOCK GateWaitBlock;
39  PKQUEUE Queue;
40  ASSERT_GATE(Gate);
42 
43  /* Start wait loop */
44  do
45  {
46  /* Acquire the APC lock */
47  KiAcquireApcLock(Thread, &ApcLock);
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 */
64  KiAcquireThreadLock(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);
77  KiReleaseThreadLock(Thread);
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 */
107  KiSetThreadSwapBusy(Thread);
108 
109  /* Release the thread lock */
110  KiReleaseThreadLock(Thread);
111 
112  /* Check if we had a queue */
113  if (Queue)
114  {
115  /* Wake it up */
116  KiActivateWaiterQueue(Queue);
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 */
126  Status = KiSwapThread(Thread, KeGetCurrentPrcb());
127 
128  /* Make sure we weren't executing an APC */
129  if (Status == STATUS_SUCCESS) return;
130  }
131  } while (TRUE);
132 }
133 
134 VOID
135 FASTCALL
137 {
138  PKTHREAD WaitThread;
139  PKWAIT_BLOCK WaitBlock;
140  KIRQL OldIrql;
141  ASSERT_GATE(Gate);
143 
144  /* Start entry loop */
145  for (;;)
146  {
147  /* Raise to synch level */
148  OldIrql = KeRaiseIrqlToSynchLevel();
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,
167  KWAIT_BLOCK,
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 */
180  KeLowerIrql(OldIrql);
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 */
223  KiExitDispatcher(OldIrql);
224  return;
225  }
226  }
227 
228  /* If we got here, then there's no rescheduling. */
229  KiReleaseDispatcherObject(&Gate->Header);
230  KeLowerIrql(OldIrql);
231 }
232 
233 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:250
#define IN
Definition: typedefs.h:38
VOID FASTCALL KeSignalGateBoostPriority(IN PKGATE Gate)
Definition: gate.c:136
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
SHORT SpecialApcDisable
Definition: ketypes.h:1052
LIST_ENTRY WaitListEntry
Definition: ketypes.h:444
return STATUS_SUCCESS
Definition: btrfs.c:2664
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
VOID FASTCALL KeWaitForGate(IN PKGATE Gate, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode)
Definition: gate.c:31
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
struct _KTHREAD * Thread
Definition: ketypes.h:445
FORCEINLINE VOID KiAcquireApcLock(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:600
#define InsertTailList(ListHead, Entry)
FORCEINLINE VOID KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:627
#define FASTCALL
Definition: nt_native.h:50
FORCEINLINE BOOLEAN KiTryThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:254
#define ASSERT_GATE(Object)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
KAPC_STATE ApcState
Definition: ketypes.h:969
FORCEINLINE VOID KiReleaseApcLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:635
struct _KGATE KGATE
UCHAR WaitReason
Definition: ketypes.h:1249
VOID FASTCALL KiExitDispatcher(KIRQL OldIrql)
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:429
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
FORCEINLINE VOID KiAcquireDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:127
volatile ULONG DeferredProcessor
Definition: ketypes.h:978
PVOID Object
Definition: ketypes.h:446
FORCEINLINE VOID KiReleaseDispatcherObject(IN DISPATCHER_HEADER *Object)
Definition: ke_x.h:137
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
PKQUEUE Queue
Definition: ketypes.h:1044
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Status
Definition: gdiplustypes.h:24
LONG_PTR WaitStatus
Definition: ketypes.h:1002
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: thrdschd.c:355
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
volatile ULONG CurrentCount
Definition: ketypes.h:1267
VOID FASTCALL KeInitializeGate(IN PKGATE Gate)
Definition: gate.c:19
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
VOID FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue)
Definition: queue.c:24
FORCEINLINE VOID KiReleaseDispatcherLockFromDpcLevel(VOID)
Definition: ke_x.h:168
enum _KWAIT_REASON KWAIT_REASON
volatile UCHAR State
Definition: ketypes.h:997
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:259
KPROCESSOR_MODE WaitMode
Definition: ketypes.h:1000
#define KeGetCurrentThread
Definition: hal.h:44
#define APC_LEVEL
Definition: env_spec_w32.h:695
FORCEINLINE VOID KiAcquireDispatcherLockAtDpcLevel(VOID)
Definition: ke_x.h:160
KIRQL WaitIrql
Definition: ketypes.h:999
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156