diff options
Diffstat (limited to 'src/liblzma/common')
| -rw-r--r-- | src/liblzma/common/alone_decoder.c | 6 | ||||
| -rw-r--r-- | src/liblzma/common/filter_common.c | 4 | ||||
| -rw-r--r-- | src/liblzma/common/lzip_decoder.c | 3 | ||||
| -rw-r--r-- | src/liblzma/common/outqueue.h | 1 | ||||
| -rw-r--r-- | src/liblzma/common/stream_decoder_mt.c | 79 | ||||
| -rw-r--r-- | src/liblzma/common/vli_decoder.c | 2 |
6 files changed, 44 insertions, 51 deletions
diff --git a/src/liblzma/common/alone_decoder.c b/src/liblzma/common/alone_decoder.c index e2b58e1f3758..8ebbbe8aa70f 100644 --- a/src/liblzma/common/alone_decoder.c +++ b/src/liblzma/common/alone_decoder.c @@ -128,8 +128,10 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator, lzma_set_ext_size(coder->options, coder->uncompressed_size); // Calculate the memory usage so that it is ready - // for SEQ_CODER_INIT. - coder->memusage = lzma_lzma_decoder_memusage(&coder->options) + // for SEQ_CODER_INIT. We know that lc/lp/pb are valid + // so we can use the _nocheck variant. + coder->memusage + = lzma_lzma_decoder_memusage_nocheck(&coder->options) + LZMA_MEMUSAGE_BASE; coder->pos = 0; diff --git a/src/liblzma/common/filter_common.c b/src/liblzma/common/filter_common.c index d15d9cc94f99..6c06c78ddc15 100644 --- a/src/liblzma/common/filter_common.c +++ b/src/liblzma/common/filter_common.c @@ -213,8 +213,8 @@ lzma_filters_copy(const lzma_filter *src, lzma_filter *real_dest, error: // Free the options which we have already allocated. - while (i-- > 0) - lzma_free(dest[i].options, allocator); + while (i > 0) + lzma_free(dest[--i].options, allocator); return ret; } diff --git a/src/liblzma/common/lzip_decoder.c b/src/liblzma/common/lzip_decoder.c index 4dff2d5889ea..5630039f97b9 100644 --- a/src/liblzma/common/lzip_decoder.c +++ b/src/liblzma/common/lzip_decoder.c @@ -212,7 +212,8 @@ lzip_decode(void *coder_ptr, const lzma_allocator *allocator, coder->options.pb = LZIP_PB; // Calculate the memory usage. - coder->memusage = lzma_lzma_decoder_memusage(&coder->options) + coder->memusage + = lzma_lzma_decoder_memusage_nocheck(&coder->options) + LZMA_MEMUSAGE_BASE; // Initialization is a separate step because if we return diff --git a/src/liblzma/common/outqueue.h b/src/liblzma/common/outqueue.h index 25f071977a8f..0e4e9141dab5 100644 --- a/src/liblzma/common/outqueue.h +++ b/src/liblzma/common/outqueue.h @@ -188,6 +188,7 @@ extern bool lzma_outq_is_readable(const lzma_outq *outq); /// \brief Read finished data /// /// \param outq Pointer to an output queue +/// \param allocator lzma_allocator for custom allocator functions /// \param out Beginning of the output buffer /// \param out_pos The next byte will be written to /// out[*out_pos]. diff --git a/src/liblzma/common/stream_decoder_mt.c b/src/liblzma/common/stream_decoder_mt.c index 271f9b07c4b8..d51366e1b02c 100644 --- a/src/liblzma/common/stream_decoder_mt.c +++ b/src/liblzma/common/stream_decoder_mt.c @@ -33,26 +33,6 @@ typedef enum { } worker_state; -typedef enum { - /// Partial updates (storing of worker thread progress - /// to lzma_outbuf) are disabled. - PARTIAL_DISABLED, - - /// Main thread requests partial updates to be enabled but - /// no partial update has been done by the worker thread yet. - /// - /// Changing from PARTIAL_DISABLED to PARTIAL_START requires - /// use of the worker-thread mutex. Other transitions don't - /// need a mutex. - PARTIAL_START, - - /// Partial updates are enabled and the worker thread has done - /// at least one partial update. - PARTIAL_ENABLED, - -} partial_update_mode; - - struct worker_thread { /// Worker state is protected with our mutex. worker_state state; @@ -104,10 +84,18 @@ struct worker_thread { /// happen if all worker threads were frequently locking the main /// mutex to update their outbuf->pos. /// - /// Only when partial_update is something else than PARTIAL_DISABLED, - /// this worker thread will update outbuf->pos after each call to - /// the Block decoder. - partial_update_mode partial_update; + /// When partial_update_enabled is true, this worker thread will + /// update outbuf->pos and outbuf->decoder_in_pos after each call + /// to the Block decoder. This is initially false. Main thread may + /// set this to true. + bool partial_update_enabled; + + /// Once the main thread has set partial_updated_enabled = true, + /// we will do the first partial update as soon as we can and + /// set partial_update_started = true. After the first update, + /// we only update if we have made progress. This avoids useless + /// locking of thr->coder->mutex. + bool partial_update_started; /// Block decoder lzma_next_coder block_decoder; @@ -335,7 +323,7 @@ worker_enable_partial_update(void *thr_ptr) struct worker_thread *thr = thr_ptr; mythread_sync(thr->mutex) { - thr->partial_update = PARTIAL_START; + thr->partial_update_enabled = true; mythread_cond_signal(&thr->cond); } } @@ -346,7 +334,7 @@ worker_decoder(void *thr_ptr) { struct worker_thread *thr = thr_ptr; size_t in_filled; - partial_update_mode partial_update; + bool partial_update_enabled; lzma_ret ret; next_loop_lock: @@ -378,14 +366,16 @@ next_loop_unlocked: thr->progress_out = thr->out_pos; // If we don't have any new input, wait for a signal from the main - // thread except if partial output has just been enabled. In that + // thread except if partial output has just been enabled + // (partial_update_enabled is true but _started is false). In that // case we will do one normal run so that the partial output info // gets passed to the main thread. The call to block_decoder.code() // is useless but harmless as it can occur only once per Block. in_filled = thr->in_filled; - partial_update = thr->partial_update; + partial_update_enabled = thr->partial_update_enabled; - if (in_filled == thr->in_pos && partial_update != PARTIAL_START) { + if (in_filled == thr->in_pos && !(partial_update_enabled + && !thr->partial_update_started)) { mythread_cond_wait(&thr->cond, &thr->mutex); goto next_loop_unlocked; } @@ -407,23 +397,21 @@ next_loop_unlocked: thr->outbuf->allocated, LZMA_RUN); if (ret == LZMA_OK) { - if (partial_update != PARTIAL_DISABLED) { - // The main thread uses thr->mutex to change from - // PARTIAL_DISABLED to PARTIAL_START. The main thread - // doesn't care about this variable after that so we - // can safely change it here to PARTIAL_ENABLED - // without a mutex. - thr->partial_update = PARTIAL_ENABLED; + if (partial_update_enabled) { + // Remember that we have done at least one partial + // update. After the first update we won't do updates + // unless we have made progress. + thr->partial_update_started = true; // The main thread is reading decompressed data // from thr->outbuf. Tell the main thread about // our progress. // // NOTE: It's possible that we consumed input without - // producing any new output so it's possible that - // only in_pos has changed. In case of PARTIAL_START - // it is possible that neither in_pos nor out_pos has - // changed. + // producing any new output so it's possible that only + // in_pos has changed. If thr->partial_update_started + // was false, it is possible that neither in_pos nor + // out_pos has changed. mythread_sync(thr->coder->mutex) { thr->outbuf->pos = thr->out_pos; thr->outbuf->decoder_in_pos = thr->in_pos; @@ -645,7 +633,8 @@ get_thread(struct lzma_stream_coder *coder, const lzma_allocator *allocator) coder->thr->progress_in = 0; coder->thr->progress_out = 0; - coder->thr->partial_update = PARTIAL_DISABLED; + coder->thr->partial_update_enabled = false; + coder->thr->partial_update_started = false; return LZMA_OK; } @@ -816,12 +805,12 @@ read_output_and_wait(struct lzma_stream_coder *coder, // keeps calling lzma_code() without providing more // input, it will eventually get LZMA_BUF_ERROR. // - // NOTE: We can read partial_update and in_filled - // without thr->mutex as only the main thread + // NOTE: We can read partial_update_enabled and + // in_filled without thr->mutex as only the main thread // modifies these variables. decoder_in_pos requires // coder->mutex which we are already holding. - if (coder->thr != NULL && coder->thr->partial_update - != PARTIAL_DISABLED) { + if (coder->thr != NULL && + coder->thr->partial_update_enabled) { // There is exactly one outbuf in the queue. assert(coder->thr->outbuf == coder->outq.head); assert(coder->thr->outbuf == coder->outq.tail); diff --git a/src/liblzma/common/vli_decoder.c b/src/liblzma/common/vli_decoder.c index 3254ccc35bde..7fa5f47e10c4 100644 --- a/src/liblzma/common/vli_decoder.c +++ b/src/liblzma/common/vli_decoder.c @@ -38,7 +38,7 @@ lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos, // Validate the arguments. if (*vli_pos >= LZMA_VLI_BYTES_MAX || (*vli >> (*vli_pos * 7)) != 0) - return LZMA_PROG_ERROR;; + return LZMA_PROG_ERROR; if (*in_pos >= in_size) return LZMA_BUF_ERROR; |
