ReactOS 0.4.15-dev-7704-gc07eb9f
eventobj.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/eventobj.c
5 * PURPOSE: Implements the Event 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/*
18 * @implemented
19 */
20VOID
23{
25
26 /* Reset Signal State */
27 Event->Header.SignalState = FALSE;
28}
29
30/*
31 * @implemented
32 */
33VOID
38{
39 /* Initialize the Dispatcher Header */
40 Event->Header.Type = Type;
41 //Event->Header.Signalling = FALSE; // fails in kmtest
42 Event->Header.Size = sizeof(KEVENT) / sizeof(ULONG);
43 Event->Header.SignalState = State;
44 InitializeListHead(&(Event->Header.WaitListHead));
45}
46
47/*
48 * @implemented
49 */
50VOID
53{
54 /* Initialize the Event Pair Type and Size */
55 EventPair->Type = EventPairObject;
56 EventPair->Size = sizeof(KEVENT_PAIR);
57
58 /* Initialize the two Events */
59 KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
60 KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
61}
62
63/*
64 * @implemented
65 */
66LONG
71{
77
78 /* Lock the Dispatcher Database */
80
81 /* Save the Old State */
82 PreviousState = Event->Header.SignalState;
83
84 /* Check if we are non-signaled and we have stuff in the Wait Queue */
85 if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead))
86 {
87 /* Set the Event to Signaled */
88 Event->Header.SignalState = 1;
89
90 /* Wake the Event */
91 KiWaitTest(&Event->Header, Increment);
92 }
93
94 /* Unsignal it */
95 Event->Header.SignalState = 0;
96
97 /* Check what wait state was requested */
98 if (Wait == FALSE)
99 {
100 /* Wait not requested, release Dispatcher Database and return */
102 }
103 else
104 {
105 /* Return Locked and with a Wait */
107 Thread->WaitNext = TRUE;
108 Thread->WaitIrql = OldIrql;
109 }
110
111 /* Return the previous State */
112 return PreviousState;
113}
114
115/*
116 * @implemented
117 */
118LONG
119NTAPI
121{
123
124 /* Return the Signal State */
125 return Event->Header.SignalState;
126}
127
128/*
129 * @implemented
130 */
131LONG
132NTAPI
134{
139
140 /* Lock the Dispatcher Database */
142
143 /* Save the Previous State */
144 PreviousState = Event->Header.SignalState;
145
146 /* Set it to zero */
147 Event->Header.SignalState = 0;
148
149 /* Release Dispatcher Database and return previous state */
151 return PreviousState;
152}
153
154/*
155 * @implemented
156 */
157LONG
158NTAPI
162{
168
169 /*
170 * Check if this is an signaled notification event without an upcoming wait.
171 * In this case, we can immediately return TRUE, without locking.
172 */
173 if ((Event->Header.Type == EventNotificationObject) &&
174 (Event->Header.SignalState == 1) &&
175 !(Wait))
176 {
177 /* Return the signal state (TRUE/Signalled) */
178 return TRUE;
179 }
180
181 /* Lock the Dispathcer Database */
183
184 /* Save the Previous State */
185 PreviousState = Event->Header.SignalState;
186
187 /* Set the Event to Signaled */
188 Event->Header.SignalState = 1;
189
190 /* Check if the event just became signaled now, and it has waiters */
191 if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))
192 {
193 /* Check the type of event */
194 if (Event->Header.Type == EventNotificationObject)
195 {
196 /* Unwait the thread */
197 KxUnwaitThread(&Event->Header, Increment);
198 }
199 else
200 {
201 /* Otherwise unwait the thread and unsignal the event */
203 }
204 }
205
206 /* Check what wait state was requested */
207 if (!Wait)
208 {
209 /* Wait not requested, release Dispatcher Database and return */
211 }
212 else
213 {
214 /* Return Locked and with a Wait */
216 Thread->WaitNext = TRUE;
217 Thread->WaitIrql = OldIrql;
218 }
219
220 /* Return the previous State */
221 return PreviousState;
222}
223
224/*
225 * @implemented
226 */
227VOID
228NTAPI
230 IN PKTHREAD *WaitingThread OPTIONAL)
231{
233 PKWAIT_BLOCK WaitBlock;
234 PKTHREAD Thread = KeGetCurrentThread(), WaitThread;
235 ASSERT(Event->Header.Type == EventSynchronizationObject);
237
238 /* Acquire Dispatcher Database Lock */
240
241 /* Check if the list is empty */
242 if (IsListEmpty(&Event->Header.WaitListHead))
243 {
244 /* Set the Event to Signaled */
245 Event->Header.SignalState = 1;
246
247 /* Return */
249 return;
250 }
251
252 /* Get the Wait Block */
253 WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
255 WaitListEntry);
256
257 /* Check if this is a WaitAll */
258 if (WaitBlock->WaitType == WaitAll)
259 {
260 /* Set the Event to Signaled */
261 Event->Header.SignalState = 1;
262
263 /* Unwait the thread and unsignal the event */
265 }
266 else
267 {
268 /* Return waiting thread to caller */
269 WaitThread = WaitBlock->Thread;
270 if (WaitingThread) *WaitingThread = WaitThread;
271
272 /* Calculate new priority */
273 Thread->Priority = KiComputeNewPriority(Thread, 0);
274
275 /* Unlink the waiting thread */
276 KiUnlinkThread(WaitThread, STATUS_SUCCESS);
277
278 /* Request priority boosting */
279 WaitThread->AdjustIncrement = Thread->Priority;
280 WaitThread->AdjustReason = AdjustBoost;
281
282 /* Ready the thread */
283 KiReadyThread(WaitThread);
284 }
285
286 /* Release the Dispatcher Database Lock */
288}
289
290/* EOF */
unsigned char BOOLEAN
Type
Definition: Type.h:7
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG KPRIORITY
Definition: compat.h:803
#define KEVENT
Definition: env_spec_w32.h:69
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG NTAPI KePulseEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:68
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI KeSetEventBoostPriority(IN PKEVENT Event, IN PKTHREAD *WaitingThread OPTIONAL)
Definition: eventobj.c:229
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
VOID NTAPI KeInitializeEventPair(IN PKEVENT_PAIR EventPair)
Definition: eventobj.c:52
LONG NTAPI KeResetEvent(IN PKEVENT Event)
Definition: eventobj.c:133
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define KeGetCurrentThread
Definition: hal.h:55
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1259
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1472
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1304
#define ASSERT(a)
Definition: mode.c:44
@ EventSynchronizationObject
Definition: ketypes.h:407
@ EventNotificationObject
Definition: ketypes.h:406
@ EventPairObject
Definition: ketypes.h:427
struct _KEVENT_PAIR KEVENT_PAIR
@ AdjustBoost
Definition: ketypes.h:441
@ SynchronizationEvent
@ WaitAll
enum _EVENT_TYPE EVENT_TYPE
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:429
VOID FASTCALL KiUnlinkThread(IN PKTHREAD Thread, IN LONG_PTR WaitStatus)
Definition: wait.c:55
VOID FASTCALL KiWaitTest(PVOID Object, KPRIORITY Increment)
long LONG
Definition: pedump.c:60
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct _KTHREAD * Thread
Definition: ketypes.h:465
UCHAR WaitType
Definition: ketypes.h:458
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define EVENT_INCREMENT
Definition: iotypes.h:597
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define ASSERT_EVENT(Object)