zstd-ruby 1.3.5.0 → 1.3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -2
  3. data/README.md +2 -1
  4. data/ext/zstdruby/libzstd/BUCK +1 -0
  5. data/ext/zstdruby/libzstd/Makefile +25 -13
  6. data/ext/zstdruby/libzstd/README.md +11 -10
  7. data/ext/zstdruby/libzstd/common/bitstream.h +8 -11
  8. data/ext/zstdruby/libzstd/common/compiler.h +30 -8
  9. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  10. data/ext/zstdruby/libzstd/common/mem.h +20 -2
  11. data/ext/zstdruby/libzstd/common/xxhash.c +1 -0
  12. data/ext/zstdruby/libzstd/common/zstd_internal.h +3 -2
  13. data/ext/zstdruby/libzstd/compress/fse_compress.c +55 -48
  14. data/ext/zstdruby/libzstd/compress/hist.h +1 -1
  15. data/ext/zstdruby/libzstd/compress/huf_compress.c +1 -1
  16. data/ext/zstdruby/libzstd/compress/zstd_compress.c +290 -147
  17. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +5 -2
  18. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +63 -51
  19. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -4
  20. data/ext/zstdruby/libzstd/compress/zstd_fast.c +44 -33
  21. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -4
  22. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +125 -116
  23. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +13 -15
  24. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +9 -11
  25. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +0 -1
  26. data/ext/zstdruby/libzstd/compress/zstd_opt.c +42 -36
  27. data/ext/zstdruby/libzstd/compress/zstd_opt.h +8 -9
  28. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +96 -51
  29. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +16 -6
  30. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +3 -3
  31. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +169 -101
  32. data/ext/zstdruby/libzstd/dictBuilder/cover.c +111 -87
  33. data/ext/zstdruby/libzstd/dictBuilder/cover.h +83 -0
  34. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +3 -3
  35. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +728 -0
  36. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +34 -31
  37. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +60 -5
  38. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +9 -3
  39. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +6 -0
  40. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +6 -0
  41. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -5
  42. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +12 -9
  43. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +10 -10
  44. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +20 -18
  45. data/ext/zstdruby/libzstd/zstd.h +109 -50
  46. data/lib/zstd-ruby/version.rb +1 -1
  47. metadata +4 -2
@@ -17,50 +17,48 @@ extern "C" {
17
17
 
18
18
  #include "zstd_compress_internal.h"
19
19
 
20
- U32 ZSTD_insertAndFindFirstIndex(
21
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
22
- const BYTE* ip);
20
+ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
23
21
 
24
22
  void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */
25
23
 
26
24
  size_t ZSTD_compressBlock_btlazy2(
27
25
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
28
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
26
+ void const* src, size_t srcSize);
29
27
  size_t ZSTD_compressBlock_lazy2(
30
28
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
31
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
29
+ void const* src, size_t srcSize);
32
30
  size_t ZSTD_compressBlock_lazy(
33
31
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
34
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
32
+ void const* src, size_t srcSize);
35
33
  size_t ZSTD_compressBlock_greedy(
36
34
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
37
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
35
+ void const* src, size_t srcSize);
38
36
 
39
37
  size_t ZSTD_compressBlock_btlazy2_dictMatchState(
40
38
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
41
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
39
+ void const* src, size_t srcSize);
42
40
  size_t ZSTD_compressBlock_lazy2_dictMatchState(
43
41
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
44
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
42
+ void const* src, size_t srcSize);
45
43
  size_t ZSTD_compressBlock_lazy_dictMatchState(
46
44
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
47
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
45
+ void const* src, size_t srcSize);
48
46
  size_t ZSTD_compressBlock_greedy_dictMatchState(
49
47
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
50
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
48
+ void const* src, size_t srcSize);
51
49
 
52
50
  size_t ZSTD_compressBlock_greedy_extDict(
53
51
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
54
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
52
+ void const* src, size_t srcSize);
55
53
  size_t ZSTD_compressBlock_lazy_extDict(
56
54
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
57
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
55
+ void const* src, size_t srcSize);
58
56
  size_t ZSTD_compressBlock_lazy2_extDict(
59
57
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
60
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
58
+ void const* src, size_t srcSize);
61
59
  size_t ZSTD_compressBlock_btlazy2_extDict(
62
60
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
63
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
61
+ void const* src, size_t srcSize);
64
62
 
65
63
  #if defined (__cplusplus)
66
64
  }
@@ -218,19 +218,18 @@ static size_t ZSTD_ldm_countBackwardsMatch(
218
218
  * The tables for the other strategies are filled within their
219
219
  * block compressors. */
220
220
  static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
221
- ZSTD_compressionParameters const* cParams,
222
221
  void const* end)
