aboutsummaryrefslogtreecommitdiff
path: root/zutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'zutil.c')
-rw-r--r--zutil.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/zutil.c b/zutil.c
index 6e8a369..3a94e91 100644
--- a/zutil.c
+++ b/zutil.c
@@ -305,3 +305,61 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
305#endif /* MY_ZCALLOC */ 305#endif /* MY_ZCALLOC */
306 306
307#endif /* !Z_SOLO */ 307#endif /* !Z_SOLO */
308
309#if defined(BUILDFIXED) || defined(DYNAMIC_CRC_TABLE)
310/*
311 Define a z_once() function depending on the availability of atomics.
312 */
313
314/* Check for the availability of atomics. */
315#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
316 !defined(__STDC_NO_ATOMICS__)
317
318#include <stdatomic.h>
319
320/*
321 Run the provided init() function exactly once, even if multiple threads
322 invoke once() at the same time. The state must be a once_t initialized with
323 Z_ONCE_INIT.
324 */
325void z_once(z_once_t *state, void (*init)(void)) {
326 if (!atomic_load(&state->done)) {
327 if (atomic_flag_test_and_set(&state->begun))
328 while (!atomic_load(&state->done))
329 ;
330 else {
331 init();
332 atomic_store(&state->done, 1);
333 }
334 }
335}
336
337#else /* no atomics */
338
339#warning zlib not thread-safe
340
341/* Test and set. Alas, not atomic, but tries to limit the period of
342 vulnerability. */
343local int test_and_set(int volatile *flag) {
344 int was;
345
346 was = *flag;
347 *flag = 1;
348 return was;
349}
350
351/* Run the provided init() function once. This is not thread-safe. */
352void z_once(z_once_t *state, void (*init)(void)) {
353 if (!state->done) {
354 if (test_and_set(&state->begun))
355 while (!state->done)
356 ;
357 else {
358 init();
359 state->done = 1;
360 }
361 }
362}
363
364#endif
365#endif