]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
liblzma: mt dec: Fix lack of parallelization in single-shot decoding
authorLasse Collin <lasse.collin@tukaani.org>
Thu, 3 Apr 2025 11:34:42 +0000 (14:34 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Thu, 3 Apr 2025 11:34:42 +0000 (14:34 +0300)
Single-shot decoding means calling lzma_code() by giving it the whole
input at once and enough output buffer space to store the uncompressed
data, and combining this with LZMA_FINISH and no timeout
(lzma_mt.timeout = 0). This way the file is decoded with a single
lzma_code() call if possible.

The bug prevented the decoder from starting more than one worker thread
in single-shot mode. The issue was noticed when reviewing the code;
there are no bug reports. Thus maybe few have tried this mode.

Fixes: 64b6d496dc81 ("liblzma: Threaded decoder: Always wait for output if LZMA_FINISH is used.")
src/liblzma/common/stream_decoder_mt.c

index 1fa92220568dcc3bb1a1f58229a6bd4589e26003..271f9b07c4b821b7e9dd5c50536ee1765b0ac77b 100644 (file)
@@ -1540,10 +1540,17 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
                // Read output from the output queue. Just like in
                // SEQ_BLOCK_HEADER, we wait to fill the output buffer
                // only if waiting_allowed was set to true in the beginning
-               // of this function (see the comment there).
+               // of this function (see the comment there) and there is
+               // no input available. In SEQ_BLOCK_HEADER, there is never
+               // input available when read_output_and_wait() is called,
+               // but here there can be when LZMA_FINISH is used, thus we
+               // need to check if *in_pos == in_size. Otherwise we would
+               // wait here instead of using the available input to start
+               // a new thread.
                return_if_error(read_output_and_wait(coder, allocator,
                                out, out_pos, out_size,
-                               NULL, waiting_allowed,
+                               NULL,
+                               waiting_allowed && *in_pos == in_size,
                                &wait_abs, &has_blocked));
 
                if (coder->pending_error != LZMA_OK) {