diff options
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 | ||
