]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
ZSTDMT_compressStream() becomes blocking when required to ensure forward progresses
authorYann Collet <cyan@fb.com>
Mon, 23 Jan 2017 07:49:52 +0000 (23:49 -0800)
committerYann Collet <cyan@fb.com>
Mon, 23 Jan 2017 07:49:52 +0000 (23:49 -0800)
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.

lib/compress/zstdmt_compress.c

index 283f7684161f6f7bdb4c3a202dfc70b84f8c9b9c..176f940c8811344ca9be7c9956f1de0303874442 100644 (file)
@@ -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) {