zstd-ruby 1.3.1.1 → 1.3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/.gitignore +1 -0
  4. data/ext/zstdruby/libzstd/Makefile +40 -26
  5. data/ext/zstdruby/libzstd/README.md +68 -45
  6. data/ext/zstdruby/libzstd/common/bitstream.h +35 -23
  7. data/ext/zstdruby/libzstd/common/compiler.h +1 -0
  8. data/ext/zstdruby/libzstd/common/error_private.c +4 -2
  9. data/ext/zstdruby/libzstd/common/error_private.h +4 -4
  10. data/ext/zstdruby/libzstd/common/fse.h +1 -1
  11. data/ext/zstdruby/libzstd/common/huf.h +1 -1
  12. data/ext/zstdruby/libzstd/common/mem.h +1 -0
  13. data/ext/zstdruby/libzstd/common/pool.c +61 -46
  14. data/ext/zstdruby/libzstd/common/pool.h +4 -0
  15. data/ext/zstdruby/libzstd/common/threading.c +11 -15
  16. data/ext/zstdruby/libzstd/common/threading.h +52 -32
  17. data/ext/zstdruby/libzstd/common/zstd_common.c +2 -2
  18. data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
  19. data/ext/zstdruby/libzstd/common/zstd_internal.h +95 -21
  20. data/ext/zstdruby/libzstd/compress/fse_compress.c +3 -1
  21. data/ext/zstdruby/libzstd/compress/huf_compress.c +4 -3
  22. data/ext/zstdruby/libzstd/compress/zstd_compress.c +922 -2102
  23. data/ext/zstdruby/libzstd/compress/zstd_compress.h +307 -0
  24. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +308 -0
  25. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +28 -0
  26. data/ext/zstdruby/libzstd/compress/zstd_fast.c +242 -0
  27. data/ext/zstdruby/libzstd/compress/zstd_fast.h +30 -0
  28. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +749 -0
  29. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +38 -0
  30. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +707 -0
  31. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +67 -0
  32. data/ext/zstdruby/libzstd/compress/zstd_opt.c +957 -0
  33. data/ext/zstdruby/libzstd/compress/zstd_opt.h +14 -922
  34. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +210 -133
  35. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +20 -3
  36. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +373 -196
  37. data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -0
  38. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -0
  39. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
  40. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -0
  41. data/ext/zstdruby/libzstd/dictBuilder/cover.c +33 -22
  42. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +8 -5
  43. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -0
  44. data/ext/zstdruby/libzstd/dll/example/Makefile +5 -5
  45. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -0
  46. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -0
  47. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -0
  48. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -0
  49. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -0
  50. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -0
  51. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -0
  52. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -0
  53. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -0
  54. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -0
  55. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -0
  56. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -0
  57. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -0
  58. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -0
  59. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -0
  60. data/ext/zstdruby/libzstd/zstd.h +366 -118
  61. data/lib/zstd-ruby/version.rb +1 -1
  62. metadata +11 -1
@@ -5,11 +5,12 @@
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
 
11
12
  /* ====== Tuning parameters ====== */
12
- #define ZSTDMT_NBTHREADS_MAX 256
13
+ #define ZSTDMT_NBTHREADS_MAX 200
13
14
  #define ZSTDMT_OVERLAPLOG_DEFAULT 6
14
15
 
15
16
 
@@ -52,22 +53,24 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
52
53
  }
53
54
 
54
55
  #define MUTEX_WAIT_TIME_DLEVEL 6
55
- #define PTHREAD_MUTEX_LOCK(mutex) { \
56
- if (ZSTD_DEBUG>=MUTEX_WAIT_TIME_DLEVEL) { \
56
+ #define ZSTD_PTHREAD_MUTEX_LOCK(mutex) { \
57
+ if (ZSTD_DEBUG >= MUTEX_WAIT_TIME_DLEVEL) { \
57
58
  unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
58
- pthread_mutex_lock(mutex); \
59
+ ZSTD_pthread_mutex_lock(mutex); \
59
60
  { unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
60
61
  unsigned long long const elapsedTime = (afterTime-beforeTime); \
61
62
  if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
62
63
  DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
63
64
  elapsedTime, #mutex); \
64
65
  } } \
65
- } else pthread_mutex_lock(mutex); \
66
+ } else { \
67
+ ZSTD_pthread_mutex_lock(mutex); \
68
+ } \
66
69
  }
67
70
 
68
71
  #else
69
72
 
70
- # define PTHREAD_MUTEX_LOCK(m) pthread_mutex_lock(m)
73
+ # define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m)
71
74
  # define DEBUG_PRINTHEX(l,p,n) {}
72
75
 
73
76
  #endif
