diff options
| author | Mark Adler <git@madler.net> | 2026-01-05 01:15:38 -0600 |
|---|---|---|
| committer | Mark Adler <git@madler.net> | 2026-01-05 15:03:04 -0600 |
| commit | c267ef7306fe9fc1399833e3556cd9798dec2eb0 (patch) | |
| tree | bc18574b8ea4fc37befdf0174fb5f04472911f6f /zutil.c | |
| parent | 916dc1ac351795c9bf86a3d19c3667b014b9d28e (diff) | |
| download | zlib-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.c | 58 |
1 files changed, 58 insertions, 0 deletions
| @@ -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 | */ | ||
| 325 | void 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. */ | ||
| 343 | local 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. */ | ||
| 352 | void 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 | ||
