2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/event.c
5 * PURPOSE: Implements the Event Dispatcher Object
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
22 KeClearEvent(IN PKEVENT Event
)
26 /* Reset Signal State */
27 Event
->Header
.SignalState
= FALSE
;
35 KeInitializeEvent(IN PKEVENT Event
,
39 /* Initialize the Dispatcher Header */
40 KeInitializeDispatcherHeader(&Event
->Header
,
42 sizeof(*Event
) / sizeof(ULONG
),
51 KeInitializeEventPair(IN PKEVENT_PAIR EventPair
)
53 /* Initialize the Event Pair Type and Size */
54 EventPair
->Type
= EventPairObject
;
55 EventPair
->Size
= sizeof(KEVENT_PAIR
);
57 /* Initialize the two Events */
58 KeInitializeEvent(&EventPair
->LowEvent
, SynchronizationEvent
, FALSE
);
59 KeInitializeEvent(&EventPair
->HighEvent
, SynchronizationEvent
, FALSE
);
67 KePulseEvent(IN PKEVENT Event
,
68 IN KPRIORITY Increment
,
75 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
77 /* Lock the Dispatcher Database */
78 OldIrql
= KiAcquireDispatcherLock();
80 /* Save the Old State */
81 PreviousState
= Event
->Header
.SignalState
;
83 /* Check if we are non-signaled and we have stuff in the Wait Queue */
84 if (!PreviousState
&& !IsListEmpty(&Event
->Header
.WaitListHead
))
86 /* Set the Event to Signaled */
87 Event
->Header
.SignalState
= 1;
90 KiWaitTest(&Event
->Header
, Increment
);
94 Event
->Header
.SignalState
= 0;
96 /* Check what wait state was requested */
99 /* Wait not requested, release Dispatcher Database and return */
100 KiReleaseDispatcherLock(OldIrql
);
104 /* Return Locked and with a Wait */
105 Thread
= KeGetCurrentThread();
106 Thread
->WaitNext
= TRUE
;
107 Thread
->WaitIrql
= OldIrql
;
110 /* Return the previous State */
111 return PreviousState
;
119 KeReadStateEvent(IN PKEVENT Event
)
123 /* Return the Signal State */
124 return Event
->Header
.SignalState
;
132 KeResetEvent(IN PKEVENT Event
)
137 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
139 /* Lock the Dispatcher Database */
140 OldIrql
= KiAcquireDispatcherLock();
142 /* Save the Previous State */
143 PreviousState
= Event
->Header
.SignalState
;
146 Event
->Header
.SignalState
= 0;
148 /* Release Dispatcher Database and return previous state */
149 KiReleaseDispatcherLock(OldIrql
);
150 return PreviousState
;
158 KeSetEvent(IN PKEVENT Event
,
159 IN KPRIORITY Increment
,
164 PKWAIT_BLOCK WaitBlock
;
167 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
170 * Check if this is an signaled notification event without an upcoming wait.
171 * In this case, we can immediately return TRUE, without locking.
173 if ((Event
->Header
.Type
== NotificationEvent
) &&
174 (Event
->Header
.SignalState
== 1) &&
177 /* Return the signal state (TRUE/Signalled) */
181 /* Lock the Dispathcer Database */
182 OldIrql
= KiAcquireDispatcherLock();
184 /* Save the Previous State */
185 PreviousState
= Event
->Header
.SignalState
;
187 /* Set the Event to Signaled */
188 Event
->Header
.SignalState
= 1;
190 /* Check if the event just became signaled now, and it has waiters */
191 if (!(PreviousState
) && !(IsListEmpty(&Event
->Header
.WaitListHead
)))
193 /* Get the Wait Block */
194 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
198 /* Check the type of event */
199 if (Event
->Header
.Type
== NotificationEvent
)
201 /* Unwait the thread */
202 KxUnwaitThread(&Event
->Header
, Increment
);
206 /* Otherwise unwait the thread and unsignal the event */
207 KxUnwaitThreadForEvent(Event
, Increment
);
211 /* Check what wait state was requested */
214 /* Wait not requested, release Dispatcher Database and return */
215 KiReleaseDispatcherLock(OldIrql
);
219 /* Return Locked and with a Wait */
220 Thread
= KeGetCurrentThread();
221 Thread
->WaitNext
= TRUE
;
222 Thread
->WaitIrql
= OldIrql
;
225 /* Return the previous State */
226 return PreviousState
;
234 KeSetEventBoostPriority(IN PKEVENT Event
,
235 IN PKTHREAD
*WaitingThread OPTIONAL
)
238 PKWAIT_BLOCK WaitBlock
;
239 PKTHREAD Thread
= KeGetCurrentThread(), WaitThread
;
240 ASSERT(Event
->Header
.Type
== SynchronizationEvent
);
241 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
243 /* Acquire Dispatcher Database Lock */
244 OldIrql
= KiAcquireDispatcherLock();
246 /* Check if the list is empty */
247 if (IsListEmpty(&Event
->Header
.WaitListHead
))
249 /* Set the Event to Signaled */
250 Event
->Header
.SignalState
= 1;
253 KiReleaseDispatcherLock(OldIrql
);
257 /* Get the Wait Block */
258 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
262 /* Check if this is a WaitAll */
263 if (WaitBlock
->WaitType
== WaitAll
)
265 /* Set the Event to Signaled */
266 Event
->Header
.SignalState
= 1;
268 /* Unwait the thread and unsignal the event */
269 KxUnwaitThreadForEvent(Event
, EVENT_INCREMENT
);
273 /* Return waiting thread to caller */
274 WaitThread
= WaitBlock
->Thread
;
275 if (WaitingThread
) *WaitingThread
= WaitThread
;
277 /* Calculate new priority */
278 Thread
->Priority
= KiComputeNewPriority(Thread
, 0);
280 /* Unlink the waiting thread */
281 KiUnlinkThread(WaitThread
, STATUS_SUCCESS
);
283 /* Request priority boosting */
284 WaitThread
->AdjustIncrement
= Thread
->Priority
;
285 WaitThread
->AdjustReason
= AdjustBoost
;
287 /* Ready the thread */
288 KiReadyThread(WaitThread
);
291 /* Release the Dispatcher Database Lock */
292 KiReleaseDispatcherLock(OldIrql
);