extzstd 0.1 → 0.3.2

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 (134) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +39 -0
  3. data/README.md +38 -56
  4. data/contrib/zstd/CHANGELOG +613 -0
  5. data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
  6. data/contrib/zstd/CONTRIBUTING.md +406 -0
  7. data/contrib/zstd/COPYING +339 -0
  8. data/contrib/zstd/Makefile +420 -0
  9. data/contrib/zstd/README.md +179 -41
  10. data/contrib/zstd/TESTING.md +44 -0
  11. data/contrib/zstd/appveyor.yml +292 -0
  12. data/contrib/zstd/lib/BUCK +234 -0
  13. data/contrib/zstd/lib/Makefile +451 -0
  14. data/contrib/zstd/lib/README.md +207 -0
  15. data/contrib/zstd/{common → lib/common}/bitstream.h +187 -138
  16. data/contrib/zstd/lib/common/compiler.h +288 -0
  17. data/contrib/zstd/lib/common/cpu.h +213 -0
  18. data/contrib/zstd/lib/common/debug.c +24 -0
  19. data/contrib/zstd/lib/common/debug.h +107 -0
  20. data/contrib/zstd/lib/common/entropy_common.c +362 -0
  21. data/contrib/zstd/{common → lib/common}/error_private.c +25 -12
  22. data/contrib/zstd/{common → lib/common}/error_private.h +14 -10
  23. data/contrib/zstd/{common → lib/common}/fse.h +173 -92
  24. data/contrib/zstd/{common → lib/common}/fse_decompress.c +149 -85
  25. data/contrib/zstd/lib/common/huf.h +361 -0
  26. data/contrib/zstd/{common → lib/common}/mem.h +115 -59
  27. data/contrib/zstd/lib/common/pool.c +350 -0
  28. data/contrib/zstd/lib/common/pool.h +84 -0
  29. data/contrib/zstd/lib/common/threading.c +122 -0
  30. data/contrib/zstd/lib/common/threading.h +155 -0
  31. data/contrib/zstd/{common → lib/common}/xxhash.c +55 -96
  32. data/contrib/zstd/{common → lib/common}/xxhash.h +23 -47
  33. data/contrib/zstd/lib/common/zstd_common.c +83 -0
  34. data/contrib/zstd/lib/common/zstd_deps.h +111 -0
  35. data/contrib/zstd/lib/common/zstd_errors.h +95 -0
  36. data/contrib/zstd/lib/common/zstd_internal.h +478 -0
  37. data/contrib/zstd/{compress → lib/compress}/fse_compress.c +214 -319
  38. data/contrib/zstd/lib/compress/hist.c +181 -0
  39. data/contrib/zstd/lib/compress/hist.h +75 -0
  40. data/contrib/zstd/lib/compress/huf_compress.c +913 -0
  41. data/contrib/zstd/lib/compress/zstd_compress.c +5208 -0
  42. data/contrib/zstd/lib/compress/zstd_compress_internal.h +1203 -0
  43. data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
  44. data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
  45. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +433 -0
  46. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
  47. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +849 -0
  48. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  49. data/contrib/zstd/lib/compress/zstd_cwksp.h +561 -0
  50. data/contrib/zstd/lib/compress/zstd_double_fast.c +521 -0
  51. data/contrib/zstd/lib/compress/zstd_double_fast.h +38 -0
  52. data/contrib/zstd/lib/compress/zstd_fast.c +496 -0
  53. data/contrib/zstd/lib/compress/zstd_fast.h +37 -0
  54. data/contrib/zstd/lib/compress/zstd_lazy.c +1412 -0
  55. data/contrib/zstd/lib/compress/zstd_lazy.h +87 -0
  56. data/contrib/zstd/lib/compress/zstd_ldm.c +660 -0
  57. data/contrib/zstd/lib/compress/zstd_ldm.h +116 -0
  58. data/contrib/zstd/lib/compress/zstd_opt.c +1345 -0
  59. data/contrib/zstd/lib/compress/zstd_opt.h +56 -0
  60. data/contrib/zstd/lib/compress/zstdmt_compress.c +1811 -0
  61. data/contrib/zstd/lib/compress/zstdmt_compress.h +110 -0
  62. data/contrib/zstd/lib/decompress/huf_decompress.c +1350 -0
  63. data/contrib/zstd/lib/decompress/zstd_ddict.c +244 -0
  64. data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
  65. data/contrib/zstd/lib/decompress/zstd_decompress.c +1930 -0
  66. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1540 -0
  67. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +62 -0
  68. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +190 -0
  69. data/contrib/zstd/{common → lib/deprecated}/zbuff.h +68 -45
  70. data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
  71. data/contrib/zstd/lib/deprecated/zbuff_compress.c +147 -0
  72. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +75 -0
  73. data/contrib/zstd/lib/dictBuilder/cover.c +1245 -0
  74. data/contrib/zstd/lib/dictBuilder/cover.h +157 -0
  75. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +3 -3
  76. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +0 -0
  77. data/contrib/zstd/lib/dictBuilder/fastcover.c +758 -0
  78. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +318 -194
  79. data/contrib/zstd/lib/dictBuilder/zdict.h +305 -0
  80. data/contrib/zstd/{legacy → lib/legacy}/zstd_legacy.h +171 -15
  81. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +191 -124
  82. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +19 -5
  83. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +125 -125
  84. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +19 -5
  85. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +125 -124
  86. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +20 -6
  87. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +151 -299
  88. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +19 -5
  89. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +237 -243
  90. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +19 -6
  91. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +130 -143
  92. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +18 -5
  93. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.c +158 -157
  94. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.h +19 -5
  95. data/contrib/zstd/lib/libzstd.pc.in +15 -0
  96. data/contrib/zstd/lib/zstd.h +2391 -0
  97. data/ext/depend +2 -0
  98. data/ext/extconf.rb +15 -6
  99. data/ext/extzstd.c +76 -145
  100. data/ext/extzstd.h +80 -31
  101. data/ext/extzstd_stream.c +417 -142
  102. data/ext/libzstd_conf.h +8 -0
  103. data/ext/zstd_common.c +10 -7
  104. data/ext/zstd_compress.c +14 -5
  105. data/ext/zstd_decompress.c +5 -4
  106. data/ext/zstd_dictbuilder.c +9 -4
  107. data/ext/zstd_dictbuilder_fastcover.c +3 -0
  108. data/ext/zstd_legacy_v01.c +3 -1
  109. data/ext/zstd_legacy_v02.c +3 -1
  110. data/ext/zstd_legacy_v03.c +3 -1
  111. data/ext/zstd_legacy_v04.c +3 -1
  112. data/ext/zstd_legacy_v05.c +3 -1
  113. data/ext/zstd_legacy_v06.c +3 -1
  114. data/ext/zstd_legacy_v07.c +3 -1
  115. data/gemstub.rb +10 -24
  116. data/lib/extzstd.rb +64 -179
  117. data/lib/extzstd/version.rb +6 -1
  118. data/test/test_basic.rb +9 -6
  119. metadata +113 -57
  120. data/HISTORY.ja +0 -5
  121. data/contrib/zstd/common/entropy_common.c +0 -225
  122. data/contrib/zstd/common/huf.h +0 -228
  123. data/contrib/zstd/common/zstd_common.c +0 -83
  124. data/contrib/zstd/common/zstd_errors.h +0 -60
  125. data/contrib/zstd/common/zstd_internal.h +0 -267
  126. data/contrib/zstd/compress/huf_compress.c +0 -533
  127. data/contrib/zstd/compress/zbuff_compress.c +0 -319
  128. data/contrib/zstd/compress/zstd_compress.c +0 -3264
  129. data/contrib/zstd/compress/zstd_opt.h +0 -900
  130. data/contrib/zstd/decompress/huf_decompress.c +0 -883
  131. data/contrib/zstd/decompress/zbuff_decompress.c +0 -252
  132. data/contrib/zstd/decompress/zstd_decompress.c +0 -1842
  133. data/contrib/zstd/dictBuilder/zdict.h +0 -111
  134. data/contrib/zstd/zstd.h +0 -640
