extzstd 0.0.3.CONCEPT → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +39 -0
  3. data/LICENSE +6 -6
  4. data/README.md +26 -45
  5. data/contrib/zstd/CHANGELOG +555 -0
  6. data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
  7. data/contrib/zstd/CONTRIBUTING.md +392 -0
  8. data/contrib/zstd/COPYING +339 -0
  9. data/contrib/zstd/LICENSE +13 -9
  10. data/contrib/zstd/Makefile +414 -0
  11. data/contrib/zstd/README.md +170 -45
  12. data/contrib/zstd/TESTING.md +44 -0
  13. data/contrib/zstd/appveyor.yml +289 -0
  14. data/contrib/zstd/lib/BUCK +234 -0
  15. data/contrib/zstd/lib/Makefile +354 -0
  16. data/contrib/zstd/lib/README.md +179 -0
  17. data/contrib/zstd/{common → lib/common}/bitstream.h +170 -130
  18. data/contrib/zstd/lib/common/compiler.h +175 -0
  19. data/contrib/zstd/lib/common/cpu.h +215 -0
  20. data/contrib/zstd/lib/common/debug.c +24 -0
  21. data/contrib/zstd/lib/common/debug.h +114 -0
  22. data/contrib/zstd/{common → lib/common}/entropy_common.c +79 -94
  23. data/contrib/zstd/lib/common/error_private.c +55 -0
  24. data/contrib/zstd/lib/common/error_private.h +80 -0
  25. data/contrib/zstd/{common → lib/common}/fse.h +153 -93
  26. data/contrib/zstd/{common → lib/common}/fse_decompress.c +37 -82
  27. data/contrib/zstd/lib/common/huf.h +340 -0
  28. data/contrib/zstd/{common → lib/common}/mem.h +154 -78
  29. data/contrib/zstd/lib/common/pool.c +344 -0
  30. data/contrib/zstd/lib/common/pool.h +84 -0
  31. data/contrib/zstd/lib/common/threading.c +121 -0
  32. data/contrib/zstd/lib/common/threading.h +155 -0
  33. data/contrib/zstd/{common → lib/common}/xxhash.c +85 -75
  34. data/contrib/zstd/{common → lib/common}/xxhash.h +85 -73
  35. data/contrib/zstd/lib/common/zstd_common.c +83 -0
  36. data/contrib/zstd/lib/common/zstd_errors.h +94 -0
  37. data/contrib/zstd/lib/common/zstd_internal.h +447 -0
  38. data/contrib/zstd/{compress → lib/compress}/fse_compress.c +194 -303
  39. data/contrib/zstd/lib/compress/hist.c +183 -0
  40. data/contrib/zstd/lib/compress/hist.h +75 -0
  41. data/contrib/zstd/lib/compress/huf_compress.c +798 -0
  42. data/contrib/zstd/lib/compress/zstd_compress.c +4278 -0
  43. data/contrib/zstd/lib/compress/zstd_compress_internal.h +1125 -0
  44. data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
  45. data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
  46. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +419 -0
  47. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
  48. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +845 -0
  49. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  50. data/contrib/zstd/lib/compress/zstd_cwksp.h +525 -0
  51. data/contrib/zstd/lib/compress/zstd_double_fast.c +521 -0
  52. data/contrib/zstd/lib/compress/zstd_double_fast.h +38 -0
  53. data/contrib/zstd/lib/compress/zstd_fast.c +496 -0
  54. data/contrib/zstd/lib/compress/zstd_fast.h +37 -0
  55. data/contrib/zstd/lib/compress/zstd_lazy.c +1138 -0
  56. data/contrib/zstd/lib/compress/zstd_lazy.h +67 -0
  57. data/contrib/zstd/lib/compress/zstd_ldm.c +619 -0
  58. data/contrib/zstd/lib/compress/zstd_ldm.h +110 -0
  59. data/contrib/zstd/lib/compress/zstd_opt.c +1200 -0
  60. data/contrib/zstd/lib/compress/zstd_opt.h +56 -0
  61. data/contrib/zstd/lib/compress/zstdmt_compress.c +2143 -0
  62. data/contrib/zstd/lib/compress/zstdmt_compress.h +192 -0
  63. data/contrib/zstd/lib/decompress/huf_decompress.c +1248 -0
  64. data/contrib/zstd/lib/decompress/zstd_ddict.c +244 -0
  65. data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
  66. data/contrib/zstd/lib/decompress/zstd_decompress.c +1885 -0
  67. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1432 -0
  68. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
  69. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +189 -0
  70. data/contrib/zstd/{common → lib/deprecated}/zbuff.h +86 -69
  71. data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
  72. data/contrib/zstd/lib/deprecated/zbuff_compress.c +147 -0
  73. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +75 -0
  74. data/contrib/zstd/lib/dictBuilder/cover.c +1236 -0
  75. data/contrib/zstd/lib/dictBuilder/cover.h +157 -0
  76. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +3 -3
  77. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +5 -5
  78. data/contrib/zstd/lib/dictBuilder/fastcover.c +757 -0
  79. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +437 -347
  80. data/contrib/zstd/lib/dictBuilder/zdict.h +305 -0
  81. data/contrib/zstd/lib/legacy/zstd_legacy.h +415 -0
  82. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +272 -292
  83. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +26 -32
  84. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +162 -392
  85. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +26 -32
  86. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +162 -391
  87. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +27 -33
  88. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +195 -604
  89. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +26 -32
  90. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +300 -575
  91. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +22 -31
  92. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +165 -592
  93. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +54 -67
  94. data/contrib/zstd/lib/legacy/zstd_v07.c +4541 -0
  95. data/contrib/zstd/lib/legacy/zstd_v07.h +187 -0
  96. data/contrib/zstd/lib/libzstd.pc.in +15 -0
  97. data/contrib/zstd/lib/zstd.h +2090 -0
  98. data/ext/depend +2 -0
  99. data/ext/extconf.rb +18 -5
  100. data/ext/extzstd.c +296 -214
  101. data/ext/extzstd.h +81 -36
  102. data/ext/extzstd_nogvls.h +0 -117
  103. data/ext/extzstd_stream.c +622 -0
  104. data/ext/libzstd_conf.h +8 -0
  105. data/ext/zstd_common.c +11 -0
  106. data/ext/zstd_compress.c +15 -0
  107. data/ext/zstd_decompress.c +6 -0
  108. data/ext/zstd_dictbuilder.c +10 -0
  109. data/ext/zstd_dictbuilder_fastcover.c +3 -0
  110. data/ext/zstd_legacy_v01.c +3 -1
  111. data/ext/zstd_legacy_v02.c +3 -1
  112. data/ext/zstd_legacy_v03.c +3 -1
  113. data/ext/zstd_legacy_v04.c +3 -1
  114. data/ext/zstd_legacy_v05.c +3 -1
  115. data/ext/zstd_legacy_v06.c +3 -1
  116. data/ext/zstd_legacy_v07.c +3 -0
  117. data/gemstub.rb +27 -21
  118. data/lib/extzstd.rb +82 -161
  119. data/lib/extzstd/version.rb +1 -1
  120. data/test/test_basic.rb +19 -6
  121. metadata +127 -59
  122. data/contrib/zstd/common/error_private.h +0 -125
  123. data/contrib/zstd/common/error_public.h +0 -77
  124. data/contrib/zstd/common/huf.h +0 -228
  125. data/contrib/zstd/common/zstd.h +0 -475
  126. data/contrib/zstd/common/zstd_common.c +0 -91
  127. data/contrib/zstd/common/zstd_internal.h +0 -238
  128. data/contrib/zstd/compress/huf_compress.c +0 -577
  129. data/contrib/zstd/compress/zbuff_compress.c +0 -327
  130. data/contrib/zstd/compress/zstd_compress.c +0 -3074
  131. data/contrib/zstd/compress/zstd_opt.h +0 -1046
  132. data/contrib/zstd/decompress/huf_decompress.c +0 -894
  133. data/contrib/zstd/decompress/zbuff_decompress.c +0 -294
  134. data/contrib/zstd/decompress/zstd_decompress.c +0 -1362
  135. data/contrib/zstd/dictBuilder/zdict.h +0 -113
  136. data/contrib/zstd/legacy/zstd_legacy.h +0 -140
  137. data/ext/extzstd_buffered.c +0 -265
  138. data/ext/zstd_amalgam.c +0 -18
