extzstd 0.0.3.CONCEPT → 0.3.1

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 (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 */