@@ -1,10 +1,11 @@
1
- /**
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
1
+ /*
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
  #ifndef MEM_H_MODULE
@@ -17,8 +18,10 @@ extern "C" {
17
18
  /*-****************************************
18
19
  * Dependencies
19
20
  ******************************************/
20
- #include <stddef.h> /* size_t, ptrdiff_t */
21
- #include <string.h> /* memcpy */
21
+ #include <stddef.h> /* size_t, ptrdiff_t */
22
+ #include "compiler.h" /* __has_builtin */
23
+ #include "debug.h" /* DEBUG_STATIC_ASSERT */
24
+ #include "zstd_deps.h" /* ZSTD_memcpy */
22
25
 
23
26
 
24
27
  /*-****************************************
@@ -38,55 +41,111 @@ extern "C" {
38
41
  # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
39
42
  #endif
40
43
 
41
- /* code only tested on 32 and 64 bits systems */
42
- #define MEM_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; }
43
- MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
44
-
45
-
46
44
  /*-**************************************************************
47
45
  * Basic Types
48
46
  *****************************************************************/
49
47
  #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
50
- # include <stdint.h>
51
- typedef uint8_t BYTE;
52
- typedef uint16_t U16;
53
- typedef int16_t S16;
54
- typedef uint32_t U32;
55
- typedef int32_t S32;
56
- typedef uint64_t U64;
57
- typedef int64_t S64;
48
+ # if defined(_AIX)
49
+ # include <inttypes.h>
50
+ # else
51
+ # include <stdint.h> /* intptr_t */
52
+ # endif
53
+ typedef uint8_t BYTE;
54
+ typedef uint16_t U16;
55
+ typedef int16_t S16;
56
+ typedef uint32_t U32;
57
+ typedef int32_t S32;
58
+ typedef uint64_t U64;
59
+ typedef int64_t S64;
58
60
  #else
