zstd-ruby 1.4.5.0 → 1.5.1.1

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/README.md +2 -2
  5. data/ext/zstdruby/extconf.rb +2 -1
  6. data/ext/zstdruby/libzstd/BUCK +5 -7
  7. data/ext/zstdruby/libzstd/Makefile +225 -222
  8. data/ext/zstdruby/libzstd/README.md +43 -5
  9. data/ext/zstdruby/libzstd/common/bitstream.h +46 -22
  10. data/ext/zstdruby/libzstd/common/compiler.h +182 -22
  11. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  12. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  13. data/ext/zstdruby/libzstd/common/debug.h +12 -19
  14. data/ext/zstdruby/libzstd/common/entropy_common.c +196 -44
  15. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  16. data/ext/zstdruby/libzstd/common/error_private.h +82 -3
  17. data/ext/zstdruby/libzstd/common/fse.h +41 -12
  18. data/ext/zstdruby/libzstd/common/fse_decompress.c +139 -22
  19. data/ext/zstdruby/libzstd/common/huf.h +47 -23
  20. data/ext/zstdruby/libzstd/common/mem.h +87 -98
  21. data/ext/zstdruby/libzstd/common/pool.c +23 -17
  22. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  23. data/ext/zstdruby/libzstd/common/portability_macros.h +131 -0
  24. data/ext/zstdruby/libzstd/common/threading.c +6 -5
  25. data/ext/zstdruby/libzstd/common/xxhash.c +6 -846
  26. data/ext/zstdruby/libzstd/common/xxhash.h +5568 -167
  27. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  28. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  29. data/ext/zstdruby/libzstd/common/zstd_internal.h +189 -142
  30. data/ext/zstdruby/libzstd/common/zstd_trace.h +163 -0
  31. data/ext/zstdruby/libzstd/compress/clevels.h +134 -0
  32. data/ext/zstdruby/libzstd/compress/fse_compress.c +89 -46
  33. data/ext/zstdruby/libzstd/compress/hist.c +27 -29
  34. data/ext/zstdruby/libzstd/compress/hist.h +2 -2
  35. data/ext/zstdruby/libzstd/compress/huf_compress.c +770 -198
  36. data/ext/zstdruby/libzstd/compress/zstd_compress.c +2894 -863
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +390 -90
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +12 -11
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +4 -2
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +31 -8
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
  42. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -297
  43. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
  44. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +206 -69
  45. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +307 -132
  46. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +1 -1
  47. data/ext/zstdruby/libzstd/compress/zstd_fast.c +322 -143
  48. data/ext/zstdruby/libzstd/compress/zstd_fast.h +1 -1
  49. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1136 -174
  50. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +59 -1
  51. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +316 -213
  52. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +9 -2
  53. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
  54. data/ext/zstdruby/libzstd/compress/zstd_opt.c +373 -150
  55. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  56. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +152 -444
  57. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +31 -113
  58. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1044 -403
  59. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +571 -0
  60. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +9 -9
  61. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +450 -105
  63. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +913 -273
  64. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +14 -5
  65. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +59 -12
  66. data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -1
  67. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -1
  68. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +24 -4
  69. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  70. data/ext/zstdruby/libzstd/dictBuilder/cover.c +55 -38
  71. data/ext/zstdruby/libzstd/dictBuilder/cover.h +7 -6
  72. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  73. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +43 -34
  74. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +128 -58
  75. data/ext/zstdruby/libzstd/dll/example/Makefile +1 -1
  76. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  77. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -1
  78. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +8 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  80. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +9 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  82. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +9 -9
  83. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  84. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +10 -10
  85. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  86. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +13 -13
  87. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -1
  88. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +13 -13
  89. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  90. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +13 -13
  91. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  92. data/ext/zstdruby/libzstd/libzstd.mk +185 -0
  93. data/ext/zstdruby/libzstd/libzstd.pc.in +4 -3
  94. data/ext/zstdruby/libzstd/modulemap/module.modulemap +4 -0
  95. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +154 -7
  96. data/ext/zstdruby/libzstd/zstd.h +699 -214
  97. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +2 -1
  98. data/ext/zstdruby/zstdruby.c +2 -2
  99. data/lib/zstd-ruby/version.rb +1 -1
  100. metadata +15 -6
  101. data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -20,8 +20,7 @@
20
20
 
21
21
 
22
22
  /* ====== Dependencies ====== */
23
- #include <string.h> /* memcpy, memset */
24
- #include <limits.h> /* INT_MAX, UINT_MAX */
23
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */
25
24
  #include "../common/mem.h" /* MEM_STATIC */
26
25
  #include "../common/pool.h" /* threadpool */
27
26
  #include "../common/threading.h" /* mutex */
@@ -106,11 +105,11 @@ typedef struct ZSTDMT_bufferPool_s {
106
105
  static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem)
107
106
  {
108
107
  unsigned const maxNbBuffers = 2*nbWorkers + 3;
109
- ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
108
+ ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
110
109
  sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
111
110
  if (bufPool==NULL) return NULL;
112
111
  if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
113
- ZSTD_free(bufPool, cMem);
112
+ ZSTD_customFree(bufPool, cMem);
114
113
  return NULL;
115
114
  }
116
115
  bufPool->bufferSize = 64 KB;
@@ -127,10 +126,10 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
127
126
  if (!bufPool) return; /* compatibility with free on NULL */
128
127
  for (u=0; u<bufPool->totalBuffers; u++) {
129
128
  DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
130
- ZSTD_free(bufPool->bTable[u].start, bufPool->cMem);
129
+ ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem);
131
130
  }
132
131
  ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
133
- ZSTD_free(bufPool, bufPool->cMem);
132
+ ZSTD_customFree(bufPool, bufPool->cMem);
134
133
  }