@@ -84,7 +87,7 @@ typedef struct buffer_s {
84
87
  static const buffer_t g_nullBuffer = { NULL, 0 };
85
88
 
86
89
  typedef struct ZSTDMT_bufferPool_s {
87
- pthread_mutex_t poolMutex;
90
+ ZSTD_pthread_mutex_t poolMutex;
88
91
  size_t bufferSize;
89
92
  unsigned totalBuffers;
90
93
  unsigned nbBuffers;
@@ -98,7 +101,7 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_custo
98
101
  ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
99
102
  sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
100
103
  if (bufPool==NULL) return NULL;
101
- if (pthread_mutex_init(&bufPool->poolMutex, NULL)) {
104
+ if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
102
105
  ZSTD_free(bufPool, cMem);
103
106
  return NULL;
104
107
  }
@@ -112,10 +115,13 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_custo
112
115
  static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
113
116
  {
114
117
  unsigned u;
118
+ DEBUGLOG(3, "ZSTDMT_freeBufferPool (address:%08X)", (U32)(size_t)bufPool);
115
119
  if (!bufPool) return; /* compatibility with free on NULL */
116
- for (u=0; u<bufPool->totalBuffers; u++)
120
+ for (u=0; u<bufPool->totalBuffers; u++) {
121
+ DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
117
122
  ZSTD_free(bufPool->bTable[u].start, bufPool->cMem);
118
- pthread_mutex_destroy(&bufPool->poolMutex);
123
+ }
124
+ ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
119
125
  ZSTD_free(bufPool, bufPool->cMem);
120
126
  }
121
127
 
@@ -126,10 +132,10 @@ static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
126
132
  + (bufPool->totalBuffers - 1) * sizeof(buffer_t);
127
133
  unsigned u;
128
134
  size_t totalBufferSize = 0;
129
- pthread_mutex_lock(&bufPool->poolMutex);
135
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
130
136
  for (u=0; u<bufPool->totalBuffers; u++)
131
137
  totalBufferSize += bufPool->bTable[u].size;
132
- pthread_mutex_unlock(&bufPool->poolMutex);
138
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
133
139
 
134
140
  return poolSize + totalBufferSize;
135
141
  }
@@ -145,20 +151,21 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
145
151
  {
146
152
  size_t const bSize = bufPool->bufferSize;
147
153
  DEBUGLOG(5, "ZSTDMT_getBuffer");
148
- pthread_mutex_lock(&bufPool->poolMutex);
154
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
149
155
  if (bufPool->nbBuffers) { /* try to use an existing buffer */
150
156
  buffer_t const buf = bufPool->bTable[--(bufPool->nbBuffers)];
151
157
  size_t const availBufferSize = buf.size;
158
+ bufPool->bTable[bufPool->nbBuffers] = g_nullBuffer;
152
159
  if ((availBufferSize >= bSize) & (availBufferSize <= 10*bSize)) {
153
160
  /* large enough, but not too much */
154
- pthread_mutex_unlock(&bufPool->poolMutex);
161
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
155
162
  return buf;
156
163
  }
157
164
  /* size conditions not respected : scratch this buffer, create new one */
158
165
  DEBUGLOG(5, "existing buffer does not meet size conditions => freeing");
159
166
  ZSTD_free(buf.start, bufPool->cMem);
160
167
  }
161
- pthread_mutex_unlock(&bufPool->poolMutex);
168
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
162
169
  /* create new buffer */
163
170
  DEBUGLOG(5, "create a new buffer");
164
171
  { buffer_t buffer;
@@ -174,24 +181,38 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
174
181
  {
175
182
  if (buf.start == NULL) return; /* compatible with release on NULL */
176
183
  DEBUGLOG(5, "ZSTDMT_releaseBuffer");
177
- pthread_mutex_lock(&bufPool->poolMutex);
184
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
178
185
  if (bufPool->nbBuffers < bufPool->totalBuffers) {
179
186
  bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
180
- pthread_mutex_unlock(&bufPool->poolMutex);
187
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
181
188
  return;
182
189
  }
183
- pthread_mutex_unlock(&bufPool->poolMutex);
190
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
184
191
  /* Reached bufferPool capacity (should not happen) */
185
192
  DEBUGLOG(5, "buffer pool capacity reached => freeing ");
186
193
  ZSTD_free(buf.start, bufPool->cMem);
187
194
  }
188
195
 
196
+ /* Sets parameters relevant to the compression job, initializing others to
197
+ * default values. Notably, nbThreads should probably be zero. */
198
+ static ZSTD_CCtx_params ZSTDMT_makeJobCCtxParams(ZSTD_CCtx_params const params)
199
+ {
200
+ ZSTD_CCtx_params jobParams;
201
+ memset(&jobParams, 0, sizeof(jobParams));
202
+
203
+ jobParams.cParams = params.cParams;
204
+ jobParams.fParams = params.fParams;
205
+ jobParams.compressionLevel = params.compressionLevel;
206
+
207
+ jobParams.ldmParams = params.ldmParams;
208
+ return jobParams;
209
+ }
189
210
 
190
211
  /* ===== CCtx Pool ===== */
191
212
  /* a single CCtx Pool can be invoked from multiple threads in parallel */
192
213
 
193
214
  typedef struct {
194
- pthread_mutex_t poolMutex;
215
+ ZSTD_pthread_mutex_t poolMutex;
195
216
  unsigned totalCCtx;
196
217
  unsigned availCCtx;
197
218
  ZSTD_customMem cMem;
@@ -204,7 +225,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
204
225
  unsigned u;
205
226
  for (u=0; u<pool->totalCCtx; u++)
206
227
  ZSTD_freeCCtx(pool->cctx[u]); /* note : compatible with free on NULL */
207
- pthread_mutex_destroy(&pool->poolMutex);
228
+ ZSTD_pthread_mutex_destroy(&pool->poolMutex);
208
229
  ZSTD_free(pool, pool->cMem);
209
230
  }
210
231
 
@@ -216,7 +237,7 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
216
237
  ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
217
238
  sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*), cMem);
218
239
  if (!cctxPool) return NULL;
219
- if (pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
240
+ if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
220
241
  ZSTD_free(cctxPool, cMem);
221
242
  return NULL;
222
243
  }
@@ -232,7 +253,7 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
232
253
  /* only works during initialization phase, not during compression */
233
254
  static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
234
255
  {
235
- pthread_mutex_lock(&cctxPool->poolMutex);
256
+ ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
236
257
  { unsigned const nbThreads = cctxPool->totalCCtx;
237
258
  size_t const poolSize = sizeof(*cctxPool)
238
259
  + (nbThreads-1)*sizeof(ZSTD_CCtx*);
@@ -241,7 +262,7 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
241
262
  for (u=0; u<nbThreads; u++) {
242
263
  totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
243
264
  }
244
- pthread_mutex_unlock(&cctxPool->poolMutex);
265
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
245
266
  return poolSize + totalCCtxSize;
246
267
  }
247
268
  }
@@ -249,14 +270,14 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
249
270
  static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
250
271
  {
251
272
  DEBUGLOG(5, "ZSTDMT_getCCtx");
252
- pthread_mutex_lock(&cctxPool->poolMutex);
273
+ ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
253
274
  if (cctxPool->availCCtx) {
254
275
  cctxPool->availCCtx--;
255
276
  { ZSTD_CCtx* const cctx = cctxPool->cctx[cctxPool->availCCtx];
256
- pthread_mutex_unlock(&cctxPool->poolMutex);
277
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
257
278
  return cctx;
258
279
  } }
259
- pthread_mutex_unlock(&cctxPool->poolMutex);
280
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
260
281
  DEBUGLOG(5, "create one more CCtx");
261
282
  return ZSTD_createCCtx_advanced(cctxPool->cMem); /* note : can be NULL, when creation fails ! */
262
283
  }
@@ -264,7 +285,7 @@ static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
264
285
  static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
265
286
  {
266
287
  if (cctx==NULL) return; /* compatibility with release on NULL */
267
- pthread_mutex_lock(&pool->poolMutex);
288
+ ZSTD_pthread_mutex_lock(&pool->poolMutex);
268
289
  if (pool->availCCtx < pool->totalCCtx)
269
290
  pool->cctx[pool->availCCtx++] = cctx;
270
291
  else {
@@ -272,7 +293,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
272
293
  DEBUGLOG(5, "CCtx pool overflow : free cctx");
273
294
  ZSTD_freeCCtx(cctx);
274
295
  }
275
- pthread_mutex_unlock(&pool->poolMutex);
296
+ ZSTD_pthread_mutex_unlock(&pool->poolMutex);
276
297
  }
277
298
 
278
299
 
@@ -290,9 +311,9 @@ typedef struct {
290
311
  unsigned lastChunk;
291
312
  unsigned jobCompleted;
292
313
  unsigned jobScanned;
293
- pthread_mutex_t* jobCompleted_mutex;
294
- pthread_cond_t* jobCompleted_cond;
295
- ZSTD_parameters params;
314
+ ZSTD_pthread_mutex_t* jobCompleted_mutex;
315
+ ZSTD_pthread_cond_t* jobCompleted_cond;
316
+ ZSTD_CCtx_params params;
296
317
  const ZSTD_CDict* cdict;
297
318
  ZSTDMT_CCtxPool* cctxPool;
298
319
  ZSTDMT_bufferPool* bufPool;
@@ -329,10 +350,15 @@ void ZSTDMT_compressChunk(void* jobDescription)
329
350
  if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
330
351
  } else { /* srcStart points at reloaded section */
331
352
  if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0; /* ensure no srcSize control */
332
- { size_t const dictModeError = ZSTD_setCCtxParameter(cctx, ZSTD_p_forceRawDict, 1); /* Force loading dictionary in "content-only" mode (no header analysis) */
333
- size_t const initError = ZSTD_compressBegin_advanced(cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
334
- if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
335
- ZSTD_setCCtxParameter(cctx, ZSTD_p_forceWindow, 1);
353
+ { ZSTD_CCtx_params jobParams = job->params;
354
+ size_t const forceWindowError =
355
+ ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstChunk);
356
+ /* Force loading dictionary in "content-only" mode (no header analysis) */
357
+ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, job->srcStart, job->dictSize, ZSTD_dm_rawContent, jobParams, job->fullFrameSize);
358
+ if (ZSTD_isError(initError) || ZSTD_isError(forceWindowError)) {
359
+ job->cSize = initError;
360
+ goto _endJob;
361
+ }
336
362
  } }
337
363
  if (!job->firstChunk) { /* flush and overwrite frame header when it's not first segment */
338
364
  size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, 0);
@@ -353,11 +379,11 @@ _endJob:
353
379
  ZSTDMT_releaseCCtx(job->cctxPool, cctx);
354
380
  ZSTDMT_releaseBuffer(job->bufPool, job->src);
355
381
  job->src = g_nullBuffer; job->srcStart = NULL;
356
- PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
382
+ ZSTD_PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
357
383
  job->jobCompleted = 1;
358
384
  job->jobScanned = 0;
359
- pthread_cond_signal(job->jobCompleted_cond);
360
- pthread_mutex_unlock(job->jobCompleted_mutex);
385
+ ZSTD_pthread_cond_signal(job->jobCompleted_cond);
386
+ ZSTD_pthread_mutex_unlock(job->jobCompleted_mutex);
361
387
  }