59
- typedef unsigned char BYTE;
61
+ # include <limits.h>
62
+ #if CHAR_BIT != 8
63
+ # error "this implementation requires char to be exactly 8-bit type"
64
+ #endif
65
+ typedef unsigned char BYTE;
66
+ #if USHRT_MAX != 65535
67
+ # error "this implementation requires short to be exactly 16-bit type"
68
+ #endif
60
69
  typedef unsigned short U16;
61
70
  typedef signed short S16;
71
+ #if UINT_MAX != 4294967295
72
+ # error "this implementation requires int to be exactly 32-bit type"
73
+ #endif
62
74
  typedef unsigned int U32;
63
75
  typedef signed int S32;
76
+ /* note : there are no limits defined for long long type in C90.
77
+ * limits exist in C99, however, in such case, <stdint.h> is preferred */
64
78
  typedef unsigned long long U64;
65
79
  typedef signed long long S64;
66
80
  #endif
67
81
 
68
82
 
69
83
  /*-**************************************************************
70
- * Memory I/O
84
+ * Memory I/O API
85
+ *****************************************************************/
86
+ /*=== Static platform detection ===*/
87
+ MEM_STATIC unsigned MEM_32bits(void);
88
+ MEM_STATIC unsigned MEM_64bits(void);
89
+ MEM_STATIC unsigned MEM_isLittleEndian(void);
90
+
91
+ /*=== Native unaligned read/write ===*/
92
+ MEM_STATIC U16 MEM_read16(const void* memPtr);
93
+ MEM_STATIC U32 MEM_read32(const void* memPtr);
94
+ MEM_STATIC U64 MEM_read64(const void* memPtr);
95
+ MEM_STATIC size_t MEM_readST(const void* memPtr);
96
+
97
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value);
98
+ MEM_STATIC void MEM_write32(void* memPtr, U32 value);
99
+ MEM_STATIC void MEM_write64(void* memPtr, U64 value);
100
+
101
+ /*=== Little endian unaligned read/write ===*/
102
+ MEM_STATIC U16 MEM_readLE16(const void* memPtr);
103
+ MEM_STATIC U32 MEM_readLE24(const void* memPtr);
104
+ MEM_STATIC U32 MEM_readLE32(const void* memPtr);
105
+ MEM_STATIC U64 MEM_readLE64(const void* memPtr);
106
+ MEM_STATIC size_t MEM_readLEST(const void* memPtr);
107
+
108
+ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
109
+ MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
110
+ MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
111
+ MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
112
+ MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
113
+
114
+ /*=== Big endian unaligned read/write ===*/
115
+ MEM_STATIC U32 MEM_readBE32(const void* memPtr);
116
+ MEM_STATIC U64 MEM_readBE64(const void* memPtr);
117
+ MEM_STATIC size_t MEM_readBEST(const void* memPtr);
118
+
119
+ MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
120
+ MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
121
+ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
122
+
123
+ /*=== Byteswap ===*/
124
+ MEM_STATIC U32 MEM_swap32(U32 in);
125
+ MEM_STATIC U64 MEM_swap64(U64 in);
126
+ MEM_STATIC size_t MEM_swapST(size_t in);
127
+
128
+
129
+ /*-**************************************************************
130
+ * Memory I/O Implementation
71
131
  *****************************************************************/
