zstd-ruby 1.3.5.0 → 1.3.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }