extzstd 0.1 → 0.3.2

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