72
132
  /* MEM_FORCE_MEMORY_ACCESS :
73
133
  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
74
134
  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
75
135
  * The below switch allow to select different access method for improved performance.
76
136
  * Method 0 (default) : use `memcpy()`. Safe and portable.
77
- * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
137
+ * Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable).
78
138
  * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
79
139
  * Method 2 : direct access. This method is portable but violate C standard.
80
140
  * It can generate buggy code on targets depending on alignment.
81
- * In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
141
+ * In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6)
82
142
  * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
83
143
  * Prefer these methods in priority order (0 > 1 > 2)
84
144
  */
85
145
  #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
86
146
  # if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
87
147
  # define MEM_FORCE_MEMORY_ACCESS 2
88
- # elif defined(__INTEL_COMPILER) /*|| defined(_MSC_VER)*/ || \
89
- (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
148
+ # elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
90
149
  # define MEM_FORCE_MEMORY_ACCESS 1
91
150
  # endif
92
151
  #endif
@@ -107,7 +166,7 @@ Only use if no other choice to achieve best performance on target platform */
107
166
  MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
108
167
  MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
109
168
  MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
110
- MEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
169
+ MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
111
170
 
112
171
  MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
113
172
  MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
@@ -118,21 +177,27 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
118
177
  /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
119
178
  /* currently only defined for gcc and icc */
120
179
  #if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
121
- __pragma( pack(push, 1) )
122
- typedef union { U16 u16; U32 u32; U64 u64; size_t st; } unalign;
180
+ __pragma( pack(push, 1) )
181
+ typedef struct { U16 v; } unalign16;
182
+ typedef struct { U32 v; } unalign32;
183
+ typedef struct { U64 v; } unalign64;
184
+ typedef struct { size_t v; } unalignArch;
123
185
  __pragma( pack(pop) )
124
186
  #else
125
- typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
187
+ typedef struct { U16 v; } __attribute__((packed)) unalign16;
188
+ typedef struct { U32 v; } __attribute__((packed)) unalign32;
189
+ typedef struct { U64 v; } __attribute__((packed)) unalign64;
190
+ typedef struct { size_t v; } __attribute__((packed)) unalignArch;
126
191
  #endif
127
192
 
128
- MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
129
- MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
130
- MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
131
- MEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
193
+ MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; }
194
+ MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; }
195
+ MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; }
196
+ MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; }
132
197
 
133
- MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
134
- MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
135
- MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
198
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; }
199
+ MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; }
200
+ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; }
136
201
 
137
202
  #else
138
203
 
@@ -141,37 +206,37 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 =
141
206
 
142
207
  MEM_STATIC U16 MEM_read16(const void* memPtr)
143
208
  {
144
- U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
209
+ U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
145
210
  }
146
211
 
147
212
  MEM_STATIC U32 MEM_read32(const void* memPtr)
148
213
  {
149
- U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
214
+ U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
150
215
  }
151
216
 
152
217
  MEM_STATIC U64 MEM_read64(const void* memPtr)
153
218
  {
154
- U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
219
+ U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
155
220
  }
156
221
 
157
222
  MEM_STATIC size_t MEM_readST(const void* memPtr)
158
223
  {
159
- size_t val; memcpy(&val, memPtr, sizeof(val)); return val;
224
+ size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
160
225
  }
161
226
 
162
227
  MEM_STATIC void MEM_write16(void* memPtr, U16 value)
163
228
  {
164
- memcpy(memPtr, &value, sizeof(value));
229
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
165
230
  }
166
231
 
167
232
  MEM_STATIC void MEM_write32(void* memPtr, U32 value)
168
233
  {
169
- memcpy(memPtr, &value, sizeof(value));
234
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
170
235
  }
171
236
 
172
237
  MEM_STATIC void MEM_write64(void* memPtr, U64 value)
173
238
  {
174
- memcpy(memPtr, &value, sizeof(value));
239
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
175
240
  }
176
241
 
177
242
  #endif /* MEM_FORCE_MEMORY_ACCESS */
