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(OUT 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
,
166 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
169 * Check if this is an signaled notification event without an upcoming wait.
170 * In this case, we can immediately return TRUE, without locking.
172 if ((Event
->Header
.Type
== EventNotificationObject
) &&
173 (Event
->Header
.SignalState
== 1) &&
176 /* Return the signal state (TRUE/Signalled) */
180 /* Lock the Dispathcer Database */
181 OldIrql
= KiAcquireDispatcherLock();
183 /* Save the Previous State */
184 PreviousState
= Event
->Header
.SignalState
;
186 /* Set the Event to Signaled */
187 Event
->Header
.SignalState
= 1;
189 /* Check if the event just became signaled now, and it has waiters */
190 if (!(PreviousState
) && !(IsListEmpty(&Event
->Header
.WaitListHead
)))
192 /* Check the type of event */
193 if (Event
->Header
.Type
== EventNotificationObject
)
195 /* Unwait the thread */
196 KxUnwaitThread(&Event
->Header
, Increment
);
200 /* Otherwise unwait the thread and unsignal the event */
201 KxUnwaitThreadForEvent(Event
, Increment
);
205 /* Check what wait state was requested */
208 /* Wait not requested, release Dispatcher Database and return */
209 KiReleaseDispatcherLock(OldIrql
);
213 /* Return Locked and with a Wait */
214 Thread
= KeGetCurrentThread();
215 Thread
->WaitNext
= TRUE
;
216 Thread
->WaitIrql
= OldIrql
;
219 /* Return the previous State */
220 return PreviousState
;
228 KeSetEventBoostPriority(IN PKEVENT Event
,
229 IN PKTHREAD
*WaitingThread OPTIONAL
)
232 PKWAIT_BLOCK WaitBlock
;
233 PKTHREAD Thread
= KeGetCurrentThread(), WaitThread
;
234 ASSERT(Event
->Header
.Type
== EventSynchronizationObject
);
235 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
237 /* Acquire Dispatcher Database Lock */
238 OldIrql
= KiAcquireDispatcherLock();
240 /* Check if the list is empty */
241 if (IsListEmpty(&Event
->Header
.WaitListHead
))
243 /* Set the Event to Signaled */
244 Event
->Header
.SignalState
= 1;
247 KiReleaseDispatcherLock(OldIrql
);
251 /* Get the Wait Block */
252 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
256 /* Check if this is a WaitAll */
257 if (WaitBlock
->WaitType
== WaitAll
)
259 /* Set the Event to Signaled */
260 Event
->Header
.SignalState
= 1;
262 /* Unwait the thread and unsignal the event */
263 KxUnwaitThreadForEvent(Event
, EVENT_INCREMENT
);
267 /* Return waiting thread to caller */
268 WaitThread
= WaitBlock
->Thread
;
269 if (WaitingThread
) *WaitingThread
= WaitThread
;
271 /* Calculate new priority */
272 Thread
->Priority
= KiComputeNewPriority(Thread
, 0);
274 /* Unlink the waiting thread */
275 KiUnlinkThread(WaitThread
, STATUS_SUCCESS
);
277 /* Request priority boosting */
278 WaitThread
->AdjustIncrement
= Thread
->Priority
;
279 WaitThread
->AdjustReason
= AdjustBoost
;
281 /* Ready the thread */
282 KiReadyThread(WaitThread
);
285 /* Release the Dispatcher Database Lock */
286 KiReleaseDispatcherLock(OldIrql
);