135
134
 
136
135
  /* only works at initialization, not during compression */
@@ -201,13 +200,13 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
201
200
  }
202
201
  /* size conditions not respected : scratch this buffer, create new one */
203
202
  DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing");
204
- ZSTD_free(buf.start, bufPool->cMem);
203
+ ZSTD_customFree(buf.start, bufPool->cMem);
205
204
  }
206
205
  ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
207
206
  /* create new buffer */
208
207
  DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer");
209
208
  { buffer_t buffer;
210
- void* const start = ZSTD_malloc(bSize, bufPool->cMem);
209
+ void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
211
210
  buffer.start = start; /* note : start can be NULL if malloc fails ! */
212
211
  buffer.capacity = (start==NULL) ? 0 : bSize;
213
212
  if (start==NULL) {
@@ -229,13 +228,13 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
229
228
  {
230
229
  size_t const bSize = bufPool->bufferSize;
231
230
  if (buffer.capacity < bSize) {
232
- void* const start = ZSTD_malloc(bSize, bufPool->cMem);
231
+ void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
233
232
  buffer_t newBuffer;
234
233
  newBuffer.start = start;
235
234
  newBuffer.capacity = start == NULL ? 0 : bSize;
236
235
  if (start != NULL) {
237
236
  assert(newBuffer.capacity >= buffer.capacity);
238
- memcpy(newBuffer.start, buffer.start, buffer.capacity);
237
+ ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity);
239
238
  DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize);
240
239
  return newBuffer;
241
240
  }
@@ -261,14 +260,12 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
261
260
  ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
262
261
  /* Reached bufferPool capacity (should not happen) */
263
262
  DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing ");
264
- ZSTD_free(buf.start, bufPool->cMem);
263
+ ZSTD_customFree(buf.start, bufPool->cMem);
265
264
  }
266
265
 
267
266
 
268
267
  /* ===== Seq Pool Wrapper ====== */
269
268
 
270
- static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0};
271
-
272
269
  typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
273
270
 
274
271
  static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
@@ -278,7 +275,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
278
275
 
279
276
  static rawSeqStore_t bufferToSeq(buffer_t buffer)
280
277
  {
281
- rawSeqStore_t seq = {NULL, 0, 0, 0};
278
+ rawSeqStore_t seq = kNullRawSeqStore;
282
279
  seq.seq = (rawSeq*)buffer.start;
283
280
  seq.capacity = buffer.capacity / sizeof(rawSeq);
284
281
  return seq;
@@ -354,7 +351,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
354
351
  for (cid=0; cid<pool->totalCCtx; cid++)
355
352
  ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
356
353
  ZSTD_pthread_mutex_destroy(&pool->poolMutex);
357
- ZSTD_free(pool, pool->cMem);
354
+ ZSTD_customFree(pool, pool->cMem);
358
355
  }
359
356
 
360
357
  /* ZSTDMT_createCCtxPool() :
@@ -362,12 +359,12 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
362
359
  static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
363
360
  ZSTD_customMem cMem)
364
361
  {
365
- ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
362
+ ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc(
366
363
  sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
367
364
  assert(nbWorkers > 0);
368
365
  if (!cctxPool) return NULL;
369
366
  if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
370
- ZSTD_free(cctxPool, cMem);
367
+ ZSTD_customFree(cctxPool, cMem);
371
368
  return NULL;
372
369
  }
373
370
  cctxPool->cMem = cMem;
@@ -470,54 +467,52 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
470
467
  ZSTD_dictContentType_e dictContentType)
471
468
  {
472
469
  /* Adjust parameters */
473
- if (params.ldmParams.enableLdm) {
470
+ if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
474
471
  DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10);
475
472
  ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
476
473
  assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
477
474
  assert(params.ldmParams.hashRateLog < 32);
478
- serialState->ldmState.hashPower =
479
- ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
480
475
  } else {
481
- memset(&params.ldmParams, 0, sizeof(params.ldmParams));
476
+ ZSTD_memset(&params.ldmParams, 0, sizeof(params.ldmParams));
482
477
  }
483
478
  serialState->nextJobID = 0;
484
479
  if (params.fParams.checksumFlag)
485
480
  XXH64_reset(&serialState->xxhState, 0);
486
- if (params.ldmParams.enableLdm) {
481
+ if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
487
482
  ZSTD_customMem cMem = params.customMem;
488
483
  unsigned const hashLog = params.ldmParams.hashLog;
489
484
  size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
490
485
  unsigned const bucketLog =
491
486
  params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
492
- size_t const bucketSize = (size_t)1 << bucketLog;
493
487
  unsigned const prevBucketLog =
494
488
  serialState->params.ldmParams.hashLog -
495
489
  serialState->params.ldmParams.bucketSizeLog;
490
+ size_t const numBuckets = (size_t)1 << bucketLog;
496
491
  /* Size the seq pool tables */
497
492
  ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
498
493
  /* Reset the window */
499
494
  ZSTD_window_init(&serialState->ldmState.window);
500
495
  /* Resize tables and output space if necessary. */
501
496
  if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
502
- ZSTD_free(serialState->ldmState.hashTable, cMem);
503
- serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_malloc(hashSize, cMem);
497
+ ZSTD_customFree(serialState->ldmState.hashTable, cMem);
498
+ serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem);
504
499
  }
505
500
  if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
506
- ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
507
- serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_malloc(bucketSize, cMem);
501
+ ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
502
+ serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);
508
503
  }
509
504
  if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
510
505
  return 1;
511
506
  /* Zero the tables */
512
- memset(serialState->ldmState.hashTable, 0, hashSize);
513
- memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
507
+ ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);
508
+ ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);
514
509
 
515
510
  /* Update window state and fill hash table with dict */
