aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <git@madler.net>2026-01-05 01:15:38 -0600
committerMark Adler <git@madler.net>2026-01-05 15:03:04 -0600
commitc267ef7306fe9fc1399833e3556cd9798dec2eb0 (patch)
treebc18574b8ea4fc37befdf0174fb5f04472911f6f
parent916dc1ac351795c9bf86a3d19c3667b014b9d28e (diff)
downloadzlib-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.
-rw-r--r--FAQ4
-rw-r--r--README4
-rw-r--r--crc32.c87
-rw-r--r--infback.c53
-rw-r--r--inffixed.h182
-rw-r--r--inflate.c120
-rw-r--r--inftrees.c114
-rw-r--r--inftrees.h2
-rw-r--r--zconf.h1
-rw-r--r--zconf.h.in1
-rw-r--r--zlib.map2
-rw-r--r--zutil.c58
-rw-r--r--zutil.h26
13 files changed, 309 insertions, 345 deletions
diff --git a/FAQ b/FAQ
index b6b11bd..57dd4f5 100644
--- a/FAQ
+++ b/FAQ
@@ -156,6 +156,10 @@ The latest zlib FAQ is at http://zlib.net/zlib_faq.html
156 library memory allocation routines by default. zlib's *Init* functions 156 library memory allocation routines by default. zlib's *Init* functions
157 allow for the application to provide custom memory allocation routines. 157 allow for the application to provide custom memory allocation routines.
158 158
159 If the non-default BUILDFIXED or DYNAMIC_CRC_TABLE defines are used on a
160 system without atomics (e.g. pre-C11), then inflate() and crc32() will not
161 be thread safe.
162
159 Of course, you should only operate on any given zlib or gzip stream from a 163 Of course, you should only operate on any given zlib or gzip stream from a
160 single thread at a time. 164 single thread at a time.
161 165
diff --git a/README b/README
index 02259d4..17b70fc 100644
--- a/README
+++ b/README
@@ -1,8 +1,8 @@
1ZLIB DATA COMPRESSION LIBRARY 1ZLIB DATA COMPRESSION LIBRARY
2 2
3zlib 1.3.1.2 is a general purpose data compression library. All the code is 3zlib 1.3.1.2 is a general purpose data compression library. All the code is
4thread safe. The data format used by the zlib library is described by RFCs 4thread safe (though see the FAQ for caveats). The data format used by the zlib
5(Request for Comments) 1950 to 1952 at 5library is described by RFCs (Request for Comments) 1950 to 1952 at
6https://datatracker.ietf.org/doc/html/rfc1950 (zlib format), rfc1951 (deflate 6https://datatracker.ietf.org/doc/html/rfc1950 (zlib format), rfc1951 (deflate
7format) and rfc1952 (gzip format). 7format) and rfc1952 (gzip format).
8 8
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}
diff --git a/infback.c b/infback.c
index 5608530..518bf3e 100644
--- a/infback.c
+++ b/infback.c
@@ -63,57 +63,6 @@ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
63 return Z_OK; 63 return Z_OK;
64} 64}
65 65
66/*
67 Return state with length and distance decoding tables and index sizes set to
68 fixed code decoding. Normally this returns fixed tables from inffixed.h.
69 If BUILDFIXED is defined, then instead this routine builds the tables the
70 first time it's called, and returns those tables the first time and
71 thereafter. This reduces the size of the code by about 2K bytes, in
72 exchange for a little execution time. However, BUILDFIXED should not be
73 used for threaded applications, since the rewriting of the tables and virgin
74 may not be thread-safe.
75 */
76local void fixedtables(struct inflate_state FAR *state) {
77#ifdef BUILDFIXED
78 static int virgin = 1;
79 static code *lenfix, *distfix;
80 static code fixed[544];
81
82 /* build fixed huffman tables if first call (may not be thread safe) */
83 if (virgin) {
84 unsigned sym, bits;
85 static code *next;
86
87 /* literal/length table */
88 sym = 0;
89 while (sym < 144) state->lens[sym++] = 8;
90 while (sym < 256) state->lens[sym++] = 9;
91 while (sym < 280) state->lens[sym++] = 7;
92 while (sym < 288) state->lens[sym++] = 8;
93 next = fixed;
94 lenfix = next;
95 bits = 9;
96 inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
97
98 /* distance table */
99 sym = 0;
100 while (sym < 32) state->lens[sym++] = 5;
101 distfix = next;
102 bits = 5;
103 inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
104
105 /* do this just once */
106 virgin = 0;
107 }
108#else /* !BUILDFIXED */
109# include "inffixed.h"
110#endif /* BUILDFIXED */
111 state->lencode = lenfix;
112 state->lenbits = 9;
113 state->distcode = distfix;
114 state->distbits = 5;
115}
116
117/* Macros for inflateBack(): */ 66/* Macros for inflateBack(): */
118 67
119/* Load returned state from inflate_fast() */ 68/* Load returned state from inflate_fast() */
@@ -293,7 +242,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
293 state->mode = STORED; 242 state->mode = STORED;
294 break; 243 break;
295 case 1: /* fixed block */ 244 case 1: /* fixed block */
296 fixedtables(state); 245 inflate_fixed(state);
297 Tracev((stderr, "inflate: fixed codes block%s\n", 246 Tracev((stderr, "inflate: fixed codes block%s\n",
298 state->last ? " (last)" : "")); 247 state->last ? " (last)" : ""));
299 state->mode = LEN; /* decode codes */ 248 state->mode = LEN; /* decode codes */
diff --git a/inffixed.h b/inffixed.h
index d628327..05ce88e 100644
--- a/inffixed.h
+++ b/inffixed.h
@@ -1,94 +1,94 @@
1 /* inffixed.h -- table for decoding fixed codes 1/* inffixed.h -- table for decoding fixed codes
2 * Generated automatically by makefixed(). 2 * Generated automatically by makefixed().
3 */ 3 */
4 4
5 /* WARNING: this file should *not* be used by applications. 5/* WARNING: this file should *not* be used by applications.
6 It is part of the implementation of this library and is 6 It is part of the implementation of this library and is
7 subject to change. Applications should only use zlib.h. 7 subject to change. Applications should only use zlib.h.
8 */ 8 */
9 9
10 static const code lenfix[512] = { 10static const code lenfix[512] = {
11 {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, 11 {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
12 {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, 12 {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
13 {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, 13 {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
14 {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, 14 {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
15 {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, 15 {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
16 {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, 16 {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
17 {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, 17 {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
18 {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, 18 {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
19 {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, 19 {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
20 {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, 20 {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
21 {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, 21 {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
22 {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, 22 {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
23 {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, 23 {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
24 {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, 24 {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
25 {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, 25 {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
26 {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, 26 {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
27 {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, 27 {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
28 {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, 28 {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
29 {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, 29 {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
30 {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, 30 {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
31 {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, 31 {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
32 {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, 32 {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
33 {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, 33 {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
34 {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, 34 {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
35 {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, 35 {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
36 {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, 36 {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
37 {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, 37 {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
38 {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, 38 {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
39 {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, 39 {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
40 {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, 40 {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
41 {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, 41 {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
42 {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, 42 {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
43 {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, 43 {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
44 {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, 44 {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
45 {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, 45 {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
46 {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, 46 {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
47 {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, 47 {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
48 {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, 48 {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
49 {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, 49 {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
50 {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, 50 {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
51 {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, 51 {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
52 {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, 52 {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
53 {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, 53 {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
54 {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, 54 {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
55 {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, 55 {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
56 {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, 56 {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
57 {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, 57 {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
58 {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, 58 {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
59 {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, 59 {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
60 {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, 60 {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
61 {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, 61 {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
62 {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, 62 {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
63 {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, 63 {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
64 {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, 64 {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
65 {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, 65 {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
66 {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, 66 {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
67 {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, 67 {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
68 {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, 68 {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
69 {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, 69 {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
70 {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, 70 {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
71 {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, 71 {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
72 {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, 72 {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
73 {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, 73 {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
74 {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, 74 {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
75 {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, 75 {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
76 {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, 76 {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
77 {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, 77 {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
78 {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, 78 {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
79 {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, 79 {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
80 {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, 80 {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
81 {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, 81 {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
82 {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, 82 {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
83 {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, 83 {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
84 {0,9,255} 84 {0,9,255}
85 }; 85};
86 86
87 static const code distfix[32] = { 87static const code distfix[32] = {
88 {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, 88 {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
89 {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, 89 {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
90 {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, 90 {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
91 {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, 91 {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
92 {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, 92 {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
93 {22,5,193},{64,5,0} 93 {22,5,193},{64,5,0}
94 }; 94};
diff --git a/inflate.c b/inflate.c
index 301b5e7..623c95b 100644
--- a/inflate.c
+++ b/inflate.c
@@ -85,12 +85,6 @@
85#include "inflate.h" 85#include "inflate.h"
86#include "inffast.h" 86#include "inffast.h"
87 87
88#ifdef MAKEFIXED
89# ifndef BUILDFIXED
90# define BUILDFIXED
91# endif
92#endif
93
94local int inflateStateCheck(z_streamp strm) { 88local int inflateStateCheck(z_streamp strm) {
95 struct inflate_state FAR *state; 89 struct inflate_state FAR *state;
96 if (strm == Z_NULL || 90 if (strm == Z_NULL ||
@@ -241,118 +235,6 @@ int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
241} 235}
242 236
243/* 237/*
244 Return state with length and distance decoding tables and index sizes set to
245 fixed code decoding. Normally this returns fixed tables from inffixed.h.
246 If BUILDFIXED is defined, then instead this routine builds the tables the
247 first time it's called, and returns those tables the first time and
248 thereafter. This reduces the size of the code by about 2K bytes, in
249 exchange for a little execution time. However, BUILDFIXED should not be
250 used for threaded applications, since the rewriting of the tables and virgin
251 may not be thread-safe.
252 */
253local void fixedtables(struct inflate_state FAR *state) {
254#ifdef BUILDFIXED
255 static int virgin = 1;
256 static code *lenfix, *distfix;
257 static code fixed[544];
258
259 /* build fixed huffman tables if first call (may not be thread safe) */
260 if (virgin) {
261 unsigned sym, bits;
262 static code *next;
263
264 /* literal/length table */
265 sym = 0;
266 while (sym < 144) state->lens[sym++] = 8;
267 while (sym < 256) state->lens[sym++] = 9;
268 while (sym < 280) state->lens[sym++] = 7;
269 while (sym < 288) state->lens[sym++] = 8;
270 next = fixed;
271 lenfix = next;
272 bits = 9;
273 inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
274
275 /* distance table */
276 sym = 0;
277 while (sym < 32) state->lens[sym++] = 5;
278 distfix = next;
279 bits = 5;
280 inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
281
282 /* do this just once */
283 virgin = 0;
284 }
285#else /* !BUILDFIXED */
286# include "inffixed.h"
287#endif /* BUILDFIXED */
288 state->lencode = lenfix;
289 state->lenbits = 9;
290 state->distcode = distfix;
291 state->distbits = 5;
292}
293
294#ifdef MAKEFIXED
295#include <stdio.h>
296
297/*
298 Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
299 defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
300 those tables to stdout, which would be piped to inffixed.h. A small program
301 can simply call makefixed to do this:
302
303 void makefixed(void);
304
305 int main(void)
306 {
307 makefixed();
308 return 0;
309 }
310
311 Then that can be linked with zlib built with MAKEFIXED defined and run:
312
313 a.out > inffixed.h
314 */
315void makefixed(void)
316{
317 unsigned low, size;
318 struct inflate_state state;
319
320 fixedtables(&state);
321 puts(" /* inffixed.h -- table for decoding fixed codes");
322 puts(" * Generated automatically by makefixed().");
323 puts(" */");
324 puts("");
325 puts(" /* WARNING: this file should *not* be used by applications.");
326 puts(" It is part of the implementation of this library and is");
327 puts(" subject to change. Applications should only use zlib.h.");
328 puts(" */");
329 puts("");
330 size = 1U << 9;
331 printf(" static const code lenfix[%u] = {", size);
332 low = 0;
333 for (;;) {
334 if ((low % 7) == 0) printf("\n ");
335 printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
336 state.lencode[low].bits, state.lencode[low].val);
337 if (++low == size) break;
338 putchar(',');
339 }
340 puts("\n };");
341 size = 1U << 5;
342 printf("\n static const code distfix[%u] = {", size);
343 low = 0;
344 for (;;) {
345 if ((low % 6) == 0) printf("\n ");
346 printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
347 state.distcode[low].val);
348 if (++low == size) break;
349 putchar(',');
350 }
351 puts("\n };");
352}
353#endif /* MAKEFIXED */
354
355/*
356 Update the window with the last wsize (normally 32K) bytes written before 238 Update the window with the last wsize (normally 32K) bytes written before
357 returning. If window does not exist yet, create it. This is only called 239 returning. If window does not exist yet, create it. This is only called
358 when a window is already in use, or when output has been written during this 240 when a window is already in use, or when output has been written during this
@@ -841,7 +723,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
841 state->mode = STORED; 723 state->mode = STORED;
842 break; 724 break;
843 case 1: /* fixed block */ 725 case 1: /* fixed block */
844 fixedtables(state); 726 inflate_fixed(state);
845 Tracev((stderr, "inflate: fixed codes block%s\n", 727 Tracev((stderr, "inflate: fixed codes block%s\n",
846 state->last ? " (last)" : "")); 728 state->last ? " (last)" : ""));
847 state->mode = LEN_; /* decode codes */ 729 state->mode = LEN_; /* decode codes */
diff --git a/inftrees.c b/inftrees.c
index f7849a7..c050f8b 100644
--- a/inftrees.c
+++ b/inftrees.c
@@ -5,6 +5,7 @@
5 5
6#include "zutil.h" 6#include "zutil.h"
7#include "inftrees.h" 7#include "inftrees.h"
8#include "inflate.h"
8 9
9#define MAXBITS 15 10#define MAXBITS 15
10 11
@@ -297,3 +298,116 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
297 *bits = root; 298 *bits = root;
298 return 0; 299 return 0;
299} 300}
301
302#ifdef BUILDFIXED
303/*
304 If this is compiled with BUILDFIXED defined, and if inflate will be used in
305 multiple threads, and if atomics are not available, then inflate() must be
306 called with a fixed block (e.g. 0x03 0x00) to initialize the tables and must
307 return before any other threads are allowed to call inflate.
308 */
309
310static code *lenfix, *distfix;
311static code fixed[544];
312
313/* State for z_once(). */
314local z_once_t built = Z_ONCE_INIT;
315
316local void buildtables(void) {
317 unsigned sym, bits;
318 static code *next;
319 unsigned short lens[288], work[288];
320
321 /* literal/length table */
322 sym = 0;
323 while (sym < 144) lens[sym++] = 8;
324 while (sym < 256) lens[sym++] = 9;
325 while (sym < 280) lens[sym++] = 7;
326 while (sym < 288) lens[sym++] = 8;
327 next = fixed;
328 lenfix = next;
329 bits = 9;
330 inflate_table(LENS, lens, 288, &(next), &(bits), work);
331
332 /* distance table */
333 sym = 0;
334 while (sym < 32) lens[sym++] = 5;
335 distfix = next;
336 bits = 5;
337 inflate_table(DISTS, lens, 32, &(next), &(bits), work);
338}
339#else /* !BUILDFIXED */
340# include "inffixed.h"
341#endif /* BUILDFIXED */
342
343/*
344 Return state with length and distance decoding tables and index sizes set to
345 fixed code decoding. Normally this returns fixed tables from inffixed.h.
346 If BUILDFIXED is defined, then instead this routine builds the tables the
347 first time it's called, and returns those tables the first time and
348 thereafter. This reduces the size of the code by about 2K bytes, in
349 exchange for a little execution time. However, BUILDFIXED should not be
350 used for threaded applications if atomics are not available, as it will
351 not be thread-safe.
352 */
353void inflate_fixed(struct inflate_state FAR *state) {
354#ifdef BUILDFIXED
355 z_once(&built, buildtables);
356#endif /* BUILDFIXED */
357 state->lencode = lenfix;
358 state->lenbits = 9;
359 state->distcode = distfix;
360 state->distbits = 5;
361}
362
363#ifdef MAKEFIXED
364#include <stdio.h>
365
366/*
367 Write out the inffixed.h that will be #include'd above. Defining MAKEFIXED
368 also defines BUILDFIXED, so the tables are built on the fly. main() writes
369 those tables to stdout, which would directed to inffixed.h. Compile this
370 along with zutil.c:
371
372 cc -DMAKEFIXED -o fix inftrees.c zutil.c
373 ./fix > inffixed.h
374 */
375int main(void) {
376 unsigned low, size;
377 struct inflate_state state;
378
379 inflate_fixed(&state);
380 puts("/* inffixed.h -- table for decoding fixed codes");
381 puts(" * Generated automatically by makefixed().");
382 puts(" */");
383 puts("");
384 puts("/* WARNING: this file should *not* be used by applications.");
385 puts(" It is part of the implementation of this library and is");
386 puts(" subject to change. Applications should only use zlib.h.");
387 puts(" */");
388 puts("");
389 size = 1U << 9;
390 printf("static const code lenfix[%u] = {", size);
391 low = 0;
392 for (;;) {
393 if ((low % 7) == 0) printf("\n ");
394 printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
395 state.lencode[low].bits, state.lencode[low].val);
396 if (++low == size) break;
397 putchar(',');
398 }
399 puts("\n};");
400 size = 1U << 5;
401 printf("\nstatic const code distfix[%u] = {", size);
402 low = 0;
403 for (;;) {
404 if ((low % 6) == 0) printf("\n ");
405 printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
406 state.distcode[low].val);
407 if (++low == size) break;
408 putchar(',');
409 }
410 puts("\n};");
411 return 0;
412}
413#endif /* MAKEFIXED */
diff --git a/inftrees.h b/inftrees.h
index 396f74b..00ec96e 100644
--- a/inftrees.h
+++ b/inftrees.h
@@ -60,3 +60,5 @@ typedef enum {
60int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, 60int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
61 unsigned codes, code FAR * FAR *table, 61 unsigned codes, code FAR * FAR *table,
62 unsigned FAR *bits, unsigned short FAR *work); 62 unsigned FAR *bits, unsigned short FAR *work);
63struct inflate_state;
64void ZLIB_INTERNAL inflate_fixed(struct inflate_state FAR *state);
diff --git a/zconf.h b/zconf.h
index 7d936c7..524192a 100644
--- a/zconf.h
+++ b/zconf.h
@@ -131,6 +131,7 @@
131# define inflate_copyright z_inflate_copyright 131# define inflate_copyright z_inflate_copyright
132# define inflate_fast z_inflate_fast 132# define inflate_fast z_inflate_fast
133# define inflate_table z_inflate_table 133# define inflate_table z_inflate_table
134# define inflate_fixed z_inflate_fixed
134# ifndef Z_SOLO 135# ifndef Z_SOLO
135# define uncompress z_uncompress 136# define uncompress z_uncompress
136# define uncompress2 z_uncompress2 137# define uncompress2 z_uncompress2
diff --git a/zconf.h.in b/zconf.h.in
index 7d936c7..524192a 100644
--- a/zconf.h.in
+++ b/zconf.h.in
@@ -131,6 +131,7 @@
131# define inflate_copyright z_inflate_copyright 131# define inflate_copyright z_inflate_copyright
132# define inflate_fast z_inflate_fast 132# define inflate_fast z_inflate_fast
133# define inflate_table z_inflate_table 133# define inflate_table z_inflate_table
134# define inflate_fixed z_inflate_fixed
134# ifndef Z_SOLO 135# ifndef Z_SOLO
135# define uncompress z_uncompress 136# define uncompress z_uncompress
136# define uncompress2 z_uncompress2 137# define uncompress2 z_uncompress2
diff --git a/zlib.map b/zlib.map
index e267d82..aba65ab 100644
--- a/zlib.map
+++ b/zlib.map
@@ -11,9 +11,11 @@ ZLIB_1.2.0 {
11 inflate_copyright; 11 inflate_copyright;
12 inflate_fast; 12 inflate_fast;
13 inflate_table; 13 inflate_table;
14 inflate_fixed;
14 zcalloc; 15 zcalloc;
15 zcfree; 16 zcfree;
16 z_errmsg; 17 z_errmsg;
18 z_once;
17 gz_error; 19 gz_error;
18 gz_intmax; 20 gz_intmax;
19 _*; 21 _*;
diff --git a/zutil.c b/zutil.c
index 6e8a369..3a94e91 100644
--- a/zutil.c
+++ b/zutil.c
@@ -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 */
325void 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. */
343local 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. */
352void 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
diff --git a/zutil.h b/zutil.h
index 27ca693..94fa1af 100644
--- a/zutil.h
+++ b/zutil.h
@@ -254,4 +254,30 @@ 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
258# ifndef BUILDFIXED
259# define BUILDFIXED
260# endif
261#endif
262#if defined(BUILDFIXED) || defined(DYNAMIC_CRC_TABLE)
263/* Structure for z_once(), which must be initialized with Z_ONCE_INIT. */
264typedef struct z_once_s z_once_t;
265void ZLIB_INTERNAL z_once(z_once_t *state, void (*init)(void));
266#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
267 !defined(__STDC_NO_ATOMICS__)
268#include <stdatomic.h>
269struct z_once_s {
270 atomic_flag begun;
271 atomic_int done;
272};
273#define Z_ONCE_INIT {ATOMIC_FLAG_INIT, 0}
274#else /* no atomics! */
275struct z_once_s {
276 volatile int begun;
277 volatile int done;
278};
279#define Z_ONCE_INIT {0, 0}
280#endif
281#endif
282
257#endif /* ZUTIL_H */ 283#endif /* ZUTIL_H */