GCC Code Coverage Report


Directory: src/gate/
File: src/gate/synchronization.c
Date: 2026-06-21 00:38:37
Exec Total Coverage
Lines: 245 331 74.0%
Functions: 29 33 87.9%
Branches: 74 140 52.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/synchronization.h"
30 #include "gate/streams.h"
31 #include "gate/debugging.h"
32 #include "gate/utilities.h"
33 #include "gate/platforms.h"
34 #include "gate/atomics.h"
35 #include "gate/results.h"
36
37 #if defined(GATE_COMPILER_MSVC15) || defined(GATE_COMPILER_GCC)
38 /*# define GATE_SYNCHRONIZATION_USE_STD_C 1*/
39 #endif
40
41 #if defined(GATE_SYNCHRONIZATION_USE_STD_C)
42 # define GATE_SYNCHRONIZATION_C11_IMPL 1
43 #elif defined(GATE_SYS_WIN16)
44 # define GATE_SYNCHRONIZATION_DUMMY_IMPL 1
45 #elif defined(GATE_SYS_WIN)
46 # define GATE_SYNCHRONIZATION_WINAPI_IMPL 1
47 #elif defined(GATE_SYS_BEOS)
48 # define GATE_SYNCHRONIZATION_BEOS_IMPL 1
49 # define GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE 1
50 # define GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE 1
51 # define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE 1
52 #elif defined(GATE_SYS_DOS)
53 # define GATE_SYNCHRONIZATION_DOS_IMPL 1
54 # define GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE 1
55 # define GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE 1
56 # define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE 1
57 #elif defined(GATE_SYS_POSIX)
58 # define GATE_SYNCHRONIZATION_POSIX_IMPL 1
59 #else
60 # define GATE_SYNCHRONIZATION_DUMMY_IMPL 1
61 #endif
62
63
64
65 /* Generic synchronized stream implementation */
66
67 GATE_INTERFACE(gate_syncmemstream)
68 {
69 GATE_METHOD0(char const*, get_interface_name);
70 GATE_METHOD0(void, release);
71 GATE_METHOD0(int, retain);
72
73 GATE_METHOD3(gate_result_t, read, char* buffer, gate_size_t bufferlength, gate_size_t * returned);
74 GATE_METHOD3(gate_result_t, peek, char* buffer, gate_size_t bufferlength, gate_size_t * returned);
75 GATE_METHOD3(gate_result_t, write, char const* buffer, gate_size_t bufferlength, gate_size_t * written);
76 GATE_METHOD0(gate_result_t, flush);
77 };
78
79 typedef struct gate_syncmemstream_impl
80 {
81 GATE_INTERFACE_VTBL(gate_syncmemstream)* vbl;
82 gate_atomic_int_t ref_counter;
83 gate_uint32_t timeout;
84 gate_mutex_t mutex;
85 gate_syncevent_t syncevent;
86 gate_memstream_t* memstream;
87 } gate_syncmemstream_impl_t;
88
89 static void gate_syncmemstream_release_impl(void* self);
90 static int gate_syncmemstream_retain_impl(void* self);
91 static char const* gate_syncmemstream_interface_name_impl(void* self);
92 static gate_result_t gate_syncmemstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
93 static gate_result_t gate_syncmemstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
94 static gate_result_t gate_syncmemstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
95 static gate_result_t gate_syncmemstream_flush_impl(void* self);
96
97 4 void gate_syncmemstream_release_impl(void* self)
98 {
99 4 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
100
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (gate_atomic_int_dec(&strm->ref_counter) == 0)
101 {
102 /* release syncmemstream */
103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (strm->memstream != NULL)
104 {
105 2 gate_object_release(strm->memstream);
106 }
107 2 gate_syncevent_destroy(&strm->syncevent);
108 2 gate_mutex_destroy(&strm->mutex);
109 2 gate_mem_dealloc(strm);
110 }
111 4 }
112 2 int gate_syncmemstream_retain_impl(void* self)
113 {
114 2 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
115 2 return gate_atomic_int_inc(&strm->ref_counter);
116 }
117 static char const* gate_syncmemstream_interface_name_impl(void* self)
118 {
119 (void)self;
120 return GATE_INTERFACE_NAME_STREAM;
121 }
122 2 static gate_result_t gate_syncmemstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
123 {
124 2 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
125 gate_result_t ret;
126 2 gate_size_t memsize = 0;
127 2 gate_size_t bytesreceived = 0;
128
129
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 while (bytesreceived == 0)
130 {
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (strm->timeout == 0)
132 {
133 ret = gate_syncevent_wait(&strm->syncevent);
134 }
135 else
136 {
137 2 ret = gate_syncevent_timed_wait(&strm->syncevent, strm->timeout);
138 }
139
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 GATE_BREAK_IF_FAILED(ret);
140
141
142 1 ret = gate_mutex_acquire(&strm->mutex);
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
144 {
145 break;
146 }
147
148 do
149 {
150 1 ret = gate_stream_read_block((gate_stream_t*)strm->memstream, buffer, bufferlength, &bytesreceived);
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
152
153 1 memsize = gate_memstream_size(strm->memstream);
154
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (memsize == 0)
155 {
156 1 gate_syncevent_reset(&strm->syncevent);
157 }
158
159 } while (0);
160
161 1 gate_mutex_release(&strm->mutex);
162
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
164 {
165 break;
166 }
167 };
168
169
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (returned != NULL)
170 {
171 2 *returned = bytesreceived;
172 }
173 2 return ret;
174 }
175 static gate_result_t gate_syncmemstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
176 {
177 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
178 gate_result_t ret;
179
180 ret = gate_mutex_acquire(&strm->mutex);
181 if (GATE_SUCCEEDED(ret))
182 {
183 /* protected by MUTEX: */
184 ret = gate_stream_peek(strm->memstream, buffer, bufferlength, returned);
185 gate_mutex_release(&strm->mutex);
186 }
187
188 return ret;
189 }
190 1 static gate_result_t gate_syncmemstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
191 {
192 1 gate_syncmemstream_impl_t* const strm = (gate_syncmemstream_impl_t*)self;
193 gate_result_t ret;
194 1 gate_size_t byteswritten = 0;
195
196 do
197 {
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (bufferlength == 0)
199 {
200 byteswritten = 0;
201 ret = GATE_RESULT_OK;
202 break;
203 }
204
205 1 ret = gate_mutex_acquire(&strm->mutex);
206
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
207 {
208 /* protected by MUTEX: */
209 1 ret = gate_stream_write(strm->memstream, buffer, bufferlength, &byteswritten);
210
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
211 {
212 1 const gate_result_t result = gate_syncevent_set(&strm->syncevent);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_syncevent_set() failed");
214 (void)result;
215 }
216 1 gate_mutex_release(&strm->mutex);
217 }
218
219 } while (0);
220
221
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (written != NULL)
222 {
223 1 *written = byteswritten;
224 }
225 1 return ret;
226 }
227 static gate_result_t gate_syncmemstream_flush_impl(void* self)
228 {
229 gate_syncmemstream_impl_t* strm = (gate_syncmemstream_impl_t*)self;
230 gate_result_t ret;
231
232 ret = gate_mutex_acquire(&strm->mutex);
233 if (GATE_SUCCEEDED(ret))
234 {
235 /* protected by MUTEX: */
236 ret = gate_syncevent_set(&strm->syncevent);
237
238 gate_mutex_release(&strm->mutex);
239 }
240
241 return ret;
242 }
243
244 static GATE_INTERFACE_VTBL(gate_syncmemstream) gate_syncmemstream_vtbl;
245
246 2 static void gate_init_syncmemstream_vtbl()
247 {
248
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_syncmemstream_vtbl.get_interface_name)
249 {
250 GATE_INTERFACE_VTBL(gate_syncmemstream) const local_vtbl =
251 {
252 &gate_syncmemstream_interface_name_impl,
253 &gate_syncmemstream_release_impl,
254 &gate_syncmemstream_retain_impl,
255 &gate_syncmemstream_read_impl,
256 &gate_syncmemstream_peek_impl,
257 &gate_syncmemstream_write_impl,
258 &gate_syncmemstream_flush_impl
259 };
260 1 gate_syncmemstream_vtbl = local_vtbl;
261 }
262 2 }
263
264 2 gate_result_t gate_syncmemstream_create(gate_size_t prealloc, gate_uint32_t timeoutms, gate_stream_t** ptrtostream)
265 {
266 gate_result_t ret;
267 2 gate_syncmemstream_impl_t* impl = NULL;
268 do
269 {
270 2 impl = (gate_syncmemstream_impl_t*)gate_mem_alloc(sizeof(gate_syncmemstream_impl_t));
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == impl)
272 {
273 ret = GATE_RESULT_OUTOFMEMORY;
274 break;
275 }
276 2 gate_mem_clear(impl, sizeof(gate_syncmemstream_impl_t));
277 2 gate_init_syncmemstream_vtbl();
278 2 impl->vbl = &gate_syncmemstream_vtbl;
279 2 gate_atomic_int_init(&impl->ref_counter, 1);
280 2 impl->timeout = timeoutms;
281
282 2 ret = gate_mutex_create(&impl->mutex);
283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
284 {
285 break;
286 }
287 2 ret = gate_syncevent_create(&impl->syncevent, false);
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
289 {
290 break;
291 }
292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == (impl->memstream = gate_memstream_create(prealloc)))
293 {
294 ret = GATE_RESULT_OUTOFMEMORY;
295 break;
296 }
297
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptrtostream)
298 {
299 2 *ptrtostream = (gate_stream_t*)impl;
300 2 impl = NULL;
301 }
302 2 ret = GATE_RESULT_OK;
303 } while (0);
304
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl != NULL)
306 {
307 impl->vbl->release(impl);
308 }
309
310 2 return ret;
311 }
312
313
314 3 gate_result_t gate_semaphore_create(gate_semaphore_t* semaphore, gate_uint32_t count)
315 {
316 gate_result_t result;
317 3 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_CREATE(semaphore, gate_platform_semaphore_t);
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ptr_sem == NULL)
319 {
320 return GATE_RESULT_OUTOFMEMORY;
321 }
322 3 result = gate_platform_semaphore_create(ptr_sem, count);
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(result))
324 {
325 GATE_HANDLESTORE_DESTROY(semaphore);
326 }
327 3 return result;
328 }
329 4 gate_result_t gate_semaphore_acquire(gate_semaphore_t* semaphore)
330 {
331 4 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
332 4 return gate_platform_semaphore_acquire(ptr_sem, NULL);
333 }
334 4 gate_result_t gate_semaphore_timed_acquire(gate_semaphore_t* semaphore, gate_uint32_t timeoutms)
335 {
336 4 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
337 4 return gate_platform_semaphore_acquire(ptr_sem, &timeoutms);
338 }
339 6 gate_result_t gate_semaphore_release(gate_semaphore_t* semaphore)
340 {
341 6 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
342 6 return gate_platform_semaphore_release(ptr_sem);
343 }
344 3 gate_result_t gate_semaphore_destroy(gate_semaphore_t* semaphore)
345 {
346 3 gate_result_t ret = GATE_RESULT_FAILED;
347 3 gate_platform_semaphore_t* ptr_sem = GATE_HANDLESTORE_ACCESS(semaphore, gate_platform_semaphore_t);
348
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_sem)
349 {
350 3 ret = gate_platform_semaphore_destroy(ptr_sem);
351 3 GATE_HANDLESTORE_DESTROY(semaphore);
352 }
353 3 return ret;
354 }
355
356
357
358 #if defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
359
360 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
361 {
362 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
363 return gate_platform_semaphore_create(ptr_sem, 1);
364 }
365
366 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
367 {
368 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
369 return gate_platform_semaphore_acquire(ptr_sem, NULL);
370 }
371
372 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
373 {
374 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
375 return gate_platform_semaphore_release(ptr_sem);
376 }
377
378 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
379 {
380 gate_platform_semaphore_t* ptr_sem = (gate_platform_semaphore_t*)mutex;
381 return gate_platform_semaphore_destroy(ptr_sem);
382 }
383
384 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
385
386
387
388 #if defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
389
390 typedef struct gate_semevent_class
391 {
392 gate_platform_semaphore_t signal;
393 gate_atomic_int_t state;
394 } gate_semevent_t;
395
396 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
397 {
398 gate_result_t result;
399 gate_semevent_t* ptr = GATE_HANDLESTORE_CREATE(syncevent, gate_semevent_t);
400 if (!ptr)
401 {
402 return GATE_RESULT_OUTOFMEMORY;
403 }
404 gate_atomic_int_init(&ptr->state, autoreset ? 0 : 0x80);
405 result = gate_platform_semaphore_create(&ptr->signal, 1);
406 if (GATE_FAILED(result))
407 {
408 GATE_HANDLESTORE_DESTROY(syncevent);
409 }
410 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
411 if (GATE_FAILED(result))
412 {
413 gate_platform_semaphore_destroy(&ptr->signal);
414 GATE_HANDLESTORE_DESTROY(syncevent);
415 }
416 return result;
417 }
418 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
419 {
420 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
421 if (ptr)
422 {
423 gate_platform_semaphore_destroy(&ptr->signal);
424 GATE_HANDLESTORE_DESTROY(syncevent);
425 return GATE_RESULT_OK;
426 }
427 return GATE_RESULT_INVALIDSTATE;
428 }
429
430 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
431 {
432 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
433 gate_result_t result;
434 gate_int32_t old_state = gate_atomic_int_xchg_if(&ptr->state, 0, 1);
435 if (old_state == 1)
436 {
437 /* was already set */
438 return GATE_RESULT_OK;
439 }
440 if (old_state == 0)
441 {
442 /* was reset, is now set */
443 result = gate_platform_semaphore_release(&ptr->signal);
444 if (GATE_FAILED(result))
445 {
446 gate_atomic_int_xchg_if(&ptr->state, 1, 0);
447 }
448 return result;
449 }
450 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x80, 0x81);
451 if (old_state == 0x81)
452 {
453 /* was already set */
454 return GATE_RESULT_OK;
455 }
456 if (old_state == 0x80)
457 {
458 /* was reset, is now set */
459 result = gate_platform_semaphore_release(&ptr->signal);
460 if (GATE_FAILED(result))
461 {
462 gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x80);
463 }
464 return result;
465 }
466 return GATE_RESULT_INVALIDSTATE;
467 }
468
469 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
470 {
471 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
472 gate_result_t result;
473 gate_int32_t old_state = gate_atomic_int_xchg_if(&ptr->state, 1, 0);
474 if (old_state == 0)
475 {
476 return GATE_RESULT_OK;
477 }
478 if (old_state == 1)
479 {
480 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
481 if (GATE_FAILED(result))
482 {
483 gate_atomic_int_xchg_if(&ptr->state, 0, 1);
484 }
485 return result;
486 }
487
488 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x80);
489 if (old_state == 0x80)
490 {
491 return GATE_RESULT_OK;
492 }
493 if (old_state == 0x81)
494 {
495 result = gate_platform_semaphore_acquire(&ptr->signal, NULL);
496 if (GATE_FAILED(result))
497 {
498 gate_atomic_int_xchg_if(&ptr->state, 0x80, 0x81);
499 }
500 return result;
501 }
502 return GATE_RESULT_INVALIDSTATE;
503 }
504
505 static gate_result_t gate_syncevent_wait_impl(gate_syncevent_t* syncevent, gate_uint32_t const* timeout)
506 {
507 gate_semevent_t* ptr = GATE_HANDLESTORE_ACCESS(syncevent, gate_semevent_t);
508 gate_result_t result;
509 gate_int32_t old_state;
510
511 result = gate_platform_semaphore_acquire(&ptr->signal, timeout);
512
513 if (GATE_FAILED(result))
514 {
515 return result;
516 }
517
518 /* try auto-reset states */
519 old_state = gate_atomic_int_xchg_if(&ptr->state, 1, 0);
520 if (old_state == 1)
521 {
522 /* event was set, we have reset it, now we release the semaphore */
523 result = gate_platform_semaphore_release(&ptr->signal);
524 if (GATE_FAILED(result))
525 {
526 gate_atomic_int_xchg_if(&ptr->state, 0, 1);
527 }
528 return result;
529 }
530 if (old_state == 0)
531 {
532 /* it should be impossoble to acquire the samephore with state zero */
533 result = gate_platform_semaphore_release(&ptr->signal);
534 return GATE_RESULT_INVALIDSTATE;
535 }
536
537 /* try non-auto-reset states */
538 old_state = gate_atomic_int_xchg_if(&ptr->state, 0x81, 0x81);
539 if (old_state == 0x81)
540 {
541 /* event is set, and will remain in this state */
542 result = gate_platform_semaphore_release(&ptr->signal);
543 return result;
544 }
545 if (old_state == 0x80)
546 {
547 /* it should be impossoble to acquire the samephore with state zero */
548 result = gate_platform_semaphore_release(&ptr->signal);
549 return GATE_RESULT_INVALIDSTATE;
550 }
551
552 return GATE_RESULT_INVALIDSTATE;
553 }
554
555 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
556 {
557 return gate_syncevent_wait_impl(syncevent, NULL);
558 }
559
560 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
561 {
562 return gate_syncevent_wait_impl(syncevent, &timeoutms);
563 }
564
565 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
566
567
568
569 #if defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
570
571 #define GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX 1023
572
573 typedef struct gate_semcond_class
574 {
575 gate_platform_semaphore_t waits;
576 gate_platform_semaphore_t signals;
577 gate_atomic_int_t wait_counter;
578 } gate_semcond_t;
579
580 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
581 {
582 gate_semcond_t* ptr = GATE_HANDLESTORE_CREATE(cond, gate_semcond_t);
583 size_t n;
584 if (!ptr)
585 {
586 return GATE_RESULT_OUTOFMEMORY;
587 }
588
589 gate_atomic_int_init(&ptr->wait_counter, 0);
590
591 /* TODO: error handling */
592 gate_platform_semaphore_create(&ptr->waits, GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX);
593 for (n = 0; n != GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX; ++n)
594 {
595 gate_platform_semaphore_acquire(&ptr->waits, NULL);
596 }
597
598 gate_platform_semaphore_create(&ptr->signals, GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX);
599 for (n = 0; n != GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE_MAX; ++n)
600 {
601 gate_platform_semaphore_acquire(&ptr->signals, NULL);
602 }
603
604 return GATE_RESULT_OK;
605 }
606
607 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
608 {
609 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
610 if (ptr)
611 {
612 gate_platform_semaphore_destroy(&ptr->signals);
613 gate_platform_semaphore_destroy(&ptr->waits);
614 GATE_HANDLESTORE_DESTROY(cond);
615 return GATE_RESULT_OK;
616 }
617 return GATE_RESULT_INVALIDSTATE;
618 }
619
620 static gate_result_t gate_synccodition_wait_impl(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t const* timeout)
621 {
622 gate_result_t result;
623 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
624
625 gate_atomic_int_inc(&ptr->wait_counter);
626
627 result = gate_mutex_release(mutex);
628 if (GATE_FAILED(result))
629 {
630 gate_atomic_int_dec(&ptr->wait_counter);
631 return result;
632 }
633
634 do
635 {
636 result = gate_platform_semaphore_acquire(&ptr->waits, timeout);
637 if (GATE_FAILED(result))
638 {
639 gate_atomic_int_dec(&ptr->wait_counter);
640 break;
641 }
642
643 result = gate_platform_semaphore_release(&ptr->signals);
644 if (GATE_FAILED(result))
645 {
646 gate_atomic_int_dec(&ptr->wait_counter);
647 gate_platform_semaphore_release(&ptr->waits);
648 break;
649 }
650 } while (0);
651
652 gate_mutex_acquire(mutex);
653
654 return result;
655 }
656
657 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
658 {
659 return gate_synccodition_wait_impl(cond, mutex, NULL);
660 }
661
662 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
663 {
664 return gate_synccodition_wait_impl(cond, mutex, &timeoutms);
665 }
666
667 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
668 {
669 gate_result_t ret = GATE_RESULT_OK;
670 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
671 gate_int32_t current_counter;
672
673 do
674 {
675 current_counter = gate_atomic_int_dec(&ptr->wait_counter);
676 if (current_counter < 0)
677 {
678 gate_atomic_int_inc(&ptr->wait_counter);
679 break;
680 }
681 gate_platform_semaphore_release(&ptr->waits);
682 gate_platform_semaphore_acquire(&ptr->signals, NULL);
683 } while (0);
684
685 return ret;
686 }
687
688 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
689 {
690 gate_result_t ret = GATE_RESULT_OK;
691 gate_semcond_t* ptr = GATE_HANDLESTORE_ACCESS(cond, gate_semcond_t);
692 gate_int32_t current_counter;
693
694 do
695 {
696 current_counter = gate_atomic_int_dec(&ptr->wait_counter);
697 if (current_counter < 0)
698 {
699 gate_atomic_int_inc(&ptr->wait_counter);
700 break;
701 }
702 gate_platform_semaphore_release(&ptr->waits);
703 gate_platform_semaphore_acquire(&ptr->signals, NULL);
704 } while (1);
705
706 return ret;
707 }
708
709 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
710
711
712
713
714
715 #if defined(GATE_SYNCHRONIZATION_C11_IMPL)
716
717 #if defined(GATE_COMPILER_MSVC)
718
719 #include <time.h>
720
721 #if _MSC_VER >= 1920
722 // MSVC 2019+
723 # include <xthreads.h>
724 #elif _MSC_VER >= 1900
725 // MSVC 2015+
726 # include <thr/xthreads.h>
727 #else
728 #endif
729
730 # define thrd_success _Thrd_success
731 # define thrd_nomem _Thrd_nomem
732 # define thrd_timedout _Thrd_timedout
733 # define thrd_busy _Thrd_busy
734 # define thrd_error _Thrd_error
735
736 # define mtx_t _Mtx_t
737 # define mtx_init(ptr_mtx, mtx_type) _Mtx_init(ptr_mtx, mtx_type)
738 # define mtx_destroy(ptr_mtx) _Mtx_destroy(*ptr_mtx)
739 # define mtx_lock(ptr_mtx) _Mtx_lock(*ptr_mtx)
740 # define mtx_unlock(ptr_mtx) _Mtx_unlock(*ptr_mtx)
741 # define mtx_trylock(ptr_mtx) _Mtx_trylock(*ptr_mtx)
742
743 # define mtx_plain _Mtx_plain
744 # define mtx_timed _Mtx_timed
745 # define mtx_recursive _Mtx_recursive
746
747 # define cnd_t _Cnd_t
748 # define cnd_init(ptr_cnd) _Cnd_init(ptr_cnd)
749 # define cnd_destroy(ptr_cnd) _Cnd_destroy(*ptr_cnd)
750 # define cnd_wait(ptr_cnd, ptr_mtx) _Cnd_wait(*ptr_cnd, *ptr_mtx)
751 # define cnd_timedwait(ptr_cnd, ptr_mtx, ptr_timespec) _Cnd_timedwait(*ptr_cnd, *ptr_mtx, (xtime const*)ptr_timespec)
752 # define cnd_signal(ptr_cnd) _Cnd_signal(*ptr_cnd)
753 # define cnd_broadcast(ptr_cnd) _Cnd_broadcast(*ptr_cnd)
754
755 #else
756 # include <threads.h>
757 #endif
758
759
760 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
761 {
762 mtx_t* ptr = (mtx_t*)mutex;
763 int result = mtx_init(ptr, mtx_plain);
764 if (result == thrd_success)
765 {
766 return GATE_RESULT_OK;
767 }
768 else
769 {
770 return GATE_RESULT_FAILED;
771 }
772 }
773
774 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
775 {
776 mtx_t* ptr = (mtx_t*)mutex;
777 int result = mtx_lock(ptr);
778 if (result == thrd_success)
779 {
780 return GATE_RESULT_OK;
781 }
782 else
783 {
784 return GATE_RESULT_FAILED;
785 }
786 }
787
788 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
789 {
790 mtx_t* ptr = (mtx_t*)mutex;
791 int result = mtx_unlock(ptr);
792 if (result == thrd_success)
793 {
794 return GATE_RESULT_OK;
795 }
796 else
797 {
798 return GATE_RESULT_FAILED;
799 }
800 }
801
802 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
803 {
804 mtx_t* ptr = (mtx_t*)mutex;
805 mtx_destroy(ptr);
806 return GATE_RESULT_OK;
807 }
808
809
810
811
812 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
813 {
814 cnd_t* ptr_cnd = GATE_HANDLESTORE_CREATE(cond, cnd_t);
815
816 if (!ptr_cnd)
817 {
818 return GATE_RESULT_OUTOFRESOURCES;
819 }
820
821 if (thrd_success == cnd_init(ptr_cnd))
822 {
823 return GATE_RESULT_OK;
824 }
825 else
826 {
827 GATE_HANDLESTORE_DESTROY(cond);
828 return GATE_RESULT_FAILED;
829 }
830 }
831 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
832 {
833 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
834 if (ptr_cnd)
835 {
836 cnd_destroy(ptr_cnd);
837 GATE_HANDLESTORE_DESTROY(cond);
838 }
839 return GATE_RESULT_OK;
840 }
841 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
842 {
843 int result;
844
845 mtx_t* ptr_mtx = (mtx_t*)mutex;
846 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
847
848 result = cnd_wait(ptr_cnd, ptr_mtx);
849 switch (result)
850 {
851 case thrd_success: return GATE_RESULT_OK;
852 default: return GATE_RESULT_FAILED;
853 }
854 }
855
856 static void calc_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeoutms)
857 {
858 timespec_get(ptr_ts, TIME_UTC);
859
860 ptr_ts->tv_sec += timeoutms / 1000;
861 ptr_ts->tv_nsec += (long)(timeoutms % 1000) * 1000000L;
862 ptr_ts->tv_sec += (ptr_ts->tv_nsec / 1000000000L);
863 ptr_ts->tv_nsec %= 1000000000L;
864 }
865
866 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
867 {
868 struct timespec time_point;
869 int result;
870
871 mtx_t* ptr_mtx = (mtx_t*)mutex;
872 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
873
874 calc_timeout_timespec(&time_point, timeoutms);
875
876 result = cnd_timedwait(ptr_cnd, ptr_mtx, &time_point);
877 switch (result)
878 {
879 case thrd_success: return GATE_RESULT_OK;
880 case thrd_timedout: return GATE_RESULT_TIMEOUT;
881 default: return GATE_RESULT_FAILED;
882 }
883 }
884 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
885 {
886 int result;
887 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
888
889 result = cnd_signal(ptr_cnd);
890 switch (result)
891 {
892 case thrd_success: return GATE_RESULT_OK;
893 default: return GATE_RESULT_FAILED;
894 }
895 }
896 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
897 {
898 int result;
899 cnd_t* ptr_cnd = GATE_HANDLESTORE_ACCESS(cond, cnd_t);
900
901 result = cnd_broadcast(ptr_cnd);
902 switch (result)
903 {
904 case thrd_success: return GATE_RESULT_OK;
905 default: return GATE_RESULT_FAILED;
906 }
907 }
908
909
910
911 typedef struct gate_syncevent_impl
912 {
913 cnd_t cond;
914 mtx_t mutex;
915 gate_bool_t state;
916 gate_bool_t autoreset;
917 } gate_syncevent_impl_t;
918
919 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
920 {
921 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_CREATE(syncevent, gate_syncevent_impl_t);
922 if (NULL == ptr_evt)
923 {
924 return GATE_RESULT_OUTOFRESOURCES;
925 }
926 cnd_init(&ptr_evt->cond);
927 mtx_init(&ptr_evt->mutex, mtx_timed);
928 ptr_evt->state = false;
929 ptr_evt->autoreset = autoreset;
930
931 return GATE_RESULT_OK;
932 }
933 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
934 {
935 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
936 if (ptr_evt)
937 {
938 mtx_destroy(&ptr_evt->mutex);
939 cnd_destroy(&ptr_evt->cond);
940 GATE_HANDLESTORE_DESTROY(syncevent);
941 }
942 return GATE_RESULT_OK;
943 }
944 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
945 {
946 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
947 mtx_lock(&ptr_evt->mutex);
948 ptr_evt->state = true;
949 if (ptr_evt->autoreset)
950 {
951 cnd_signal(&ptr_evt->cond);
952 }
953 else
954 {
955 cnd_broadcast(&ptr_evt->cond);
956 }
957
958 mtx_unlock(&ptr_evt->mutex);
959 return GATE_RESULT_OK;
960 }
961 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
962 {
963 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
964
965 do
966 {
967 } while (0);
968
969 mtx_lock(&ptr_evt->mutex);
970 ptr_evt->state = false;
971 mtx_unlock(&ptr_evt->mutex);
972 return GATE_RESULT_OK;
973 }
974 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
975 {
976 gate_result_t ret = GATE_RESULT_OK;
977
978 do
979 {
980 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
981 int status = mtx_lock(&ptr_evt->mutex);
982 if (status != thrd_success)
983 {
984 ret = GATE_RESULT_FAILED;
985 break;
986 }
987
988 while (!ptr_evt->state)
989 {
990 status = cnd_wait(&ptr_evt->cond, &ptr_evt->mutex);
991 if (status != thrd_success)
992 {
993 ret = GATE_RESULT_FAILED;
994 break;
995 }
996 }
997
998 mtx_unlock(&ptr_evt->mutex);
999 } while (0);
1000 return ret;
1001 }
1002
1003 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
1004 {
1005 gate_result_t ret = GATE_RESULT_OK;
1006
1007 do
1008 {
1009 gate_syncevent_impl_t* ptr_evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_syncevent_impl_t);
1010 int status;
1011 struct timespec time_point;
1012
1013 calc_timeout_timespec(&time_point, timeoutms);
1014
1015 status = mtx_lock(&ptr_evt->mutex);
1016 if (status != thrd_success)
1017 {
1018 ret = GATE_RESULT_FAILED;
1019 break;
1020 }
1021
1022 while (!ptr_evt->state)
1023 {
1024 status = cnd_timedwait(&ptr_evt->cond, &ptr_evt->mutex, &time_point);
1025 if (status == thrd_timedout)
1026 {
1027 ret = GATE_RESULT_TIMEOUT;
1028 break;
1029 }
1030 else if (status != thrd_success)
1031 {
1032 ret = GATE_RESULT_FAILED;
1033 break;
1034 }
1035 }
1036
1037 mtx_unlock(&ptr_evt->mutex);
1038 } while (0);
1039
1040 return ret;
1041 }
1042
1043
1044 /*
1045 typedef struct gate_semaphore_impl_class
1046 {
1047 cnd_t cond;
1048 mtx_t mutex;
1049 gate_uint32_t counter;
1050 gate_uint32_t max;
1051 } gate_semaphore_impl_t;
1052
1053 gate_result_t gate_semaphore_create(gate_semaphore_t* semaphore, gate_uint32_t count)
1054 {
1055 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_CREATE(semaphore, gate_semaphore_impl_t);
1056 if(!impl)
1057 {
1058 return GATE_RESULT_OUTOFRESOURCES;
1059 }
1060
1061 cnd_init(&impl->cond);
1062 mtx_init(&impl->mutex, mtx_timed);
1063 impl->counter = count;
1064 impl->max = count;
1065
1066 return GATE_RESULT_OK;
1067 }
1068
1069 gate_result_t gate_semaphore_acquire(gate_semaphore_t* semaphore)
1070 {
1071 gate_result_t ret = GATE_RESULT_OK;
1072 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1073 int status;
1074
1075 do
1076 {
1077 mtx_lock(&impl->mutex);
1078 for(;;)
1079 {
1080 if(impl->counter > 0)
1081 {
1082 --impl->counter;
1083 ret = GATE_RESULT_OK;
1084 break;
1085 }
1086
1087 status = cnd_wait(&impl->cond, &impl->mutex);
1088 if(status != thrd_success)
1089 {
1090 ret = GATE_RESULT_FAILED;
1091 break;
1092 }
1093 }
1094 mtx_unlock(&impl->mutex);
1095 } while(0);
1096
1097 return ret;
1098 }
1099
1100 gate_result_t gate_semaphore_timed_acquire(gate_semaphore_t* semaphore, gate_uint32_t timeoutms)
1101 {
1102 gate_result_t ret = GATE_RESULT_OK;
1103 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1104 struct timespec time_point;
1105 int status;
1106
1107 calc_timeout_timespec(&time_point, timeoutms);
1108
1109 do
1110 {
1111 mtx_lock(&impl->mutex);
1112 for(;;)
1113 {
1114 if(impl->counter > 0)
1115 {
1116 --impl->counter;
1117 ret = GATE_RESULT_OK;
1118 break;
1119 }
1120 // TODO
1121 status = cnd_timedwait(&impl->cond, &impl->mutex, &time_point);
1122 if(status == thrd_timedout)
1123 {
1124 ret = GATE_RESULT_TIMEOUT;
1125 break;
1126 }
1127 else if(status != thrd_success)
1128 {
1129 ret = GATE_RESULT_FAILED;
1130 break;
1131 }
1132 }
1133
1134 mtx_unlock(&impl->mutex);
1135 } while(0);
1136
1137 return ret;
1138 }
1139
1140 gate_result_t gate_semaphore_release(gate_semaphore_t* semaphore)
1141 {
1142 gate_result_t ret = GATE_RESULT_OK;
1143 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1144 mtx_lock(&impl->mutex);
1145 ++impl->counter;
1146 cnd_broadcast(&impl->cond);
1147 mtx_unlock(&impl->mutex);
1148 return ret;
1149 }
1150
1151 gate_result_t gate_semaphore_destroy(gate_semaphore_t* semaphore)
1152 {
1153 gate_semaphore_impl_t* impl = GATE_HANDLESTORE_ACCESS(semaphore, gate_semaphore_impl_t);
1154 if(impl)
1155 {
1156 mtx_destroy(&impl->mutex);
1157 cnd_destroy(&impl->cond);
1158 GATE_HANDLESTORE_DESTROY(semaphore);
1159 }
1160 return GATE_RESULT_OK;
1161 }
1162 */
1163
1164
1165 #endif /* GATE_SYNCHRONIZATION_C11_IMPL */
1166
1167
1168
1169 #if defined(GATE_SYNCHRONIZATION_WINAPI_IMPL)
1170
1171 #include "gate/platforms.h"
1172
1173
1174 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
1175
1176 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
1177 {
1178 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1179 GATE_DEBUG_ASSERT(sizeof(mutex->handles) >= sizeof(CRITICAL_SECTION));
1180 if (gate_win32_section_create(section))
1181 {
1182 return GATE_RESULT_OK;
1183 }
1184 else
1185 {
1186 return GATE_RESULT_OUTOFRESOURCES;
1187 }
1188 }
1189 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
1190 {
1191 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1192 if (gate_win32_section_enter(section))
1193 {
1194 return GATE_RESULT_OK;
1195 }
1196 else
1197 {
1198 return GATE_RESULT_INVALIDSTATE;
1199 }
1200 }
1201 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
1202 {
1203 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1204 gate_win32_section_leave(section);
1205 return GATE_RESULT_OK;
1206 }
1207 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
1208 {
1209 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1210 gate_win32_section_delete(section);
1211 return GATE_RESULT_OK;
1212 }
1213 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
1214
1215
1216 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
1217 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
1218 {
1219 HANDLE* hevent = GATE_HANDLESTORE_CREATE(syncevent, HANDLE);
1220 if (hevent == NULL)
1221 {
1222 return GATE_RESULT_OUTOFMEMORY;
1223 }
1224 *hevent = CreateEvent(NULL, (autoreset == false) ? TRUE : FALSE, FALSE, NULL);
1225 if (*hevent == NULL)
1226 {
1227 gate_handlestore_destroy(syncevent);
1228 return GATE_RESULT_FAILED;
1229 }
1230 return GATE_RESULT_OK;
1231 }
1232 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
1233 {
1234 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1235 if (CloseHandle(*hevent) == FALSE)
1236 {
1237 return GATE_RESULT_FAILED;
1238 }
1239 *hevent = NULL;
1240 GATE_HANDLESTORE_DESTROY(syncevent);
1241 return GATE_RESULT_OK;
1242 }
1243 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
1244 {
1245 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1246 if (SetEvent(*hevent) == FALSE)
1247 {
1248 return GATE_RESULT_FAILED;
1249 }
1250 return GATE_RESULT_OK;
1251 }
1252 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
1253 {
1254 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1255 if (ResetEvent(*hevent) == FALSE)
1256 {
1257 return GATE_RESULT_FAILED;
1258 }
1259 return GATE_RESULT_OK;
1260 }
1261 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
1262 {
1263 return gate_syncevent_timed_wait(syncevent, INFINITE);
1264 }
1265 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeout)
1266 {
1267 HANDLE* hevent = GATE_HANDLESTORE_ACCESS(syncevent, HANDLE);
1268 DWORD result = WaitForSingleObject(*hevent, timeout);
1269 switch (result)
1270 {
1271 case WAIT_OBJECT_0: return GATE_RESULT_OK;
1272 case WAIT_TIMEOUT: return GATE_RESULT_TIMEOUT;
1273 case WAIT_FAILED:
1274 default: return GATE_RESULT_FAILED;
1275 }
1276 }
1277 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
1278
1279
1280 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
1281
1282 #if defined(GATE_SYS_WIN_MODERN_ARCH) && !defined(GATE_SYS_WINCE)
1283 /* We do not need NT4/5 workarounds and can use NT6 directly */
1284 # define GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE 1
1285 #endif
1286
1287 #if defined(GATE_SYS_WINCE)
1288 /* We have no NT6 and always need NT4/5/CE workaround */
1289 # define GATE_SYNCHRONIZATION_CONDITION_NO_NT6 1
1290 #endif
1291
1292
1293 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE) || defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1294
1295 /* WinNT 4 to XP/2K3 compatible workaround for conditions */
1296
1297 typedef struct gate_win32_ntcond_class
1298 {
1299 gate_atomic_int_t wait_counter;
1300 gate_atomic_int_t signal_all;
1301 HANDLE wait_semaphore;
1302 HANDLE wakeup_completed;
1303 CRITICAL_SECTION signal_lock; /**< lock entry of signal and wait routines, when a signal is currently published */
1304 } gate_win32_ntcond_t;
1305
1306 static gate_result_t gate_win32_nt4cond_create(gate_synccondition_t* cond)
1307 {
1308 gate_result_t ret = GATE_RESULT_FAILED;
1309 gate_win32_ntcond_t* ntcond;
1310 do
1311 {
1312 ntcond = GATE_HANDLESTORE_CREATE(cond, gate_win32_ntcond_t);
1313 if (NULL == ntcond)
1314 {
1315 ret = GATE_RESULT_OUTOFMEMORY;
1316 break;
1317 }
1318
1319 ntcond->wait_semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
1320 if (NULL == ntcond->wait_semaphore)
1321 {
1322 GATE_HANDLESTORE_DESTROY(cond);
1323 ret = GATE_RESULT_OUTOFRESOURCES;
1324 break;
1325 }
1326
1327 ntcond->wakeup_completed = CreateEvent(NULL, FALSE, FALSE, NULL);
1328 if (NULL == ntcond->wakeup_completed)
1329 {
1330 CloseHandle(ntcond->wait_semaphore);
1331 GATE_HANDLESTORE_DESTROY(cond);
1332 ret = GATE_RESULT_OUTOFRESOURCES;
1333 break;
1334 }
1335
1336 if (!gate_win32_section_create(&ntcond->signal_lock))
1337 {
1338 CloseHandle(ntcond->wakeup_completed);
1339 CloseHandle(ntcond->wait_semaphore);
1340 GATE_HANDLESTORE_DESTROY(cond);
1341 ret = GATE_RESULT_OUTOFRESOURCES;
1342 break;
1343 }
1344
1345 gate_atomic_int_init(&ntcond->wait_counter, 0);
1346 gate_atomic_int_init(&ntcond->signal_all, 0);
1347
1348 ret = GATE_RESULT_OK;
1349 } while (0);
1350 return ret;
1351 }
1352 static gate_result_t gate_win32_nt4cond_destroy(gate_synccondition_t* cond)
1353 {
1354 gate_result_t ret = GATE_RESULT_FAILED;
1355 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1356 if (ntcond)
1357 {
1358 gate_win32_section_delete(&ntcond->signal_lock);
1359 CloseHandle(ntcond->wakeup_completed);
1360 CloseHandle(ntcond->wait_semaphore);
1361 GATE_HANDLESTORE_DESTROY(cond);
1362 ret = GATE_RESULT_OK;
1363 }
1364 return ret;
1365 }
1366
1367 GATE_CORE_API BOOL WINAPI gate_win32_section_enter(LPCRITICAL_SECTION section);
1368 GATE_CORE_API void WINAPI gate_win32_section_leave(LPCRITICAL_SECTION section);
1369
1370 static gate_result_t gate_win32_nt4cond_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1371 {
1372 gate_result_t ret = GATE_RESULT_FAILED;
1373 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1374 DWORD wait_result;
1375 gate_bool_t is_last_wakeup;
1376 gate_int32_t current_wait_counter;
1377
1378 if (!cond || !mutex)
1379 {
1380 return GATE_RESULT_INVALIDARG;
1381 }
1382
1383 { /* wait until running signal publishing has finished */
1384 gate_win32_section_enter(&ntcond->signal_lock);
1385
1386 gate_atomic_int_inc(&ntcond->wait_counter);
1387 gate_mutex_release(mutex); /* unlock mutex */
1388
1389 gate_win32_section_leave(&ntcond->signal_lock);
1390 }
1391
1392 /* await a signal */
1393 wait_result = WaitForSingleObject(ntcond->wait_semaphore, timeoutms);
1394
1395 current_wait_counter = gate_atomic_int_dec(&ntcond->wait_counter);
1396
1397 /* lock mutex again */
1398 ret = gate_mutex_acquire(mutex);
1399
1400 is_last_wakeup = gate_atomic_int_get(&ntcond->signal_all) && (current_wait_counter == 0);
1401 if (is_last_wakeup)
1402 {
1403 /* notify publisher, that his was the last receiver that woke up */
1404 SetEvent(ntcond->wakeup_completed);
1405 }
1406
1407 if (GATE_FAILED(ret))
1408 {
1409 /* CRITICAL: mutex acquisition failed,
1410 implementation is now broken,
1411 cannot proceed correctly
1412 */
1413 return ret;
1414 }
1415
1416 switch (wait_result)
1417 {
1418 case WAIT_OBJECT_0: return GATE_RESULT_OK;
1419 case WAIT_TIMEOUT: return GATE_RESULT_TIMEOUT;
1420 default: break;
1421 }
1422 return GATE_RESULT_FAILED;
1423 }
1424
1425 static gate_result_t gate_win32_nt4cond_signal(gate_synccondition_t* cond, gate_bool_t signal_all)
1426 {
1427 gate_win32_ntcond_t* ntcond = GATE_HANDLESTORE_ACCESS(cond, gate_win32_ntcond_t);
1428 gate_int32_t waiters;
1429
1430 /* block parallel signals and new waiters */
1431 gate_win32_section_enter(&ntcond->signal_lock);
1432
1433 waiters = gate_atomic_int_get(&ntcond->wait_counter);
1434 if (waiters > 0)
1435 {
1436 if (!signal_all)
1437 {
1438 ReleaseSemaphore(ntcond->wait_semaphore, 1, NULL);
1439 }
1440 else
1441 {
1442 gate_atomic_int_set(&ntcond->signal_all, 1);
1443 ReleaseSemaphore(ntcond->wait_semaphore, waiters, NULL);
1444
1445 WaitForSingleObject(ntcond->wakeup_completed, INFINITE);
1446 /* asure that the semaphore reaches count zero (if some waiters have timed out in between) */
1447 while (waiters-- != 0)
1448 {
1449 if (WAIT_OBJECT_0 != WaitForSingleObject(ntcond->wait_semaphore, 0))
1450 {
1451 break;
1452 }
1453 }
1454 gate_atomic_int_set(&ntcond->signal_all, 0);
1455 }
1456 }
1457
1458 gate_win32_section_leave(&ntcond->signal_lock);
1459
1460 return GATE_RESULT_OK;
1461 }
1462
1463 static gate_result_t gate_win32_nt4cond_signal_one(gate_synccondition_t* cond)
1464 {
1465 return gate_win32_nt4cond_signal(cond, false);
1466 }
1467
1468 static gate_result_t gate_win32_nt4cond_signal_all(gate_synccondition_t* cond)
1469 {
1470 return gate_win32_nt4cond_signal(cond, true);
1471 }
1472
1473 #endif /* !defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE) || defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6) */
1474
1475
1476 /* WinNT 6 (Vista+) conditional variables */
1477 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1478
1479 #if defined(GATE_SYS_WIN_MODERN_ARCH)
1480
1481 #if !defined(GATE_COMPILER_MSVC) || defined(GATE_COMPILER_MSVC12)
1482 /* NOTICE: MSVC 2010 does ship synchapi.h by default */
1483 # include <synchapi.h>
1484 #endif
1485
1486 #define Win32InitializeConditionVariable(c) InitializeConditionVariable((PCONDITION_VARIABLE)c)
1487 #define Win32SleepConditionVariableCS(c, s, t) SleepConditionVariableCS((PCONDITION_VARIABLE)c, (PCRITICAL_SECTION)s, t)
1488 #define Win32WakeAllConditionVariable(c) WakeAllConditionVariable((PCONDITION_VARIABLE)c)
1489 #define Win32WakeConditionVariable(c) WakeConditionVariable((PCONDITION_VARIABLE)c)
1490
1491 #else
1492
1493 static void (WINAPI* Win32InitializeConditionVariable)(PVOID ConditionVariable);
1494 static BOOL(WINAPI* Win32SleepConditionVariableCS)(PVOID ConditionVariable, PVOID CriticalSection, DWORD dwMilliseconds);
1495 static void (WINAPI* Win32WakeAllConditionVariable)(PVOID ConditionVariable);
1496 static void (WINAPI* Win32WakeConditionVariable)(PVOID ConditionVariable);
1497
1498 static gate_bool_t win32_condition_variable_supported()
1499 {
1500 static gate_atomic_int_t cond_api_load_state = 0;
1501 gate_int32_t state;
1502
1503 do
1504 {
1505 state = gate_atomic_int_xchg_if(&cond_api_load_state, 0, 1);
1506 if (state == 2)
1507 {
1508 /* api successfully loaded */
1509 return true;
1510 }
1511 else if (state >= 3)
1512 {
1513 /* api loader failed */
1514 return false;
1515 }
1516 else if (state == 0)
1517 {
1518 /* try to load api */
1519 const HMODULE hkernel = gate_win32_get_kernel_module();
1520 const gate_bool_t api_loaded
1521 = gate_win32_get_proc_address(hkernel, "InitializeConditionVariable", &Win32InitializeConditionVariable)
1522 && gate_win32_get_proc_address(hkernel, "SleepConditionVariableCS", &Win32SleepConditionVariableCS)
1523 && gate_win32_get_proc_address(hkernel, "WakeAllConditionVariable", &Win32WakeAllConditionVariable)
1524 && gate_win32_get_proc_address(hkernel, "WakeConditionVariable", &Win32WakeConditionVariable)
1525 ;
1526 if (api_loaded)
1527 {
1528 gate_atomic_int_set(&cond_api_load_state, 2);
1529 return true;
1530 }
1531 else
1532 {
1533 gate_atomic_int_set(&cond_api_load_state, 3);
1534 return false;
1535 }
1536 }
1537 else if (state < 0)
1538 {
1539 /* invalid state */
1540 return false;
1541 }
1542
1543 /* state == 1 -> another thread loads, wait/retry*/
1544 Sleep(0);
1545 } while (state == 1);
1546
1547 return false;
1548 }
1549
1550 #endif
1551
1552
1553 /* extracted from synchapi.h and winnt.h */
1554 typedef struct _GATE_CONDITION_VARIABLE {
1555 PVOID Ptr;
1556 } GATE_CONDITION_VARIABLE, * PGATE_CONDITION_VARIABLE;
1557
1558 static gate_result_t gate_win32_nt6cond_create(gate_synccondition_t* cond)
1559 {
1560 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_CREATE(cond, GATE_CONDITION_VARIABLE);
1561 Win32InitializeConditionVariable(hcond);
1562 return GATE_RESULT_OK;
1563 }
1564 static gate_result_t gate_win32_nt6cond_destroy(gate_synccondition_t* cond)
1565 {
1566 GATE_HANDLESTORE_DESTROY(cond);
1567 return GATE_RESULT_OK;
1568 }
1569 static gate_result_t gate_win32_nt6cond_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1570 {
1571 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1572 LPCRITICAL_SECTION section = (LPCRITICAL_SECTION)&mutex->handles[0];
1573 if (FALSE == Win32SleepConditionVariableCS(hcond, section, timeoutms))
1574 {
1575 if (gate_win32_getlasterror() == ERROR_TIMEOUT)
1576 {
1577 return GATE_RESULT_TIMEOUT;
1578 }
1579 else
1580 {
1581 return GATE_RESULT_FAILED;
1582 }
1583 }
1584 else
1585 {
1586 return GATE_RESULT_OK;
1587 }
1588 }
1589 static gate_result_t gate_win32_nt6cond_signal_one(gate_synccondition_t* cond)
1590 {
1591 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1592 Win32WakeConditionVariable(hcond);
1593 return GATE_RESULT_OK;
1594 }
1595 static gate_result_t gate_win32_nt6cond_signal_all(gate_synccondition_t* cond)
1596 {
1597 GATE_CONDITION_VARIABLE* hcond = GATE_HANDLESTORE_ACCESS(cond, GATE_CONDITION_VARIABLE);
1598 Win32WakeAllConditionVariable(hcond);
1599 return GATE_RESULT_OK;
1600 }
1601
1602 #endif /* !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6) */
1603
1604 typedef struct gate_win32_cond_impl
1605 {
1606 gate_result_t(*create)(gate_synccondition_t* cond);
1607 gate_result_t(*destroy)(gate_synccondition_t* cond);
1608 gate_result_t(*timed_wait)(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms);
1609 gate_result_t(*signal_one)(gate_synccondition_t* cond);
1610 gate_result_t(*signal_all)(gate_synccondition_t* cond);
1611 } gate_win32_cond_impl_t;
1612
1613
1614
1615 #if defined(GATE_SYNCHRONIZATION_CONDITION_NT6_NATIVE)
1616
1617 static gate_win32_cond_impl_t gate_win32_cond = {
1618 &gate_win32_nt6cond_create,
1619 &gate_win32_nt6cond_destroy,
1620 &gate_win32_nt6cond_timed_wait,
1621 &gate_win32_nt6cond_signal_one,
1622 &gate_win32_nt6cond_signal_all
1623 };
1624
1625 static void gate_win32_cond_init()
1626 {
1627 }
1628
1629 #else
1630
1631 /* compatibility to NT4 is default*/
1632 static gate_win32_cond_impl_t gate_win32_cond = {
1633 &gate_win32_nt4cond_create,
1634 &gate_win32_nt4cond_destroy,
1635 &gate_win32_nt4cond_timed_wait,
1636 &gate_win32_nt4cond_signal_one,
1637 &gate_win32_nt4cond_signal_all
1638 };
1639
1640 static void gate_win32_cond_init()
1641 {
1642 #if !defined(GATE_SYNCHRONIZATION_CONDITION_NO_NT6)
1643 static gate_bool_t volatile is_initialized = false;
1644 if (!is_initialized)
1645 {
1646 if (win32_condition_variable_supported())
1647 {
1648 /* switch to NT6 condition-var if available on platform */
1649 const gate_win32_cond_impl_t gate_win32_cond_nt6 = {
1650 &gate_win32_nt6cond_create,
1651 &gate_win32_nt6cond_destroy,
1652 &gate_win32_nt6cond_timed_wait,
1653 &gate_win32_nt6cond_signal_one,
1654 &gate_win32_nt6cond_signal_all
1655 };
1656 gate_win32_cond = gate_win32_cond_nt6;
1657 }
1658 is_initialized = true;
1659 }
1660 #endif
1661 }
1662
1663 #endif
1664
1665 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
1666 {
1667 gate_win32_cond_init();
1668 return gate_win32_cond.create(cond);
1669 }
1670 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
1671 {
1672 return gate_win32_cond.destroy(cond);
1673 }
1674 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
1675 {
1676 return gate_win32_cond.timed_wait(cond, mutex, INFINITE);
1677 }
1678 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
1679 {
1680 if (timeoutms == INFINITE)
1681 {
1682 --timeoutms;
1683 }
1684 return gate_win32_cond.timed_wait(cond, mutex, timeoutms);
1685 }
1686 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
1687 {
1688 return gate_win32_cond.signal_one(cond);
1689 }
1690 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
1691 {
1692 return gate_win32_cond.signal_all(cond);
1693 }
1694
1695 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
1696
1697 #endif /* defined(GATE_SYNCHRONIZATION_WINAPI_IMPL) */
1698
1699
1700
1701
1702 #if defined(GATE_SYNCHRONIZATION_POSIX_IMPL)
1703
1704 #define __USE_GNU
1705 #include <unistd.h>
1706 #include <sys/time.h>
1707 #include <time.h>
1708 #if defined(GATE_SYS_ANDROID) || defined(GATE_SYS_BEOS)
1709 # define GATE_SYS_USE_POSIX_SEMAPHORE
1710 #endif
1711 #include <sys/ipc.h>
1712 #include <sys/types.h>
1713 #include <errno.h>
1714 #include <pthread.h>
1715 #if defined(GATE_SYS_USE_POSIX_SEMAPHORE)
1716 # include <sys/stat.h>
1717 # include <fcntl.h>
1718 # include <semaphore.h>
1719 #else
1720 # include <sys/shm.h>
1721 # include <sys/sem.h>
1722 #endif
1723
1724 #include "gate/platforms.h"
1725
1726 #if !defined(GATE_SYS_DARWIN)
1727 #define GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK 1
1728 #endif
1729
1730 static void calc_realtime_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeout_ms)
1731 {
1732 #if 0
1733 struct timeval tv;
1734 gate_mem_clear(&tv, sizeof(tv));
1735 gettimeofday(&tv, 0);
1736 ptr_ts->tv_sec = time(0);
1737 ptr_ts->tv_nsec = tv.tv_usec;
1738 #else
1739 long seconds = 0, nanoseconds = 0;
1740 gate_posix_clock_gettime(&seconds, &nanoseconds);
1741 ptr_ts->tv_sec = seconds;
1742 ptr_ts->tv_nsec = nanoseconds;
1743 #endif
1744 ptr_ts->tv_sec += timeout_ms / 1000;
1745 ptr_ts->tv_nsec = (timeout_ms % 1000) * 1000000;
1746 ptr_ts->tv_sec += ptr_ts->tv_nsec / 1000000000;
1747 ptr_ts->tv_nsec %= 1000000000;
1748 }
1749
1750 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
1751 19 static void calc_timeout_timespec(struct timespec* ptr_ts, gate_uint32_t timeout_ms)
1752 {
1753 19 long seconds = 0, nanoseconds = 0;
1754 19 gate_posix_clock_gettime_monotonic(&seconds, &nanoseconds);
1755 19 ptr_ts->tv_sec = seconds;
1756 19 ptr_ts->tv_nsec = nanoseconds;
1757 19 ptr_ts->tv_sec += timeout_ms / 1000;
1758 19 ptr_ts->tv_nsec = (timeout_ms % 1000) * 1000000;
1759 19 ptr_ts->tv_sec += ptr_ts->tv_nsec / 1000000000;
1760 19 ptr_ts->tv_nsec %= 1000000000;
1761 19 }
1762 #else
1763 #define calc_timeout_timespec(ptr_ts, timeout_ms) calc_realtime_timeout_timespec(ptr_ts, timeout_ms)
1764 #endif
1765
1766
1767 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
1768
1769 30 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
1770 {
1771 30 gate_result_t ret = GATE_RESULT_FAILED;
1772 do
1773 {
1774 pthread_mutexattr_t attrib;
1775 30 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1776 30 int result = pthread_mutexattr_init(&attrib);
1777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (result != 0)
1778 {
1779 break;
1780 }
1781
1782 30 pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_ERRORCHECK);
1783
1784 30 result = pthread_mutex_init(ptr, &attrib);
1785 30 pthread_mutexattr_destroy(&attrib);
1786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (0 != result)
1787 {
1788 ret = GATE_RESULT_OUTOFRESOURCES;
1789 break;
1790 }
1791
1792 30 ret = GATE_RESULT_OK;
1793 } while (0);
1794
1795 30 return ret;
1796 }
1797
1798 384 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
1799 {
1800 gate_result_t ret;
1801 384 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1802 384 int error = pthread_mutex_lock(ptr);
1803
1/3
✓ Branch 0 taken 384 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
384 switch (error)
1804 {
1805 384 case 0: ret = GATE_RESULT_OK; break;
1806 case EDEADLK: ret = GATE_RESULT_INVALIDSTATE; break;
1807 default: ret = GATE_RESULT_FAILED; break;
1808 }
1809 384 return ret;
1810 }
1811 384 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
1812 {
1813 gate_result_t ret;
1814 384 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1815 384 int error = pthread_mutex_unlock(ptr);
1816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (error != 0)
1817 {
1818 ret = GATE_RESULT_FAILED;
1819 }
1820 else
1821 {
1822 384 ret = GATE_RESULT_OK;
1823 }
1824 384 return ret;
1825 }
1826 30 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
1827 {
1828 gate_result_t ret;
1829 30 pthread_mutex_t* ptr = (pthread_mutex_t*)mutex;
1830
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (0 != pthread_mutex_destroy(ptr))
1831 {
1832 ret = GATE_RESULT_FAILED;
1833 }
1834 else
1835 {
1836 30 ret = GATE_RESULT_OK;
1837 }
1838 30 return ret;
1839 }
1840
1841 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
1842
1843
1844
1845 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
1846 typedef struct gate_syncevent_impl
1847 {
1848 pthread_cond_t cond;
1849 pthread_mutex_t mutex;
1850 gate_bool_t state;
1851 gate_bool_t autoreset;
1852 } gate_synevent_impl_t;
1853
1854 16 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
1855 {
1856 16 gate_result_t ret = GATE_RESULT_FAILED;
1857 16 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_create(syncevent, sizeof(gate_synevent_impl_t));
1858
1859 do
1860 {
1861 int result;
1862 pthread_condattr_t cond_attr;
1863
1864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (evt == NULL)
1865 {
1866 ret = GATE_RESULT_OUTOFMEMORY;
1867 break;
1868 }
1869
1870
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (0 != pthread_condattr_init(&cond_attr))
1871 {
1872 ret = GATE_RESULT_OUTOFRESOURCES;
1873 break;
1874 }
1875 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
1876
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (0 != pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC))
1877 {
1878 ret = GATE_RESULT_OUTOFRESOURCES;
1879 break;
1880 }
1881 #endif
1882
1883 16 result = pthread_cond_init(&evt->cond, &cond_attr);
1884 16 pthread_condattr_destroy(&cond_attr);
1885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (result != 0)
1886 {
1887 ret = GATE_RESULT_OUTOFRESOURCES;
1888 break;
1889 }
1890 16 result = pthread_mutex_init(&evt->mutex, 0);
1891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (result)
1892 {
1893 pthread_cond_destroy(&evt->cond);
1894 ret = GATE_RESULT_OUTOFRESOURCES;
1895 break;
1896 }
1897
1898 16 evt->state = 0;
1899 16 evt->autoreset = autoreset;
1900
1901 16 ret = GATE_RESULT_OK;
1902 } while (0);
1903
1904
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 if (GATE_FAILED(ret) && (evt != NULL))
1905 {
1906 gate_handlestore_destroy(syncevent);
1907 }
1908
1909 16 return ret;
1910 }
1911 16 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
1912 {
1913 16 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
1914
1915 16 pthread_cond_destroy(&evt->cond);
1916 16 pthread_mutex_destroy(&evt->mutex);
1917
1918 16 gate_handlestore_destroy(syncevent);
1919
1920 16 return GATE_RESULT_OK;
1921 }
1922 7 static gate_result_t translate_sync_error(int error)
1923 {
1924
1/7
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
7 switch (error)
1925 {
1926 7 case ETIMEDOUT: return GATE_RESULT_TIMEOUT;
1927 case EINVAL: return GATE_RESULT_INVALIDARG;
1928 case EBUSY: return GATE_RESULT_INVALIDSTATE;
1929 case EAGAIN: return GATE_RESULT_OUTOFRESOURCES;
1930 case EDEADLK: return GATE_RESULT_LOCKED;
1931 case EPERM: return GATE_RESULT_NOTREADY;
1932 default: return GATE_RESULT_FAILED;
1933 }
1934 }
1935
1936 19 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
1937 {
1938 19 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
1939
1940 19 int error = pthread_mutex_lock(&evt->mutex);
1941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (error)
1942 {
1943 return translate_sync_error(error);
1944 }
1945 19 evt->state = true;
1946
1947
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 12 times.
19 if (evt->autoreset)
1948 {
1949 7 error = pthread_cond_signal(&evt->cond);
1950 }
1951 else
1952 {
1953 12 error = pthread_cond_broadcast(&evt->cond);
1954 }
1955
1956 19 pthread_mutex_unlock(&evt->mutex);
1957
1958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (error)
1959 {
1960 return translate_sync_error(error);
1961 }
1962 19 return GATE_RESULT_OK;
1963 }
1964 5 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
1965 {
1966 5 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
1967
1968 5 int error = pthread_mutex_lock(&evt->mutex);
1969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (error)
1970 {
1971 return translate_sync_error(error);
1972 }
1973 5 evt->state = false;
1974
1975 5 pthread_mutex_unlock(&evt->mutex);
1976
1977 5 return GATE_RESULT_OK;
1978 }
1979 6 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
1980 {
1981 6 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
1982
1983 6 int error = pthread_mutex_lock(&evt->mutex);
1984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (error)
1985 {
1986 return translate_sync_error(error);
1987 }
1988
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 while (!error && !evt->state)
1989 {
1990 2 error = pthread_cond_wait(&evt->cond, &evt->mutex);
1991 }
1992
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
6 if (!error && evt->autoreset)
1993 {
1994 3 evt->state = false;
1995 }
1996 6 pthread_mutex_unlock(&evt->mutex);
1997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (error)
1998 {
1999 return translate_sync_error(error);
2000 }
2001 6 return GATE_RESULT_OK;
2002 }
2003
2004 14 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeout)
2005 {
2006 14 gate_synevent_impl_t* evt = (gate_synevent_impl_t*)gate_handlestore_access(syncevent);
2007 int error;
2008 struct timespec tm;
2009
2010 14 calc_timeout_timespec(&tm, timeout);
2011
2012 14 error = pthread_mutex_lock(&evt->mutex);
2013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (error)
2014 {
2015 return translate_sync_error(error);
2016 }
2017 {
2018
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7 times.
22 while (!error && !evt->state)
2019 {
2020 8 error = pthread_cond_timedwait(&evt->cond, &evt->mutex, &tm);
2021 }
2022
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
14 if (!error && evt->autoreset)
2023 {
2024 evt->state = false;
2025 }
2026 }
2027 14 pthread_mutex_unlock(&evt->mutex);
2028
2029
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (error)
2030 {
2031 7 return translate_sync_error(error);
2032 }
2033 else
2034 {
2035 7 return GATE_RESULT_OK;
2036 }
2037 }
2038
2039 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2040
2041
2042
2043 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2044
2045 7 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2046 {
2047 7 gate_result_t ret = GATE_RESULT_FAILED;
2048 7 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_CREATE(cond, pthread_cond_t);
2049
2050 do
2051 {
2052 pthread_condattr_t cond_attr;
2053 int failed;
2054
2055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ptr_cond == NULL)
2056 {
2057 ret = GATE_RESULT_OUTOFMEMORY;
2058 break;
2059 }
2060 7 failed = pthread_condattr_init(&cond_attr);
2061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (failed)
2062 {
2063 ret = GATE_RESULT_OUTOFRESOURCES;
2064 break;
2065 }
2066 #if defined(GATE_SYNCHRONIZATION_POSIX_MONOTONIC_CLOCK)
2067 7 failed = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
2068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (failed)
2069 {
2070 ret = GATE_RESULT_OUTOFRESOURCES;
2071 break;
2072 }
2073 #endif
2074
2075 7 failed = pthread_cond_init(ptr_cond, &cond_attr);
2076 7 pthread_condattr_destroy(&cond_attr);
2077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (failed)
2078 {
2079 ret = GATE_RESULT_OUTOFRESOURCES;
2080 break;
2081 }
2082
2083 7 ret = GATE_RESULT_OK;
2084 } while (0);
2085
2086
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (GATE_FAILED(ret) && (ptr_cond != NULL))
2087 {
2088 GATE_HANDLESTORE_DESTROY(cond);
2089 }
2090
2091 7 return ret;
2092 }
2093
2094 7 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2095 {
2096 7 gate_result_t ret = GATE_RESULT_FAILED;
2097 7 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2098
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (ptr_cond)
2099 {
2100 7 int const failed = pthread_cond_destroy(ptr_cond);
2101
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (!failed)
2102 {
2103 7 ret = GATE_RESULT_OK;
2104 }
2105 7 GATE_HANDLESTORE_DESTROY(cond);
2106 }
2107 7 return ret;
2108 }
2109
2110 5 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2111 {
2112 5 gate_result_t ret = GATE_RESULT_FAILED;
2113
2114 do
2115 {
2116 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2117 5 pthread_mutex_t* ptr_mutex = (pthread_mutex_t*)mutex;
2118 5 int const failed = pthread_cond_wait(ptr_cond, ptr_mutex);
2119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (failed)
2120 {
2121 ret = GATE_RESULT_FAILED;
2122 break;
2123 }
2124
2125 5 ret = GATE_RESULT_OK;
2126 } while (0);
2127 5 return ret;
2128 }
2129
2130 5 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2131 {
2132 5 gate_result_t ret = GATE_RESULT_FAILED;
2133 5 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2134 5 pthread_mutex_t* ptr_mutex = (pthread_mutex_t*)mutex;
2135 struct timespec timeout;
2136 int status;
2137
2138 5 calc_timeout_timespec(&timeout, timeoutms);
2139
2140 5 status = pthread_cond_timedwait(ptr_cond, ptr_mutex, &timeout);
2141 switch (ETIMEDOUT)
2142 {
2143 case 0: ret = GATE_RESULT_OK; break;
2144 5 case ETIMEDOUT: ret = GATE_RESULT_TIMEOUT; break;
2145 default: ret = GATE_RESULT_FAILED; break;
2146 }
2147 5 return ret;
2148 }
2149
2150 19 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2151 {
2152 19 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2153 19 int const failed = pthread_cond_signal(ptr_cond);
2154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (failed)
2155 {
2156 return GATE_RESULT_FAILED;
2157 }
2158 19 return GATE_RESULT_OK;
2159 }
2160
2161 9 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2162 {
2163 9 pthread_cond_t* ptr_cond = GATE_HANDLESTORE_ACCESS(cond, pthread_cond_t);
2164 9 int const failed = pthread_cond_broadcast(ptr_cond);
2165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (failed)
2166 {
2167 return GATE_RESULT_FAILED;
2168 }
2169 9 return GATE_RESULT_OK;
2170 }
2171
2172 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2173
2174 #endif /* GATE_SYNCHRONIZATION_POSIX_IMPL */
2175
2176
2177
2178
2179
2180 #if defined(GATE_SYNCHRONIZATION_BEOS_IMPL)
2181
2182 #include <kernel/OS.h>
2183
2184 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
2185
2186 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
2187 {
2188 sem_id* sem = (sem_id*)mutex;
2189 *sem = create_sem(1, "gate_mutex");
2190 if (*sem < B_OK)
2191 {
2192 return GATE_RESULT_FAILED;
2193 }
2194 else
2195 {
2196 return GATE_RESULT_OK;
2197 }
2198 }
2199 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
2200 {
2201 sem_id* sem = (sem_id*)mutex;
2202 status_t status = acquire_sem(*sem);
2203 switch (status)
2204 {
2205 case B_NO_ERROR: return GATE_RESULT_OK;
2206 case B_BAD_SEM_ID: return GATE_RESULT_INVALIDARG;
2207 case B_INTERRUPTED: return GATE_RESULT_TIMEOUT;
2208 default: return GATE_RESULT_FAILED;
2209 }
2210 }
2211 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
2212 {
2213 sem_id* sem = (sem_id*)mutex;
2214 status_t status = release_sem(*sem);
2215 switch (status)
2216 {
2217 case B_NO_ERROR: return GATE_RESULT_OK;
2218 case B_BAD_SEM_ID: return GATE_RESULT_INVALIDARG;
2219 default: return GATE_RESULT_FAILED;
2220 }
2221 }
2222 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
2223 {
2224 sem_id* sem = (sem_id*)mutex;
2225 status_t status = delete_sem(*sem);
2226 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2227 }
2228 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
2229
2230
2231
2232 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
2233
2234 #define GATE_SYNCEVENT_MAX_SEMCOUNT 64
2235 #define GATE_SYNCEVENT_FLAG_SET 0x01
2236 #define GATE_SYNCEVENT_FLAG_AUTORESET 0x80
2237
2238 typedef struct sem_syncevent_class
2239 {
2240 sem_id lock;
2241 sem_id signal;
2242 int state;
2243 } sem_syncevent_t;
2244
2245 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
2246 {
2247 sem_syncevent_t* evt = GATE_HANDLESTORE_CREATE(syncevent, sem_syncevent_t);
2248 status_t status;
2249 if (evt == NULL)
2250 {
2251 return GATE_RESULT_OUTOFMEMORY;
2252 }
2253 evt->lock = create_sem(1, "gate_syncevent");
2254 if (evt->lock < B_OK)
2255 {
2256 GATE_HANDLESTORE_DESTROY(syncevent);
2257 return GATE_RESULT_OUTOFRESOURCES;
2258 }
2259 evt->signal = create_sem(GATE_SYNCEVENT_MAX_SEMCOUNT, "gate_syncevent");
2260 if (evt->signal < B_OK)
2261 {
2262 delete_sem(evt->lock);
2263 GATE_HANDLESTORE_DESTROY(syncevent);
2264 return GATE_RESULT_OUTOFRESOURCES;
2265 }
2266 status = acquire_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2267 if (B_NO_ERROR != status)
2268 {
2269 delete_sem(evt->signal);
2270 delete_sem(evt->lock);
2271 GATE_HANDLESTORE_DESTROY(syncevent);
2272 return GATE_RESULT_OUTOFRESOURCES;
2273 }
2274 evt->state = autoreset ? GATE_SYNCEVENT_FLAG_AUTORESET : 0;
2275 return GATE_RESULT_OK;
2276 }
2277
2278 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
2279 {
2280 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2281 if (evt)
2282 {
2283 delete_sem(evt->signal);
2284 delete_sem(evt->lock);
2285 GATE_HANDLESTORE_DESTROY(syncevent);
2286 }
2287 return GATE_RESULT_OK;
2288 }
2289
2290 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
2291 {
2292 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2293 status_t status;
2294 gate_bool_t is_autoreset;
2295
2296 status = acquire_sem(evt->lock);
2297 if (status != B_NO_ERROR)
2298 {
2299 return GATE_RESULT_FAILED;
2300 }
2301 evt->state |= (GATE_SYNCEVENT_FLAG_SET);
2302 is_autoreset = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_AUTORESET);
2303
2304 if (is_autoreset)
2305 {
2306 release_sem(evt->signal);
2307 }
2308 else
2309 {
2310 release_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_DO_NOT_RESCHEDULE);
2311 }
2312
2313 release_sem(evt->lock);
2314
2315 if (is_autoreset)
2316 {
2317 status = acquire_sem(evt->signal);
2318 }
2319 else
2320 {
2321 status = acquire_sem_etc(evt->signal, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2322 }
2323
2324 return (status != B_NO_ERROR) ? GATE_RESULT_FAILED : GATE_RESULT_OK;
2325 }
2326
2327 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
2328 {
2329 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2330 status_t status;
2331 status = acquire_sem(evt->lock);
2332 if (status != B_NO_ERROR)
2333 {
2334 return GATE_RESULT_FAILED;
2335 }
2336 evt->state &= ~(GATE_SYNCEVENT_FLAG_SET);
2337 release_sem(evt->lock);
2338
2339 return GATE_RESULT_OK;
2340 }
2341 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
2342 {
2343 return gate_syncevent_timed_wait(syncevent, (gate_uint32_t)0xffffffff);
2344 }
2345 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
2346 {
2347 sem_syncevent_t* evt = GATE_HANDLESTORE_ACCESS(syncevent, sem_syncevent_t);
2348 status_t status;
2349 gate_bool_t is_autoreset;
2350 gate_bool_t is_signaled = false;
2351 bigtime_t now = system_time();
2352 bigtime_t next_timeout;
2353 bigtime_t final_timeout = now + ((bigtime_t)timeoutms * (bigtime_t)1000);
2354
2355 for (;;)
2356 {
2357
2358 status = acquire_sem(evt->lock);
2359 if (status != B_NO_ERROR)
2360 {
2361 break;
2362 }
2363 is_autoreset = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_AUTORESET);
2364 is_signaled = GATE_FLAG_ENABLED(evt->state, GATE_SYNCEVENT_FLAG_SET);
2365 if (is_signaled && is_autoreset)
2366 {
2367 /* autoreset */
2368 evt->state &= ~(GATE_SYNCEVENT_FLAG_SET);
2369 }
2370
2371 if (is_signaled)
2372 {
2373 break;
2374 }
2375
2376 now = system_time();
2377 if (now > final_timeout)
2378 {
2379 /* timeout reached */
2380 break;
2381 }
2382 if (timeoutms == 0xffffffff)
2383 {
2384 next_timeout = B_INFINITE_TIMEOUT;
2385 }
2386 else
2387 {
2388 next_timeout = final_timeout - now;
2389 }
2390 status = acquire_sem_etc(evt->signal, 1, B_RELATIVE_TIMEOUT, next_timeout);
2391 if (status == B_NO_ERROR)
2392 {
2393 release_sem(evt->signal);
2394 }
2395 }
2396 return is_signaled ? GATE_RESULT_OK : GATE_RESULT_TIMEOUT;
2397 }
2398
2399 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2400
2401
2402
2403 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2404
2405 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2406 {
2407 sem_id* ptr_sem = GATE_HANDLESTORE_CREATE(cond, sem_id);
2408 status_t status;
2409 if (ptr_sem == NULL)
2410 {
2411 return GATE_RESULT_OUTOFMEMORY;
2412 }
2413 *ptr_sem = create_sem(GATE_SYNCEVENT_MAX_SEMCOUNT, "gate_synccondition");
2414 if (*ptr_sem < B_OK)
2415 {
2416 GATE_HANDLESTORE_DESTROY(cond);
2417 return GATE_RESULT_OUTOFRESOURCES;
2418 }
2419 status = acquire_sem_etc(*ptr_sem, GATE_SYNCEVENT_MAX_SEMCOUNT, B_RELATIVE_TIMEOUT, B_INFINITE_TIMEOUT);
2420 if (status != B_NO_ERROR)
2421 {
2422 delete_sem(*ptr_sem);
2423 GATE_HANDLESTORE_DESTROY(cond);
2424 return GATE_RESULT_OUTOFRESOURCES;
2425 }
2426 return GATE_RESULT_OK;
2427 }
2428 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2429 {
2430 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2431 if (ptr_sem)
2432 {
2433 delete_sem(*ptr_sem);
2434 GATE_HANDLESTORE_DESTROY(cond);
2435 }
2436 return GATE_RESULT_OK;
2437 }
2438 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2439 {
2440 return gate_synccondition_timed_wait(cond, mutex, 0xffffffff);
2441 }
2442 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2443 {
2444 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2445 gate_result_t ret;
2446 status_t status;
2447 bigtime_t timeout_us;
2448
2449 if (timeoutms == 0xffffffff)
2450 {
2451 timeout_us = B_INFINITE_TIMEOUT;
2452 }
2453 else
2454 {
2455 timeout_us = (bigtime_t)timeoutms * (bigtime_t)1000;
2456 }
2457
2458 do
2459 {
2460 if (mutex)
2461 {
2462 ret = gate_mutex_release(mutex);
2463 GATE_BREAK_IF_FAILED(ret);
2464 }
2465
2466 status = acquire_sem_etc(*ptr_sem, 1, B_RELATIVE_TIMEOUT, timeout_us);
2467
2468 if (B_NO_ERROR == status)
2469 {
2470 ret = GATE_RESULT_OK;
2471 }
2472 else if ((B_TIMED_OUT == status) || ((B_WOULD_BLOCK == status) && (timeoutms == 0)) || (B_INTERRUPTED == status))
2473 {
2474 ret == GATE_RESULT_TIMEOUT;
2475 }
2476 else
2477 {
2478 ret = GATE_RESULT_FAILED;
2479 }
2480
2481 if (mutex)
2482 {
2483 gate_mutex_acquire(mutex);
2484 }
2485
2486 if (B_NO_ERROR == status)
2487 {
2488 release_sem(*ptr_sem);
2489 }
2490 } while (0);
2491
2492 return ret;
2493 }
2494 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2495 {
2496 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2497 status_t status;
2498 release_sem(*ptr_sem);
2499 do
2500 {
2501 status = acquire_sem(*ptr_sem);
2502 } while (status == B_INTERRUPTED);
2503
2504 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2505 }
2506 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2507 {
2508 sem_id* ptr_sem = GATE_HANDLESTORE_ACCESS(cond, sem_id);
2509 status_t status;
2510 unsigned ndx;
2511 release_sem_etc(*ptr_sem, GATE_SYNCEVENT_MAX_SEMCOUNT, 0);
2512 release_sem(*ptr_sem);
2513
2514 for (ndx = 0; ndx != GATE_SYNCEVENT_MAX_SEMCOUNT; ++ndx)
2515 {
2516 do
2517 {
2518 status = acquire_sem(*ptr_sem);
2519 } while (status == B_INTERRUPTED);
2520 }
2521 return (status == B_NO_ERROR) ? GATE_RESULT_OK : GATE_RESULT_FAILED;
2522 }
2523
2524 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2525
2526 #endif /* GATE_SYNCHRONIZATION_BEOS_IMPL */
2527
2528
2529
2530 #if defined(GATE_SYS_DOS)
2531
2532 #endif /* GATE_SYNCHRONIZATION_DOS_IMPL */
2533
2534
2535 #if defined(GATE_SYNCHRONIZATION_DUMMY_IMPL)
2536
2537 #include "gate/atomics.h"
2538
2539
2540 #if !defined(GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE)
2541
2542 gate_result_t gate_mutex_create(gate_mutex_t* mutex)
2543 {
2544 int volatile* lock = (int volatile*)mutex;
2545 gate_mem_clear(mutex, sizeof(gate_mutex_t));
2546 *lock = 0;
2547 return GATE_RESULT_OK;
2548 }
2549 gate_result_t gate_mutex_acquire(gate_mutex_t* mutex)
2550 {
2551 int volatile* lock = (int volatile*)mutex;
2552 if (*lock == 1)
2553 {
2554 return GATE_RESULT_LOCKED;
2555 }
2556 *lock = 1;
2557 return GATE_RESULT_OK;
2558 }
2559 gate_result_t gate_mutex_release(gate_mutex_t* mutex)
2560 {
2561 int volatile* lock = (int volatile*)mutex;
2562 *lock = 0;
2563 return GATE_RESULT_OK;
2564 }
2565 gate_result_t gate_mutex_destroy(gate_mutex_t* mutex)
2566 {
2567 gate_mem_clear(mutex, sizeof(gate_mutex_t));
2568 return GATE_RESULT_OK;
2569 }
2570
2571 #endif /* GATE_SYNCHRONIZATION_MUTEX_SEMAPHORE */
2572
2573
2574
2575 #if !defined(GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE)
2576 typedef struct gate_plain_syncevent_class
2577 {
2578 int autoreset;
2579 int state;
2580 } gate_plain_syncevent_t;
2581
2582 gate_result_t gate_syncevent_create(gate_syncevent_t* syncevent, gate_bool_t autoreset)
2583 {
2584 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_CREATE(syncevent, gate_plain_syncevent_t volatile);
2585 if (evt == NULL)
2586 {
2587 return GATE_RESULT_OUTOFMEMORY;
2588 }
2589 evt->autoreset = autoreset ? 1 : 0;
2590 evt->state = 0;
2591 return GATE_RESULT_OK;
2592 }
2593 gate_result_t gate_syncevent_destroy(gate_syncevent_t* syncevent)
2594 {
2595 GATE_HANDLESTORE_DESTROY(syncevent);
2596 return GATE_RESULT_OK;
2597 }
2598 gate_result_t gate_syncevent_set(gate_syncevent_t* syncevent)
2599 {
2600 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2601 evt->state = 1;
2602 return GATE_RESULT_OK;
2603 }
2604 gate_result_t gate_syncevent_reset(gate_syncevent_t* syncevent)
2605 {
2606 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2607 evt->state = 0;
2608 return GATE_RESULT_OK;
2609 }
2610 gate_result_t gate_syncevent_wait(gate_syncevent_t* syncevent)
2611 {
2612 return gate_syncevent_timed_wait(syncevent, (gate_uint32_t)0xffffffff);
2613 }
2614 gate_result_t gate_syncevent_timed_wait(gate_syncevent_t* syncevent, gate_uint32_t timeoutms)
2615 {
2616 gate_plain_syncevent_t volatile* evt = GATE_HANDLESTORE_ACCESS(syncevent, gate_plain_syncevent_t volatile);
2617 GATE_UNUSED_ARG(timeoutms);
2618 if (evt->state)
2619 {
2620 if (evt->autoreset)
2621 {
2622 evt->state = 0;
2623 }
2624 return GATE_RESULT_OK;
2625 }
2626 return GATE_RESULT_TIMEOUT;
2627 }
2628
2629 #endif /* GATE_SYNCHRONIZATION_SYNCEVENT_SEMAPHORE */
2630
2631
2632
2633 #if !defined(GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE)
2634
2635 gate_result_t gate_synccondition_create(gate_synccondition_t* cond)
2636 {
2637 int volatile* evt = GATE_HANDLESTORE_CREATE(cond, int volatile);
2638 if (evt == NULL)
2639 {
2640 return GATE_RESULT_OUTOFMEMORY;
2641 }
2642 *evt = 0;
2643 return GATE_RESULT_OK;
2644 }
2645 gate_result_t gate_synccondition_destroy(gate_synccondition_t* cond)
2646 {
2647 GATE_HANDLESTORE_DESTROY(cond);
2648 return GATE_RESULT_OK;
2649 }
2650 gate_result_t gate_synccondition_wait(gate_synccondition_t* cond, gate_mutex_t* mutex)
2651 {
2652 return gate_synccondition_timed_wait(cond, mutex, 0xffffffff);
2653 }
2654 gate_result_t gate_synccondition_timed_wait(gate_synccondition_t* cond, gate_mutex_t* mutex, gate_uint32_t timeoutms)
2655 {
2656 gate_result_t result;
2657 int volatile* evt = GATE_HANDLESTORE_ACCESS(cond, int volatile);
2658 GATE_UNUSED_ARG(timeoutms);
2659 do
2660 {
2661 result = gate_mutex_release(mutex);
2662 GATE_BREAK_IF_FAILED(result);
2663 if (*evt == 0)
2664 {
2665 result = GATE_RESULT_TIMEOUT;
2666 }
2667 else
2668 {
2669 *evt = 1;
2670 result = GATE_RESULT_OK;
2671 }
2672 gate_mutex_acquire(mutex);
2673 } while (0);
2674 return result;
2675 }
2676 gate_result_t gate_synccondition_signal_one(gate_synccondition_t* cond)
2677 {
2678 int volatile* evt = GATE_HANDLESTORE_ACCESS(cond, int volatile);
2679 *evt = 1;
2680 return GATE_RESULT_OK;
2681 }
2682 gate_result_t gate_synccondition_signal_all(gate_synccondition_t* cond)
2683 {
2684 return gate_synccondition_signal_one(cond);
2685 }
2686
2687 #endif /* GATE_SYNCHRONIZATION_CONDITION_SEMAPHORE */
2688
2689 #endif /* GATE_SYNCHRONIZATION_DUMMY_IMPL */
2690