516
511
  serialState->ldmState.loadedDictEnd = 0;
517
512
  if (dictSize > 0) {
518
513
  if (dictContentType == ZSTD_dct_rawContent) {
519
514
  BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
520
- ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
515
+ ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);
521
516
  ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, &params.ldmParams);
522
517
  serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
523
518
  } else {
@@ -537,7 +532,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
537
532
  static int ZSTDMT_serialState_init(serialState_t* serialState)
538
533
  {
539
534
  int initError = 0;
540
- memset(serialState, 0, sizeof(*serialState));
535
+ ZSTD_memset(serialState, 0, sizeof(*serialState));
541
536
  initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
542
537
  initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
543
538
  initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
@@ -552,8 +547,8 @@ static void ZSTDMT_serialState_free(serialState_t* serialState)
552
547
  ZSTD_pthread_cond_destroy(&serialState->cond);
553
548
  ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
554
549
  ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
555
- ZSTD_free(serialState->ldmState.hashTable, cMem);
556
- ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
550
+ ZSTD_customFree(serialState->ldmState.hashTable, cMem);
551
+ ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
557
552
  }
558
553
 
559
554
  static void ZSTDMT_serialState_update(serialState_t* serialState,
@@ -569,12 +564,12 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
569
564
  /* A future job may error and skip our job */
570
565
  if (serialState->nextJobID == jobID) {
571
566
  /* It is now our turn, do any processing necessary */
572
- if (serialState->params.ldmParams.enableLdm) {
567
+ if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) {
573
568
  size_t error;
574
569
  assert(seqStore.seq != NULL && seqStore.pos == 0 &&
575
570
  seqStore.size == 0 && seqStore.capacity > 0);
576
571
  assert(src.size <= serialState->params.jobSize);
577
- ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
572
+ ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);
578
573
  error = ZSTD_ldm_generateSequences(
579
574
  &serialState->ldmState, &seqStore,
580
575
  &serialState->params.ldmParams, src.start, src.size);
@@ -599,7 +594,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
599
594
  if (seqStore.size > 0) {
600
595
  size_t const err = ZSTD_referenceExternalSequences(
601
596
  jobCCtx, seqStore.seq, seqStore.size);
602
- assert(serialState->params.ldmParams.enableLdm);
597
+ assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable);
603
598
  assert(!ZSTD_isError(err));
604
599
  (void)err;
605
600
  }
@@ -677,7 +672,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
677
672
  if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));
678
673
  job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
679
674
  }
680
- if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL)
675
+ if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL)
681
676
  JOB_ERROR(ERROR(memory_allocation));
682
677
 
683
678
  /* Don't compute the checksum for chunks, since we compute it externally,
@@ -685,7 +680,9 @@ static void ZSTDMT_compressionJob(void* jobDescription)
685
680
  */
686
681
  if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
687
682
  /* Don't run LDM for the chunks, since we handle it externally */
688
- jobParams.ldmParams.enableLdm = 0;
683
+ jobParams.ldmParams.enableLdm = ZSTD_ps_disable;
684
+ /* Correct nbWorkers to 0. */
685
+ jobParams.nbWorkers = 0;
689
686
 
690
687
 
691
688
  /* init */
@@ -698,6 +695,10 @@ static void ZSTDMT_compressionJob(void* jobDescription)
698
695
  { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
699
696
  if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
700
697
  }
698
+ if (!job->firstJob) {
699
+ size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);
700
+ if (ZSTD_isError(err)) JOB_ERROR(err);
701
+ }
701
702
  { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
702
703
  job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
703
704
  ZSTD_dtlm_fast,
@@ -753,6 +754,13 @@ static void ZSTDMT_compressionJob(void* jobDescription)
753
754
  if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
754
755
  lastCBlockSize = cSize;
755
756
  } }
757
+ if (!job->firstJob) {
758
+ /* Double check that we don't have an ext-dict, because then our
759
+ * repcode invalidation doesn't work.
760
+ */
761
+ assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
762
+ }
763
+ ZSTD_CCtx_trace(cctx, 0);
756
764
 
757
765
  _endJob:
758
766
  ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
@@ -799,6 +807,15 @@ typedef struct {
799
807
  static const roundBuff_t kNullRoundBuff = {NULL, 0, 0};
800
808
 
801
809
  #define RSYNC_LENGTH 32
810
+ /* Don't create chunks smaller than the zstd block size.
811
+ * This stops us from regressing compression ratio too much,
812
+ * and ensures our output fits in ZSTD_compressBound().
813
+ *
814
+ * If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then
815
+ * ZSTD_COMPRESSBOUND() will need to be updated.
816
+ */
817
+ #define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX
818
+ #define RSYNC_MIN_BLOCK_SIZE (1<<RSYNC_MIN_BLOCK_LOG)
802
819
 
803
820
  typedef struct {
804
821
  U64 hash;
@@ -820,7 +837,6 @@ struct ZSTDMT_CCtx_s {
820
837
  roundBuff_t roundBuff;
821
838
  serialState_t serial;
822
839
  rsyncState_t rsync;
823
- unsigned singleBlockingThread;
824
840
  unsigned jobIDMask;
825
841
  unsigned doneJobID;
826
842
  unsigned nextJobID;
@@ -832,6 +848,7 @@ struct ZSTDMT_CCtx_s {
832
848
  ZSTD_customMem cMem;
833
849
  ZSTD_CDict* cdictLocal;
834
850
  const ZSTD_CDict* cdict;
851
+ unsigned providedFactory: 1;
835
852
  };
836
853
 
837
854
  static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)
@@ -842,7 +859,7 @@ static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZS
842
859
  ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);
843
860
  ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);
844
861
  }
845
- ZSTD_free(jobTable, cMem);
862
+ ZSTD_customFree(jobTable, cMem);
846
863
  }
