fix kernel queues + misc fixes/cleanups
[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((DISPATCHER_HEADER *)Event);
93
94 if (Wait == FALSE)
95 {
96 KeReleaseDispatcherDatabaseLock(OldIrql);
97 }
98 else
99 {
100 KTHREAD *Thread = KeGetCurrentThread();
101 Thread->WaitNext = Wait;
102 Thread->WaitIrql = OldIrql;
103 }
104
105 return(ret);
106 }
107
108 /*
109 * @implemented
110 */
111 NTSTATUS STDCALL KePulseEvent (PKEVENT Event,
112 KPRIORITY Increment,
113 BOOLEAN Wait)
114 {
115 KIRQL OldIrql;
116 int ret;
117
118 DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
119 OldIrql = KeAcquireDispatcherDatabaseLock();
120 ret = InterlockedExchange(&(Event->Header.SignalState),1);
121 KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
122 InterlockedExchange(&(Event->Header.SignalState),0);
123
124 if (Wait == FALSE)
125 {
126 KeReleaseDispatcherDatabaseLock(OldIrql);
127 }
128 else
129 {
130 KTHREAD *Thread = KeGetCurrentThread();
131 Thread->WaitNext = Wait;
132 Thread->WaitIrql = OldIrql;
133 }
134
135 return ((NTSTATUS)ret);
136 }
137
138 /*
139 * @implemented
140 */
141 VOID
142 STDCALL
143 KeSetEventBoostPriority(
144 IN PKEVENT Event,
145 IN PKTHREAD *Thread OPTIONAL
146 )
147 {
148 PKTHREAD WaitingThread;
149 KIRQL OldIrql;
150
151 OldIrql = KeAcquireDispatcherDatabaseLock();
152
153 /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
154 WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
155
156 /* Return it to caller if requested */
157 if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
158
159 /* Reset the Quantum and Unwait the Thread */
160 WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
161 KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
162
163 KeReleaseDispatcherDatabaseLock(OldIrql);
164 }
165
166 /* EOF */