362
388
 
363
389
 
@@ -375,24 +401,21 @@ struct ZSTDMT_CCtx_s {
375
401
  ZSTDMT_jobDescription* jobs;
376
402
  ZSTDMT_bufferPool* bufPool;
377
403
  ZSTDMT_CCtxPool* cctxPool;
378
- pthread_mutex_t jobCompleted_mutex;
379
- pthread_cond_t jobCompleted_cond;
404
+ ZSTD_pthread_mutex_t jobCompleted_mutex;
405
+ ZSTD_pthread_cond_t jobCompleted_cond;
380
406
  size_t targetSectionSize;
381
407
  size_t inBuffSize;
382
408
  size_t dictSize;
383
409
  size_t targetDictSize;
384
410
  inBuff_t inBuff;
385
- ZSTD_parameters params;
411
+ ZSTD_CCtx_params params;
386
412
  XXH64_state_t xxhState;
387
- unsigned nbThreads;
388
413
  unsigned jobIDMask;
389
414
  unsigned doneJobID;
390
415
  unsigned nextJobID;
391
416
  unsigned frameEnded;
392
417
  unsigned allJobsCompleted;
393
- unsigned overlapLog;
394
418
  unsigned long long frameContentSize;
395
- size_t sectionSize;
396
419
  ZSTD_customMem cMem;
397
420
  ZSTD_CDict* cdictLocal;
398
421
  const ZSTD_CDict* cdict;
@@ -407,6 +430,15 @@ static ZSTDMT_jobDescription* ZSTDMT_allocJobsTable(U32* nbJobsPtr, ZSTD_customM
407
430
  nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
408
431
  }
409
432
 
433
+ /* Internal only */
434
+ size_t ZSTDMT_initializeCCtxParameters(ZSTD_CCtx_params* params, unsigned nbThreads)
435
+ {
436
+ params->nbThreads = nbThreads;
437
+ params->overlapSizeLog = ZSTDMT_OVERLAPLOG_DEFAULT;
438
+ params->jobSize = 0;
439
+ return 0;
440
+ }
441
+
410
442
  ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
411
443
  {
412
444
  ZSTDMT_CCtx* mtctx;
@@ -421,12 +453,10 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
421
453
 
422
454
  mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
423
455
  if (!mtctx) return NULL;
456
+ ZSTDMT_initializeCCtxParameters(&mtctx->params, nbThreads);
424
457
  mtctx->cMem = cMem;
425
- mtctx->nbThreads = nbThreads;
426
458
  mtctx->allJobsCompleted = 1;
427
- mtctx->sectionSize = 0;
428
- mtctx->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
429
- mtctx->factory = POOL_create(nbThreads, 0);
459
+ mtctx->factory = POOL_create_advanced(nbThreads, 0, cMem);
430
460
  mtctx->jobs = ZSTDMT_allocJobsTable(&nbJobs, cMem);
431
461
  mtctx->jobIDMask = nbJobs - 1;
432
462
  mtctx->bufPool = ZSTDMT_createBufferPool(nbThreads, cMem);
@@ -435,11 +465,11 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
435
465
  ZSTDMT_freeCCtx(mtctx);
436
466
  return NULL;
437
467
  }
438
- if (pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
468
+ if (ZSTD_pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
439
469
  ZSTDMT_freeCCtx(mtctx);
440
470
  return NULL;
441
471
  }
442
- if (pthread_cond_init(&mtctx->jobCompleted_cond, NULL)) {
472
+ if (ZSTD_pthread_cond_init(&mtctx->jobCompleted_cond, NULL)) {
443
473
  ZSTDMT_freeCCtx(mtctx);
444
474
  return NULL;
445
475
  }
@@ -459,28 +489,46 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
459
489
  unsigned jobID;
460
490
  DEBUGLOG(3, "ZSTDMT_releaseAllJobResources");
461
491
  for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {
492
+ DEBUGLOG(4, "job%02u: release dst address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);
462
493
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
463
494
  mtctx->jobs[jobID].dstBuff = g_nullBuffer;
495
+ DEBUGLOG(4, "job%02u: release src address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].src.start);
464
496
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].src);
465
497
  mtctx->jobs[jobID].src = g_nullBuffer;
466
498
  }
467
499
  memset(mtctx->jobs, 0, (mtctx->jobIDMask+1)*sizeof(ZSTDMT_jobDescription));
500
+ DEBUGLOG(4, "input: release address %08X", (U32)(size_t)mtctx->inBuff.buffer.start);
468
501
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->inBuff.buffer);
469
502
  mtctx->inBuff.buffer = g_nullBuffer;
470
503
  mtctx->allJobsCompleted = 1;
471
504
  }
472
505
 
506
+ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
507
+ {
508
+ DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted");
509
+ while (zcs->doneJobID < zcs->nextJobID) {
510
+ unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
511
+ ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
512
+ while (zcs->jobs[jobID].jobCompleted==0) {
513
+ DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
514
+ ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
515
+ }
516
+ ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
517
+ zcs->doneJobID++;
518
+ }
519
+ }
520
+
473
521
  size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
474
522
  {
475
523
  if (mtctx==NULL) return 0; /* compatible with free on NULL */
476
- POOL_free(mtctx->factory);
477
- if (!mtctx->allJobsCompleted) ZSTDMT_releaseAllJobResources(mtctx); /* stop workers first */
478
- ZSTDMT_freeBufferPool(mtctx->bufPool); /* release job resources into pools first */
524
+ POOL_free(mtctx->factory); /* stop and free worker threads */
525
+ ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
479
526
  ZSTD_free(mtctx->jobs, mtctx->cMem);
527
+ ZSTDMT_freeBufferPool(mtctx->bufPool);
480
528
  ZSTDMT_freeCCtxPool(mtctx->cctxPool);
481
529
  ZSTD_freeCDict(mtctx->cdictLocal);
482
- pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
483
- pthread_cond_destroy(&mtctx->jobCompleted_cond);
530
+ ZSTD_pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
531
+ ZSTD_pthread_cond_destroy(&mtctx->jobCompleted_cond);
484
532
  ZSTD_free(mtctx, mtctx->cMem);
485
533
  return 0;
486
534
  }
@@ -496,22 +544,35 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
496
544
  + ZSTD_sizeof_CDict(mtctx->cdictLocal);
497
545
  }