847
864
 
848
865
  /* ZSTDMT_allocJobsTable()
@@ -854,7 +871,7 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom
854
871
  U32 const nbJobs = 1 << nbJobsLog2;
855
872
  U32 jobNb;
856
873
  ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)
857
- ZSTD_calloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
874
+ ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
858
875
  int initError = 0;
859
876
  if (jobTable==NULL) return NULL;
860
877
  *nbJobsPtr = nbJobs;
@@ -885,12 +902,12 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
885
902
 
886
903
  /* ZSTDMT_CCtxParam_setNbWorkers():
887
904
  * Internal use only */
888
- size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
905
+ static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
889
906
  {
890
907
  return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
891
908
  }
892
909
 
893
- MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
910
+ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
894
911
  {
895
912
  ZSTDMT_CCtx* mtctx;
896
913
  U32 nbJobs = nbWorkers + 2;
@@ -903,12 +920,19 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
903
920
  /* invalid custom allocator */
904
921
  return NULL;
905
922
 
906
- mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
923
+ mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem);
907
924
  if (!mtctx) return NULL;
908
925
  ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);
909
926
  mtctx->cMem = cMem;
910
927
  mtctx->allJobsCompleted = 1;
911
- mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
928
+ if (pool != NULL) {
929
+ mtctx->factory = pool;
930
+ mtctx->providedFactory = 1;
931
+ }
932
+ else {
933
+ mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
934
+ mtctx->providedFactory = 0;
935
+ }
912
936
  mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
913
937
  assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
914
938
  mtctx->jobIDMask = nbJobs - 1;
@@ -925,22 +949,18 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
925
949
  return mtctx;
926
950
  }
927
951
 
928
- ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
952
+ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
929
953
  {
930
954
  #ifdef ZSTD_MULTITHREAD
931
- return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
955
+ return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool);
932
956
  #else
933
957
  (void)nbWorkers;
934
958
  (void)cMem;
959
+ (void)pool;
935
960
  return NULL;
936
961
  #endif
937
962
  }
938
963
 
939
- ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
940
- {
941
- return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
942
- }
943
-
944
964
 
945
965
  /* ZSTDMT_releaseAllJobResources() :
946
966
  * note : ensure all workers are killed first ! */
@@ -957,7 +977,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
957
977
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
958
978
 
959
979
  /* Clear the job description, but keep the mutex/cond */
960
- memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
980
+ ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
961
981
  mtctx->jobs[jobID].job_mutex = mutex;
962
982
  mtctx->jobs[jobID].job_cond = cond;
963
983
  }
@@ -984,7 +1004,8 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
984
1004
  size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
985
1005
  {
986
1006
  if (mtctx==NULL) return 0; /* compatible with free on NULL */
987
- POOL_free(mtctx->factory); /* stop and free worker threads */
1007
+ if (!mtctx->providedFactory)
1008
+ POOL_free(mtctx->factory); /* stop and free worker threads */
988
1009
  ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
989
1010
  ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
990
1011
  ZSTDMT_freeBufferPool(mtctx->bufPool);
@@ -993,8 +1014,8 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
993
1014
  ZSTDMT_serialState_free(&mtctx->serial);
994
1015
  ZSTD_freeCDict(mtctx->cdictLocal);
995
1016
  if (mtctx->roundBuff.buffer)
996
- ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
997
- ZSTD_free(mtctx, mtctx->cMem);
1017
+ ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
1018
+ ZSTD_customFree(mtctx, mtctx->cMem);
998
1019
  return 0;
999
1020
  }
1000
1021
 
@@ -1011,65 +1032,6 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
1011
1032
  + mtctx->roundBuff.capacity;
1012
1033
  }
1013
1034
 
1014
- /* Internal only */
1015
- size_t
1016
- ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
1017
- ZSTDMT_parameter parameter,
1018
- int value)
1019
- {
1020
- DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter");
1021
- switch(parameter)
1022
- {
1023
- case ZSTDMT_p_jobSize :
1024
- DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
1025
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
1026
- case ZSTDMT_p_overlapLog :
1027
- DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
1028
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
1029
- case ZSTDMT_p_rsyncable :
1030
- DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
1031
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
1032
- default :
1033
- return ERROR(parameter_unsupported);
1034
- }
1035
- }
1036
-
1037
- size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value)
1038
- {
1039
- DEBUGLOG(4, "ZSTDMT_setMTCtxParameter");
1040
- return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
1041
- }
1042
-
1043
- size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value)
1044
- {
1045
- switch (parameter) {
1046
- case ZSTDMT_p_jobSize:
1047
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
1048
- case ZSTDMT_p_overlapLog:
1049
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
1050
- case ZSTDMT_p_rsyncable:
1051
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
1052
- default:
1053
- return ERROR(parameter_unsupported);
1054
- }
1055
- }
1056
-
1057
- /* Sets parameters relevant to the compression job,
1058
- * initializing others to default values. */
1059
- static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params)
1060
- {
1061
- ZSTD_CCtx_params jobParams = *params;
1062
- /* Clear parameters related to multithreading */
1063
- jobParams.forceWindow = 0;
1064
- jobParams.nbWorkers = 0;
1065
- jobParams.jobSize = 0;
1066
- jobParams.overlapLog = 0;
1067
- jobParams.rsyncable = 0;
1068
- memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
1069
- memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
1070
- return jobParams;
1071
- }
1072
-
1073
1035
 
1074
1036
  /* ZSTDMT_resize() :
1075
1037
  * @return : error code if fails, 0 on success */
@@ -1098,7 +1060,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
1098
1060
  DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)",
1099
1061
  compressionLevel);
1100
1062
  mtctx->params.compressionLevel = compressionLevel;