223
222
  {
224
223
  const BYTE* const iend = (const BYTE*)end;
225
224
 
226
- switch(cParams->strategy)
225
+ switch(ms->cParams.strategy)
227
226
  {
228
227
  case ZSTD_fast:
229
- ZSTD_fillHashTable(ms, cParams, iend, ZSTD_dtlm_fast);
228
+ ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast);
230
229
  break;
231
230
 
232
231
  case ZSTD_dfast:
233
- ZSTD_fillDoubleHashTable(ms, cParams, iend, ZSTD_dtlm_fast);
232
+ ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast);
234
233
  break;
235
234
 
236
235
  case ZSTD_greedy:
@@ -591,8 +590,9 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
591
590
 
592
591
  size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
593
592
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
594
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
593
+ void const* src, size_t srcSize)
595
594
  {
595
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
596
596
  unsigned const minMatch = cParams->searchLength;
597
597
  ZSTD_blockCompressor const blockCompressor =
598
598
  ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms));
@@ -620,13 +620,12 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
620
620
 
621
621
  /* Fill tables for block compressor */
622
622
  ZSTD_ldm_limitTableUpdate(ms, ip);
623
- ZSTD_ldm_fillFastTables(ms, cParams, ip);
623
+ ZSTD_ldm_fillFastTables(ms, ip);
624
624
  /* Run the block compressor */
625
625
  DEBUGLOG(5, "calling block compressor on segment of size %u", sequence.litLength);
626
626
  {
627
627
  size_t const newLitLength =
628
- blockCompressor(ms, seqStore, rep, cParams, ip,
629
- sequence.litLength);
628
+ blockCompressor(ms, seqStore, rep, ip, sequence.litLength);
630
629
  ip += sequence.litLength;
631
630
  /* Update the repcodes */
632
631
  for (i = ZSTD_REP_NUM - 1; i > 0; i--)
@@ -641,8 +640,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
641
640
  }
642
641
  /* Fill the tables for the block compressor */
643
642
  ZSTD_ldm_limitTableUpdate(ms, ip);
644
- ZSTD_ldm_fillFastTables(ms, cParams, ip);
643
+ ZSTD_ldm_fillFastTables(ms, ip);
645
644
  /* Compress the last literals */
646
- return blockCompressor(ms, seqStore, rep, cParams,
647
- ip, iend - ip);
645
+ return blockCompressor(ms, seqStore, rep, ip, iend - ip);
648
646
  }
@@ -61,7 +61,6 @@ size_t ZSTD_ldm_generateSequences(
61
61
  */
62
62
  size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
63
63
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
64
- ZSTD_compressionParameters const* cParams,
65
64
  void const* src, size_t srcSize);
66
65
 
67
66
  /**
@@ -360,10 +360,11 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
360
360
  * ip : assumed <= iend-8 .
361
361
  * @return : nb of positions added */
362
362
  static U32 ZSTD_insertBt1(
363
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
363
+ ZSTD_matchState_t* ms,
364
364
  const BYTE* const ip, const BYTE* const iend,
365
365
  U32 const mls, const int extDict)