498
546
 
499
- size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value)
500
- {
547
+ /* Internal only */
548
+ size_t ZSTDMT_CCtxParam_setMTCtxParameter(
549
+ ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value) {
501
550
  switch(parameter)
502
551
  {
503
552
  case ZSTDMT_p_sectionSize :
504
- mtctx->sectionSize = value;
553
+ params->jobSize = value;
505
554
  return 0;
506
555
  case ZSTDMT_p_overlapSectionLog :
507
- DEBUGLOG(5, "ZSTDMT_p_overlapSectionLog : %u", value);
508
- mtctx->overlapLog = (value >= 9) ? 9 : value;
556
+ DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
557
+ params->overlapSizeLog = (value >= 9) ? 9 : value;
509
558
  return 0;
510
559
  default :
511
560
  return ERROR(parameter_unsupported);
512
561
  }
513
562
  }
514
563
 
564
+ size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value)
565
+ {
566
+ switch(parameter)
567
+ {
568
+ case ZSTDMT_p_sectionSize :
569
+ return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
570
+ case ZSTDMT_p_overlapSectionLog :
571
+ return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
572
+ default :
573
+ return ERROR(parameter_unsupported);
574
+ }
575
+ }
515
576
 
516
577
  /* ------------------------------------------ */
517
578
  /* ===== Multi-threaded compression ===== */
