aboutsummaryrefslogtreecommitdiff
path: root/zutil.h
diff options
context:
space:
mode:
Diffstat (limited to 'zutil.h')
-rw-r--r--zutil.h76
1 files changed, 60 insertions, 16 deletions
diff --git a/zutil.h b/zutil.h
index 94fa1aff..acc1907f 100644
--- a/zutil.h
+++ b/zutil.h
@@ -254,30 +254,74 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
254#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ 254#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
255 (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) 255 (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
256 256
257#ifdef MAKEFIXED 257#ifdef Z_ONCE
258# ifndef BUILDFIXED 258/*
259# define BUILDFIXED 259 Create a local z_once() function depending on the availability of atomics.
260# endif 260 */
261#endif 261
262#if defined(BUILDFIXED) || defined(DYNAMIC_CRC_TABLE) 262/* Check for the availability of atomics. */
263/* Structure for z_once(), which must be initialized with Z_ONCE_INIT. */
264typedef struct z_once_s z_once_t;
265void ZLIB_INTERNAL z_once(z_once_t *state, void (*init)(void));
266#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ 263#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
267 !defined(__STDC_NO_ATOMICS__) 264 !defined(__STDC_NO_ATOMICS__)
265
268#include <stdatomic.h> 266#include <stdatomic.h>
269struct z_once_s { 267typedef struct {
270 atomic_flag begun; 268 atomic_flag begun;
271 atomic_int done; 269 atomic_int done;
272}; 270} z_once_t;
273#define Z_ONCE_INIT {ATOMIC_FLAG_INIT, 0} 271#define Z_ONCE_INIT {ATOMIC_FLAG_INIT, 0}
274#else /* no atomics! */ 272
275struct z_once_s { 273/*
274 Run the provided init() function exactly once, even if multiple threads
275 invoke once() at the same time. The state must be a once_t initialized with
276 Z_ONCE_INIT.
277 */
278local void z_once(z_once_t *state, void (*init)(void)) {
279 if (!atomic_load(&state->done)) {
280 if (atomic_flag_test_and_set(&state->begun))
281 while (!atomic_load(&state->done))
282 ;
283 else {
284 init();
285 atomic_store(&state->done, 1);
286 }
287 }
288}
289
290#else /* no atomics */
291
292#warning zlib not thread-safe
293
294typedef struct z_once_s {
276 volatile int begun; 295 volatile int begun;
277 volatile int done; 296 volatile int done;
278}; 297} z_once_t;
279#define Z_ONCE_INIT {0, 0} 298#define Z_ONCE_INIT {0, 0}
280#endif 299
281#endif 300/* Test and set. Alas, not atomic, but tries to limit the period of
301 vulnerability. */
302local int test_and_set(int volatile *flag) {
303 int was;
304
305 was = *flag;
306 *flag = 1;
307 return was;
308}
309
310/* Run the provided init() function once. This is not thread-safe. */
311local void z_once(z_once_t *state, void (*init)(void)) {
312 if (!state->done) {
313 if (test_and_set(&state->begun))
314 while (!state->done)
315 ;
316 else {
317 init();
318 state->done = 1;
319 }
320 }
321}
322
323#endif /* ?atomics */
324
325#endif /* Z_ONCE */
282 326
283#endif /* ZUTIL_H */ 327#endif /* ZUTIL_H */