366
366
  {
367
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
367
368
  U32* const hashTable = ms->hashTable;
368
369
  U32 const hashLog = cParams->hashLog;
369
370
  size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
@@ -471,7 +472,7 @@ static U32 ZSTD_insertBt1(
471
472
 
472
473
  FORCE_INLINE_TEMPLATE
473
474
  void ZSTD_updateTree_internal(
474
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
475
+ ZSTD_matchState_t* ms,
475
476
  const BYTE* const ip, const BYTE* const iend,
476
477
  const U32 mls, const ZSTD_dictMode_e dictMode)
477
478
  {
@@ -482,24 +483,22 @@ void ZSTD_updateTree_internal(
482
483
  idx, target, dictMode);
483
484
 
484
485
  while(idx < target)
485
- idx += ZSTD_insertBt1(ms, cParams, base+idx, iend, mls, dictMode == ZSTD_extDict);
486
+ idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
486
487
  ms->nextToUpdate = target;
487
488
  }
488
489
 
489
- void ZSTD_updateTree(
490
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
491
- const BYTE* ip, const BYTE* iend)
492
- {
493
- ZSTD_updateTree_internal(ms, cParams, ip, iend, cParams->searchLength, ZSTD_noDict);
490
+ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
491
+ ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.searchLength, ZSTD_noDict);
494
492
  }
495
493
 
496
494
  FORCE_INLINE_TEMPLATE
497
495
  U32 ZSTD_insertBtAndGetAllMatches (
498
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
496
+ ZSTD_matchState_t* ms,
499
497
  const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
500
498
  U32 rep[ZSTD_REP_NUM], U32 const ll0,
501
499
  ZSTD_match_t* matches, const U32 lengthToBeat, U32 const mls /* template */)
502
500
  {
501
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
503
502
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
504
503
  const BYTE* const base = ms->window.base;
505
504
  U32 const current = (U32)(ip-base);
@@ -527,12 +526,17 @@ U32 ZSTD_insertBtAndGetAllMatches (
527
526
  U32 nbCompares = 1U << cParams->searchLog;
528
527
 
529
528
  const ZSTD_matchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL;
529
+ const ZSTD_compressionParameters* const dmsCParams =
530
+ dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL;
530
531
  const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL;
531
532
  const BYTE* const dmsEnd = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL;
532
533
  U32 const dmsHighLimit = dictMode == ZSTD_dictMatchState ? (U32)(dmsEnd - dmsBase) : 0;
533
534
  U32 const dmsLowLimit = dictMode == ZSTD_dictMatchState ? dms->window.lowLimit : 0;
534
535
  U32 const dmsIndexDelta = dictMode == ZSTD_dictMatchState ? windowLow - dmsHighLimit : 0;
535
- U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && btMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - btMask : dmsLowLimit;
536
+ U32 const dmsHashLog = dictMode == ZSTD_dictMatchState ? dmsCParams->hashLog : hashLog;
537
+ U32 const dmsBtLog = dictMode == ZSTD_dictMatchState ? dmsCParams->chainLog - 1 : btLog;
538
+ U32 const dmsBtMask = dictMode == ZSTD_dictMatchState ? (1U << dmsBtLog) - 1 : 0;
539
+ U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;
536
540
 
537
541
  size_t bestLength = lengthToBeat-1;
538
542
  DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current);
@@ -667,11 +671,12 @@ U32 ZSTD_insertBtAndGetAllMatches (
667
671
  *smallerPtr = *largerPtr = 0;
668
672
 
669
673
  if (dictMode == ZSTD_dictMatchState && nbCompares) {
670
- U32 dictMatchIndex = dms->hashTable[h];
674
+ size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);
675
+ U32 dictMatchIndex = dms->hashTable[dmsH];
671
676
  const U32* const dmsBt = dms->chainTable;
672
677
  commonLengthSmaller = commonLengthLarger = 0;
673
678
  while (nbCompares-- && (dictMatchIndex > dmsLowLimit)) {
674
- const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & btMask);
679
+ const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);
675
680
  size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
676
681
  const BYTE* match = dmsBase + dictMatchIndex;
677
682
  matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dmsEnd, prefixStart);
@@ -713,23 +718,24 @@ U32 ZSTD_insertBtAndGetAllMatches (
713
718
 
714
719
 
715
720
  FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
716
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
721
+ ZSTD_matchState_t* ms,
717
722
  const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
718
723
  U32 rep[ZSTD_REP_NUM], U32 const ll0,
719
724
  ZSTD_match_t* matches, U32 const lengthToBeat)
720
725
  {
726
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
721
727
  U32 const matchLengthSearch = cParams->searchLength;
722
728
  DEBUGLOG(8, "ZSTD_BtGetAllMatches");
723
729
  if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
724
- ZSTD_updateTree_internal(ms, cParams, ip, iHighLimit, matchLengthSearch, dictMode);
730
+ ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
725
731
  switch(matchLengthSearch)
726
732
  {
727
- case 3 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
733
+ case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
728
734
  default :
729
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
730
- case 5 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
735
+ case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
736
+ case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
731
737
  case 7 :
732
- case 6 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
738
+ case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
733
739
  }
734
740
  }
735
741
 
@@ -741,7 +747,7 @@ typedef struct repcodes_s {
741
747
  U32 rep[3];
742
748
  } repcodes_t;
743
749
 
744
- repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
750
+ static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
745
751
  {
746
752
  repcodes_t newReps;
747
753
  if (offset >= ZSTD_REP_NUM) { /* full offset */
@@ -772,7 +778,6 @@ FORCE_INLINE_TEMPLATE size_t
772
778
  ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
773
779
  seqStore_t* seqStore,
774
780
  U32 rep[ZSTD_REP_NUM],
775
- const ZSTD_compressionParameters* cParams,
776
781
  const void* src, size_t srcSize,
777
782
  const int optLevel, const ZSTD_dictMode_e dictMode)
778
783
  {
@@ -784,6 +789,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
784
789
  const BYTE* const ilimit = iend - 8;
785
790
  const BYTE* const base = ms->window.base;
786
791
  const BYTE* const prefixStart = base + ms->window.dictLimit;
792
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
787
793
 
788
794
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
789
795
  U32 const minMatch = (cParams->searchLength == 3) ? 3 : 4;
@@ -806,7 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
806
812
  /* find first match */
807
813
  { U32 const litlen = (U32)(ip - anchor);
808
814
  U32 const ll0 = !litlen;
809
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, ip, iend, dictMode, rep, ll0, matches, minMatch);
815
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
810
816
  if (!nbMatches) { ip++; continue; }
811
817
 
812
818
  /* initialize opt[0] */
@@ -903,7 +909,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
903
909
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
904
910
  U32 const previousPrice = opt[cur].price;
905
911
  U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
906
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
912
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
907
913
  U32 matchNb;
908
914
  if (!nbMatches) {
909
915
  DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -970,7 +976,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
970
976
  U32 seqPos = cur;
971
977
 
972
978
  DEBUGLOG(6, "start reverse traversal (last_pos:%u, cur:%u)",
973
- last_pos, cur);
979
+ last_pos, cur); (void)last_pos;
974
980
  assert(storeEnd < ZSTD_OPT_NUM);
975
981
  DEBUGLOG(6, "last sequence copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
976
982
  storeEnd, lastSequence.litlen, lastSequence.mlen, lastSequence.off);
@@ -1033,10 +1039,10 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1033
1039
 
1034
1040
  size_t ZSTD_compressBlock_btopt(
1035
1041
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1036
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1042
+ const void* src, size_t srcSize)
1037
1043
  {
1038
1044
  DEBUGLOG(5, "ZSTD_compressBlock_btopt");
1039
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, ZSTD_noDict);
1045
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_noDict);
1040
1046
  }
1041
1047
 
1042
1048
 
@@ -1064,7 +1070,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
1064
1070
 
1065
1071
  size_t ZSTD_compressBlock_btultra(
1066
1072
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1067
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1073
+ const void* src, size_t srcSize)
1068
1074
  {
1069
1075
  DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize);
1070
1076
  #if 0
@@ -1082,7 +1088,7 @@ size_t ZSTD_compressBlock_btultra(
1082
1088
  assert(ms->nextToUpdate >= ms->window.dictLimit
1083
1089
  && ms->nextToUpdate <= ms->window.dictLimit + 1);
1084
1090
  memcpy(tmpRep, rep, sizeof(tmpRep));
1085
- ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, cParams, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/
1091
+ ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/
1086
1092
  ZSTD_resetSeqStore(seqStore);
1087
1093
  /* invalidate first scan from history */
1088
1094
  ms->window.base -= srcSize;
@@ -1094,33 +1100,33 @@ size_t ZSTD_compressBlock_btultra(
1094
1100
  ZSTD_upscaleStats(&ms->opt);
1095
1101
  }
1096
1102
  #endif
1097
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
1103
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
1098
1104
  }
1099
1105
 
1100
1106
  size_t ZSTD_compressBlock_btopt_dictMatchState(
1101
1107
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1102
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1108
+ const void* src, size_t srcSize)
1103
1109
  {
1104
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState);
1110
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState);
1105
1111
  }
