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 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
));
52 KeInitializeEventPair(IN PKEVENT_PAIR EventPair
)
54 /* Initialize the Event Pair Type and Size */
55 EventPair
->Type
= EventPairObject
;
56 EventPair
->Size
= sizeof(KEVENT_PAIR
);
58 /* Initialize the two Events */
59 KeInitializeEvent(&EventPair
->LowEvent
, SynchronizationEvent
, FALSE
);
60 KeInitializeEvent(&EventPair
->HighEvent
, SynchronizationEvent
, FALSE
);
68 KePulseEvent(IN PKEVENT Event
,
69 IN KPRIORITY Increment
,
76 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
78 /* Lock the Dispatcher Database */
79 OldIrql
= KiAcquireDispatcherLock();
81 /* Save the Old State */
82 PreviousState
= Event
->Header
.SignalState
;
84 /* Check if we are non-signaled and we have stuff in the Wait Queue */
85 if (!PreviousState
&& !IsListEmpty(&Event
->Header
.WaitListHead
))
87 /* Set the Event to Signaled */
88 Event
->Header
.SignalState
= 1;
91 KiWaitTest(&Event
->Header
, Increment
);
95 Event
->Header
.SignalState
= 0;
97 /* Check what wait state was requested */
100 /* Wait not requested, release Dispatcher Database and return */
101 KiReleaseDispatcherLock(OldIrql
);
105 /* Return Locked and with a Wait */
106 Thread
= KeGetCurrentThread();
107 Thread
->WaitNext
= TRUE
;
108 Thread
->WaitIrql
= OldIrql
;
111 /* Return the previous State */
112 return PreviousState
;
120 KeReadStateEvent(IN PKEVENT Event
)
124 /* Return the Signal State */
125 return Event
->Header
.SignalState
;
133 KeResetEvent(IN PKEVENT Event
)
138 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
140 /* Lock the Dispatcher Database */
141 OldIrql
= KiAcquireDispatcherLock();
143 /* Save the Previous State */
144 PreviousState
= Event
->Header
.SignalState
;
147 Event
->Header
.SignalState
= 0;
149 /* Release Dispatcher Database and return previous state */
150 KiReleaseDispatcherLock(OldIrql
);
151 return PreviousState
;
159 KeSetEvent(IN PKEVENT Event
,
160 IN KPRIORITY Increment
,
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
== EventNotificationObject
) &&
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 /* Check the type of event */
194 if (Event
->Header
.Type
== EventNotificationObject
)
196 /* Unwait the thread */
197 KxUnwaitThread(&Event
->Header
, Increment
);
201 /* Otherwise unwait the thread and unsignal the event */
202 KxUnwaitThreadForEvent(Event
, Increment
);
206 /* Check what wait state was requested */
209 /* Wait not requested, release Dispatcher Database and return */
210 KiReleaseDispatcherLock(OldIrql
);
214 /* Return Locked and with a Wait */
215 Thread
= KeGetCurrentThread();
216 Thread
->WaitNext
= TRUE
;
217 Thread
->WaitIrql
= OldIrql
;
220 /* Return the previous State */
221 return PreviousState
;
229 KeSetEventBoostPriority(IN PKEVENT Event
,
230 IN PKTHREAD
*WaitingThread OPTIONAL
)
233 PKWAIT_BLOCK WaitBlock
;
234 PKTHREAD Thread
= KeGetCurrentThread(), WaitThread
;
235 ASSERT(Event
->Header
.Type
== EventSynchronizationObject
);
236 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
238 /* Acquire Dispatcher Database Lock */
239 OldIrql
= KiAcquireDispatcherLock();
241 /* Check if the list is empty */
242 if (IsListEmpty(&Event
->Header
.WaitListHead
))
244 /* Set the Event to Signaled */
245 Event
->Header
.SignalState
= 1;
248 KiReleaseDispatcherLock(OldIrql
);
252 /* Get the Wait Block */
253 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
257 /* Check if this is a WaitAll */
258 if (WaitBlock
->WaitType
== WaitAll
)
260 /* Set the Event to Signaled */
261 Event
->Header
.SignalState
= 1;
263 /* Unwait the thread and unsignal the event */
264 KxUnwaitThreadForEvent(Event
, EVENT_INCREMENT
);
268 /* Return waiting thread to caller */
269 WaitThread
= WaitBlock
->Thread
;
270 if (WaitingThread
) *WaitingThread
= WaitThread
;
272 /* Calculate new priority */
273 Thread
->Priority
= KiComputeNewPriority(Thread
, 0);
275 /* Unlink the waiting thread */
276 KiUnlinkThread(WaitThread
, STATUS_SUCCESS
);
278 /* Request priority boosting */
279 WaitThread
->AdjustIncrement
= Thread
->Priority
;
280 WaitThread
->AdjustReason
= AdjustBoost
;
282 /* Ready the thread */
283 KiReadyThread(WaitThread
);
286 /* Release the Dispatcher Database Lock */
287 KiReleaseDispatcherLock(OldIrql
);