From: Yann Collet Date: Mon, 23 Jan 2017 07:49:52 +0000 (-0800) Subject: ZSTDMT_compressStream() becomes blocking when required to ensure forward progresses X-Git-Tag: v1.1.3^2~19^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1a2547f6540c8f208fe116072cd935960acfe62a;p=thirdparty%2Fzstd.git ZSTDMT_compressStream() becomes blocking when required to ensure forward progresses In some (rare) cases, job list could be blocked by a first job still being processed, while all following ones are completed, waiting to be flushed. In such case, the current job-table implementation is unable to accept new job. As a consequence, a call to ZSTDMT_compressStream() can be useless (nothing read, nothing flushed), with the risk to trigger a busy-wait on the caller side (needlessly loop over ZSTDMT_compressStream() ). In such a case, ZSTDMT_compressStream() will block until the first job is completed and ready to flush. It ensures some forward progress by guaranteeing it will flush at least a part of the completed job. Energy-wasting busy-wait is avoided. --- diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 283f76841..176f940c8 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -565,6 +565,10 @@ size_t ZSTDMT_compressStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, ZSTD_inBu { unsigned const jobID = zcs->doneJobID & zcs->jobIDMask; unsigned jobCompleted; pthread_mutex_lock(&zcs->jobCompleted_mutex); + while (zcs->jobs[jobID].jobCompleted == 0 && zcs->inBuff.filled == zcs->inBuffSize) { + /* when no new job could be started, block until there is something to flush, ensuring forward progress */ + pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); + } jobCompleted = zcs->jobs[jobID].jobCompleted; pthread_mutex_unlock(&zcs->jobCompleted_mutex); if (jobCompleted) {