@@ -528,17 +589,17 @@ static unsigned computeNbChunks(size_t srcSize, unsigned windowLog, unsigned nbT
528
589
  return (multiplier>1) ? nbChunksLarge : nbChunksSmall;
529
590
  }
530
591
 
531
-
532
- size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
533
- void* dst, size_t dstCapacity,
534
- const void* src, size_t srcSize,
535
- const ZSTD_CDict* cdict,
536
- ZSTD_parameters const params,
537
- unsigned overlapLog)
592
+ static size_t ZSTDMT_compress_advanced_internal(
593
+ ZSTDMT_CCtx* mtctx,
594
+ void* dst, size_t dstCapacity,
595
+ const void* src, size_t srcSize,
596
+ const ZSTD_CDict* cdict,
597
+ ZSTD_CCtx_params const params)
538
598
  {
539
- unsigned const overlapRLog = (overlapLog>9) ? 0 : 9-overlapLog;
599
+ ZSTD_CCtx_params const jobParams = ZSTDMT_makeJobCCtxParams(params);
600
+ unsigned const overlapRLog = (params.overlapSizeLog>9) ? 0 : 9-params.overlapSizeLog;
540
601
  size_t const overlapSize = (overlapRLog>=9) ? 0 : (size_t)1 << (params.cParams.windowLog - overlapRLog);
541
- unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, mtctx->nbThreads);
602
+ unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, params.nbThreads);
542
603
  size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
543
604
  size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0x7FFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
544
605
  const char* const srcStart = (const char*)src;
@@ -546,12 +607,14 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
546
607
  unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
547
608
  size_t frameStartPos = 0, dstBufferPos = 0;
548
609
  XXH64_state_t xxh64;
610
+ assert(jobParams.nbThreads == 0);
611
+ assert(mtctx->cctxPool->totalCCtx == params.nbThreads);
549
612
 