1101
- { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1063
+ { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
1102
1064
  cParams.windowLog = saved_wlog;
1103
1065
  mtctx->params.cParams = cParams;
1104
1066
  }
@@ -1182,11 +1144,11 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
1182
1144
  static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)
1183
1145
  {
1184
1146
  unsigned jobLog;
1185
- if (params->ldmParams.enableLdm) {
1147
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
1186
1148
  /* In Long Range Mode, the windowLog is typically oversized.
1187
1149
  * In which case, it's preferable to determine the jobSize
1188
- * based on chainLog instead. */
1189
- jobLog = MAX(21, params->cParams.chainLog + 4);
1150
+ * based on cycleLog instead. */
1151
+ jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3);
1190
1152
  } else {
1191
1153
  jobLog = MAX(20, params->cParams.windowLog + 2);
1192
1154
  }
@@ -1226,7 +1188,7 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
1226
1188
  int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);
1227
1189
  int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);
1228
1190
  assert(0 <= overlapRLog && overlapRLog <= 8);
1229
- if (params->ldmParams.enableLdm) {
1191
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
1230
1192
  /* In Long Range Mode, the windowLog is typically oversized.
1231
1193
  * In which case, it's preferable to determine the jobSize
1232
1194
  * based on chainLog instead.
@@ -1240,174 +1202,6 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
1240
1202
  return (ovLog==0) ? 0 : (size_t)1 << ovLog;
1241
1203
  }
1242
1204
 
1243
- static unsigned
1244
- ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers)
1245
- {
1246
- assert(nbWorkers>0);
1247
- { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
1248
- size_t const jobMaxSize = jobSizeTarget << 2;
1249
- size_t const passSizeMax = jobMaxSize * nbWorkers;
1250
- unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1;
1251
- unsigned const nbJobsLarge = multiplier * nbWorkers;
1252
- unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1;
1253
- unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers);
1254
- return (multiplier>1) ? nbJobsLarge : nbJobsSmall;
1255
- } }
1256
-
1257
- /* ZSTDMT_compress_advanced_internal() :
1258
- * This is a blocking function : it will only give back control to caller after finishing its compression job.
1259
- */
1260
- static size_t
1261
- ZSTDMT_compress_advanced_internal(
1262
- ZSTDMT_CCtx* mtctx,
1263
- void* dst, size_t dstCapacity,
1264
- const void* src, size_t srcSize,
1265
- const ZSTD_CDict* cdict,
1266
- ZSTD_CCtx_params params)
1267
- {
1268
- ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(&params);
1269
- size_t const overlapSize = ZSTDMT_computeOverlapSize(&params);
1270
- unsigned const nbJobs = ZSTDMT_computeNbJobs(&params, srcSize, params.nbWorkers);
1271
- size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
1272
- size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
1273
- const char* const srcStart = (const char*)src;
1274
- size_t remainingSrcSize = srcSize;
1275
- unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */
1276
- size_t frameStartPos = 0, dstBufferPos = 0;
1277
- assert(jobParams.nbWorkers == 0);
1278
- assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
1279
-
1280
- params.jobSize = (U32)avgJobSize;
1281
- DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ",
1282
- nbJobs, (U32)proposedJobSize, (U32)avgJobSize);
1283
-
1284
- if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */
1285
- ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
1286
- DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode");
1287
- if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
1288
- return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams);
1289
- }
1290
-
1291
- assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
1292
- ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
1293
- /* LDM doesn't even try to load the dictionary in single-ingestion mode */
1294
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto))
1295
- return ERROR(memory_allocation);
1296
-
1297
- FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */
1298
-
1299
- { unsigned u;
1300
- for (u=0; u<nbJobs; u++) {
1301
- size_t const jobSize = MIN(remainingSrcSize, avgJobSize);
1302
- size_t const dstBufferCapacity = ZSTD_compressBound(jobSize);
1303
- buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
1304
- buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer;
1305
- size_t dictSize = u ? overlapSize : 0;
1306
-
1307
- mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize;
1308
- mtctx->jobs[u].prefix.size = dictSize;
1309
- mtctx->jobs[u].src.start = srcStart + frameStartPos;
1310
- mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */
1311
- mtctx->jobs[u].consumed = 0;
1312
- mtctx->jobs[u].cSize = 0;
1313
- mtctx->jobs[u].cdict = (u==0) ? cdict : NULL;
1314
- mtctx->jobs[u].fullFrameSize = srcSize;
1315
- mtctx->jobs[u].params = jobParams;
1316
- /* do not calculate checksum within sections, but write it in header for first section */
1317
- mtctx->jobs[u].dstBuff = dstBuffer;
1318
- mtctx->jobs[u].cctxPool = mtctx->cctxPool;
1319
- mtctx->jobs[u].bufPool = mtctx->bufPool;
1320
- mtctx->jobs[u].seqPool = mtctx->seqPool;
1321
- mtctx->jobs[u].serial = &mtctx->serial;
1322
- mtctx->jobs[u].jobID = u;
1323
- mtctx->jobs[u].firstJob = (u==0);
1324
- mtctx->jobs[u].lastJob = (u==nbJobs-1);
1325
-
1326
- DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize);
1327
- DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12);
1328
- POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]);
1329
-
1330
- frameStartPos += jobSize;
1331
- dstBufferPos += dstBufferCapacity;
1332
- remainingSrcSize -= jobSize;
1333
- } }
1334
-
1335
- /* collect result */
1336
- { size_t error = 0, dstPos = 0;
1337
- unsigned jobID;
1338
- for (jobID=0; jobID<nbJobs; jobID++) {
1339
- DEBUGLOG(5, "waiting for job %u ", jobID);
1340
- ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
1341
- while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
1342
- DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID);
1343
- ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
1344
- }
1345
- ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
1346
- DEBUGLOG(5, "ready to write job %u ", jobID);
1347
-
1348
- { size_t const cSize = mtctx->jobs[jobID].cSize;
1349
- if (ZSTD_isError(cSize)) error = cSize;
1350
- if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
1351
- if (jobID) { /* note : job 0 is written directly at dst, which is correct position */
1352
- if (!error)
1353
- memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */
1354
- if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */
1355
- DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst);
1356
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
1357
- } }
1358
- mtctx->jobs[jobID].dstBuff = g_nullBuffer;
1359
- mtctx->jobs[jobID].cSize = 0;
1360
- dstPos += cSize ;
1361
- }
1362
- } /* for (jobID=0; jobID<nbJobs; jobID++) */
1363
-
1364
- DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag);
1365
- if (params.fParams.checksumFlag) {
1366
- U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);
1367
- if (dstPos + 4 > dstCapacity) {
1368
- error = ERROR(dstSize_tooSmall);
1369
- } else {
1370
- DEBUGLOG(4, "writing checksum : %08X \n", checksum);
1371
- MEM_writeLE32((char*)dst + dstPos, checksum);
1372
- dstPos += 4;
1373
- } }
1374
-
1375
- if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos);
1376
- return error ? error : dstPos;
1377
- }
1378
- }
1379
-
1380
- size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
1381
- void* dst, size_t dstCapacity,
1382
- const void* src, size_t srcSize,
1383
- const ZSTD_CDict* cdict,
1384
- ZSTD_parameters params,
1385
- int overlapLog)
1386
- {
1387
- ZSTD_CCtx_params cctxParams = mtctx->params;
1388
- cctxParams.cParams = params.cParams;
1389
- cctxParams.fParams = params.fParams;
1390
- assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX);
1391
- cctxParams.overlapLog = overlapLog;
1392
- return ZSTDMT_compress_advanced_internal(mtctx,
1393
- dst, dstCapacity,
1394
- src, srcSize,
1395
- cdict, cctxParams);
1396
- }
1397
-
1398
-
1399
- size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
1400
- void* dst, size_t dstCapacity,
1401
- const void* src, size_t srcSize,
1402
- int compressionLevel)
1403
- {
1404
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
1405
- int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy);
1406
- params.fParams.contentSizeFlag = 1;
1407
- return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog);
1408
- }
1409
-
1410
-
1411
1205
  /* ====================================== */
