dcb8f737f2341e94106d169105edae69c41a75f0
[reactos.git] / reactos / ntoskrnl / ke / event.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/event.c
5 * PURPOSE: Implements events
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 /*
20 * @implemented
21 */
22 VOID STDCALL KeClearEvent (PKEVENT Event)
23 {
24 DPRINT("KeClearEvent(Event %x)\n", Event);
25 Event->Header.SignalState = FALSE;
26 }
27
28 /*
29 * @implemented
30 */
31 VOID STDCALL KeInitializeEvent (PKEVENT Event,
32 EVENT_TYPE Type,
33 BOOLEAN State)
34 {
35 ULONG IType;
36
37 if (Type == NotificationEvent)
38 {
39 IType = InternalNotificationEvent;
40 }
41 else if (Type == SynchronizationEvent)
42 {
43 IType = InternalSynchronizationEvent;
44 }
45 else
46 {
47 ASSERT(FALSE);
48 return;
49 }
50
51 KeInitializeDispatcherHeader(&(Event->Header),
52 IType,
53 sizeof(Event)/sizeof(ULONG),State);
54 InitializeListHead(&(Event->Header.WaitListHead));
55 }
56
57 /*
58 * @implemented
59 */
60 LONG STDCALL KeReadStateEvent (PKEVENT Event)
61 {
62 return(Event->Header.SignalState);
63 }
64
65 /*
66 * @implemented
67 */
68 LONG STDCALL KeResetEvent (PKEVENT Event)
69 {
70 /* FIXME: must use interlocked func. everywhere! (wait.c)
71 * or use dispather lock instead
72 * -Gunnar */
73 return(InterlockedExchange(&(Event->Header.SignalState),0));
74 }
75
76 /*
77 * @implemented
78 */
79 LONG STDCALL KeSetEvent (PKEVENT Event,
80 KPRIORITY Increment,
81 BOOLEAN Wait)
82 {
83 KIRQL OldIrql;
84 int ret;
85
86 DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
87
88 OldIrql = KeAcquireDispatcherDatabaseLock();
89
90 ret = InterlockedExchange(&Event->Header.SignalState,1);
91
92 KiDispatcherObjectWake(&Event->Header, Increment);
93
94 if (Wait == FALSE)
95 {
96 KeReleaseDispatcherDatabaseLock(OldIrql);
97 }
98 else
99 {
100 KTHREAD *Thread = KeGetCurrentThread();
101 Thread->WaitNext = TRUE;
102 Thread->WaitIrql = OldIrql;
103 }
104
105 return(ret);
106 }
107
108 /*
109 * @implemented
110 */
111 LONG STDCALL
112 KePulseEvent (IN PKEVENT Event,
113 IN KPRIORITY Increment,
114 IN BOOLEAN Wait)
115 {
116 KIRQL OldIrql;
117 LONG Ret;
118
119 DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
120 OldIrql = KeAcquireDispatcherDatabaseLock();
121 Ret = InterlockedExchange(&Event->Header.SignalState,1);
122 KiDispatcherObjectWake(&Event->Header, Increment);
123 InterlockedExchange(&(Event->Header.SignalState),0);
124
125 if (Wait == FALSE)
126 {
127 KeReleaseDispatcherDatabaseLock(OldIrql);
128 }
129 else
130 {
131 KTHREAD *Thread = KeGetCurrentThread();
132 Thread->WaitNext = TRUE;
133 Thread->WaitIrql = OldIrql;
134 }
135
136 return Ret;
137 }
138
139 /*
140 * @implemented
141 */
142 VOID
143 STDCALL
144 KeSetEventBoostPriority(
145 IN PKEVENT Event,
146 IN PKTHREAD *Thread OPTIONAL
147 )
148 {
149 PKTHREAD WaitingThread;
150 KIRQL OldIrql;
151
152 OldIrql = KeAcquireDispatcherDatabaseLock();
153
154 /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
155 WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
156
157 /* Return it to caller if requested */
158 if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
159
160 /* Reset the Quantum and Unwait the Thread */
161 WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
162 KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
163
164 KeReleaseDispatcherDatabaseLock(OldIrql);
165 }
166
167 /* EOF */