ReactOS 0.4.16-dev-1946-g52006dd
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 */
41 Event->Header.Type = EventNotificationObject + Type;
42 //Event->Header.Signalling = FALSE; // fails in kmtest
43 Event->Header.Size = sizeof(KEVENT) / sizeof(ULONG);
44 Event->Header.SignalState = State;
45 InitializeListHead(&(Event->Header.WaitListHead));
46}
47
48/*
49 * @implemented
50 */
51VOID
54{
55 /* Initialize the Event Pair Type and Size */
56 EventPair->Type = EventPairObject;
57 EventPair->Size = sizeof(KEVENT_PAIR);
58
59 /* Initialize the two Events */
60 KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
61 KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
62}
63
64/*
65 * @implemented
66 */
67LONG
72{
78
79 /* Lock the Dispatcher Database */
81
82 /* Save the Old State */
83 PreviousState = Event->Header.SignalState;
84
85 /* Check if we are non-signaled and we have stuff in the Wait Queue */
86 if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead))
87 {
88 /* Set the Event to Signaled */
89 Event->Header.SignalState = 1;
90
91 /* Wake the Event */
92 KiWaitTest(&Event->Header, Increment);
93 }
94
95 /* Unsignal it */
96 Event->Header.SignalState = 0;
97
98 /* Check what wait state was requested */
99 if (Wait == FALSE)
100 {
101 /* Wait not requested, release Dispatcher Database and return */
103 }
104 else
105 {
106 /* Return Locked and with a Wait */
108 Thread->WaitNext = TRUE;
109 Thread->WaitIrql = OldIrql;
110 }
111
112 /* Return the previous State */
113 return PreviousState;
114}
115
116/*
117 * @implemented
118 */
119LONG
120NTAPI
122{
124
125 /* Return the Signal State */
126 return Event->Header.SignalState;
127}
128
129/*
130 * @implemented
131 */
132LONG
133NTAPI
135{
140
141 /* Lock the Dispatcher Database */
143
144 /* Save the Previous State */
145 PreviousState = Event->Header.SignalState;
146
147 /* Set it to zero */
148 Event->Header.SignalState = 0;
149
150 /* Release Dispatcher Database and return previous state */
152 return PreviousState;
153}
154
155/*
156 * @implemented
157 */
158LONG
159NTAPI
163{
169
170 /*
171 * Check if this is an signaled notification event without an upcoming wait.
172 * In this case, we can immediately return TRUE, without locking.
173 */
174 if ((Event->Header.Type == EventNotificationObject) &&
175 (Event->Header.SignalState == 1) &&
176 !(Wait))
177 {
178 /* Return the signal state (TRUE/Signalled) */
179 return TRUE;
180 }
181
182 /* Lock the Dispathcer Database */
184
185 /* Save the Previous State */
186 PreviousState = Event->Header.SignalState;
187
188 /* Set the Event to Signaled */
189 Event->Header.SignalState = 1;
190
191 /* Check if the event just became signaled now, and it has waiters */
192 if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))
193 {
194 /* Check the type of event */
195 if (Event->Header.Type == EventNotificationObject)
196 {
197 /* Unwait the thread */
198 KxUnwaitThread(&Event->Header, Increment);
199 }
200 else
201 {
202 /* Otherwise unwait the thread and unsignal the event */
204 }
205 }
206
207 /* Check what wait state was requested */
208 if (!Wait)
209 {
210 /* Wait not requested, release Dispatcher Database and return */
212 }
213 else
214 {
215 /* Return Locked and with a Wait */
217 Thread->WaitNext = TRUE;
218 Thread->WaitIrql = OldIrql;
219 }
220
221 /* Return the previous State */
222 return PreviousState;
223}
224
225/*
226 * @implemented
227 */
228VOID
229NTAPI
231 IN PKTHREAD *WaitingThread OPTIONAL)
232{
234 PKWAIT_BLOCK WaitBlock;
235 PKTHREAD Thread = KeGetCurrentThread(), WaitThread;
236 ASSERT(Event->Header.Type == EventSynchronizationObject);
238
239 /* Acquire Dispatcher Database Lock */
241
242 /* Check if the list is empty */
243 if (IsListEmpty(&Event->Header.WaitListHead))
244 {
245 /* Set the Event to Signaled */
246 Event->Header.SignalState = 1;
247
248 /* Return */
250 return;
251 }
252
253 /* Get the Wait Block */
254 WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
256 WaitListEntry);
257
258 /* Check if this is a WaitAll */
259 if (WaitBlock->WaitType == WaitAll)
260 {
261 /* Set the Event to Signaled */
262 Event->Header.SignalState = 1;
263
264 /* Unwait the thread and unsignal the event */
266 }
267 else
268 {
269 /* Return waiting thread to caller */
270 WaitThread = WaitBlock->Thread;
271 if (WaitingThread) *WaitingThread = WaitThread;
272
273 /* Calculate new priority */
274 Thread->Priority = KiComputeNewPriority(Thread, 0);
275
276 /* Unlink the waiting thread */
277 KiUnlinkThread(WaitThread, STATUS_SUCCESS);
278
279 /* Request priority boosting */
280 WaitThread->AdjustIncrement = Thread->Priority;
281 WaitThread->AdjustReason = AdjustBoost;
282
283 /* Ready the thread */
284 KiReadyThread(WaitThread);
285 }
286
287 /* Release the Dispatcher Database Lock */
289}
290
291/* 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:69
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI KeSetEventBoostPriority(IN PKEVENT Event, IN PKTHREAD *WaitingThread OPTIONAL)
Definition: eventobj.c:230
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:121
VOID NTAPI KeInitializeEventPair(IN PKEVENT_PAIR EventPair)
Definition: eventobj.c:53
LONG NTAPI KeResetEvent(IN PKEVENT Event)
Definition: eventobj.c:134
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
@ NotificationEvent
@ SynchronizationEvent
@ WaitAll
enum _EVENT_TYPE EVENT_TYPE
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:502
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:517
UCHAR WaitType
Definition: ketypes.h:510
#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)