This source file includes following definitions.
- glwthread_waitqueue_init
- glwthread_waitqueue_add
- glwthread_waitqueue_remove
- glwthread_waitqueue_notify_first
- glwthread_waitqueue_notify_all
- glwthread_cond_init
- glwthread_cond_wait
- glwthread_cond_timedwait
- glwthread_cond_signal
- glwthread_cond_broadcast
- glwthread_cond_destroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include "windows-cond.h"
24
25 #include <errno.h>
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <sys/time.h>
29
30
31 #undef CreateEvent
32 #define CreateEvent CreateEventA
33
34
35 #define glwthread_waitqueue_t glwthread_linked_waitqueue_t
36
37
38
39 struct glwthread_waitqueue_element
40 {
41 struct glwthread_waitqueue_link link;
42 HANDLE event;
43
44 };
45
46 static void
47 glwthread_waitqueue_init (glwthread_waitqueue_t *wq)
48 {
49 wq->wq_list.wql_next = &wq->wq_list;
50 wq->wq_list.wql_prev = &wq->wq_list;
51 }
52
53
54
55 static struct glwthread_waitqueue_element *
56 glwthread_waitqueue_add (glwthread_waitqueue_t *wq)
57 {
58 struct glwthread_waitqueue_element *elt;
59 HANDLE event;
60
61
62
63
64 elt =
65 (struct glwthread_waitqueue_element *)
66 malloc (sizeof (struct glwthread_waitqueue_element));
67 if (elt == NULL)
68
69 return NULL;
70
71
72
73 event = CreateEvent (NULL, TRUE, FALSE, NULL);
74 if (event == INVALID_HANDLE_VALUE)
75 {
76
77 free (elt);
78 return NULL;
79 }
80 elt->event = event;
81
82 (elt->link.wql_prev = wq->wq_list.wql_prev)->wql_next = &elt->link;
83 (elt->link.wql_next = &wq->wq_list)->wql_prev = &elt->link;
84 return elt;
85 }
86
87
88
89
90 static bool
91 glwthread_waitqueue_remove (glwthread_waitqueue_t *wq,
92 struct glwthread_waitqueue_element *elt)
93 {
94 if (elt->link.wql_next != NULL && elt->link.wql_prev != NULL)
95 {
96
97 struct glwthread_waitqueue_link *prev = elt->link.wql_prev;
98 struct glwthread_waitqueue_link *next = elt->link.wql_next;
99 prev->wql_next = next;
100 next->wql_prev = prev;
101 elt->link.wql_next = NULL;
102 elt->link.wql_prev = NULL;
103 return true;
104 }
105 else
106 return false;
107 }
108
109
110 static void
111 glwthread_waitqueue_notify_first (glwthread_waitqueue_t *wq)
112 {
113 if (wq->wq_list.wql_next != &wq->wq_list)
114 {
115 struct glwthread_waitqueue_element *elt =
116 (struct glwthread_waitqueue_element *) wq->wq_list.wql_next;
117 struct glwthread_waitqueue_link *prev;
118 struct glwthread_waitqueue_link *next;
119
120
121 prev = &wq->wq_list;
122 next = elt->link.wql_next;
123 prev->wql_next = next;
124 next->wql_prev = prev;
125 elt->link.wql_next = NULL;
126 elt->link.wql_prev = NULL;
127
128 SetEvent (elt->event);
129
130
131 }
132 }
133
134
135 static void
136 glwthread_waitqueue_notify_all (glwthread_waitqueue_t *wq)
137 {
138 struct glwthread_waitqueue_link *l;
139
140 for (l = wq->wq_list.wql_next; l != &wq->wq_list; )
141 {
142 struct glwthread_waitqueue_element *elt =
143 (struct glwthread_waitqueue_element *) l;
144 struct glwthread_waitqueue_link *prev;
145 struct glwthread_waitqueue_link *next;
146
147
148 prev = &wq->wq_list;
149 next = elt->link.wql_next;
150 prev->wql_next = next;
151 next->wql_prev = prev;
152 elt->link.wql_next = NULL;
153 elt->link.wql_prev = NULL;
154
155 SetEvent (elt->event);
156
157
158
159 l = next;
160 }
161 if (!(wq->wq_list.wql_next == &wq->wq_list
162 && wq->wq_list.wql_prev == &wq->wq_list))
163 abort ();
164 }
165
166 int
167 glwthread_cond_init (glwthread_cond_t *cond)
168 {
169 InitializeCriticalSection (&cond->lock);
170 glwthread_waitqueue_init (&cond->waiters);
171
172 cond->guard.done = 1;
173 return 0;
174 }
175
176 int
177 glwthread_cond_wait (glwthread_cond_t *cond,
178 void *mutex, int (*mutex_lock) (void *), int (*mutex_unlock) (void *))
179 {
180 if (!cond->guard.done)
181 {
182 if (InterlockedIncrement (&cond->guard.started) == 0)
183
184
185 glwthread_cond_init (cond);
186 else
187 {
188
189 InterlockedDecrement (&cond->guard.started);
190
191
192 while (!cond->guard.done)
193 Sleep (0);
194 }
195 }
196
197 EnterCriticalSection (&cond->lock);
198 {
199 struct glwthread_waitqueue_element *elt =
200 glwthread_waitqueue_add (&cond->waiters);
201 LeaveCriticalSection (&cond->lock);
202 if (elt == NULL)
203 {
204
205 return EAGAIN;
206 }
207 else
208 {
209 HANDLE event = elt->event;
210 int err;
211 DWORD result;
212
213
214 err = mutex_unlock (mutex);
215 if (err != 0)
216 {
217 EnterCriticalSection (&cond->lock);
218 glwthread_waitqueue_remove (&cond->waiters, elt);
219 LeaveCriticalSection (&cond->lock);
220 CloseHandle (event);
221 free (elt);
222 return err;
223 }
224
225
226
227
228
229
230
231
232
233 result = WaitForSingleObject (event, INFINITE);
234 if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
235 abort ();
236 CloseHandle (event);
237 free (elt);
238
239
240 return mutex_lock (mutex);
241 }
242 }
243 }
244
245 int
246 glwthread_cond_timedwait (glwthread_cond_t *cond,
247 void *mutex, int (*mutex_lock) (void *), int (*mutex_unlock) (void *),
248 const struct timespec *abstime)
249 {
250 if (!cond->guard.done)
251 {
252 if (InterlockedIncrement (&cond->guard.started) == 0)
253
254
255 glwthread_cond_init (cond);
256 else
257 {
258
259 InterlockedDecrement (&cond->guard.started);
260
261
262 while (!cond->guard.done)
263 Sleep (0);
264 }
265 }
266
267 {
268 struct timeval currtime;
269
270 gettimeofday (&currtime, NULL);
271 if (currtime.tv_sec > abstime->tv_sec
272 || (currtime.tv_sec == abstime->tv_sec
273 && currtime.tv_usec * 1000 >= abstime->tv_nsec))
274 return ETIMEDOUT;
275
276 EnterCriticalSection (&cond->lock);
277 {
278 struct glwthread_waitqueue_element *elt =
279 glwthread_waitqueue_add (&cond->waiters);
280 LeaveCriticalSection (&cond->lock);
281 if (elt == NULL)
282 {
283
284 return EAGAIN;
285 }
286 else
287 {
288 HANDLE event = elt->event;
289 int err;
290 DWORD timeout;
291 DWORD result;
292
293
294 err = mutex_unlock (mutex);
295 if (err != 0)
296 {
297 EnterCriticalSection (&cond->lock);
298 glwthread_waitqueue_remove (&cond->waiters, elt);
299 LeaveCriticalSection (&cond->lock);
300 CloseHandle (event);
301 free (elt);
302 return err;
303 }
304
305
306
307
308
309
310
311
312
313
314 gettimeofday (&currtime, NULL);
315 if (currtime.tv_sec > abstime->tv_sec)
316 timeout = 0;
317 else
318 {
319 unsigned long seconds = abstime->tv_sec - currtime.tv_sec;
320 timeout = seconds * 1000;
321 if (timeout / 1000 != seconds)
322 timeout = INFINITE;
323 else
324 {
325 long milliseconds =
326 abstime->tv_nsec / 1000000 - currtime.tv_usec / 1000;
327 if (milliseconds >= 0)
328 {
329 timeout += milliseconds;
330 if (timeout < milliseconds)
331 timeout = INFINITE;
332 }
333 else
334 {
335 if (timeout >= - milliseconds)
336 timeout -= (- milliseconds);
337 else
338 timeout = 0;
339 }
340 }
341 }
342 result = WaitForSingleObject (event, timeout);
343 if (result == WAIT_FAILED)
344 abort ();
345 if (result == WAIT_TIMEOUT)
346 {
347 EnterCriticalSection (&cond->lock);
348 if (glwthread_waitqueue_remove (&cond->waiters, elt))
349 {
350
351
352 if (!(WaitForSingleObject (event, 0) == WAIT_TIMEOUT))
353 abort ();
354 }
355 else
356 {
357
358
359 if (!(WaitForSingleObject (event, 0) == WAIT_OBJECT_0))
360 abort ();
361
362 result = WAIT_OBJECT_0;
363 }
364 LeaveCriticalSection (&cond->lock);
365 }
366 else
367 {
368
369
370 }
371 CloseHandle (event);
372 free (elt);
373
374
375 err = mutex_lock (mutex);
376 return (err ? err :
377 result == WAIT_OBJECT_0 ? 0 :
378 result == WAIT_TIMEOUT ? ETIMEDOUT :
379 EAGAIN);
380 }
381 }
382 }
383 }
384
385 int
386 glwthread_cond_signal (glwthread_cond_t *cond)
387 {
388 if (!cond->guard.done)
389 return EINVAL;
390
391 EnterCriticalSection (&cond->lock);
392
393
394
395 if (cond->waiters.wq_list.wql_next != &cond->waiters.wq_list)
396 glwthread_waitqueue_notify_first (&cond->waiters);
397 LeaveCriticalSection (&cond->lock);
398
399 return 0;
400 }
401
402 int
403 glwthread_cond_broadcast (glwthread_cond_t *cond)
404 {
405 if (!cond->guard.done)
406 return EINVAL;
407
408 EnterCriticalSection (&cond->lock);
409
410
411
412
413 glwthread_waitqueue_notify_all (&cond->waiters);
414 LeaveCriticalSection (&cond->lock);
415
416 return 0;
417 }
418
419 int
420 glwthread_cond_destroy (glwthread_cond_t *cond)
421 {
422 if (!cond->guard.done)
423 return EINVAL;
424 if (cond->waiters.wq_list.wql_next != &cond->waiters.wq_list)
425 return EBUSY;
426 DeleteCriticalSection (&cond->lock);
427 cond->guard.done = 0;
428 return 0;
429 }