Release 980215
[wine] / scheduler / event.c
1 /*
2  * Win32 events
3  *
4  * Copyright 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include "windows.h"
9 #include "winerror.h"
10 #include "k32obj.h"
11 #include "process.h"
12 #include "thread.h"
13 #include "heap.h"
14
15 typedef struct
16 {
17     K32OBJ        header;
18     THREAD_QUEUE  wait_queue;
19     BOOL32        manual_reset;
20     BOOL32        signaled;
21 } EVENT;
22
23 static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id );
24 static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id );
25 static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id );
26 static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id );
27 static void EVENT_Destroy( K32OBJ *obj );
28
29 const K32OBJ_OPS EVENT_Ops =
30 {
31     EVENT_Signaled,     /* signaled */
32     EVENT_Satisfied,    /* satisfied */
33     EVENT_AddWait,      /* add_wait */
34     EVENT_RemoveWait,   /* remove_wait */
35     EVENT_Destroy       /* destroy */
36 };
37
38
39 /***********************************************************************
40  *           EVENT_Set
41  *
42  * Implementation of SetEvent. Used by ExitThread and ExitProcess.
43  */
44 void EVENT_Set( K32OBJ *obj )
45 {
46     EVENT *event = (EVENT *)obj;
47     assert( obj->type == K32OBJ_EVENT );
48     SYSTEM_LOCK();
49     event->signaled = TRUE;
50     SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
51     SYSTEM_UNLOCK();
52 }
53
54 /***********************************************************************
55  *           EVENT_Create
56  *
57  * Partial implementation of CreateEvent.
58  * Used internally by processes and threads.
59  */
60 K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state )
61 {
62     EVENT *event;
63
64     SYSTEM_LOCK();
65     if ((event = HeapAlloc( SystemHeap, 0, sizeof(*event) )))
66     {
67         event->header.type     = K32OBJ_EVENT;
68         event->header.refcount = 1;
69         event->wait_queue      = NULL;
70         event->manual_reset    = manual_reset;
71         event->signaled        = initial_state;
72     }
73     SYSTEM_UNLOCK();
74     return event ? &event->header : NULL;
75 }
76
77
78 /***********************************************************************
79  *           CreateEvent32A    (KERNEL32.156)
80  */
81 HANDLE32 WINAPI CreateEvent32A( SECURITY_ATTRIBUTES *sa, BOOL32 manual_reset,
82                                 BOOL32 initial_state, LPCSTR name )
83 {
84     HANDLE32 handle;
85     EVENT *event;
86
87     SYSTEM_LOCK();
88     event = (EVENT *)K32OBJ_Create( K32OBJ_EVENT, sizeof(*event),
89                                     name, EVENT_ALL_ACCESS, &handle );
90     if (event)
91     {
92         /* Finish initializing it */
93         event->wait_queue   = NULL;
94         event->manual_reset = manual_reset;
95         event->signaled     = initial_state;
96         K32OBJ_DecCount( &event->header );
97     }
98     SYSTEM_UNLOCK();
99     return handle;
100 }
101
102
103 /***********************************************************************
104  *           CreateEvent32W    (KERNEL32.157)
105  */
106 HANDLE32 WINAPI CreateEvent32W( SECURITY_ATTRIBUTES *sa, BOOL32 manual_reset,
107                                 BOOL32 initial_state, LPCWSTR name )
108 {
109     LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
110     HANDLE32 ret = CreateEvent32A( sa, manual_reset, initial_state, nameA );
111     if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
112     return ret;
113 }
114
115
116 /***********************************************************************
117  *           OpenEvent32A    (KERNEL32.536)
118  */
119 HANDLE32 WINAPI OpenEvent32A( DWORD access, BOOL32 inherit, LPCSTR name )
120 {
121     HANDLE32 handle = 0;
122     K32OBJ *obj;
123     SYSTEM_LOCK();
124     if ((obj = K32OBJ_FindNameType( name, K32OBJ_EVENT )) != NULL)
125     {
126         handle = HANDLE_Alloc( obj, access, inherit );
127         K32OBJ_DecCount( obj );
128     }
129     SYSTEM_UNLOCK();
130     return handle;
131 }
132
133
134 /***********************************************************************
135  *           OpenEvent32W    (KERNEL32.537)
136  */
137 HANDLE32 WINAPI OpenEvent32W( DWORD access, BOOL32 inherit, LPCWSTR name )
138 {
139     LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
140     HANDLE32 ret = OpenEvent32A( access, inherit, nameA );
141     if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
142     return ret;
143 }
144
145
146 /***********************************************************************
147  *           PulseEvent    (KERNEL32.557)
148  */
149 BOOL32 WINAPI PulseEvent( HANDLE32 handle )
150 {
151     EVENT *event;
152     SYSTEM_LOCK();
153     if (!(event = (EVENT *)HANDLE_GetObjPtr( handle, K32OBJ_EVENT,
154                                              EVENT_MODIFY_STATE )))
155     {
156         SYSTEM_UNLOCK();
157         return FALSE;
158     }
159     event->signaled = TRUE;
160     SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
161     event->signaled = FALSE;
162     K32OBJ_DecCount( &event->header );
163     SYSTEM_UNLOCK();
164     return TRUE;
165 }
166
167
168 /***********************************************************************
169  *           SetEvent    (KERNEL32.644)
170  */
171 BOOL32 WINAPI SetEvent( HANDLE32 handle )
172 {
173     EVENT *event;
174     SYSTEM_LOCK();
175     if (!(event = (EVENT *)HANDLE_GetObjPtr( handle, K32OBJ_EVENT,
176                                              EVENT_MODIFY_STATE )))
177     {
178         SYSTEM_UNLOCK();
179         return FALSE;
180     }
181     event->signaled = TRUE;
182     SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
183     K32OBJ_DecCount( &event->header );
184     SYSTEM_UNLOCK();
185     return TRUE;
186 }
187
188
189 /***********************************************************************
190  *           ResetEvent    (KERNEL32.586)
191  */
192 BOOL32 WINAPI ResetEvent( HANDLE32 handle )
193 {
194     EVENT *event;
195     SYSTEM_LOCK();
196     if (!(event = (EVENT *)HANDLE_GetObjPtr( handle, K32OBJ_EVENT,
197                                              EVENT_MODIFY_STATE )))
198     {
199         SYSTEM_UNLOCK();
200         return FALSE;
201     }
202     event->signaled = FALSE;
203     K32OBJ_DecCount( &event->header );
204     SYSTEM_UNLOCK();
205     return TRUE;
206 }
207
208
209 /***********************************************************************
210  *           EVENT_Signaled
211  */
212 static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id )
213 {
214     EVENT *event = (EVENT *)obj;
215     assert( obj->type == K32OBJ_EVENT );
216     return event->signaled;
217 }
218
219
220 /***********************************************************************
221  *           EVENT_Satisfied
222  *
223  * Wait on this object has been satisfied.
224  */
225 static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
226 {
227     EVENT *event = (EVENT *)obj;
228     assert( obj->type == K32OBJ_EVENT );
229     /* Reset if it's an auto-reset event */
230     if (!event->manual_reset) event->signaled = FALSE;
231     return FALSE;  /* Not abandoned */
232 }
233
234
235 /***********************************************************************
236  *           EVENT_AddWait
237  *
238  * Add thread to object wait queue.
239  */
240 static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id )
241 {
242     EVENT *event = (EVENT *)obj;
243     assert( obj->type == K32OBJ_EVENT );
244     THREAD_AddQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
245 }
246
247
248 /***********************************************************************
249  *           EVENT_RemoveWait
250  *
251  * Remove thread from object wait queue.
252  */
253 static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id )
254 {
255     EVENT *event = (EVENT *)obj;
256     assert( obj->type == K32OBJ_EVENT );
257     THREAD_RemoveQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
258 }
259
260
261 /***********************************************************************
262  *           EVENT_Destroy
263  */
264 static void EVENT_Destroy( K32OBJ *obj )
265 {
266     EVENT *event = (EVENT *)obj;
267     assert( obj->type == K32OBJ_EVENT );
268     /* There cannot be any thread on the list since the ref count is 0 */
269     assert( event->wait_queue == NULL );
270     obj->type = K32OBJ_UNKNOWN;
271     HeapFree( SystemHeap, 0, event );
272 }