@@ -180,7 +245,8 @@ MEM_STATIC U32 MEM_swap32(U32 in)
180
245
  {
181
246
  #if defined(_MSC_VER) /* Visual Studio */
182
247
  return _byteswap_ulong(in);
183
- #elif defined (__GNUC__)
248
+ #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
249
+ || (defined(__clang__) && __has_builtin(__builtin_bswap32))
184
250
  return __builtin_bswap32(in);
185
251
  #else
186
252
  return ((in << 24) & 0xff000000 ) |
@@ -194,7 +260,8 @@ MEM_STATIC U64 MEM_swap64(U64 in)
194
260
  {
195
261
  #if defined(_MSC_VER) /* Visual Studio */
196
262
  return _byteswap_uint64(in);
197
- #elif defined (__GNUC__)
263
+ #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
264
+ || (defined(__clang__) && __has_builtin(__builtin_bswap64))
198
265
  return __builtin_bswap64(in);
199
266
  #else
200
267
  return ((in << 56) & 0xff00000000000000ULL) |
@@ -348,20 +415,9 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
348
415
  MEM_writeBE64(memPtr, (U64)val);
349
416
  }
350
417
 
418
+ /* code only tested on 32 and 64 bits systems */
419
+ MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
351
420
 
352
- /* function safe only for comparisons */
353
- MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)
354
- {
355
- switch (length)
356
- {
357
- default :
358
- case 4 : return MEM_read32(memPtr);
359
- case 3 : if (MEM_isLittleEndian())
360
- return MEM_read32(memPtr)<<8;
361
- else
362
- return MEM_read32(memPtr)>>8;
363
- }
364
- }
365
421
 
366
422
  #if defined (__cplusplus)
367
423
  }
