diff options
Diffstat (limited to 'zutil.h')
| -rw-r--r-- | zutil.h | 76 |
1 files changed, 60 insertions, 16 deletions
| @@ -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. */ | ||
| 264 | typedef struct z_once_s z_once_t; | ||
| 265 | void 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> |
| 269 | struct z_once_s { | 267 | typedef 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 | |
| 275 | struct 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 | */ | ||
| 278 | local 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 | |||
| 294 | typedef 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. */ | ||
| 302 | local 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. */ | ||
| 311 | local 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 */ |
