diff options
| author | Mark Adler <git@madler.net> | 2026-01-05 01:15:38 -0600 |
|---|---|---|
| committer | Mark Adler <git@madler.net> | 2026-01-05 15:03:04 -0600 |
| commit | c267ef7306fe9fc1399833e3556cd9798dec2eb0 (patch) | |
| tree | bc18574b8ea4fc37befdf0174fb5f04472911f6f /inftrees.c | |
| parent | 916dc1ac351795c9bf86a3d19c3667b014b9d28e (diff) | |
| download | zlib-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.
Diffstat (limited to 'inftrees.c')
| -rw-r--r-- | inftrees.c | 114 |
1 files changed, 114 insertions, 0 deletions
| @@ -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 | |||
| 310 | static code *lenfix, *distfix; | ||
| 311 | static code fixed[544]; | ||
| 312 | |||
| 313 | /* State for z_once(). */ | ||
| 314 | local z_once_t built = Z_ONCE_INIT; | ||
| 315 | |||
| 316 | local 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 | */ | ||
| 353 | void 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 | */ | ||
| 375 | int 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 */ | ||