@@ -0,0 +1,350 @@
1
+ /*
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+
12
+ /* ====== Dependencies ======= */
13
+ #include "zstd_deps.h" /* size_t */
14
+ #include "debug.h" /* assert */
15
+ #include "zstd_internal.h" /* ZSTD_customMalloc, ZSTD_customFree */
16
+ #include "pool.h"
17
+
18
+ /* ====== Compiler specifics ====== */
19
+ #if defined(_MSC_VER)
20
+ # pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
21
+ #endif
22
+
23
+
24
+ #ifdef ZSTD_MULTITHREAD
25
+
26
+ #include "threading.h" /* pthread adaptation */
27
+
28
+ /* A job is a function and an opaque argument */
29
+ typedef struct POOL_job_s {
30
+ POOL_function function;
31
+ void *opaque;
32
+ } POOL_job;
33
+
34
+ struct POOL_ctx_s {
35
+ ZSTD_customMem customMem;
36
+ /* Keep track of the threads */
37
+ ZSTD_pthread_t* threads;
38
+ size_t threadCapacity;
39
+ size_t threadLimit;
40
+
41
+ /* The queue is a circular buffer */
42
+ POOL_job *queue;
43
+ size_t queueHead;
44
+ size_t queueTail;
45
+ size_t queueSize;
46
+
47
+ /* The number of threads working on jobs */
48
+ size_t numThreadsBusy;
49
+ /* Indicates if the queue is empty */
50
+ int queueEmpty;
51
+
52
+ /* The mutex protects the queue */
53
+ ZSTD_pthread_mutex_t queueMutex;
54
+ /* Condition variable for pushers to wait on when the queue is full */
55
+ ZSTD_pthread_cond_t queuePushCond;
56
+ /* Condition variables for poppers to wait on when the queue is empty */
57
+ ZSTD_pthread_cond_t queuePopCond;
58
+ /* Indicates if the queue is shutting down */
59
+ int shutdown;
60
+ };
61
+
62
+ /* POOL_thread() :
63
+ * Work thread for the thread pool.
64
+ * Waits for jobs and executes them.
65
+ * @returns : NULL on failure else non-null.
66
+ */
67
+ static void* POOL_thread(void* opaque) {
68
+ POOL_ctx* const ctx = (POOL_ctx*)opaque;
69
+ if (!ctx) { return NULL; }
70
+ for (;;) {
71
+ /* Lock the mutex and wait for a non-empty queue or until shutdown */
72
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
73
+
74
+ while ( ctx->queueEmpty
75
+ || (ctx->numThreadsBusy >= ctx->threadLimit) ) {
76
+ if (ctx->shutdown) {
77
+ /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
78
+ * a few threads will be shutdown while !queueEmpty,
79
+ * but enough threads will remain active to finish the queue */
80
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
81
+ return opaque;
82
+ }
83
+ ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
84
+ }
85
+ /* Pop a job off the queue */
86
+ { POOL_job const job = ctx->queue[ctx->queueHead];
87
+ ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
88
+ ctx->numThreadsBusy++;
89
+ ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
90
+ /* Unlock the mutex, signal a pusher, and run the job */
91
+ ZSTD_pthread_cond_signal(&ctx->queuePushCond);
92
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
93
+
94
+ job.function(job.opaque);
95
+
96
+ /* If the intended queue size was 0, signal after finishing job */
97
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
98
+ ctx->numThreadsBusy--;
99
+ if (ctx->queueSize == 1) {
100
+ ZSTD_pthread_cond_signal(&ctx->queuePushCond);
101
+ }
102
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
103
+ }
104
+ } /* for (;;) */
105
+ assert(0); /* Unreachable */
106
+ }
107
+
108
+ POOL_ctx* ZSTD_createThreadPool(size_t numThreads) {
109
+ return POOL_create (numThreads, 0);
110
+ }
111
+
112
+ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
113
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
114
+ }
115
+
116
+ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
117
+ ZSTD_customMem customMem) {
118
+ POOL_ctx* ctx;
119
+ /* Check parameters */
120
+ if (!numThreads) { return NULL; }
121
+ /* Allocate the context and zero initialize */
122
+ ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem);
123
+ if (!ctx) { return NULL; }
124
+ /* Initialize the job queue.
125
+ * It needs one extra space since one space is wasted to differentiate
126
+ * empty and full queues.
127
+ */
128
+ ctx->queueSize = queueSize + 1;
129
+ ctx->queue = (POOL_job*)ZSTD_customMalloc(ctx->queueSize * sizeof(POOL_job), customMem);
130
+ ctx->queueHead = 0;
131
+ ctx->queueTail = 0;
132
+ ctx->numThreadsBusy = 0;
133
+ ctx->queueEmpty = 1;
134
+ {
135
+ int error = 0;
136
+ error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
137
+ error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
138
+ error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
139
+ if (error) { POOL_free(ctx); return NULL; }
140
+ }
141
+ ctx->shutdown = 0;
142
+ /* Allocate space for the thread handles */
143
+ ctx->threads = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
144
+ ctx->threadCapacity = 0;
145
+ ctx->customMem = customMem;
146
+ /* Check for errors */
147
+ if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
148
+ /* Initialize the threads */
149
+ { size_t i;
150
+ for (i = 0; i < numThreads; ++i) {
151
+ if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
152
+ ctx->threadCapacity = i;
153
+ POOL_free(ctx);
154
+ return NULL;
155
+ } }
156
+ ctx->threadCapacity = numThreads;
157
+ ctx->threadLimit = numThreads;
158
+ }
159
+ return ctx;
160
+ }
161
+
162
+ /*! POOL_join() :
163
+ Shutdown the queue, wake any sleeping threads, and join all of the threads.
164
+ */
165
+ static void POOL_join(POOL_ctx* ctx) {
166
+ /* Shut down the queue */
167
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
168
+ ctx->shutdown = 1;
169
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
170
+ /* Wake up sleeping threads */
171
+ ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);
172
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
173
+ /* Join all of the threads */
174
+ { size_t i;
175
+ for (i = 0; i < ctx->threadCapacity; ++i) {
176
+ ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */
177
+ } }
178
+ }
179
+
180
+ void POOL_free(POOL_ctx *ctx) {
181
+ if (!ctx) { return; }
182
+ POOL_join(ctx);
183
+ ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
184
+ ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
185
+ ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
186
+ ZSTD_customFree(ctx->queue, ctx->customMem);
187
+ ZSTD_customFree(ctx->threads, ctx->customMem);
188
+ ZSTD_customFree(ctx, ctx->customMem);
189
+ }
190
+
191
+ void ZSTD_freeThreadPool (ZSTD_threadPool* pool) {
192
+ POOL_free (pool);
193
+ }
194
+
195
+ size_t POOL_sizeof(POOL_ctx *ctx) {
196
+ if (ctx==NULL) return 0; /* supports sizeof NULL */
197
+ return sizeof(*ctx)
198
+ + ctx->queueSize * sizeof(POOL_job)
199
+ + ctx->threadCapacity * sizeof(ZSTD_pthread_t);
200
+ }
201
+
202
+
203
+ /* @return : 0 on success, 1 on error */
204
+ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
205
+ {
206
+ if (numThreads <= ctx->threadCapacity) {
207
+ if (!numThreads) return 1;
208
+ ctx->threadLimit = numThreads;
209
+ return 0;
210
+ }
211
+ /* numThreads > threadCapacity */
212
+ { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
213
+ if (!threadPool) return 1;
214
+ /* replace existing thread pool */
215
+ ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
216
+ ZSTD_customFree(ctx->threads, ctx->customMem);
217
+ ctx->threads = threadPool;
218
+ /* Initialize additional threads */
219
+ { size_t threadId;
220
+ for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
221
+ if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
222
+ ctx->threadCapacity = threadId;
223
+ return 1;
224
+ } }
225
+ } }
226
+ /* successfully expanded */
227
+ ctx->threadCapacity = numThreads;
228
+ ctx->threadLimit = numThreads;
229
+ return 0;
230
+ }
231
+
232
+ /* @return : 0 on success, 1 on error */
233
+ int POOL_resize(POOL_ctx* ctx, size_t numThreads)
234
+ {
235
+ int result;
236
+ if (ctx==NULL) return 1;
237
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
238
+ result = POOL_resize_internal(ctx, numThreads);
239
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
240
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
241
+ return result;
242
+ }
243
+
244
+ /**
245
+ * Returns 1 if the queue is full and 0 otherwise.
246
+ *
247
+ * When queueSize is 1 (pool was created with an intended queueSize of 0),
248
+ * then a queue is empty if there is a thread free _and_ no job is waiting.
249
+ */
250
+ static int isQueueFull(POOL_ctx const* ctx) {
251
+ if (ctx->queueSize > 1) {
252
+ return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
253
+ } else {
254
+ return (ctx->numThreadsBusy == ctx->threadLimit) ||
255
+ !ctx->queueEmpty;
256
+ }
257
+ }
258
+
259
+
260
+ static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
261
+ {
262
+ POOL_job const job = {function, opaque};
263
+ assert(ctx != NULL);
264
+ if (ctx->shutdown) return;
265
+
266
+ ctx->queueEmpty = 0;
267
+ ctx->queue[ctx->queueTail] = job;
268
+ ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
269
+ ZSTD_pthread_cond_signal(&ctx->queuePopCond);
270
+ }
271
+
272
+ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
273
+ {
274
+ assert(ctx != NULL);
275
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
276
+ /* Wait until there is space in the queue for the new job */
277
+ while (isQueueFull(ctx) && (!ctx->shutdown)) {
278
+ ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
279
+ }
280
+ POOL_add_internal(ctx, function, opaque);
281
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
282
+ }
283
+
284
+
285
+ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
286
+ {
287
+ assert(ctx != NULL);
288
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
289
+ if (isQueueFull(ctx)) {
290
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
291
+ return 0;
292
+ }
293
+ POOL_add_internal(ctx, function, opaque);
294
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
295
+ return 1;
296
+ }
297
+
298
+
299
+ #else /* ZSTD_MULTITHREAD not defined */
300
+
301
+ /* ========================== */
302
+ /* No multi-threading support */
303
+ /* ========================== */
304
+
305
+
306
+ /* We don't need any data, but if it is empty, malloc() might return NULL. */
307
+ struct POOL_ctx_s {
308
+ int dummy;
309
+ };
310
+ static POOL_ctx g_poolCtx;
311
+
312
+ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
313
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
314
+ }
315
+
316
+ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
317
+ (void)numThreads;
318
+ (void)queueSize;
319
+ (void)customMem;
320
+ return &g_poolCtx;
321
+ }
322
+
323
+ void POOL_free(POOL_ctx* ctx) {
324
+ assert(!ctx || ctx == &g_poolCtx);
325
+ (void)ctx;
326
+ }
327
+
328
+ int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
329
+ (void)ctx; (void)numThreads;
330
+ return 0;
331
+ }
332
+
333
+ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
334
+ (void)ctx;
335
+ function(opaque);
336
+ }
337
+
338
+ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
339
+ (void)ctx;
340
+ function(opaque);
341
+ return 1;
342
+ }
343
+
344
+ size_t POOL_sizeof(POOL_ctx* ctx) {
345
+ if (ctx==NULL) return 0; /* supports sizeof NULL */
346
+ assert(ctx == &g_poolCtx);
347
+ return sizeof(*ctx);
348
+ }
349
+
350
+ #endif /* ZSTD_MULTITHREAD */