1412
1206
  /* ======= Streaming API ======= */
1413
1207
  /* ====================================== */
@@ -1432,16 +1226,6 @@ size_t ZSTDMT_initCStream_internal(
1432
1226
  if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
1433
1227
  if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
1434
1228
 
1435
- mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
1436
- if (mtctx->singleBlockingThread) {
1437
- ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(&params);
1438
- DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode");
1439
- assert(singleThreadParams.nbWorkers == 0);
1440
- return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0],
1441
- dict, dictSize, cdict,
1442
- &singleThreadParams, pledgedSrcSize);
1443
- }
1444
-
1445
1229
  DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers);
1446
1230
 
1447
1231
  if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */
@@ -1475,9 +1259,11 @@ size_t ZSTDMT_initCStream_internal(
1475
1259
 
1476
1260
  if (params.rsyncable) {
1477
1261
  /* Aim for the targetsectionSize as the average job size. */
1478
- U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
1479
- U32 const rsyncBits = ZSTD_highbit32(jobSizeMB) + 20;
1480
- assert(jobSizeMB >= 1);
1262
+ U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);
1263
+ U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);
1264
+ /* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our
1265
+ * expected job size is at least 4x larger. */
1266
+ assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2);
1481
1267
  DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
1482
1268
  mtctx->rsync.hash = 0;
1483
1269
  mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
@@ -1489,7 +1275,7 @@ size_t ZSTDMT_initCStream_internal(
1489
1275
  ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));
1490
1276
  {
1491
1277
  /* If ldm is enabled we need windowSize space. */
1492
- size_t const windowSize = mtctx->params.ldmParams.enableLdm ? (1U << mtctx->params.cParams.windowLog) : 0;
1278
+ size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0;
1493
1279
  /* Two buffers of slack, plus extra space for the overlap
1494
1280
  * This is the minimum slack that LDM works with. One extra because
1495
1281
  * flush might waste up to targetSectionSize-1 bytes. Another extra
@@ -1504,8 +1290,8 @@ size_t ZSTDMT_initCStream_internal(
1504
1290
  size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;
1505
1291
  if (mtctx->roundBuff.capacity < capacity) {
1506
1292
  if (mtctx->roundBuff.buffer)
1507
- ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
1508
- mtctx->roundBuff.buffer = (BYTE*)ZSTD_malloc(capacity, mtctx->cMem);
1293
+ ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
1294
+ mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem);
1509
1295
  if (mtctx->roundBuff.buffer == NULL) {
1510
1296
  mtctx->roundBuff.capacity = 0;
1511
1297
  return ERROR(memory_allocation);
@@ -1530,53 +1316,6 @@ size_t ZSTDMT_initCStream_internal(
1530
1316
  return 0;
1531
1317
  }
1532
1318
 
1533
- size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
1534
- const void* dict, size_t dictSize,
1535
- ZSTD_parameters params,
1536
- unsigned long long pledgedSrcSize)
1537
- {
1538
- ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
1539
- DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
1540
- cctxParams.cParams = params.cParams;
1541
- cctxParams.fParams = params.fParams;
1542
- return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL,
1543
- cctxParams, pledgedSrcSize);
1544
- }
1545
-
1546
- size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
1547
- const ZSTD_CDict* cdict,
1548
- ZSTD_frameParameters fParams,
1549
- unsigned long long pledgedSrcSize)
1550
- {
1551
- ZSTD_CCtx_params cctxParams = mtctx->params;
1552
- if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
1553
- cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
1554
- cctxParams.fParams = fParams;
1555
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict,
1556
- cctxParams, pledgedSrcSize);
1557
- }
1558
-
1559
-
1560
- /* ZSTDMT_resetCStream() :
1561
- * pledgedSrcSize can be zero == unknown (for the time being)
1562
- * prefer using ZSTD_CONTENTSIZE_UNKNOWN,
1563
- * as `0` might mean "empty" in the future */
1564
- size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize)
1565
- {
1566
- if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1567
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params,
1568
- pledgedSrcSize);
1569
- }
1570
-
1571
- size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
1572
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1573
- ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
1574
- DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel);
1575
- cctxParams.cParams = params.cParams;
1576
- cctxParams.fParams = params.fParams;
1577
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
1578
- }
1579
-
1580
1319
 