1106
1112
 
1107
1113
  size_t ZSTD_compressBlock_btultra_dictMatchState(
1108
1114
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1109
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1115
+ const void* src, size_t srcSize)
1110
1116
  {
1111
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState);
1117
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState);
1112
1118
  }
1113
1119
 
1114
1120
  size_t ZSTD_compressBlock_btopt_extDict(
1115
1121
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1116
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1122
+ const void* src, size_t srcSize)
1117
1123
  {
1118
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, ZSTD_extDict);
1124
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_extDict);
1119
1125
  }
1120
1126
 
1121
1127
  size_t ZSTD_compressBlock_btultra_extDict(
1122
1128
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
1123
- const ZSTD_compressionParameters* cParams, const void* src, size_t srcSize)
1129
+ const void* src, size_t srcSize)
1124
1130
  {
1125
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, ZSTD_extDict);
1131
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_extDict);
1126
1132
  }
@@ -17,30 +17,29 @@ extern "C" {
17
17
 
18
18
  #include "zstd_compress_internal.h"
19
19
 
20
- void ZSTD_updateTree(
21
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
22
- const BYTE* ip, const BYTE* iend); /* used in ZSTD_loadDictionaryContent() */
20
+ /* used in ZSTD_loadDictionaryContent() */
21
+ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend);
23
22
 
24
23
  size_t ZSTD_compressBlock_btopt(
25
24
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
26
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
25
+ void const* src, size_t srcSize);
27
26
  size_t ZSTD_compressBlock_btultra(
28
27
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
29
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
28
+ void const* src, size_t srcSize);
30
29
 
31
30
  size_t ZSTD_compressBlock_btopt_dictMatchState(
32
31
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
33
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
32
+ void const* src, size_t srcSize);
34
33
  size_t ZSTD_compressBlock_btultra_dictMatchState(
35
34
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
36
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
35
+ void const* src, size_t srcSize);
37
36
 
