aboutsummaryrefslogtreecommitdiff
path: root/crc32.c
diff options
context:
space:
mode:
Diffstat (limited to 'crc32.c')
-rw-r--r--crc32.c87
1 files changed, 6 insertions, 81 deletions
diff --git a/crc32.c b/crc32.c
index 33d8c79..630049f 100644
--- a/crc32.c
+++ b/crc32.c
@@ -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. */
216typedef 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. */
225struct 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 */
236local 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. */
251struct 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. */
259local 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. */
268local 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(). */
283local once_t made = ONCE_INIT; 208local 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 */
549const z_crc_t FAR * ZEXPORT get_crc_table(void) { 474const 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}