1581
1320
  /* ZSTDMT_writeLastEmptyBlock()
1582
1321
  * Write a single empty block with an end-of-frame to finish a frame.
@@ -1740,7 +1479,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
1740
1479
  assert(cSize >= mtctx->jobs[wJobID].dstFlushed);
1741
1480
  assert(mtctx->jobs[wJobID].dstBuff.start != NULL);
1742
1481
  if (toFlush > 0) {
1743
- memcpy((char*)output->dst + output->pos,
1482
+ ZSTD_memcpy((char*)output->dst + output->pos,
1744
1483
  (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
1745
1484
  toFlush);
1746
1485
  }
@@ -1811,17 +1550,21 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
1811
1550
  static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
1812
1551
  {
1813
1552
  BYTE const* const bufferStart = (BYTE const*)buffer.start;
1814
- BYTE const* const bufferEnd = bufferStart + buffer.capacity;
1815
1553
  BYTE const* const rangeStart = (BYTE const*)range.start;
1816
- BYTE const* const rangeEnd = range.size != 0 ? rangeStart + range.size : rangeStart;
1817
1554
 
1818
1555
  if (rangeStart == NULL || bufferStart == NULL)
1819
1556
  return 0;
1820
- /* Empty ranges cannot overlap */
1821
- if (bufferStart == bufferEnd || rangeStart == rangeEnd)
1822
- return 0;
1823
1557
 
1824
- return bufferStart < rangeEnd && rangeStart < bufferEnd;
1558
+ {
1559
+ BYTE const* const bufferEnd = bufferStart + buffer.capacity;
1560
+ BYTE const* const rangeEnd = rangeStart + range.size;
1561
+
1562
+ /* Empty ranges cannot overlap */
1563
+ if (bufferStart == bufferEnd || rangeStart == rangeEnd)
1564
+ return 0;
1565
+
1566
+ return bufferStart < rangeEnd && rangeStart < bufferEnd;
1567
+ }
1825
1568
  }
1826
1569
 
1827
1570
  static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
@@ -1848,7 +1591,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
1848
1591
 
1849
1592
  static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
1850
1593
  {
1851
- if (mtctx->params.ldmParams.enableLdm) {
1594
+ if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) {
1852
1595
  ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
1853
1596
  DEBUGLOG(5, "ZSTDMT_waitForLdmComplete");
1854
1597
  DEBUGLOG(5, "source [0x%zx, 0x%zx)",
@@ -1894,7 +1637,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
1894
1637
  return 0;
1895
1638
  }
1896
1639
  ZSTDMT_waitForLdmComplete(mtctx, buffer);
1897
- memmove(start, mtctx->inBuff.prefix.start, prefixSize);
1640
+ ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);
1898
1641
  mtctx->inBuff.prefix.start = start;
1899
1642
  mtctx->roundBuff.pos = prefixSize;
1900
1643
  }
@@ -1951,6 +1694,11 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
1951
1694
  if (!mtctx->params.rsyncable)
1952
1695
  /* Rsync is disabled. */
1953
1696
  return syncPoint;
1697
+ if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE)
1698
+ /* We don't emit synchronization points if it would produce too small blocks.
1699
+ * We don't have enough input to find a synchronization point, so don't look.
1700
+ */
1701
+ return syncPoint;
1954
1702
  if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)
1955
1703
  /* Not enough to compute the hash.
1956
1704
  * We will miss any synchronization points in this RSYNC_LENGTH byte
@@ -1961,23 +1709,41 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
1961
1709
  */
1962
1710
  return syncPoint;
1963
1711
  /* Initialize the loop variables. */
1964
- if (mtctx->inBuff.filled >= RSYNC_LENGTH) {
1965
- /* We have enough bytes buffered to initialize the hash.
1712
+ if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) {
1713
+ /* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions
1714
+ * because they can't possibly be a sync point. So we can start
1715
+ * part way through the input buffer.
1716
+ */
1717
+ pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled;
1718
+ if (pos >= RSYNC_LENGTH) {
1719
+ prev = istart + pos - RSYNC_LENGTH;
1720
+ hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
1721
+ } else {
1722
+ assert(mtctx->inBuff.filled >= RSYNC_LENGTH);
1723
+ prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
1724
+ hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos));
1725
+ hash = ZSTD_rollingHash_append(hash, istart, pos);
1726
+ }
1727
+ } else {
1728
+ /* We have enough bytes buffered to initialize the hash,
1729
+ * and are have processed enough bytes to find a sync point.
1966
1730
  * Start scanning at the beginning of the input.
1967
1731
  */
1732
+ assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE);
1733
+ assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH);
1968
1734
  pos = 0;
1969
1735
  prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
1970
1736
  hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