38
37
  size_t ZSTD_compressBlock_btopt_extDict(
39
38
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
40
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
39
+ void const* src, size_t srcSize);
41
40
  size_t ZSTD_compressBlock_btultra_extDict(
42
41
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
43
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
42
+ void const* src, size_t srcSize);
44
43
 
45
44
  #if defined (__cplusplus)
46
45
  }
@@ -37,7 +37,9 @@
37
37
  #define ZSTD_RESIZE_SEQPOOL 0
38
38
 
39
39
  /* ====== Debug ====== */
40
- #if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) && !defined(_MSC_VER)
40
+ #if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) \
41
+ && !defined(_MSC_VER) \
42
+ && !defined(__MINGW32__)
41
43
 
42
44
  # include <stdio.h>
43
45
  # include <unistd.h>
@@ -247,8 +249,8 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
247
249
  /* store buffer for later re-use, up to pool capacity */
248
250
  static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
249
251
  {
250
- if (buf.start == NULL) return; /* compatible with release on NULL */
251
252
  DEBUGLOG(5, "ZSTDMT_releaseBuffer");
253
+ if (buf.start == NULL) return; /* compatible with release on NULL */
252
254
  ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
253
255
  if (bufPool->nbBuffers < bufPool->totalBuffers) {
254
256
  bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
@@ -318,7 +320,8 @@ static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
318
320
 
319
321
  static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
320
322
  {
321
- ZSTDMT_seqPool* seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
323
+ ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
324
+ if (seqPool == NULL) return NULL;
322
325
  ZSTDMT_setNbSeq(seqPool, 0);
323
326
  return seqPool;
324
327
  }
@@ -539,6 +542,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
539
542
  /* Wait for our turn */
540
543
  ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);
541
544
  while (serialState->nextJobID < jobID) {
545
+ DEBUGLOG(5, "wait for serialState->cond");
542
546
  ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);
543
547
  }
544
548
  /* A future job may error and skip our job */
@@ -628,32 +632,32 @@ typedef struct {
628
632
  unsigned frameChecksumNeeded; /* used only by mtctx */
629
633
  } ZSTDMT_jobDescription;
630
634
 
635
+ #define JOB_ERROR(e) { \
636
+ ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); \
637
+ job->cSize = e; \
638
+ ZSTD_pthread_mutex_unlock(&job->job_mutex); \
639
+ goto _endJob; \
640
+ }
641
+
631
642
  /* ZSTDMT_compressionJob() is a POOL_function type */
632
- void ZSTDMT_compressionJob(void* jobDescription)
643
+ static void ZSTDMT_compressionJob(void* jobDescription)
633
644
  {
634
645
  ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
635
646
  ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */
636
647
  ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);
637
648
  rawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool);
638
649
  buffer_t dstBuff = job->dstBuff;
650
+ size_t lastCBlockSize = 0;
639
651
 
640
652
  /* ressources */
641
- if (cctx==NULL) {
642
- job->cSize = ERROR(memory_allocation);
643
- goto _endJob;
644
- }
653
+ if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
645
654
  if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
646
655
  dstBuff = ZSTDMT_getBuffer(job->bufPool);
647
- if (dstBuff.start==NULL) {
648
- job->cSize = ERROR(memory_allocation);
649
- goto _endJob;
650
- }
656
+ if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));
651
657
  job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
652
658
  }
653
- if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL) {
654
- job->cSize = ERROR(memory_allocation);
655
- goto _endJob;
656
- }
659
+ if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL)
660
+ JOB_ERROR(ERROR(memory_allocation));
657
661
 
658
662
  /* Don't compute the checksum for chunks, since we compute it externally,
659
663
  * but write it in the header.
@@ -667,30 +671,26 @@ void ZSTDMT_compressionJob(void* jobDescription)
667
671
  if (job->cdict) {
668
672
  size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, jobParams, job->fullFrameSize);
669
673
  assert(job->firstJob); /* only allowed for first job */
670
- if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
674
+ if (ZSTD_isError(initError)) JOB_ERROR(initError);
671
675
  } else { /* srcStart points at reloaded section */
672
676
  U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
673
677
  { size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstJob);
674
- if (ZSTD_isError(forceWindowError)) {
675
- job->cSize = forceWindowError;
676
- goto _endJob;
677
- } }
678
+ if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
679
+ }
678
680
  { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
679
681
  job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
680
682
  ZSTD_dtlm_fast,
681
683
  NULL, /*cdict*/
682
684
  jobParams, pledgedSrcSize);
683
- if (ZSTD_isError(initError)) {
684
- job->cSize = initError;
685
- goto _endJob;
686
- } } }
685
+ if (ZSTD_isError(initError)) JOB_ERROR(initError);
686
+ } }
687
687
 
688
688
  /* Perform serial step as early as possible, but after CCtx initialization */
689
689
  ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID);
690
690
 
691
691
  if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */
692
692
  size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);
693
- if (ZSTD_isError(hSize)) { job->cSize = hSize; /* save error code */ goto _endJob; }
693
+ if (ZSTD_isError(hSize)) JOB_ERROR(hSize);
694
694
  DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize);
695
695
  ZSTD_invalidateRepCodes(cctx);
696
696
  }
@@ -708,7 +708,7 @@ void ZSTDMT_compressionJob(void* jobDescription)
708
708
  assert(job->cSize == 0);
709
709
  for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {
710
710
  size_t const cSize = ZSTD_compressContinue(cctx, op, oend-op, ip, chunkSize);
711
- if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
711
+ if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
712
712
  ip += chunkSize;
713
713
  op += cSize; assert(op < oend);
714
714
  /* stats */
@@ -721,18 +721,16 @@ void ZSTDMT_compressionJob(void* jobDescription)
721
721
  ZSTD_pthread_mutex_unlock(&job->job_mutex);
722
722
  }
723
723
  /* last block */
724
- assert(chunkSize > 0); assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */
724
+ assert(chunkSize > 0);
725
+ assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */
725
726
  if ((nbChunks > 0) | job->lastJob /*must output a "last block" flag*/ ) {
726
727
  size_t const lastBlockSize1 = job->src.size & (chunkSize-1);
727
728
  size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;
728
729
  size_t const cSize = (job->lastJob) ?
729
730
  ZSTD_compressEnd (cctx, op, oend-op, ip, lastBlockSize) :
730
731
  ZSTD_compressContinue(cctx, op, oend-op, ip, lastBlockSize);
731
- if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
732
- /* stats */
733
- ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
734
- job->cSize += cSize;
735
- ZSTD_pthread_mutex_unlock(&job->job_mutex);
732
+ if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
733
+ lastCBlockSize = cSize;
736
734
  } }
737
735
 
738
736
  _endJob:
@@ -745,7 +743,9 @@ _endJob:
745
743
  ZSTDMT_releaseCCtx(job->cctxPool, cctx);
746
744
  /* report */
747
745
  ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
748
- job->consumed = job->src.size;
746
+ if (ZSTD_isError(job->cSize)) assert(lastCBlockSize == 0);
747
+ job->cSize += lastCBlockSize;
748
+ job->consumed = job->src.size; /* when job->consumed == job->src.size , compression job is presumed completed */
749
749
  ZSTD_pthread_cond_signal(&job->job_cond);
750
750
  ZSTD_pthread_mutex_unlock(&job->job_mutex);
751
751
  }
@@ -930,7 +930,7 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
930
930
  unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask;
931
931
  ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
932
932
  while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
933
- DEBUGLOG(5, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
933
+ DEBUGLOG(4, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
934
934
  ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
935
935
  }
936
936
  ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
@@ -1055,7 +1055,7 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
1055
1055
 
1056
1056
 
1057
1057
  /*! ZSTDMT_updateCParams_whileCompressing() :
1058
- * Updates only a selected set of compression parameters, to remain compatible with current frame.
1058
+ * Updates a selected set of compression parameters, remaining compatible with currently active frame.
1059
1059
  * New parameters will be applied to next compression job. */
1060
1060
  void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams)
