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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/.gitignore +1 -0
- data/ext/zstdruby/libzstd/Makefile +40 -26
- data/ext/zstdruby/libzstd/README.md +68 -45
- data/ext/zstdruby/libzstd/common/bitstream.h +35 -23
- data/ext/zstdruby/libzstd/common/compiler.h +1 -0
- data/ext/zstdruby/libzstd/common/error_private.c +4 -2
- data/ext/zstdruby/libzstd/common/error_private.h +4 -4
- data/ext/zstdruby/libzstd/common/fse.h +1 -1
- data/ext/zstdruby/libzstd/common/huf.h +1 -1
- data/ext/zstdruby/libzstd/common/mem.h +1 -0
- data/ext/zstdruby/libzstd/common/pool.c +61 -46
- data/ext/zstdruby/libzstd/common/pool.h +4 -0
- data/ext/zstdruby/libzstd/common/threading.c +11 -15
- data/ext/zstdruby/libzstd/common/threading.h +52 -32
- data/ext/zstdruby/libzstd/common/zstd_common.c +2 -2
- data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +95 -21
- data/ext/zstdruby/libzstd/compress/fse_compress.c +3 -1
- data/ext/zstdruby/libzstd/compress/huf_compress.c +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +922 -2102
- data/ext/zstdruby/libzstd/compress/zstd_compress.h +307 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +308 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +28 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +242 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +30 -0
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +749 -0
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +38 -0
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +707 -0
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +67 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +957 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +14 -922
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +210 -133
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +20 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +373 -196
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -0
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +33 -22
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +8 -5
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -0
- data/ext/zstdruby/libzstd/dll/example/Makefile +5 -5
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -0
- data/ext/zstdruby/libzstd/zstd.h +366 -118
- data/lib/zstd-ruby/version.rb +1 -1
- 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
|
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
|
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
|
-
|
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
|
66
|
+
} else { \
|
67
|
+
ZSTD_pthread_mutex_lock(mutex); \
|
68
|
+
} \
|
66
69
|
}
|
67
70
|
|
68
71
|
#else
|
69
72
|
|
70
|
-
# define
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
135
|
+
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
130
136
|
for (u=0; u<bufPool->totalBuffers; u++)
|
131
137
|
totalBufferSize += bufPool->bTable[u].size;
|
132
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
187
|
+
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
181
188
|
return;
|
182
189
|
}
|
183
|
-
|
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
|
-
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
277
|
+
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
|
257
278
|
return cctx;
|
258
279
|
} }
|
259
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
294
|
-
|
295
|
-
|
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
|
-
{
|
333
|
-
|
334
|
-
|
335
|
-
|
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
|
-
|
382
|
+
ZSTD_PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
|
357
383
|
job->jobCompleted = 1;
|
358
384
|
job->jobScanned = 0;
|
359
|
-
|
360
|
-
|
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
|
-
|
379
|
-
|
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
|
-
|
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->
|
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 (
|
468
|
+
if (ZSTD_pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
|
439
469
|
ZSTDMT_freeCCtx(mtctx);
|
440
470
|
return NULL;
|
441
471
|
}
|
442
|
-
if (
|
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
|
-
|
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
|
-
|
483
|
-
|
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
|
-
|
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
|
-
|
553
|
+
params->jobSize = value;
|
505
554
|
return 0;
|
506
555
|
case ZSTDMT_p_overlapSectionLog :
|
507
|
-
DEBUGLOG(
|
508
|
-
|
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
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
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
|
-
|
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,
|
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,
|
554
|
-
return
|
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 =
|
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
|
-
|
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
|
-
|
679
|
+
ZSTD_pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
|
617
680
|
}
|
618
|
-
|
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
|
-
|
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
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
unsigned
|
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 (
|
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
|
-
|
702
|
-
|
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
|
-
|
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 = (
|
729
|
-
DEBUGLOG(4, "overlapLog : %u ",
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
764
|
-
|
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,
|
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
|
-
|
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
|
-
|
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) {
|
863
|
-
|
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
|
-
|
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
|
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 :
|
929
|
-
if ( (mtctx->nextJobID==0)
|
930
|
-
&& (mtctx->inBuff.filled==0)
|
931
|
-
&& (endOp==ZSTD_e_end)
|
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 =
|
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
|
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
|
-
|
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,
|
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
|
}
|