@@ -1,37 +1,13 @@
1
- /* ******************************************************************
2
- mem.h
3
- low-level memory access routines
4
- Copyright (C) 2013-2015, Yann Collet.
5
-
6
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
-
8
- Redistribution and use in source and binary forms, with or without
9
- modification, are permitted provided that the following conditions are
10
- met:
11
-
12
- * Redistributions of source code must retain the above copyright
13
- notice, this list of conditions and the following disclaimer.
14
- * Redistributions in binary form must reproduce the above
15
- copyright notice, this list of conditions and the following disclaimer
16
- in the documentation and/or other materials provided with the
17
- distribution.
18
-
19
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
-
31
- You can contact the author at :
32
- - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
33
- - Public forum : https://groups.google.com/forum/#!forum/lz4c
34
- ****************************************************************** */
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
+
35
11
  #ifndef MEM_H_MODULE
36
12
  #define MEM_H_MODULE
37
13
 
@@ -44,19 +20,17 @@ extern "C" {
44
20
  ******************************************/
45
21
  #include <stddef.h> /* size_t, ptrdiff_t */
46
22
  #include <string.h> /* memcpy */
47
- #if defined(_MSC_VER) /* Visual Studio */
48
- # include <stdlib.h> /* _byteswap_ulong */
49
- #endif
50
23
 
51
24
 
52
25
  /*-****************************************
53
26
  * Compiler specifics
54
27
  ******************************************/
55
- #if defined(_MSC_VER)
56
- # include <intrin.h> /* _byteswap_ */
28
+ #if defined(_MSC_VER) /* Visual Studio */
29
+ # include <stdlib.h> /* _byteswap_ulong */
30
+ # include <intrin.h> /* _byteswap_* */
57
31
  #endif
58
32
  #if defined(__GNUC__)
59
- # define MEM_STATIC static __attribute__((unused))
33
+ # define MEM_STATIC static __inline __attribute__((unused))
60
34
  #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
61
35
  # define MEM_STATIC static inline
62
36
  #elif defined(_MSC_VER)
@@ -65,25 +39,118 @@ extern "C" {
65
39
  # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
66
40
  #endif
67
41
 
42
+ #ifndef __has_builtin
43
+ # define __has_builtin(x) 0 /* compat. with non-clang compilers */
44
+ #endif
45
+
46
+ /* code only tested on 32 and 64 bits systems */
47
+ #define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; }
48
+ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
49
+
50
+ /* detects whether we are being compiled under msan */
51
+ #if defined (__has_feature)
52
+ # if __has_feature(memory_sanitizer)
53
+ # define MEMORY_SANITIZER 1
54
+ # endif
55
+ #endif
56
+
57
+ #if defined (MEMORY_SANITIZER)
58
+ /* Not all platforms that support msan provide sanitizers/msan_interface.h.
59
+ * We therefore declare the functions we need ourselves, rather than trying to
60
+ * include the header file... */
61
+
62
+ #include <stdint.h> /* intptr_t */
63
+
64
+ /* Make memory region fully initialized (without changing its contents). */
65
+ void __msan_unpoison(const volatile void *a, size_t size);
66
+
67
+ /* Make memory region fully uninitialized (without changing its contents).
68
+ This is a legacy interface that does not update origin information. Use
69
+ __msan_allocated_memory() instead. */
70
+ void __msan_poison(const volatile void *a, size_t size);
71
+
72
+ /* Returns the offset of the first (at least partially) poisoned byte in the
73
+ memory range, or -1 if the whole range is good. */
74
+ intptr_t __msan_test_shadow(const volatile void *x, size_t size);
75
+ #endif
76
+
77
+ /* detects whether we are being compiled under asan */
78
+ #if defined (__has_feature)
79
+ # if __has_feature(address_sanitizer)
80
+ # define ADDRESS_SANITIZER 1
81
+ # endif
82
+ #elif defined(__SANITIZE_ADDRESS__)
83
+ # define ADDRESS_SANITIZER 1
84
+ #endif
85
+
86
+ #if defined (ADDRESS_SANITIZER)
87
+ /* Not all platforms that support asan provide sanitizers/asan_interface.h.
88
+ * We therefore declare the functions we need ourselves, rather than trying to
89
+ * include the header file... */
90
+
91
+ /**
92
+ * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.
93
+ *
94
+ * This memory must be previously allocated by your program. Instrumented
95
+ * code is forbidden from accessing addresses in this region until it is
96
+ * unpoisoned. This function is not guaranteed to poison the entire region -
97
+ * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan
98
+ * alignment restrictions.
99
+ *
100
+ * \note This function is not thread-safe because no two threads can poison or
101
+ * unpoison memory in the same memory region simultaneously.
102
+ *
103
+ * \param addr Start of memory region.
104
+ * \param size Size of memory region. */
105
+ void __asan_poison_memory_region(void const volatile *addr, size_t size);
106
+
107
+ /**
108
+ * Marks a memory region (<c>[addr, addr+size)</c>) as addressable.
109
+ *
110
+ * This memory must be previously allocated by your program. Accessing
111
+ * addresses in this region is allowed until this region is poisoned again.
112
+ * This function could unpoison a super-region of <c>[addr, addr+size)</c> due
113
+ * to ASan alignment restrictions.
114
+ *
115
+ * \note This function is not thread-safe because no two threads can
116
+ * poison or unpoison memory in the same memory region simultaneously.
117
+ *
118
+ * \param addr Start of memory region.
119
+ * \param size Size of memory region. */
120
+ void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
121
+ #endif
122
+
68
123
 
69
124
  /*-**************************************************************
70
125
  * Basic Types
71
126
  *****************************************************************/
72
127
  #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
73
128
  # include <stdint.h>
74
- typedef uint8_t BYTE;
75
- typedef uint16_t U16;
76
- typedef int16_t S16;
77
- typedef uint32_t U32;
78
- typedef int32_t S32;
79
- typedef uint64_t U64;
80
- typedef int64_t S64;
129
+ typedef uint8_t BYTE;
130
+ typedef uint16_t U16;
131
+ typedef int16_t S16;
132
+ typedef uint32_t U32;
133
+ typedef int32_t S32;
134
+ typedef uint64_t U64;
135
+ typedef int64_t S64;
81
136
  #else
82
- typedef unsigned char BYTE;
137
+ # include <limits.h>
138
+ #if CHAR_BIT != 8
139
+ # error "this implementation requires char to be exactly 8-bit type"
140
+ #endif
141
+ typedef unsigned char BYTE;
142
+ #if USHRT_MAX != 65535
143
+ # error "this implementation requires short to be exactly 16-bit type"
144
+ #endif
83
145
  typedef unsigned short U16;
84
146
  typedef signed short S16;
147
+ #if UINT_MAX != 4294967295
148
+ # error "this implementation requires int to be exactly 32-bit type"
149
+ #endif
85
150
  typedef unsigned int U32;
86
151
  typedef signed int S32;
152
+ /* note : there are no limits defined for long long type in C90.
153
+ * limits exist in C99, however, in such case, <stdint.h> is preferred */
87
154
  typedef unsigned long long U64;
88
155
  typedef signed long long S64;
89
156
  #endif
@@ -97,19 +164,18 @@ extern "C" {
97
164
  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
98
165
  * The below switch allow to select different access method for improved performance.
99
166
  * Method 0 (default) : use `memcpy()`. Safe and portable.
100
- * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
167
+ * Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable).
101
168
  * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
102
169
  * Method 2 : direct access. This method is portable but violate C standard.
103
170
  * It can generate buggy code on targets depending on alignment.
104
- * In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
171
+ * In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6)
105
172
  * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
106
173
  * Prefer these methods in priority order (0 > 1 > 2)
107
174
  */
108
175
  #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
109
176
  # 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__) )
110
177
  # define MEM_FORCE_MEMORY_ACCESS 2
111
- # elif defined(__INTEL_COMPILER) || \
112
- (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
178
+ # elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
113
179
  # define MEM_FORCE_MEMORY_ACCESS 1
114
180
  # endif
115
181
  #endif
@@ -130,7 +196,7 @@ Only use if no other choice to achieve best performance on target platform */
130
196
  MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
131
197
  MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
132
198
  MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
133
- MEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
199
+ MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
134
200
 
135
201
  MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
136
202
  MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
@@ -140,16 +206,28 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
140
206
 
141
207
  /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
142
208
  /* currently only defined for gcc and icc */
143
- typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
209
+ #if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
210
+ __pragma( pack(push, 1) )
211
+ typedef struct { U16 v; } unalign16;
212
+ typedef struct { U32 v; } unalign32;
213
+ typedef struct { U64 v; } unalign64;
214
+ typedef struct { size_t v; } unalignArch;
215
+ __pragma( pack(pop) )
216
+ #else
217
+ typedef struct { U16 v; } __attribute__((packed)) unalign16;
218
+ typedef struct { U32 v; } __attribute__((packed)) unalign32;
219
+ typedef struct { U64 v; } __attribute__((packed)) unalign64;
220
+ typedef struct { size_t v; } __attribute__((packed)) unalignArch;
221
+ #endif
144
222
 
145
- MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
146
- MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
147
- MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
148
- MEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
223
+ MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; }
224
+ MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; }
225
+ MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; }
226
+ MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; }
149
227
 
