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)
10 // Enters a Critical Region
12 #define KeEnterGuardedRegion() \
14 PKTHREAD Thread = KeGetCurrentThread(); \
17 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
18 ASSERT(Thread == KeGetCurrentThread()); \
19 ASSERT((Thread->SpecialApcDisable <= 0) && \
20 (Thread->SpecialApcDisable != -32768)); \
22 /* Disable Special APCs */ \
23 Thread->SpecialApcDisable--; \
27 // Leaves a Critical Region
29 #define KeLeaveGuardedRegion() \
31 PKTHREAD Thread = KeGetCurrentThread(); \
34 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
35 ASSERT(Thread == KeGetCurrentThread()); \
36 ASSERT(Thread->SpecialApcDisable < 0); \
38 /* Leave region and check if APCs are OK now */ \
39 if (!(++Thread->SpecialApcDisable)) \
41 /* Check for Kernel APCs on the list */ \
42 if (!IsListEmpty(&Thread->ApcState. \
43 ApcListHead[KernelMode])) \
45 /* Check for APC Delivery */ \
46 KiCheckForKernelApcDelivery(); \
52 // TODO: Guarded Mutex Routines
56 // TODO: Critical Region Routines
60 // Satisfies the wait of any dispatcher object
62 #define KiSatisfyObjectWait(Object, Thread) \
64 /* Special case for Mutants */ \
65 if ((Object)->Header.Type == MutantObject) \
67 /* Decrease the Signal State */ \
68 (Object)->Header.SignalState--; \
70 /* Check if it's now non-signaled */ \
71 if (!(Object)->Header.SignalState) \
73 /* Set the Owner Thread */ \
74 (Object)->OwnerThread = Thread; \
76 /* Disable APCs if needed */ \
77 Thread->KernelApcDisable -= (Object)->ApcDisable; \
79 /* Check if it's abandoned */ \
80 if ((Object)->Abandoned) \
83 (Object)->Abandoned = FALSE; \
86 Thread->WaitStatus = STATUS_ABANDONED; \
89 /* Insert it into the Mutant List */ \
90 InsertHeadList(&Thread->MutantListHead, \
91 &(Object)->MutantListEntry); \
94 else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
95 EventSynchronizationObject) \
97 /* Synchronization Timers and Events just get un-signaled */ \
98 (Object)->Header.SignalState = 0; \
100 else if ((Object)->Header.Type == SemaphoreObject) \
102 /* These ones can have multiple states, so we only decrease it */ \
103 (Object)->Header.SignalState--; \
108 // Satisfies the wait of a mutant dispatcher object
110 #define KiSatisfyMutantWait(Object, Thread) \
112 /* Decrease the Signal State */ \
113 (Object)->Header.SignalState--; \
115 /* Check if it's now non-signaled */ \
116 if (!(Object)->Header.SignalState) \
118 /* Set the Owner Thread */ \
119 (Object)->OwnerThread = Thread; \
121 /* Disable APCs if needed */ \
122 Thread->KernelApcDisable -= (Object)->ApcDisable; \
124 /* Check if it's abandoned */ \
125 if ((Object)->Abandoned) \
128 (Object)->Abandoned = FALSE; \
130 /* Return Status */ \
131 Thread->WaitStatus = STATUS_ABANDONED; \
134 /* Insert it into the Mutant List */ \
135 InsertHeadList(&Thread->MutantListHead, \
136 &(Object)->MutantListEntry); \
141 // Satisfies the wait of any nonmutant dispatcher object
143 #define KiSatisfyNonMutantWait(Object, Thread) \
145 if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
146 EventSynchronizationObject) \
148 /* Synchronization Timers and Events just get un-signaled */ \
149 (Object)->Header.SignalState = 0; \
151 else if ((Object)->Header.Type == SemaphoreObject) \
153 /* These ones can have multiple states, so we only decrease it */ \
154 (Object)->Header.SignalState--; \
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.
167 #define KiCheckAlertability() \
171 if (CurrentThread->Alerted[(int)WaitMode]) \
173 CurrentThread->Alerted[(int)WaitMode] = FALSE; \
174 WaitStatus = STATUS_ALERTED; \
177 else if ((WaitMode != KernelMode) && \
178 (!IsListEmpty(&CurrentThread-> \
179 ApcState.ApcListHead[UserMode]))) \
181 CurrentThread->ApcState.UserApcPending = TRUE; \
182 WaitStatus = STATUS_USER_APC; \
185 else if (CurrentThread->Alerted[KernelMode]) \
187 CurrentThread->Alerted[KernelMode] = FALSE; \
188 WaitStatus = STATUS_ALERTED; \
192 else if ((WaitMode != KernelMode) && \
193 (CurrentThread->ApcState.UserApcPending)) \
195 WaitStatus = STATUS_USER_APC; \