7683afa3b4211b003278363e7322c60d145eadbf
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: David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* FUNCTIONS ****************************************************************/
24 KeClearEvent(PKEVENT Event
)
26 DPRINT("KeClearEvent(Event %x)\n", Event
);
28 /* Reset Signal State */
29 Event
->Header
.SignalState
= FALSE
;
37 KeInitializeEvent(PKEVENT Event
,
41 DPRINT("KeInitializeEvent(Event %x)\n", Event
);
43 /* Initialize the Dispatcher Header */
44 KeInitializeDispatcherHeader(&Event
->Header
,
46 sizeof(Event
) / sizeof(ULONG
),
55 KeInitializeEventPair(PKEVENT_PAIR EventPair
)
57 DPRINT("KeInitializeEventPair(Event %x)\n", EventPair
);
59 /* Initialize the Event Pair Type and Size */
60 EventPair
->Type
= EventPairObject
;
61 EventPair
->Size
= sizeof(KEVENT_PAIR
);
63 /* Initialize the two Events */
64 KeInitializeEvent(&EventPair
->LowEvent
, SynchronizationEvent
, FALSE
);
65 KeInitializeEvent(&EventPair
->HighEvent
, SynchronizationEvent
, FALSE
);
72 KePulseEvent(IN PKEVENT Event
,
73 IN KPRIORITY Increment
,
79 DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event
,Wait
);
81 /* Lock the Dispatcher Database */
82 OldIrql
= KeAcquireDispatcherDatabaseLock();
84 /* Save the Old State */
85 PreviousState
= Event
->Header
.SignalState
;
87 /* Check if we are non-signaled and we have stuff in the Wait Queue */
88 if (!PreviousState
&& !IsListEmpty(&Event
->Header
.WaitListHead
)) {
90 /* Set the Event to Signaled */
91 Event
->Header
.SignalState
= 1;
94 KiWaitTest(&Event
->Header
, Increment
);
98 Event
->Header
.SignalState
= 0;
100 /* Check what wait state was requested */
103 /* Wait not requested, release Dispatcher Database and return */
104 KeReleaseDispatcherDatabaseLock(OldIrql
);
108 /* Return Locked and with a Wait */
109 KTHREAD
*Thread
= KeGetCurrentThread();
110 Thread
->WaitNext
= TRUE
;
111 Thread
->WaitIrql
= OldIrql
;
114 /* Return the previous State */
115 return PreviousState
;
123 KeReadStateEvent(PKEVENT Event
)
125 /* Return the Signal State */
126 return Event
->Header
.SignalState
;
134 KeResetEvent(PKEVENT Event
)
139 DPRINT("KeResetEvent(Event %x)\n",Event
);
141 /* Lock the Dispatcher Database */
142 OldIrql
= KeAcquireDispatcherDatabaseLock();
144 /* Save the Previous State */
145 PreviousState
= Event
->Header
.SignalState
;
148 Event
->Header
.SignalState
= 0;
150 /* Release Dispatcher Database and return previous state */
151 KeReleaseDispatcherDatabaseLock(OldIrql
);
152 return PreviousState
;
160 KeSetEvent(PKEVENT Event
,
166 PKWAIT_BLOCK WaitBlock
;
168 DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event
,Wait
);
170 /* Lock the Dispathcer Database */
171 OldIrql
= KeAcquireDispatcherDatabaseLock();
173 /* Save the Previous State */
174 PreviousState
= Event
->Header
.SignalState
;
176 /* Check if we have stuff in the Wait Queue */
177 if (IsListEmpty(&Event
->Header
.WaitListHead
)) {
179 /* Set the Event to Signaled */
180 DPRINT("Empty Wait Queue, Signal the Event\n");
181 Event
->Header
.SignalState
= 1;
185 /* Get the Wait Block */
186 WaitBlock
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
191 /* Check the type of event */
192 if (Event
->Header
.Type
== NotificationEvent
|| WaitBlock
->WaitType
== WaitAll
) {
194 if (PreviousState
== 0) {
196 /* We must do a full wait satisfaction */
197 DPRINT("Notification Event or WaitAll, Wait on the Event and Signal\n");
198 Event
->Header
.SignalState
= 1;
199 KiWaitTest(&Event
->Header
, Increment
);
204 /* We can satisfy wait simply by waking the thread, since our signal state is 0 now */
205 DPRINT("WaitAny or Sync Event, just unwait the thread\n");
206 KiAbortWaitThread(WaitBlock
->Thread
, WaitBlock
->WaitKey
);
210 /* Check what wait state was requested */
213 /* Wait not requested, release Dispatcher Database and return */
214 KeReleaseDispatcherDatabaseLock(OldIrql
);
218 /* Return Locked and with a Wait */
219 KTHREAD
*Thread
= KeGetCurrentThread();
220 Thread
->WaitNext
= TRUE
;
221 Thread
->WaitIrql
= OldIrql
;
224 /* Return the previous State */
225 DPRINT("Done: %d\n", PreviousState
);
226 return PreviousState
;
234 KeSetEventBoostPriority(IN PKEVENT Event
,
235 IN PKTHREAD
*Thread OPTIONAL
)
237 PKTHREAD WaitingThread
;
240 DPRINT("KeSetEventBoostPriority(Event %x, Thread %x)\n",Event
,Thread
);
242 /* Acquire Dispatcher Database Lock */
243 OldIrql
= KeAcquireDispatcherDatabaseLock();
245 /* If our wait list is empty, then signal the event and return */
246 if (IsListEmpty(&Event
->Header
.WaitListHead
)) {
248 Event
->Header
.SignalState
= 1;
252 /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
253 WaitingThread
= CONTAINING_RECORD(Event
->Header
.WaitListHead
.Flink
,
255 WaitListEntry
)->Thread
;
257 /* Return it to caller if requested */
258 if ARGUMENT_PRESENT(Thread
) *Thread
= WaitingThread
;
260 /* Reset the Quantum and Unwait the Thread */
261 WaitingThread
->Quantum
= WaitingThread
->ApcState
.Process
->ThreadQuantum
;
262 KiAbortWaitThread(WaitingThread
, STATUS_SUCCESS
);
265 /* Release the Dispatcher Database Lock */
266 KeReleaseDispatcherDatabaseLock(OldIrql
);