150
- MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
151
- MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
152
- MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
228
+ MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; }
229
+ MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; }
230
+ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; }
153
231
 
154
232
  #else
155
233
 
@@ -197,7 +275,8 @@ MEM_STATIC U32 MEM_swap32(U32 in)
197
275
  {
198
276
  #if defined(_MSC_VER) /* Visual Studio */
199
277
  return _byteswap_ulong(in);
200
- #elif defined (__GNUC__)
278
+ #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
279
+ || (defined(__clang__) && __has_builtin(__builtin_bswap32))
201
280
  return __builtin_bswap32(in);
202
281
  #else
203
282
  return ((in << 24) & 0xff000000 ) |
@@ -211,7 +290,8 @@ MEM_STATIC U64 MEM_swap64(U64 in)
211
290
  {
212
291
  #if defined(_MSC_VER) /* Visual Studio */
213
292
  return _byteswap_uint64(in);
214
- #elif defined (__GNUC__)
293
+ #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
294
+ || (defined(__clang__) && __has_builtin(__builtin_bswap64))
215
295
  return __builtin_bswap64(in);
216
296
  #else
217
297
  return ((in << 56) & 0xff00000000000000ULL) |
@@ -256,6 +336,17 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
256
336
  }
257
337
  }
258
338
 
339
+ MEM_STATIC U32 MEM_readLE24(const void* memPtr)
340
+ {
341
+ return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
342
+ }
343
+
344
+ MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
345
+ {
346
+ MEM_writeLE16(memPtr, (U16)val);
347
+ ((BYTE*)memPtr)[2] = (BYTE)(val>>16);
348
+ }
349
+
259
350
  MEM_STATIC U32 MEM_readLE32(const void* memPtr)
