aboutsummaryrefslogtreecommitdiff
path: root/zutil.c
diff options
context:
space:
mode:
authorMark Adler <git@madler.net>2026-01-05 01:15:38 -0600
committerMark Adler <git@madler.net>2026-01-05 15:03:04 -0600
commitc267ef7306fe9fc1399833e3556cd9798dec2eb0 (patch)
treebc18574b8ea4fc37befdf0174fb5f04472911f6f /zutil.c
parent916dc1ac351795c9bf86a3d19c3667b014b9d28e (diff)
downloadzlib-c267ef7306fe9fc1399833e3556cd9798dec2eb0.tar.gz
zlib-c267ef7306fe9fc1399833e3556cd9798dec2eb0.tar.bz2
zlib-c267ef7306fe9fc1399833e3556cd9798dec2eb0.zip
Use atomics to build inflate fixed tables once.
This moves the once code from crc32.c to zutil.c, and uses it also for building the inflate fixed tables when BUILDFIXED is defined. The fixed tables are now housed in inftrees.c, shared by inflate.c and infback.c. The once() function is now external, and so is renamed to z_once() to avoid name collisions. If either BUILDFIXED or DYNAMIC_CRC_TABLE is defined, and atomics are not available, then a warning is issued noting that zlib is not thread-safe.
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