550
613
  DEBUGLOG(4, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
551
614
  if (nbChunks==1) { /* fallback to single-thread mode */
552
615
  ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
553
- if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, params.fParams);
554
- return ZSTD_compress_advanced(cctx, dst, dstCapacity, src, srcSize, NULL, 0, params);
616
+ if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
617
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, jobParams);
555
618
  }
556
619
  assert(avgChunkSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), which is required for compressWithinDst */
557
620
  ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgChunkSize) );
@@ -580,7 +643,7 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
580
643
  mtctx->jobs[u].srcSize = chunkSize;
581
644
  mtctx->jobs[u].cdict = mtctx->nextJobID==0 ? cdict : NULL;
582
645
  mtctx->jobs[u].fullFrameSize = srcSize;
583
- mtctx->jobs[u].params = params;
646
+ mtctx->jobs[u].params = jobParams;
584
647
  /* do not calculate checksum within sections, but write it in header for first section */
585
648
  if (u!=0) mtctx->jobs[u].params.fParams.checksumFlag = 0;
586
649
  mtctx->jobs[u].dstBuff = dstBuffer;
@@ -610,12 +673,12 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
610
673
  unsigned chunkID;
611
674
  for (chunkID=0; chunkID<nbChunks; chunkID++) {
612
675
  DEBUGLOG(5, "waiting for chunk %u ", chunkID);
613
- PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
676
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
614
677
  while (mtctx->jobs[chunkID].jobCompleted==0) {
615
678
  DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", chunkID);
616
- pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
679
+ ZSTD_pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
617
680
  }
618
- pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
681
+ ZSTD_pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
619
682
  DEBUGLOG(5, "ready to write chunk %u ", chunkID);
620
683
 
621
684
  mtctx->jobs[chunkID].srcStart = NULL;
@@ -628,9 +691,8 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
628
691
  if (chunkID >= compressWithinDst) { /* chunk compressed into its own buffer, which must be released */
629
692
  DEBUGLOG(5, "releasing buffer %u>=%u", chunkID, compressWithinDst);
630
693
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[chunkID].dstBuff);
631
- }
632
- mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
633
- }
694
+ } }
695
+ mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
634
696
  dstPos += cSize ;
635
697
  }
636
698
  } /* for (chunkID=0; chunkID<nbChunks; chunkID++) */
@@ -651,6 +713,23 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
651
713
  }
652
714
  }
653
715
 
716
+ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
717
+ void* dst, size_t dstCapacity,
718
+ const void* src, size_t srcSize,
719
+ const ZSTD_CDict* cdict,
720
+ ZSTD_parameters const params,
721
+ unsigned overlapLog)
722
+ {
723
+ ZSTD_CCtx_params cctxParams = mtctx->params;
724
+ cctxParams.cParams = params.cParams;
725
+ cctxParams.fParams = params.fParams;
726
+ cctxParams.overlapSizeLog = overlapLog;
727
+ return ZSTDMT_compress_advanced_internal(mtctx,
728
+ dst, dstCapacity,
729
+ src, srcSize,
730
+ cdict, cctxParams);
731
+ }
732
+
654
733
 
655
734
  size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
656
735
  void* dst, size_t dstCapacity,
@@ -668,38 +747,25 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
668
747
  /* ======= Streaming API ======= */
669
748
  /* ====================================== */
670
749
 
671
- static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
672
- {
673
- DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted");
674
- while (zcs->doneJobID < zcs->nextJobID) {
675
- unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
676
- PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
677
- while (zcs->jobs[jobID].jobCompleted==0) {
678
- DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
679
- pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
680
- }
681
- pthread_mutex_unlock(&zcs->jobCompleted_mutex);
682
- zcs->doneJobID++;
683
- }
684
- }
685
-
686
-
687
- /** ZSTDMT_initCStream_internal() :
688
- * internal usage only */
689
- size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
690
- const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
691
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
750
+ size_t ZSTDMT_initCStream_internal(
751
+ ZSTDMT_CCtx* zcs,
752
+ const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
753
+ const ZSTD_CDict* cdict, ZSTD_CCtx_params params,
754
+ unsigned long long pledgedSrcSize)
692
755
  {
693
756
  DEBUGLOG(4, "ZSTDMT_initCStream_internal");
694
757
  /* params are supposed to be fully validated at this point */
695
758
  assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
696
759
  assert(!((dict) && (cdict))); /* either dict or cdict, not both */
760
+ assert(zcs->cctxPool->totalCCtx == params.nbThreads);
697
761
 
698
- if (zcs->nbThreads==1) {
762
+ if (params.nbThreads==1) {
763
+ ZSTD_CCtx_params const singleThreadParams = ZSTDMT_makeJobCCtxParams(params);
699
764
  DEBUGLOG(4, "single thread mode");
765
+ assert(singleThreadParams.nbThreads == 0);
700
766
  return ZSTD_initCStream_internal(zcs->cctxPool->cctx[0],
701
- dict, dictSize, cdict,
702
- params, pledgedSrcSize);
767
+ dict, dictSize, cdict,
768
+ singleThreadParams, pledgedSrcSize);
703
769
  }
704
770
 
705
771
  if (zcs->allJobsCompleted == 0) { /* previous compression not correctly finished */
@@ -714,7 +780,7 @@ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
714
780
  DEBUGLOG(4,"cdictLocal: %08X", (U32)(size_t)zcs->cdictLocal);
715
781
  ZSTD_freeCDict(zcs->cdictLocal);
716
782
  zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
717
- 0 /* byRef */, ZSTD_dm_auto, /* note : a loadPrefix becomes an internal CDict */
783
+ ZSTD_dlm_byCopy, dictMode, /* note : a loadPrefix becomes an internal CDict */
718
784
  params.cParams, zcs->cMem);
719
785
  zcs->cdict = zcs->cdictLocal;
720
786
  if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
@@ -725,10 +791,10 @@ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
725
791
  zcs->cdict = cdict;
726
792
  }
