Release 980118
[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, &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 = PROCESS_AllocHandle( obj, 0 );
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 *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
154     {
155         SYSTEM_UNLOCK();
156         return FALSE;
157     }
158     event->signaled = TRUE;
159     SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
160     event->signaled = FALSE;
161     K32OBJ_DecCount( &event->header );
162     SYSTEM_UNLOCK();
163     return TRUE;
164 }
165
166
167 /***********************************************************************
168  *           SetEvent    (KERNEL32.644)
169  */
170 BOOL32 WINAPI SetEvent( HANDLE32 handle )
171 {
172     EVENT *event;
173     SYSTEM_LOCK();
174     if (!(event = (EVENT *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
175     {
176         SYSTEM_UNLOCK();
177         return FALSE;
178     }
179     event->signaled = TRUE;
180     SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
181     K32OBJ_DecCount( &event->header );
182     SYSTEM_UNLOCK();
183     return TRUE;
184 }
185
186
187 /***********************************************************************
188  *           ResetEvent    (KERNEL32.586)
189  */
190 BOOL32 WINAPI ResetEvent( HANDLE32 handle )
191 {
192     EVENT *event;
193     SYSTEM_LOCK();
194     if (!(event = (EVENT *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
195     {
196         SYSTEM_UNLOCK();
197         return FALSE;
198     }
199     event->signaled = FALSE;
200     K32OBJ_DecCount( &event->header );
201     SYSTEM_UNLOCK();
202     return TRUE;
203 }
204
205
206 /***********************************************************************
207  *           EVENT_Signaled
208  */
209 static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id )
210 {
211     EVENT *event = (EVENT *)obj;
212     assert( obj->type == K32OBJ_EVENT );
213     return event->signaled;
214 }
215
216
217 /***********************************************************************
218  *           EVENT_Satisfied
219  *
220  * Wait on this object has been satisfied.
221  */
222 static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
223 {
224     EVENT *event = (EVENT *)obj;
225     assert( obj->type == K32OBJ_EVENT );
226     /* Reset if it's an auto-reset event */
227     if (!event->manual_reset) event->signaled = FALSE;
228     return FALSE;  /* Not abandoned */
229 }
230
231
232 /***********************************************************************
233  *           EVENT_AddWait
234  *
235  * Add thread to object wait queue.
236  */
237 static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id )
238 {
239     EVENT *event = (EVENT *)obj;
240     assert( obj->type == K32OBJ_EVENT );
241     THREAD_AddQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
242 }
243
244
245 /***********************************************************************
246  *           EVENT_RemoveWait
247  *
248  * Remove thread from object wait queue.
249  */
250 static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id )
251 {
252     EVENT *event = (EVENT *)obj;
253     assert( obj->type == K32OBJ_EVENT );
254     THREAD_RemoveQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
255 }
256
257
258 /***********************************************************************
259  *           EVENT_Destroy
260  */
261 static void EVENT_Destroy( K32OBJ *obj )
262 {
263     EVENT *event = (EVENT *)obj;
264     assert( obj->type == K32OBJ_EVENT );
265     /* There cannot be any thread on the list since the ref count is 0 */
266     assert( event->wait_queue == NULL );
267     obj->type = K32OBJ_UNKNOWN;
268     HeapFree( SystemHeap, 0, event );
269 }