diff options
Diffstat (limited to 'crc32.c')
| -rw-r--r-- | crc32.c | 87 |
1 files changed, 6 insertions, 81 deletions
| @@ -204,83 +204,8 @@ local z_crc_t FAR crc_table[256]; | |||
| 204 | local void write_table64(FILE *, const z_word_t FAR *, int); | 204 | local void write_table64(FILE *, const z_word_t FAR *, int); |
| 205 | #endif /* MAKECRCH */ | 205 | #endif /* MAKECRCH */ |
| 206 | 206 | ||
| 207 | /* | ||
| 208 | Define a once() function depending on the availability of atomics. If this is | ||
| 209 | compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in | ||
| 210 | multiple threads, and if atomics are not available, then get_crc_table() must | ||
| 211 | be called to initialize the tables and must return before any threads are | ||
| 212 | allowed to compute or combine CRCs. | ||
| 213 | */ | ||
| 214 | |||
| 215 | /* Definition of once functionality. */ | ||
| 216 | typedef struct once_s once_t; | ||
| 217 | |||
| 218 | /* Check for the availability of atomics. */ | ||
| 219 | #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ | ||
| 220 | !defined(__STDC_NO_ATOMICS__) | ||
| 221 | |||
| 222 | #include <stdatomic.h> | ||
| 223 | |||
| 224 | /* Structure for once(), which must be initialized with ONCE_INIT. */ | ||
| 225 | struct once_s { | ||
| 226 | atomic_flag begun; | ||
| 227 | atomic_int done; | ||
| 228 | }; | ||
| 229 | #define ONCE_INIT {ATOMIC_FLAG_INIT, 0} | ||
| 230 | |||
| 231 | /* | ||
| 232 | Run the provided init() function exactly once, even if multiple threads | ||
| 233 | invoke once() at the same time. The state must be a once_t initialized with | ||
| 234 | ONCE_INIT. | ||
| 235 | */ | ||
| 236 | local void once(once_t *state, void (*init)(void)) { | ||
| 237 | if (!atomic_load(&state->done)) { | ||
| 238 | if (atomic_flag_test_and_set(&state->begun)) | ||
| 239 | while (!atomic_load(&state->done)) | ||
| 240 | ; | ||
| 241 | else { | ||
| 242 | init(); | ||
| 243 | atomic_store(&state->done, 1); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | #else /* no atomics */ | ||
| 249 | |||
| 250 | /* Structure for once(), which must be initialized with ONCE_INIT. */ | ||
| 251 | struct once_s { | ||
| 252 | volatile int begun; | ||
| 253 | volatile int done; | ||
| 254 | }; | ||
| 255 | #define ONCE_INIT {0, 0} | ||
| 256 | |||
| 257 | /* Test and set. Alas, not atomic, but tries to minimize the period of | ||
| 258 | vulnerability. */ | ||
| 259 | local int test_and_set(int volatile *flag) { | ||
| 260 | int was; | ||
| 261 | |||
| 262 | was = *flag; | ||
| 263 | *flag = 1; | ||
| 264 | return was; | ||
| 265 | } | ||
| 266 | |||
| 267 | /* Run the provided init() function once. This is not thread-safe. */ | ||
| 268 | local void once(once_t *state, void (*init)(void)) { | ||
| 269 | if (!state->done) { | ||
| 270 | if (test_and_set(&state->begun)) | ||
| 271 | while (!state->done) | ||
| 272 | ; | ||
| 273 | else { | ||
| 274 | init(); | ||
| 275 | state->done = 1; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | #endif | ||
| 281 | |||
| 282 | /* State for once(). */ | 207 | /* State for once(). */ |
| 283 | local once_t made = ONCE_INIT; | 208 | local z_once_t made = Z_ONCE_INIT; |
| 284 | 209 | ||
| 285 | /* | 210 | /* |
| 286 | Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: | 211 | Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: |
| @@ -548,7 +473,7 @@ local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { | |||
| 548 | */ | 473 | */ |
| 549 | const z_crc_t FAR * ZEXPORT get_crc_table(void) { | 474 | const z_crc_t FAR * ZEXPORT get_crc_table(void) { |
| 550 | #ifdef DYNAMIC_CRC_TABLE | 475 | #ifdef DYNAMIC_CRC_TABLE |
| 551 | once(&made, make_crc_table); | 476 | z_once(&made, make_crc_table); |
| 552 | #endif /* DYNAMIC_CRC_TABLE */ | 477 | #endif /* DYNAMIC_CRC_TABLE */ |
| 553 | return (const z_crc_t FAR *)crc_table; | 478 | return (const z_crc_t FAR *)crc_table; |
| 554 | } | 479 | } |
| @@ -585,7 +510,7 @@ unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, | |||
| 585 | if (buf == Z_NULL) return 0; | 510 | if (buf == Z_NULL) return 0; |
| 586 | 511 | ||
| 587 | #ifdef DYNAMIC_CRC_TABLE | 512 | #ifdef DYNAMIC_CRC_TABLE |
| 588 | once(&made, make_crc_table); | 513 | z_once(&made, make_crc_table); |
| 589 | #endif /* DYNAMIC_CRC_TABLE */ | 514 | #endif /* DYNAMIC_CRC_TABLE */ |
| 590 | 515 | ||
| 591 | /* Pre-condition the CRC */ | 516 | /* Pre-condition the CRC */ |
| @@ -697,7 +622,7 @@ unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, | |||
| 697 | if (buf == Z_NULL) return 0; | 622 | if (buf == Z_NULL) return 0; |
| 698 | 623 | ||
| 699 | #ifdef DYNAMIC_CRC_TABLE | 624 | #ifdef DYNAMIC_CRC_TABLE |
| 700 | once(&made, make_crc_table); | 625 | z_once(&made, make_crc_table); |
| 701 | #endif /* DYNAMIC_CRC_TABLE */ | 626 | #endif /* DYNAMIC_CRC_TABLE */ |
| 702 | 627 | ||
| 703 | /* Pre-condition the CRC */ | 628 | /* Pre-condition the CRC */ |
| @@ -1022,7 +947,7 @@ uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { | |||
| 1022 | if (len2 < 0) | 947 | if (len2 < 0) |
| 1023 | return 0; | 948 | return 0; |
| 1024 | #ifdef DYNAMIC_CRC_TABLE | 949 | #ifdef DYNAMIC_CRC_TABLE |
| 1025 | once(&made, make_crc_table); | 950 | z_once(&made, make_crc_table); |
| 1026 | #endif /* DYNAMIC_CRC_TABLE */ | 951 | #endif /* DYNAMIC_CRC_TABLE */ |
| 1027 | return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); | 952 | return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); |
| 1028 | } | 953 | } |
| @@ -1037,7 +962,7 @@ uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { | |||
| 1037 | if (len2 < 0) | 962 | if (len2 < 0) |
| 1038 | return 0; | 963 | return 0; |
| 1039 | #ifdef DYNAMIC_CRC_TABLE | 964 | #ifdef DYNAMIC_CRC_TABLE |
| 1040 | once(&made, make_crc_table); | 965 | z_once(&made, make_crc_table); |
| 1041 | #endif /* DYNAMIC_CRC_TABLE */ | 966 | #endif /* DYNAMIC_CRC_TABLE */ |
| 1042 | return x2nmodp(len2, 3); | 967 | return x2nmodp(len2, 3); |
| 1043 | } | 968 | } |
