- Cleanup + formatting fixes for wait.c
[reactos.git] / reactos / ntoskrnl / include / internal / ke_x.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/ke_x.h
5 * PURPOSE: Internal Inlined Functions for the Kernel
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 //
10 // Enters a Critical Region
11 //
12 #define KeEnterGuardedRegion() \
13 { \
14 PKTHREAD Thread = KeGetCurrentThread(); \
15 \
16 /* Sanity checks */ \
17 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
18 ASSERT(Thread == KeGetCurrentThread()); \
19 ASSERT((Thread->SpecialApcDisable <= 0) && \
20 (Thread->SpecialApcDisable != -32768)); \
21 \
22 /* Disable Special APCs */ \
23 Thread->SpecialApcDisable--; \
24 }
25
26 //
27 // Leaves a Critical Region
28 //
29 #define KeLeaveGuardedRegion() \
30 { \
31 PKTHREAD Thread = KeGetCurrentThread(); \
32 \
33 /* Sanity checks */ \
34 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
35 ASSERT(Thread == KeGetCurrentThread()); \
36 ASSERT(Thread->SpecialApcDisable < 0); \
37 \
38 /* Leave region and check if APCs are OK now */ \
39 if (!(++Thread->SpecialApcDisable)) \
40 { \
41 /* Check for Kernel APCs on the list */ \
42 if (!IsListEmpty(&Thread->ApcState. \
43 ApcListHead[KernelMode])) \
44 { \
45 /* Check for APC Delivery */ \
46 KiCheckForKernelApcDelivery(); \
47 } \
48 } \
49 }
50
51 //
52 // TODO: Guarded Mutex Routines
53 //
54
55 //
56 // TODO: Critical Region Routines
57 //
58
59 //
60 // Satisfies the wait of any dispatcher object
61 //
62 #define KiSatisfyObjectWait(Object, Thread) \
63 { \
64 /* Special case for Mutants */ \
65 if ((Object)->Header.Type == MutantObject) \
66 { \
67 /* Decrease the Signal State */ \
68 (Object)->Header.SignalState--; \
69 \
70 /* Check if it's now non-signaled */ \
71 if (!(Object)->Header.SignalState) \
72 { \
73 /* Set the Owner Thread */ \
74 (Object)->OwnerThread = Thread; \
75 \
76 /* Disable APCs if needed */ \
77 Thread->KernelApcDisable -= (Object)->ApcDisable; \
78 \
79 /* Check if it's abandoned */ \
80 if ((Object)->Abandoned) \
81 { \
82 /* Unabandon it */ \
83 (Object)->Abandoned = FALSE; \
84 \
85 /* Return Status */ \
86 Thread->WaitStatus = STATUS_ABANDONED; \
87 } \
88 \
89 /* Insert it into the Mutant List */ \
90 InsertHeadList(&Thread->MutantListHead, \
91 &(Object)->MutantListEntry); \
92 } \
93 } \
94 else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
95 EventSynchronizationObject) \
96 { \
97 /* Synchronization Timers and Events just get un-signaled */ \
98 (Object)->Header.SignalState = 0; \
99 } \
100 else if ((Object)->Header.Type == SemaphoreObject) \
101 { \
102 /* These ones can have multiple states, so we only decrease it */ \
103 (Object)->Header.SignalState--; \
104 } \
105 }
106
107 //
108 // Satisfies the wait of a mutant dispatcher object
109 //
110 #define KiSatisfyMutantWait(Object, Thread) \
111 { \
112 /* Decrease the Signal State */ \
113 (Object)->Header.SignalState--; \
114 \
115 /* Check if it's now non-signaled */ \
116 if (!(Object)->Header.SignalState) \
117 { \
118 /* Set the Owner Thread */ \
119 (Object)->OwnerThread = Thread; \
120 \
121 /* Disable APCs if needed */ \
122 Thread->KernelApcDisable -= (Object)->ApcDisable; \
123 \
124 /* Check if it's abandoned */ \
125 if ((Object)->Abandoned) \
126 { \
127 /* Unabandon it */ \
128 (Object)->Abandoned = FALSE; \
129 \
130 /* Return Status */ \
131 Thread->WaitStatus = STATUS_ABANDONED; \
132 } \
133 \
134 /* Insert it into the Mutant List */ \
135 InsertHeadList(&Thread->MutantListHead, \
136 &(Object)->MutantListEntry); \
137 } \
138 }
139
140 //
141 // Satisfies the wait of any nonmutant dispatcher object
142 //
143 #define KiSatisfyNonMutantWait(Object, Thread) \
144 { \
145 if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
146 EventSynchronizationObject) \
147 { \
148 /* Synchronization Timers and Events just get un-signaled */ \
149 (Object)->Header.SignalState = 0; \
150 } \
151 else if ((Object)->Header.Type == SemaphoreObject) \
152 { \
153 /* These ones can have multiple states, so we only decrease it */ \
154 (Object)->Header.SignalState--; \
155 } \
156 }
157
158 //
159 // Rules for checking alertability:
160 // - For Alertable waits ONLY:
161 // * We don't wait and return STATUS_ALERTED if the thread is alerted
162 // in EITHER the specified wait mode OR in Kernel Mode.
163 // - For BOTH Alertable AND Non-Alertable waits:
164 // * We don't want and return STATUS_USER_APC if the User Mode APC list
165 // is not empty AND the wait mode is User Mode.
166 //
167 #define KiCheckAlertability() \
168 { \
169 if (Alertable) \
170 { \
171 if (CurrentThread->Alerted[(int)WaitMode]) \
172 { \
173 CurrentThread->Alerted[(int)WaitMode] = FALSE; \
174 WaitStatus = STATUS_ALERTED; \
175 break; \
176 } \
177 else if ((WaitMode != KernelMode) && \
178 (!IsListEmpty(&CurrentThread-> \
179 ApcState.ApcListHead[UserMode]))) \
180 { \
181 CurrentThread->ApcState.UserApcPending = TRUE; \
182 WaitStatus = STATUS_USER_APC; \
183 break; \
184 } \
185 else if (CurrentThread->Alerted[KernelMode]) \
186 { \
187 CurrentThread->Alerted[KernelMode] = FALSE; \
188 WaitStatus = STATUS_ALERTED; \
189 break; \
190 } \
191 } \
192 else if ((WaitMode != KernelMode) && \
193 (CurrentThread->ApcState.UserApcPending)) \
194 { \
195 WaitStatus = STATUS_USER_APC; \
196 break; \
197 } \
198 }