GCC Code Coverage Report


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