3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/event.c
6 * PURPOSE: Implements events
8 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 * David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* FUNCTIONS ****************************************************************/
25 KeClearEvent(PKEVENT Event
)
27 DPRINT("KeClearEvent(Event %x)\n", Event
);
29 /* Reset Signal State */
30 Event
->Header
.SignalState
= FALSE
;
38 KeInitializeEvent(PKEVENT Event
,
42 DPRINT("KeInitializeEvent(Event %x)\n", Event
);
44 /* Initialize the Dispatcher Header */
45 KeInitializeDispatcherHeader(&Event
->Header
,
47 sizeof(*Event
) / sizeof(ULONG
),
56 KeInitializeEventPair(PKEVENT_PAIR EventPair
)
58 DPRINT("KeInitializeEventPair(Event %x)\n", EventPair
);
60 /* Initialize the Event Pair Type and Size */
61 EventPair
->Type
= EventPairObject
;
62 EventPair
->Size
= sizeof(KEVENT_PAIR
);
64 /* Initialize the two Events */
65 KeInitializeEvent(&EventPair
->LowEvent
, SynchronizationEvent
, FALSE
);
66 KeInitializeEvent(&EventPair
->HighEvent
, SynchronizationEvent
, FALSE
);
73 KePulseEvent(IN PKEVENT Event
,
74 IN KPRIORITY Increment
,
80 DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event
,Wait
);
82 /* Lock the Dispatcher Database */
83 OldIrql
= KeAcquireDispatcherDatabaseLock();
85 /* Save the Old State */
86 PreviousState
= Event
->Header
.SignalState
;
88 /* Check if we are non-signaled and we have stuff in the Wait Queue */
89 if (!PreviousState
&& !IsListEmpty(&Event
->Header
.WaitListHead
)) {
91 /* Set the Event to Signaled */
92 Event
->Header
.SignalState
= 1;
95 KiWaitTest(&Event
->Header
, Increment
);
99 Event
->Header
.SignalState
= 0;
101 /* Check what wait state was requested */
104 /* Wait not requested, release Dispatcher Database and return */
105 KeReleaseDispatcherDatabaseLock(OldIrql
);
109 /* Return Locked and with a Wait */
110 KTHREAD
*Thread
= KeGetCurrentThread();
111 Thread
->WaitNext
= TRUE
;
112 Thread
->WaitIrql
= OldIrql
;
115 /* Return the previous State */
116 return PreviousState
;
124 KeReadStateEvent(PKEVENT Event
)
126 /* Return the Signal State */
127 return Event
->Header
.SignalState
;
135 KeResetEvent(PKEVENT Event
)
140 DPRINT("KeResetEvent(Event %x)\n",Event
);
142 /* Lock the Dispatcher Database */
143 OldIrql
= KeAcquireDispatcherDatabaseLock();
145 /* Save the Previous State */
146 PreviousState
= Event
->Header
.SignalState
;
149 Event
->Header
.SignalState
= 0;
151 /* Release Dispatcher Database and return previous state */
152 KeReleaseDispatcherDatabaseLock(OldIrql
);
153 return PreviousState
;
161 KeSetEvent(PKEVENT Event
,
167 PKWAIT_BLOCK WaitBlock
;
169 DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event
,Wait
);
171 /* Lock the Dispathcer Database */
172 OldIrql
= KeAcquireDispatcherDatabaseLock();
174 /* Save the Previous State */
175 PreviousState
= Event
->Header
.SignalState
;
177 /* Check if we have stuff in the Wait Queue */
178 if (IsListEmpty(&Event
->Header
.WaitListHead
)) {
180 /* Set the Event to Signaled */
181 DPRINT("Empty Wait Queue, Signal the Event\n");
182 Event
->Header
.SignalState
= 1;
186 /* Get the Wait Block */
187 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
192 /* Check the type of event */
193 if (Event
->Header
.Type
== NotificationEvent
|| WaitBlock
->WaitType
== WaitAll
) {
195 if (PreviousState
== 0) {
197 /* We must do a full wait satisfaction */
198 DPRINT("Notification Event or WaitAll, Wait on the Event and Signal\n");
199 Event
->Header
.SignalState
= 1;
200 KiWaitTest(&Event
->Header
, Increment
);
205 /* We can satisfy wait simply by waking the thread, since our signal state is 0 now */
206 DPRINT("WaitAny or Sync Event, just unwait the thread\n");
207 KiAbortWaitThread(WaitBlock
->Thread
, WaitBlock
->WaitKey
, Increment
);
211 /* Check what wait state was requested */
214 /* Wait not requested, release Dispatcher Database and return */
215 KeReleaseDispatcherDatabaseLock(OldIrql
);
219 /* Return Locked and with a Wait */
220 KTHREAD
*Thread
= KeGetCurrentThread();
221 Thread
->WaitNext
= TRUE
;
222 Thread
->WaitIrql
= OldIrql
;
225 /* Return the previous State */
226 DPRINT("Done: %d\n", PreviousState
);
227 return PreviousState
;
235 KeSetEventBoostPriority(IN PKEVENT Event
,
236 IN PKTHREAD
*Thread OPTIONAL
)
238 PKTHREAD WaitingThread
;
241 DPRINT("KeSetEventBoostPriority(Event %x, Thread %x)\n",Event
,Thread
);
243 /* Acquire Dispatcher Database Lock */
244 OldIrql
= KeAcquireDispatcherDatabaseLock();
246 /* If our wait list is empty, then signal the event and return */
247 if (IsListEmpty(&Event
->Header
.WaitListHead
)) {
249 Event
->Header
.SignalState
= 1;
253 /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
254 WaitingThread
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
256 WaitListEntry
)->Thread
;
258 /* Return it to caller if requested */
259 if ARGUMENT_PRESENT(Thread
) *Thread
= WaitingThread
;
261 /* Reset the Quantum and Unwait the Thread */
262 WaitingThread
->Quantum
= WaitingThread
->QuantumReset
;
263 KiAbortWaitThread(WaitingThread
, STATUS_SUCCESS
, EVENT_INCREMENT
);
266 /* Release the Dispatcher Database Lock */
267 KeReleaseDispatcherDatabaseLock(OldIrql
);