727
793
 
728
- zcs->targetDictSize = (zcs->overlapLog==0) ? 0 : (size_t)1 << (zcs->params.cParams.windowLog - (9 - zcs->overlapLog));
729
- DEBUGLOG(4, "overlapLog : %u ", zcs->overlapLog);
794
+ zcs->targetDictSize = (params.overlapSizeLog==0) ? 0 : (size_t)1 << (params.cParams.windowLog - (9 - params.overlapSizeLog));
795
+ DEBUGLOG(4, "overlapLog : %u ", params.overlapSizeLog);
730
796
  DEBUGLOG(4, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
731
- zcs->targetSectionSize = zcs->sectionSize ? zcs->sectionSize : (size_t)1 << (zcs->params.cParams.windowLog + 2);
797
+ zcs->targetSectionSize = params.jobSize ? params.jobSize : (size_t)1 << (params.cParams.windowLog + 2);
732
798
  zcs->targetSectionSize = MAX(ZSTDMT_SECTION_SIZE_MIN, zcs->targetSectionSize);
733
799
  zcs->targetSectionSize = MAX(zcs->targetDictSize, zcs->targetSectionSize);
734
800
  DEBUGLOG(4, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
@@ -749,8 +815,12 @@ size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
749
815
  ZSTD_parameters params,
750
816
  unsigned long long pledgedSrcSize)
751
817
  {
818
+ ZSTD_CCtx_params cctxParams = mtctx->params;
752
819
  DEBUGLOG(5, "ZSTDMT_initCStream_advanced");
753
- return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, NULL, params, pledgedSrcSize);
820
+ cctxParams.cParams = params.cParams;
821
+ cctxParams.fParams = params.fParams;
822
+ return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dm_auto, NULL,
823
+ cctxParams, pledgedSrcSize);
754
824
  }
755
825
 
756
826
  size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
@@ -758,11 +828,12 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
758
828
  ZSTD_frameParameters fParams,
759
829
  unsigned long long pledgedSrcSize)
760
830
  {
761
- ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
831
+ ZSTD_CCtx_params cctxParams = mtctx->params;
832
+ cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
833
+ cctxParams.fParams = fParams;
762
834
  if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
763
- params.fParams = fParams;
764
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, cdict,
765
- params, pledgedSrcSize);
835
+ return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dm_auto, cdict,
836
+ cctxParams, pledgedSrcSize);
766
837
  }
767
838
 
768
839
 
@@ -770,14 +841,18 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
770
841
  * pledgedSrcSize is optional and can be zero == unknown */
771
842
  size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
772
843
  {
773
- if (zcs->nbThreads==1)
844
+ if (zcs->params.nbThreads==1)
774
845
  return ZSTD_resetCStream(zcs->cctxPool->cctx[0], pledgedSrcSize);
775
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, 0, zcs->params, pledgedSrcSize);
846
+ return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, 0, zcs->params,
847
+ pledgedSrcSize);
776
848
  }
777
849
 
778
850
  size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
779
851
  ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
780
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
852
+ ZSTD_CCtx_params cctxParams = zcs->params;
853
+ cctxParams.cParams = params.cParams;
854
+ cctxParams.fParams = params.fParams;
855
+ return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, NULL, cctxParams, 0);
781
856
  }
782
857
 
783
858
 