1061
1061
  {
@@ -1073,26 +1073,33 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
1073
1073
  /* ZSTDMT_getFrameProgression():
1074
1074
  * tells how much data has been consumed (input) and produced (output) for current frame.
1075
1075
  * able to count progression inside worker threads.
1076
- * Note : mutex will be acquired during statistics collection. */
1076
+ * Note : mutex will be acquired during statistics collection inside workers. */
1077
1077
  ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
1078
1078
  {
1079
1079
  ZSTD_frameProgression fps;
1080
- DEBUGLOG(6, "ZSTDMT_getFrameProgression");
1081
- fps.consumed = mtctx->consumed;
1082
- fps.produced = mtctx->produced;
1080
+ DEBUGLOG(5, "ZSTDMT_getFrameProgression");
1083
1081
  fps.ingested = mtctx->consumed + mtctx->inBuff.filled;
1082
+ fps.consumed = mtctx->consumed;
1083
+ fps.produced = fps.flushed = mtctx->produced;
1084
+ fps.currentJobID = mtctx->nextJobID;
1085
+ fps.nbActiveWorkers = 0;
1084
1086
  { unsigned jobNb;
1085
1087
  unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);
1086
1088
  DEBUGLOG(6, "ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)",
1087
1089
  mtctx->doneJobID, lastJobNb, mtctx->jobReady)
1088
1090
  for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {
1089
1091
  unsigned const wJobID = jobNb & mtctx->jobIDMask;
1090
- ZSTD_pthread_mutex_lock(&mtctx->jobs[wJobID].job_mutex);
1091
- { size_t const cResult = mtctx->jobs[wJobID].cSize;
1092
+ ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID];
1093
+ ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);
1094
+ { size_t const cResult = jobPtr->cSize;
1092
1095
  size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
1093
- fps.consumed += mtctx->jobs[wJobID].consumed;
1094
- fps.ingested += mtctx->jobs[wJobID].src.size;
1096
+ size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
1097
+ assert(flushed <= produced);
1098
+ fps.ingested += jobPtr->src.size;
1099
+ fps.consumed += jobPtr->consumed;
1095
1100
  fps.produced += produced;
1101
+ fps.flushed += flushed;
1102
+ fps.nbActiveWorkers += (jobPtr->consumed < jobPtr->src.size);
1096
1103
  }
1097
1104
  ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
1098
1105
  }
@@ -1101,6 +1108,34 @@ ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
1101
1108
  }
1102
1109
 
1103
1110
 
1111
+ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
1112
+ {
1113
+ size_t toFlush;
1114
+ unsigned const jobID = mtctx->doneJobID;
1115
+ assert(jobID <= mtctx->nextJobID);
1116
+ if (jobID == mtctx->nextJobID) return 0; /* no active job => nothing to flush */
1117
+
1118
+ /* look into oldest non-fully-flushed job */
1119
+ { unsigned const wJobID = jobID & mtctx->jobIDMask;
1120
+ ZSTDMT_jobDescription* const jobPtr = &mtctx->jobs[wJobID];
1121
+ ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);
1122
+ { size_t const cResult = jobPtr->cSize;
1123
+ size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
1124
+ size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
1125
+ assert(flushed <= produced);
1126
+ toFlush = produced - flushed;
1127
+ if (toFlush==0 && (jobPtr->consumed >= jobPtr->src.size)) {
1128
+ /* doneJobID is not-fully-flushed, but toFlush==0 : doneJobID should be compressing some more data */
1129
+ assert(jobPtr->consumed < jobPtr->src.size);
1130
+ }
1131
+ }
1132
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
1133
+ }
1134
+
1135
+ return toFlush;
1136
+ }
1137
+
1138
+
1104
1139
  /* ------------------------------------------ */
1105
1140
  /* ===== Multi-threaded compression ===== */
1106
1141
  /* ------------------------------------------ */
@@ -1495,7 +1530,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZS
1495
1530
  mtctx->jobs[jobID].jobID = mtctx->nextJobID;
1496
1531
  mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0);
1497
1532
  mtctx->jobs[jobID].lastJob = endFrame;
1498
- mtctx->jobs[jobID].frameChecksumNeeded = endFrame && (mtctx->nextJobID>0) && mtctx->params.fParams.checksumFlag;
1533
+ mtctx->jobs[jobID].frameChecksumNeeded = mtctx->params.fParams.checksumFlag && endFrame && (mtctx->nextJobID>0);
1499
1534
  mtctx->jobs[jobID].dstFlushed = 0;
1500
1535
 
1501
1536
  /* Update the round buffer pos and clear the input buffer to be reset */
@@ -1543,6 +1578,8 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZS
1543
1578
 
1544
1579
 
1545
1580
  /*! ZSTDMT_flushProduced() :
1581
+ * flush whatever data has been produced but not yet flushed in current job.
1582
+ * move to next job if current one is fully flushed.
1546
1583
  * `output` : `pos` will be updated with amount of data flushed .
1547
1584
  * `blockToFlush` : if >0, the function will block and wait if there is no data available to flush .
1548
1585
  * @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */
@@ -1571,7 +1608,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
1571
1608
  /* try to flush something */
