GCC Code Coverage Report


Directory: src/gate/
File: src/gate/synchronization.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 313 429 73.0%
Functions: 36 43 83.7%
Branches: 104 204 51.0%

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