@@ -856,13 +931,13 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
856
931
  {
857
932
  unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
858
933
  if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */
859
- PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
934
+ ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
860
935
  while (zcs->jobs[wJobID].jobCompleted==0) {
861
936
  DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID);
862
- if (!blockToFlush) { pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
863
- pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
937
+ if (!blockToFlush) { ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
938
+ ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
864
939
  }
865
- pthread_mutex_unlock(&zcs->jobCompleted_mutex);
940
+ ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
866
941
  /* compression job completed : output can be flushed */
867
942
  { ZSTDMT_jobDescription job = zcs->jobs[wJobID];
868
943
  if (!job.jobScanned) {
@@ -906,7 +981,7 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
906
981
 
907
982
 
908
983
  /** ZSTDMT_compressStream_generic() :
909
- * internal use only
984
+ * internal use only - exposed to be invoked from zstd_compress.c
910
985
  * assumption : output and input are valid (pos <= size)
911
986
  * @return : minimum amount of data remaining to flush, 0 if none */
912
987
  size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
@@ -915,25 +990,26 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
915
990
  ZSTD_EndDirective endOp)
916
991
  {
917
992
  size_t const newJobThreshold = mtctx->dictSize + mtctx->targetSectionSize;
993
+ unsigned forwardInputProgress = 0;
918
994
  assert(output->pos <= output->size);
919
995
  assert(input->pos <= input->size);
920
996
  if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
921
- /* current frame being ended. Only flush/end are allowed. Or start new frame with init */
997
+ /* current frame being ended. Only flush/end are allowed */
922
998
  return ERROR(stage_wrong);
923
999
  }
924
- if (mtctx->nbThreads==1) { /* delegate to single-thread (synchronous) */
1000
+ if (mtctx->params.nbThreads==1) { /* delegate to single-thread (synchronous) */
925
1001
  return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
926
1002
  }
927
1003
 
928
- /* single-pass shortcut (note : this is synchronous-mode) */
929
- if ( (mtctx->nextJobID==0) /* just started */
930
- && (mtctx->inBuff.filled==0) /* nothing buffered */
931
- && (endOp==ZSTD_e_end) /* end order */
1004
+ /* single-pass shortcut (note : synchronous-mode) */
1005
+ if ( (mtctx->nextJobID == 0) /* just started */
1006
+ && (mtctx->inBuff.filled == 0) /* nothing buffered */
1007
+ && (endOp == ZSTD_e_end) /* end order */
932
1008
  && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough room */
933
- size_t const cSize = ZSTDMT_compress_advanced(mtctx,
1009
+ size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
934
1010
  (char*)output->dst + output->pos, output->size - output->pos,
935
1011
  (const char*)input->src + input->pos, input->size - input->pos,
936
- mtctx->cdict, mtctx->params, mtctx->overlapLog);
1012
+ mtctx->cdict, mtctx->params);
937
1013
  if (ZSTD_isError(cSize)) return cSize;
938
1014
  input->pos = input->size;
939
1015
  output->pos += cSize;
@@ -946,15 +1022,16 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
946
1022
  /* fill input buffer */
947
1023
  if (input->size > input->pos) { /* support NULL input */
948
1024
  if (mtctx->inBuff.buffer.start == NULL) {
949
- mtctx->inBuff.buffer = ZSTDMT_getBuffer(mtctx->bufPool);
950
- if (mtctx->inBuff.buffer.start == NULL) return ERROR(memory_allocation);
1025
+ mtctx->inBuff.buffer = ZSTDMT_getBuffer(mtctx->bufPool); /* note : may fail, in which case, no forward input progress */
951
1026
  mtctx->inBuff.filled = 0;
952
1027
  }
953
- { size_t const toLoad = MIN(input->size - input->pos, mtctx->inBuffSize - mtctx->inBuff.filled);
1028
+ if (mtctx->inBuff.buffer.start) {
1029
+ size_t const toLoad = MIN(input->size - input->pos, mtctx->inBuffSize - mtctx->inBuff.filled);
954
1030
  DEBUGLOG(5, "inBuff:%08X; inBuffSize=%u; ToCopy=%u", (U32)(size_t)mtctx->inBuff.buffer.start, (U32)mtctx->inBuffSize, (U32)toLoad);
955
1031
  memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, toLoad);
956
1032
  input->pos += toLoad;
957
1033
  mtctx->inBuff.filled += toLoad;
1034
+ forwardInputProgress = toLoad>0;
958
1035
  } }
959
1036
 
960
1037
  if ( (mtctx->inBuff.filled >= newJobThreshold) /* filled enough : let's compress */
@@ -963,7 +1040,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
963
1040
  }
964
1041
 
965
1042
  /* check for potential compressed data ready to be flushed */
966
- CHECK_F( ZSTDMT_flushNextJob(mtctx, output, (mtctx->inBuff.filled == mtctx->inBuffSize) /* blockToFlush */) ); /* block if it wasn't possible to create new job due to saturation */
1043
+ CHECK_F( ZSTDMT_flushNextJob(mtctx, output, !forwardInputProgress /* blockToFlush */) ); /* block if there was no forward input progress */
967
1044
 
968
1045
  if (input->pos < input->size) /* input not consumed : do not flush yet */
969
1046
  endOp = ZSTD_e_continue;
@@ -1008,7 +1085,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* outp
1008
1085
  size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
1009
1086
  {
1010
1087
  DEBUGLOG(5, "ZSTDMT_flushStream");
1011
- if (zcs->nbThreads==1)
1088
+ if (zcs->params.nbThreads==1)
1012
1089
  return ZSTD_flushStream(zcs->cctxPool->cctx[0], output);
1013
1090
  return ZSTDMT_flushStream_internal(zcs, output, 0 /* endFrame */);
1014
1091
  }
@@ -1016,7 +1093,7 @@ size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
1016
1093
  size_t ZSTDMT_endStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
1017
1094
  {
1018
1095
  DEBUGLOG(4, "ZSTDMT_endStream");
1019
- if (zcs->nbThreads==1)
1096
+ if (zcs->params.nbThreads==1)
1020
1097
  return ZSTD_endStream(zcs->cctxPool->cctx[0], output);
1021
1098
  return ZSTDMT_flushStream_internal(zcs, output, 1 /* endFrame */);
1022
1099
  }