1572
1609
  { size_t cSize = mtctx->jobs[wJobID].cSize; /* shared */
1573
1610
  size_t const srcConsumed = mtctx->jobs[wJobID].consumed; /* shared */
1574
- size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */
1611
+ size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */
1575
1612
  ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
1576
1613
  if (ZSTD_isError(cSize)) {
1577
1614
  DEBUGLOG(5, "ZSTDMT_flushProduced: job %u : compression error detected : %s",
@@ -1591,6 +1628,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
1591
1628
  mtctx->jobs[wJobID].cSize += 4; /* can write this shared value, as worker is no longer active */
1592
1629
  mtctx->jobs[wJobID].frameChecksumNeeded = 0;
1593
1630
  }
1631
+
1594
1632
  if (cSize > 0) { /* compression is ongoing or completed */
1595
1633
  size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos);
1596
1634
  DEBUGLOG(5, "ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)",
@@ -1604,11 +1642,12 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
1604
1642
  output->pos += toFlush;
1605
1643
  mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */
1606
1644
 
1607
- if ( (srcConsumed == srcSize) /* job completed */
1645
+ if ( (srcConsumed == srcSize) /* job is completed */
1608
1646
  && (mtctx->jobs[wJobID].dstFlushed == cSize) ) { /* output buffer fully flushed => free this job position */
1609
1647
  DEBUGLOG(5, "Job %u completed (%u bytes), moving to next one",
1610
1648
  mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);
1611
1649
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff);
1650
+ DEBUGLOG(5, "dstBuffer released");
1612
1651
  mtctx->jobs[wJobID].dstBuff = g_nullBuffer;
1613
1652
  mtctx->jobs[wJobID].cSize = 0; /* ensure this job slot is considered "not started" in future check */
1614
1653
  mtctx->consumed += srcSize;
@@ -1685,6 +1724,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
1685
1724
  range_t extDict;
1686
1725
  range_t prefix;
1687
1726
 
1727
+ DEBUGLOG(5, "ZSTDMT_doesOverlapWindow");
1688
1728
  extDict.start = window.dictBase + window.lowLimit;
1689
1729
  extDict.size = window.dictLimit - window.lowLimit;
1690
1730
 
@@ -1705,12 +1745,13 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
1705
1745
  {
1706
1746
  if (mtctx->params.ldmParams.enableLdm) {
1707
1747
  ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
1748
+ DEBUGLOG(5, "ZSTDMT_waitForLdmComplete");
1708
1749
  DEBUGLOG(5, "source [0x%zx, 0x%zx)",
1709
1750
  (size_t)buffer.start,
1710
1751
  (size_t)buffer.start + buffer.capacity);
1711
1752
  ZSTD_PTHREAD_MUTEX_LOCK(mutex);
1712
1753
  while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {
1713
- DEBUGLOG(6, "Waiting for LDM to finish...");
1754
+ DEBUGLOG(5, "Waiting for LDM to finish...");
1714
1755
  ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);
1715
1756
  }
1716
1757
  DEBUGLOG(6, "Done waiting for LDM to finish");
@@ -1730,6 +1771,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
1730
1771
  size_t const target = mtctx->targetSectionSize;
1731
1772
  buffer_t buffer;
1732
1773
 
1774
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange");
1733
1775
  assert(mtctx->inBuff.buffer.start == NULL);
1734
1776
  assert(mtctx->roundBuff.capacity >= target);
1735
1777
 
@@ -1743,7 +1785,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
1743
1785
  buffer.start = start;
1744
1786
  buffer.capacity = prefixSize;
1745
1787
  if (ZSTDMT_isOverlapped(buffer, inUse)) {
1746
- DEBUGLOG(6, "Waiting for buffer...");
1788
+ DEBUGLOG(5, "Waiting for buffer...");
1747
1789
  return 0;
1748
1790
  }
1749
1791
  ZSTDMT_waitForLdmComplete(mtctx, buffer);
@@ -1755,7 +1797,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
1755
1797
  buffer.capacity = target;
1756
1798
 
1757
1799
  if (ZSTDMT_isOverlapped(buffer, inUse)) {
1758
- DEBUGLOG(6, "Waiting for buffer...");
1800
+ DEBUGLOG(5, "Waiting for buffer...");
1759
1801
  return 0;
1760
1802
  }
1761
1803
  assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));
@@ -1828,8 +1870,10 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
1828
1870
  /* It is only possible for this operation to fail if there are
1829
1871
  * still compression jobs ongoing.
1830
1872
  */
1873
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange failed");
1831
1874
  assert(mtctx->doneJobID != mtctx->nextJobID);
1832
- }
1875
+ } else
1876
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p", mtctx->inBuff.buffer.start);
1833
1877
  }
1834
1878
  if (mtctx->inBuff.buffer.start != NULL) {
1835
1879
  size_t const toLoad = MIN(input->size - input->pos, mtctx->targetSectionSize - mtctx->inBuff.filled);
@@ -1857,6 +1901,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
1857
1901
  /* check for potential compressed data ready to be flushed */
1858
1902
  { size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */
1859
1903
  if (input->pos < input->size) return MAX(remainingToFlush, 1); /* input not consumed : do not end flush yet */
1904
+ DEBUGLOG(5, "end of ZSTDMT_compressStream_generic: remainingToFlush = %u", (U32)remainingToFlush);
1860
1905
  return remainingToFlush;
1861
1906
  }
1862
1907
  }