260
351
  {
261
352
  if (MEM_isLittleEndian())
@@ -355,23 +446,8 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
355
446
  }
356
447
 
357
448
 
358
- /* function safe only for comparisons */
359
- MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)
360
- {
361
- switch (length)
362
- {
363
- default :
364
- case 4 : return MEM_read32(memPtr);
365
- case 3 : if (MEM_isLittleEndian())
366
- return MEM_read32(memPtr)<<8;
367
- else
368
- return MEM_read32(memPtr)>>8;
369
- }
370
- }
371
-
372
449
  #if defined (__cplusplus)
373
450
  }
374
451
  #endif
375
452
 
376
453
  #endif /* MEM_H_MODULE */
377
-
@@ -0,0 +1,344 @@
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 <stddef.h> /* size_t */
14
+ #include "debug.h" /* assert */
15
+ #include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */
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* POOL_create(size_t numThreads, size_t queueSize) {
109
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
110
+ }
111
+
112
+ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
113
+ ZSTD_customMem customMem) {
114
+ POOL_ctx* ctx;
115
+ /* Check parameters */
116
+ if (!numThreads) { return NULL; }
117
+ /* Allocate the context and zero initialize */
118
+ ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
119
+ if (!ctx) { return NULL; }
120
+ /* Initialize the job queue.
121
+ * It needs one extra space since one space is wasted to differentiate
122
+ * empty and full queues.
123
+ */
124
+ ctx->queueSize = queueSize + 1;
125
+ ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem);
126
+ ctx->queueHead = 0;
127
+ ctx->queueTail = 0;
128
+ ctx->numThreadsBusy = 0;
129
+ ctx->queueEmpty = 1;
130
+ {
131
+ int error = 0;
132
+ error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
133
+ error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
134
+ error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
135
+ if (error) { POOL_free(ctx); return NULL; }
136
+ }
137
+ ctx->shutdown = 0;
138
+ /* Allocate space for the thread handles */
139
+ ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
140
+ ctx->threadCapacity = 0;
141
+ ctx->customMem = customMem;
142
+ /* Check for errors */
143
+ if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
144
+ /* Initialize the threads */
145
+ { size_t i;
146
+ for (i = 0; i < numThreads; ++i) {
147
+ if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
148
+ ctx->threadCapacity = i;
149
+ POOL_free(ctx);
150
+ return NULL;
151
+ } }
152
+ ctx->threadCapacity = numThreads;
153
+ ctx->threadLimit = numThreads;
154
+ }
155
+ return ctx;
156
+ }
157
+
158
+ /*! POOL_join() :
159
+ Shutdown the queue, wake any sleeping threads, and join all of the threads.
160
+ */
161
+ static void POOL_join(POOL_ctx* ctx) {
162
+ /* Shut down the queue */
163
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
164
+ ctx->shutdown = 1;
165
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
166
+ /* Wake up sleeping threads */
167
+ ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);
168
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
169
+ /* Join all of the threads */
170
+ { size_t i;
171
+ for (i = 0; i < ctx->threadCapacity; ++i) {
172
+ ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */
173
+ } }
174
+ }
175
+
176
+ void POOL_free(POOL_ctx *ctx) {
177
+ if (!ctx) { return; }
178
+ POOL_join(ctx);
179
+ ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
180
+ ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
181
+ ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
182
+ ZSTD_free(ctx->queue, ctx->customMem);
183
+ ZSTD_free(ctx->threads, ctx->customMem);
184
+ ZSTD_free(ctx, ctx->customMem);
185
+ }
186
+
187
+
188
+
189
+ size_t POOL_sizeof(POOL_ctx *ctx) {
190
+ if (ctx==NULL) return 0; /* supports sizeof NULL */
191
+ return sizeof(*ctx)
192
+ + ctx->queueSize * sizeof(POOL_job)
193
+ + ctx->threadCapacity * sizeof(ZSTD_pthread_t);
194
+ }
195
+
196
+
197
+ /* @return : 0 on success, 1 on error */
198
+ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
199
+ {
200
+ if (numThreads <= ctx->threadCapacity) {
201
+ if (!numThreads) return 1;
202
+ ctx->threadLimit = numThreads;
203
+ return 0;
204
+ }
205
+ /* numThreads > threadCapacity */
206
+ { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
207
+ if (!threadPool) return 1;
208
+ /* replace existing thread pool */
209
+ memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
210
+ ZSTD_free(ctx->threads, ctx->customMem);
211
+ ctx->threads = threadPool;
212
+ /* Initialize additional threads */
213
+ { size_t threadId;
214
+ for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
215
+ if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
216
+ ctx->threadCapacity = threadId;
217
+ return 1;
218
+ } }
219
+ } }
220
+ /* successfully expanded */
221
+ ctx->threadCapacity = numThreads;
222
+ ctx->threadLimit = numThreads;
223
+ return 0;
224
+ }
225
+
226
+ /* @return : 0 on success, 1 on error */
227
+ int POOL_resize(POOL_ctx* ctx, size_t numThreads)
228
+ {
229
+ int result;
230
+ if (ctx==NULL) return 1;
231
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
232
+ result = POOL_resize_internal(ctx, numThreads);
233
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
234
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
235
+ return result;
236
+ }
237
+
238
+ /**
239
+ * Returns 1 if the queue is full and 0 otherwise.
240
+ *
241
+ * When queueSize is 1 (pool was created with an intended queueSize of 0),
242
+ * then a queue is empty if there is a thread free _and_ no job is waiting.
243
+ */
244
+ static int isQueueFull(POOL_ctx const* ctx) {
245
+ if (ctx->queueSize > 1) {
246
+ return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
247
+ } else {
248
+ return (ctx->numThreadsBusy == ctx->threadLimit) ||
249
+ !ctx->queueEmpty;
250
+ }
251
+ }
252
+
253
+
254
+ static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
255
+ {
256
+ POOL_job const job = {function, opaque};
257
+ assert(ctx != NULL);
258
+ if (ctx->shutdown) return;
259
+
260
+ ctx->queueEmpty = 0;
261
+ ctx->queue[ctx->queueTail] = job;
262
+ ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
263
+ ZSTD_pthread_cond_signal(&ctx->queuePopCond);
264
+ }
265
+
266
+ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
267
+ {
268
+ assert(ctx != NULL);
269
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
270
+ /* Wait until there is space in the queue for the new job */
271
+ while (isQueueFull(ctx) && (!ctx->shutdown)) {
272
+ ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
273
+ }
274
+ POOL_add_internal(ctx, function, opaque);
275
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
276
+ }
277
+
278
+
279
+ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
280
+ {
281
+ assert(ctx != NULL);
282
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
283
+ if (isQueueFull(ctx)) {
284
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
285
+ return 0;
286
+ }
287
+ POOL_add_internal(ctx, function, opaque);
288
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
289
+ return 1;
290
+ }
291
+
292
+
293
+ #else /* ZSTD_MULTITHREAD not defined */
294
+
295
+ /* ========================== */
296
+ /* No multi-threading support */
297
+ /* ========================== */
298
+
299
+
300
+ /* We don't need any data, but if it is empty, malloc() might return NULL. */
301
+ struct POOL_ctx_s {
302
+ int dummy;
303
+ };
304
+ static POOL_ctx g_ctx;
305
+
306
+ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
307
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
308
+ }
309
+
310
+ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
311
+ (void)numThreads;
312
+ (void)queueSize;
313
+ (void)customMem;
314
+ return &g_ctx;
315
+ }
316
+
317
+ void POOL_free(POOL_ctx* ctx) {
318
+ assert(!ctx || ctx == &g_ctx);
319
+ (void)ctx;
320
+ }
321
+
322
+ int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
323
+ (void)ctx; (void)numThreads;
324
+ return 0;
325
+ }
326
+
327
+ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
328
+ (void)ctx;
329
+ function(opaque);
330
+ }
331
+
332
+ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
333
+ (void)ctx;
334
+ function(opaque);
335
+ return 1;
336
+ }
337
+
338
+ size_t POOL_sizeof(POOL_ctx* ctx) {
339
+ if (ctx==NULL) return 0; /* supports sizeof NULL */
340
+ assert(ctx == &g_ctx);
341
+ return sizeof(*ctx);
342
+ }
343
+
344
+ #endif /* ZSTD_MULTITHREAD */