1971
- } else {
1972
- /* We don't have enough bytes buffered to initialize the hash, but
1973
- * we know we have at least RSYNC_LENGTH bytes total.
1974
- * Start scanning after the first RSYNC_LENGTH bytes less the bytes
1975
- * already buffered.
1976
- */
1977
- pos = RSYNC_LENGTH - mtctx->inBuff.filled;
1978
- prev = (BYTE const*)mtctx->inBuff.buffer.start - pos;
1979
- hash = ZSTD_rollingHash_compute(mtctx->inBuff.buffer.start, mtctx->inBuff.filled);
1980
- hash = ZSTD_rollingHash_append(hash, istart, pos);
1737
+ if ((hash & hitMask) == hitMask) {
1738
+ /* We're already at a sync point so don't load any more until
1739
+ * we're able to flush this sync point.
1740
+ * This likely happened because the job table was full so we
1741
+ * couldn't add our job.
1742
+ */
1743
+ syncPoint.toLoad = 0;
1744
+ syncPoint.flush = 1;
1745
+ return syncPoint;
1746
+ }
1981
1747
  }
1982
1748
  /* Starting with the hash of the previous RSYNC_LENGTH bytes, roll
1983
1749
  * through the input. If we hit a synchronization point, then cut the
@@ -1989,8 +1755,9 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
1989
1755
  */
1990
1756
  for (; pos < syncPoint.toLoad; ++pos) {
1991
1757
  BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];
1992
- /* if (pos >= RSYNC_LENGTH) assert(ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); */
1758
+ assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);
1993
1759
  hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);
1760
+ assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE);
1994
1761
  if ((hash & hitMask) == hitMask) {
1995
1762
  syncPoint.toLoad = pos + 1;
1996
1763
  syncPoint.flush = 1;
@@ -2022,34 +1789,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
2022
1789
  assert(output->pos <= output->size);
2023
1790
  assert(input->pos <= input->size);
2024
1791
 
2025
- if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
2026
- return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
2027
- }
2028
-
2029
1792
  if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
2030
1793
  /* current frame being ended. Only flush/end are allowed */
2031
1794
  return ERROR(stage_wrong);
2032
1795
  }
2033
1796
 
2034
- /* single-pass shortcut (note : synchronous-mode) */
2035
- if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */
2036
- && (mtctx->nextJobID == 0) /* just started */
2037
- && (mtctx->inBuff.filled == 0) /* nothing buffered */
2038
- && (!mtctx->jobReady) /* no job already created */
2039
- && (endOp == ZSTD_e_end) /* end order */
2040
- && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */
2041
- size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
2042
- (char*)output->dst + output->pos, output->size - output->pos,
2043
- (const char*)input->src + input->pos, input->size - input->pos,
2044
- mtctx->cdict, mtctx->params);
2045
- if (ZSTD_isError(cSize)) return cSize;
2046
- input->pos = input->size;
2047
- output->pos += cSize;
2048
- mtctx->allJobsCompleted = 1;
2049
- mtctx->frameEnded = 1;
2050
- return 0;
2051
- }
2052
-
2053
1797
  /* fill input buffer */
2054
1798
  if ( (!mtctx->jobReady)
2055
1799
  && (input->size > input->pos) ) { /* support NULL input */
@@ -2072,13 +1816,21 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
2072
1816
  assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);
2073
1817
  DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u",
2074
1818
  (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
2075
- memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
1819
+ ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
2076
1820
  input->pos += syncPoint.toLoad;
2077
1821
  mtctx->inBuff.filled += syncPoint.toLoad;
2078
1822
  forwardInputProgress = syncPoint.toLoad>0;
2079
1823
  }
2080
- if ((input->pos < input->size) && (endOp == ZSTD_e_end))
2081
- endOp = ZSTD_e_flush; /* can't end now : not all input consumed */
1824
+ }
1825
+ if ((input->pos < input->size) && (endOp == ZSTD_e_end)) {
1826
+ /* Can't end yet because the input is not fully consumed.
1827
+ * We are in one of these cases:
1828
+ * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job.
1829
+ * - We filled the input buffer: flush this job but don't end the frame.
1830
+ * - We hit a synchronization point: flush this job but don't end the frame.
1831
+ */
1832
+ assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable);
1833
+ endOp = ZSTD_e_flush;
2082
1834
  }
2083
1835
 
2084
1836
  if ( (mtctx->jobReady)
@@ -2097,47 +1849,3 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
2097
1849
  return remainingToFlush;
2098
1850
  }
2099
1851
  }
2100
-
2101
-
2102
- size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
2103
- {
2104
- FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , "");
2105
-
2106
- /* recommended next input size : fill current input buffer */
2107
- return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
2108
- }
2109
-
2110
-
2111
- static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame)
2112
- {
2113
- size_t const srcSize = mtctx->inBuff.filled;
2114
- DEBUGLOG(5, "ZSTDMT_flushStream_internal");
2115
-
2116
- if ( mtctx->jobReady /* one job ready for a worker to pick up */
2117
- || (srcSize > 0) /* still some data within input buffer */
2118
- || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
2119
- DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
2120
- (U32)srcSize, (U32)endFrame);
2121
- FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , "");
2122
- }
2123
-
2124
- /* check if there is any data available to flush */
2125
- return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame);
2126
- }
2127
-
2128
-
2129
- size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
2130
- {
2131
- DEBUGLOG(5, "ZSTDMT_flushStream");
2132
- if (mtctx->singleBlockingThread)
2133
- return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output);
2134
- return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush);
2135
- }
2136
-
2137
- size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
2138
- {
2139
- DEBUGLOG(4, "ZSTDMT_endStream");
2140
- if (mtctx->singleBlockingThread)
2141
- return ZSTD_endStream(mtctx->cctxPool->cctx[0], output);
2142
- return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end);
2143
- }