@shd101wyy/yo 0.1.23 → 0.1.25
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.
- package/.github/skills/yo-async-effects/async-effects-recipes.md +74 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +115 -0
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +626 -6
- package/out/cjs/index.cjs +563 -564
- package/out/cjs/yo-cli.cjs +722 -715
- package/out/cjs/yo-lsp.cjs +601 -602
- package/out/esm/index.mjs +506 -507
- package/out/types/src/codegen/utils/index.d.ts +1 -0
- package/out/types/src/expr.d.ts +1 -0
- package/out/types/src/parser.d.ts +1 -0
- package/out/types/src/test-runner.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/build.yo +2 -2
- package/std/collections/array_list.yo +26 -0
- package/std/imm/map.yo +15 -15
- package/std/imm/sorted_map.yo +14 -14
- package/std/imm/string.yo +4 -4
- package/std/prelude.yo +18 -23
- package/std/process/command.yo +8 -8
- package/std/string/string.yo +76 -55
- package/std/string/unicode.yo +6 -6
- package/std/sys/signal.yo +6 -6
- package/vendor/mimalloc/.github/workflows/release.yaml +55 -0
- package/vendor/mimalloc/.github/workflows/stale.yaml +27 -0
- package/vendor/mimalloc/.github/workflows/test.yaml +163 -0
- package/vendor/mimalloc/CMakeLists.txt +52 -33
- package/vendor/mimalloc/azure-pipelines.yml +4 -3
- package/vendor/mimalloc/bin/bundle.bat +74 -0
- package/vendor/mimalloc/bin/bundle.sh +232 -0
- package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +2 -2
- package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +2 -2
- package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +4 -3
- package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +1 -1
- package/vendor/mimalloc/doc/mimalloc-doc.h +42 -4
- package/vendor/mimalloc/doc/release-notes.md +15 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +3 -3
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj +511 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj.filters +117 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-dep.vcxproj +360 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-override-static.vcxproj +310 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc.sln +92 -35
- package/vendor/mimalloc/include/mimalloc/atomic.h +178 -182
- package/vendor/mimalloc/include/mimalloc/bits.h +8 -10
- package/vendor/mimalloc/include/mimalloc/internal.h +76 -32
- package/vendor/mimalloc/include/mimalloc/prim.h +25 -18
- package/vendor/mimalloc/include/mimalloc/track.h +7 -2
- package/vendor/mimalloc/include/mimalloc/types.h +57 -29
- package/vendor/mimalloc/include/mimalloc-override.h +10 -10
- package/vendor/mimalloc/include/mimalloc-stats.h +18 -6
- package/vendor/mimalloc/include/mimalloc.h +22 -12
- package/vendor/mimalloc/readme.md +42 -17
- package/vendor/mimalloc/src/alloc-aligned.c +13 -11
- package/vendor/mimalloc/src/alloc-override.c +97 -17
- package/vendor/mimalloc/src/alloc-posix.c +44 -27
- package/vendor/mimalloc/src/alloc.c +73 -23
- package/vendor/mimalloc/src/arena-meta.c +3 -3
- package/vendor/mimalloc/src/arena.c +380 -192
- package/vendor/mimalloc/src/bitmap.c +68 -18
- package/vendor/mimalloc/src/bitmap.h +8 -4
- package/vendor/mimalloc/src/free.c +83 -47
- package/vendor/mimalloc/src/heap.c +94 -40
- package/vendor/mimalloc/src/init.c +273 -102
- package/vendor/mimalloc/src/libc.c +53 -8
- package/vendor/mimalloc/src/options.c +43 -40
- package/vendor/mimalloc/src/os.c +110 -45
- package/vendor/mimalloc/src/page-map.c +14 -8
- package/vendor/mimalloc/src/page-queue.c +9 -6
- package/vendor/mimalloc/src/page.c +26 -16
- package/vendor/mimalloc/src/prim/emscripten/prim.c +10 -1
- package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +35 -16
- package/vendor/mimalloc/src/prim/unix/prim.c +26 -22
- package/vendor/mimalloc/src/prim/wasi/prim.c +7 -4
- package/vendor/mimalloc/src/prim/windows/prim.c +247 -44
- package/vendor/mimalloc/src/random.c +8 -3
- package/vendor/mimalloc/src/stats.c +59 -48
- package/vendor/mimalloc/src/theap.c +85 -44
- package/vendor/mimalloc/src/threadlocal.c +102 -41
- package/vendor/mimalloc/test/main-override-static.c +31 -2
- package/vendor/mimalloc/test/main-override.c +27 -14
- package/vendor/mimalloc/test/main-static-dep.cpp +46 -0
- package/vendor/mimalloc/test/main-static-dep.h +11 -0
- package/vendor/mimalloc/test/test-api-fill.c +2 -2
- package/vendor/mimalloc/test/test-stress.c +3 -3
- package/vendor/mimalloc/test/test-wrong.c +11 -7
|
@@ -97,7 +97,6 @@ terms of the MIT license. A copy of the license can be found in the file
|
|
|
97
97
|
#define mi_atomic_increment_acq_rel(p) mi_atomic_add_acq_rel(p,(uintptr_t)1)
|
|
98
98
|
#define mi_atomic_decrement_acq_rel(p) mi_atomic_sub_acq_rel(p,(uintptr_t)1)
|
|
99
99
|
|
|
100
|
-
static inline void mi_atomic_yield(void);
|
|
101
100
|
static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add);
|
|
102
101
|
static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub);
|
|
103
102
|
|
|
@@ -159,14 +158,18 @@ static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) {
|
|
|
159
158
|
|
|
160
159
|
#elif defined(_MSC_VER)
|
|
161
160
|
|
|
162
|
-
//
|
|
161
|
+
// Deprecated: MSVC plain C compilation wrapper that uses Interlocked operations to model C11 atomics.
|
|
162
|
+
// It is recommended to always compile as C++ when using MSVC.
|
|
163
|
+
|
|
163
164
|
#include <intrin.h>
|
|
164
165
|
#ifdef _WIN64
|
|
165
|
-
typedef LONG64
|
|
166
|
-
#define
|
|
166
|
+
typedef LONG64 msc_intptr_t;
|
|
167
|
+
#define MI_MSC_64(f) f##64
|
|
168
|
+
#define MI_MSC_XX(f) f##64
|
|
167
169
|
#else
|
|
168
|
-
typedef LONG
|
|
169
|
-
#define
|
|
170
|
+
typedef LONG msc_intptr_t;
|
|
171
|
+
#define MI_MSC_64(f) f
|
|
172
|
+
#define MI_MSC_XX(f) f##32
|
|
170
173
|
#endif
|
|
171
174
|
|
|
172
175
|
typedef enum mi_memory_order_e {
|
|
@@ -180,23 +183,23 @@ typedef enum mi_memory_order_e {
|
|
|
180
183
|
|
|
181
184
|
static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) {
|
|
182
185
|
(void)(mo);
|
|
183
|
-
return (uintptr_t)
|
|
186
|
+
return (uintptr_t)MI_MSC_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add);
|
|
184
187
|
}
|
|
185
188
|
static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) {
|
|
186
189
|
(void)(mo);
|
|
187
|
-
return (uintptr_t)
|
|
190
|
+
return (uintptr_t)MI_MSC_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub));
|
|
188
191
|
}
|
|
189
192
|
static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
|
|
190
193
|
(void)(mo);
|
|
191
|
-
return (uintptr_t)
|
|
194
|
+
return (uintptr_t)MI_MSC_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
|
|
192
195
|
}
|
|
193
196
|
static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
|
|
194
197
|
(void)(mo);
|
|
195
|
-
return (uintptr_t)
|
|
198
|
+
return (uintptr_t)MI_MSC_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
|
|
196
199
|
}
|
|
197
200
|
static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) {
|
|
198
201
|
(void)(mo1); (void)(mo2);
|
|
199
|
-
uintptr_t read = (uintptr_t)
|
|
202
|
+
const uintptr_t read = (uintptr_t)MI_MSC_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected));
|
|
200
203
|
if (read == *expected) {
|
|
201
204
|
return true;
|
|
202
205
|
}
|
|
@@ -210,68 +213,119 @@ static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p
|
|
|
210
213
|
}
|
|
211
214
|
static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) {
|
|
212
215
|
(void)(mo);
|
|
213
|
-
return (uintptr_t)
|
|
216
|
+
return (uintptr_t)MI_MSC_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange);
|
|
214
217
|
}
|
|
215
218
|
static inline void mi_atomic_thread_fence(mi_memory_order mo) {
|
|
216
219
|
(void)(mo);
|
|
217
220
|
_Atomic(uintptr_t) x = 0;
|
|
218
221
|
mi_atomic_exchange_explicit(&x, 1, mo);
|
|
219
222
|
}
|
|
223
|
+
|
|
220
224
|
static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) {
|
|
221
225
|
(void)(mo);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
// assert(mo<=mi_memory_order_acquire); // others are not used by mimalloc
|
|
227
|
+
#if defined(_M_IX86) || defined(_M_X64)
|
|
228
|
+
return (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
|
|
229
|
+
#elif defined(_M_ARM) || defined(_M_ARM64)
|
|
230
|
+
if (mo == mi_memory_order_relaxed) {
|
|
231
|
+
return (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
|
|
232
|
+
}
|
|
233
|
+
else if (mo <= mi_memory_order_acquire) {
|
|
234
|
+
return MI_MSC_XX(__ldar)((volatile const uintptr_t*)p);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const uintptr_t u = (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
|
|
238
|
+
__dmb(15); // _ARM(64)_BARRIER_SY
|
|
239
|
+
return u;
|
|
240
|
+
}
|
|
241
|
+
#else
|
|
242
|
+
#warning "define mi_atomic_load_explicit for MSVC C compilation on this platform (which should be readonly, see issue #1277)"
|
|
243
|
+
return MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
|
|
244
|
+
#endif
|
|
231
245
|
}
|
|
232
246
|
static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
|
|
233
247
|
(void)(mo);
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
248
|
+
// assert(mo<=mi_memory_order_release); // others are not used by mimalloc
|
|
249
|
+
#if defined(_M_IX86) || defined(_M_X64)
|
|
250
|
+
MI_MSC_XX(__iso_volatile_store)((volatile intptr_t*)p, x);
|
|
251
|
+
#elif defined(_M_ARM) || defined(_M_ARM64)
|
|
252
|
+
if (mo == mi_memory_order_relaxed) {
|
|
253
|
+
MI_MSC_XX(__iso_volatile_store)((volatile intptr_t*)p, x);
|
|
254
|
+
}
|
|
255
|
+
else if (mo <= mi_memory_order_release) {
|
|
256
|
+
MI_MSC_XX(__stlr)((volatile uintptr_t*)p,x);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
mi_atomic_exchange_explicit(p, x, mo);
|
|
260
|
+
}
|
|
261
|
+
#else
|
|
262
|
+
mi_atomic_exchange_explicit(p, x, mo);
|
|
263
|
+
#endif
|
|
239
264
|
}
|
|
265
|
+
|
|
240
266
|
static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) {
|
|
241
267
|
(void)(mo);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
268
|
+
// assert(mo<=mi_memory_order_acquire); // others are not used by mimalloc
|
|
269
|
+
#if defined(_M_IX86) || defined(_M_X64)
|
|
270
|
+
return __iso_volatile_load64((volatile const int64_t*)p);
|
|
271
|
+
#elif defined(_M_ARM) || defined(_M_ARM64)
|
|
272
|
+
if (mo == mi_memory_order_relaxed) {
|
|
273
|
+
return __iso_volatile_load64((volatile const int64_t*)p);
|
|
274
|
+
}
|
|
275
|
+
#if defined(_M_ARM64)
|
|
276
|
+
else if (mo <= mi_memory_order_acquire) {
|
|
277
|
+
return __ldar64((volatile const uintptr_t*)p);
|
|
278
|
+
}
|
|
279
|
+
#endif
|
|
280
|
+
else {
|
|
281
|
+
const int64_t i = __iso_volatile_load64((volatile const int64_t*)p);
|
|
282
|
+
__dmb(15); // _ARM(64)_BARRIER_SY
|
|
283
|
+
return i;
|
|
284
|
+
}
|
|
285
|
+
#else
|
|
286
|
+
#warning "define mi_atomic_loadi64_explicit for MSVC C compilation on this platform (which should be readonly, see issue #1277)"
|
|
287
|
+
return __iso_volatile_load64((volatile const int64_t*)p);
|
|
288
|
+
#endif
|
|
252
289
|
}
|
|
290
|
+
|
|
253
291
|
static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) {
|
|
254
292
|
(void)(mo);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
293
|
+
// assert(mo<=mi_memory_order_release); // others are not used by mimalloc
|
|
294
|
+
#if defined(_M_IX86) || defined(_M_X64)
|
|
295
|
+
__iso_volatile_store64((volatile int64_t*)p,x);
|
|
296
|
+
#elif defined(_M_ARM) || defined(_M_ARM64)
|
|
297
|
+
if (mo == mi_memory_order_relaxed) {
|
|
298
|
+
__iso_volatile_store64((volatile int64_t*)p,x);
|
|
299
|
+
}
|
|
300
|
+
#if defined(_M_ARM64)
|
|
301
|
+
else if (mo == mi_memory_order_release) {
|
|
302
|
+
__stlr64((volatile uint64_t*)p, (uint64_t)x);
|
|
303
|
+
}
|
|
304
|
+
#endif
|
|
305
|
+
else {
|
|
306
|
+
InterlockedExchange64(p, x);
|
|
307
|
+
}
|
|
308
|
+
#else
|
|
309
|
+
InterlockedExchange64(p, x);
|
|
310
|
+
#endif
|
|
260
311
|
}
|
|
261
312
|
|
|
262
313
|
// These are used by the statistics
|
|
263
314
|
static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) {
|
|
264
|
-
#ifdef _WIN64
|
|
265
|
-
|
|
266
|
-
#
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
current
|
|
271
|
-
sum
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
315
|
+
#ifdef _WIN64
|
|
316
|
+
return (int64_t)mi_atomic_addi((int64_t*)p, add);
|
|
317
|
+
#elif defined(_M_ARM)
|
|
318
|
+
return _InterlockedExchangeAdd64(p, add);
|
|
319
|
+
#else
|
|
320
|
+
// x86
|
|
321
|
+
int64_t current;
|
|
322
|
+
int64_t sum;
|
|
323
|
+
do {
|
|
324
|
+
current = __iso_volatile_load64((volatile const int64_t*)p);
|
|
325
|
+
sum = current + add;
|
|
326
|
+
} while (_InterlockedCompareExchange64(p, sum, current) != current);
|
|
327
|
+
return current;
|
|
328
|
+
#endif
|
|
275
329
|
}
|
|
276
330
|
|
|
277
331
|
static inline void mi_atomic_void_addi64_relaxed(volatile int64_t* p, const volatile int64_t* padd) {
|
|
@@ -293,7 +347,7 @@ static inline void mi_atomic_addi64_acq_rel(volatile _Atomic(int64_t*)p, int64_t
|
|
|
293
347
|
}
|
|
294
348
|
|
|
295
349
|
static inline bool mi_atomic_casi64_strong_acq_rel(volatile _Atomic(int64_t*)p, int64_t* exp, int64_t des) {
|
|
296
|
-
int64_t read = _InterlockedCompareExchange64(p, des, *exp);
|
|
350
|
+
const int64_t read = _InterlockedCompareExchange64(p, des, *exp);
|
|
297
351
|
if (read == *exp) {
|
|
298
352
|
return true;
|
|
299
353
|
}
|
|
@@ -337,21 +391,12 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) {
|
|
|
337
391
|
|
|
338
392
|
|
|
339
393
|
// ----------------------------------------------------------------------
|
|
340
|
-
//
|
|
394
|
+
// Guard
|
|
341
395
|
// ----------------------------------------------------------------------
|
|
342
396
|
|
|
343
|
-
typedef _Atomic(uintptr_t) mi_atomic_once_t;
|
|
344
|
-
|
|
345
|
-
// Returns true only on the first invocation
|
|
346
|
-
static inline bool mi_atomic_once( mi_atomic_once_t* once ) {
|
|
347
|
-
if (mi_atomic_load_relaxed(once) != 0) return false; // quick test
|
|
348
|
-
uintptr_t expected = 0;
|
|
349
|
-
return mi_atomic_cas_strong_acq_rel(once, &expected, (uintptr_t)1); // try to set to 1
|
|
350
|
-
}
|
|
351
|
-
|
|
352
397
|
typedef _Atomic(uintptr_t) mi_atomic_guard_t;
|
|
353
398
|
|
|
354
|
-
// Allows only one thread to execute at a time
|
|
399
|
+
// Allows only one thread to execute at a time (without blocking anyone)
|
|
355
400
|
#define mi_atomic_guard(guard) \
|
|
356
401
|
uintptr_t _mi_guard_expected = 0; \
|
|
357
402
|
for(bool _mi_guard_once = true; \
|
|
@@ -359,77 +404,6 @@ typedef _Atomic(uintptr_t) mi_atomic_guard_t;
|
|
|
359
404
|
(mi_atomic_store_release(guard,(uintptr_t)0), _mi_guard_once = false) )
|
|
360
405
|
|
|
361
406
|
|
|
362
|
-
|
|
363
|
-
// ----------------------------------------------------------------------
|
|
364
|
-
// Yield
|
|
365
|
-
// ----------------------------------------------------------------------
|
|
366
|
-
|
|
367
|
-
#if defined(__cplusplus)
|
|
368
|
-
#include <thread>
|
|
369
|
-
static inline void mi_atomic_yield(void) {
|
|
370
|
-
std::this_thread::yield();
|
|
371
|
-
}
|
|
372
|
-
#elif defined(_WIN32)
|
|
373
|
-
static inline void mi_atomic_yield(void) {
|
|
374
|
-
YieldProcessor();
|
|
375
|
-
}
|
|
376
|
-
#elif defined(__SSE2__)
|
|
377
|
-
#include <emmintrin.h>
|
|
378
|
-
static inline void mi_atomic_yield(void) {
|
|
379
|
-
_mm_pause();
|
|
380
|
-
}
|
|
381
|
-
#elif (defined(__GNUC__) || defined(__clang__)) && \
|
|
382
|
-
(defined(__x86_64__) || defined(__i386__) || \
|
|
383
|
-
defined(__aarch64__) || defined(__arm__) || \
|
|
384
|
-
defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__))
|
|
385
|
-
#if defined(__x86_64__) || defined(__i386__)
|
|
386
|
-
static inline void mi_atomic_yield(void) {
|
|
387
|
-
__asm__ volatile ("pause" ::: "memory");
|
|
388
|
-
}
|
|
389
|
-
#elif defined(__aarch64__)
|
|
390
|
-
static inline void mi_atomic_yield(void) {
|
|
391
|
-
__asm__ volatile("wfe");
|
|
392
|
-
}
|
|
393
|
-
#elif defined(__arm__)
|
|
394
|
-
#if __ARM_ARCH >= 7
|
|
395
|
-
static inline void mi_atomic_yield(void) {
|
|
396
|
-
__asm__ volatile("yield" ::: "memory");
|
|
397
|
-
}
|
|
398
|
-
#else
|
|
399
|
-
static inline void mi_atomic_yield(void) {
|
|
400
|
-
__asm__ volatile ("nop" ::: "memory");
|
|
401
|
-
}
|
|
402
|
-
#endif
|
|
403
|
-
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__)
|
|
404
|
-
#ifdef __APPLE__
|
|
405
|
-
static inline void mi_atomic_yield(void) {
|
|
406
|
-
__asm__ volatile ("or r27,r27,r27" ::: "memory");
|
|
407
|
-
}
|
|
408
|
-
#else
|
|
409
|
-
static inline void mi_atomic_yield(void) {
|
|
410
|
-
__asm__ __volatile__ ("or 27,27,27" ::: "memory");
|
|
411
|
-
}
|
|
412
|
-
#endif
|
|
413
|
-
#endif
|
|
414
|
-
#elif defined(__sun)
|
|
415
|
-
// Fallback for other archs
|
|
416
|
-
#include <synch.h>
|
|
417
|
-
static inline void mi_atomic_yield(void) {
|
|
418
|
-
smt_pause();
|
|
419
|
-
}
|
|
420
|
-
#elif defined(__wasi__)
|
|
421
|
-
#include <sched.h>
|
|
422
|
-
static inline void mi_atomic_yield(void) {
|
|
423
|
-
sched_yield();
|
|
424
|
-
}
|
|
425
|
-
#else
|
|
426
|
-
#include <unistd.h>
|
|
427
|
-
static inline void mi_atomic_yield(void) {
|
|
428
|
-
sleep(0);
|
|
429
|
-
}
|
|
430
|
-
#endif
|
|
431
|
-
|
|
432
|
-
|
|
433
407
|
// ----------------------------------------------------------------------
|
|
434
408
|
// Locks
|
|
435
409
|
// These should be light-weight in-process only locks.
|
|
@@ -439,95 +413,90 @@ static inline void mi_atomic_yield(void) {
|
|
|
439
413
|
#pragma warning(disable:26110) // unlock with holding lock
|
|
440
414
|
#endif
|
|
441
415
|
|
|
442
|
-
#define mi_lock(lock)
|
|
416
|
+
#define mi_lock(lock) for(bool _mi_go = (mi_lock_acquire(lock),true); _mi_go; (mi_lock_release(lock), _mi_go=false) )
|
|
417
|
+
#define mi_lock_maybe(lock,acquire) for(bool _mi_go = (acquire ? (mi_lock_acquire(lock),true) : true); _mi_go; _mi_go = (acquire ? (mi_lock_release(lock),false) : false) )
|
|
418
|
+
|
|
443
419
|
|
|
444
420
|
#if defined(_WIN32)
|
|
445
421
|
|
|
446
|
-
|
|
447
|
-
|
|
422
|
+
typedef struct mi_lock_s {
|
|
423
|
+
SRWLOCK mutex; // slim reader-writer lock
|
|
424
|
+
} mi_lock_t;
|
|
448
425
|
|
|
449
|
-
|
|
450
|
-
return TryAcquireSRWLockExclusive(lock);
|
|
451
|
-
}
|
|
452
|
-
static inline void mi_lock_acquire(mi_lock_t* lock) {
|
|
453
|
-
AcquireSRWLockExclusive(lock);
|
|
454
|
-
}
|
|
455
|
-
static inline void mi_lock_release(mi_lock_t* lock) {
|
|
456
|
-
ReleaseSRWLockExclusive(lock);
|
|
457
|
-
}
|
|
458
|
-
static inline void mi_lock_init(mi_lock_t* lock) {
|
|
459
|
-
InitializeSRWLock(lock);
|
|
460
|
-
}
|
|
461
|
-
static inline void mi_lock_done(mi_lock_t* lock) {
|
|
462
|
-
(void)(lock);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
#else
|
|
466
|
-
#define mi_lock_t CRITICAL_SECTION
|
|
426
|
+
#define MI_LOCK_INITIALIZER { SRWLOCK_INIT }
|
|
467
427
|
|
|
468
428
|
static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
|
|
469
|
-
return
|
|
429
|
+
return TryAcquireSRWLockExclusive(&lock->mutex);
|
|
470
430
|
}
|
|
471
431
|
static inline void mi_lock_acquire(mi_lock_t* lock) {
|
|
472
|
-
|
|
432
|
+
AcquireSRWLockExclusive(&lock->mutex);
|
|
473
433
|
}
|
|
474
434
|
static inline void mi_lock_release(mi_lock_t* lock) {
|
|
475
|
-
|
|
435
|
+
ReleaseSRWLockExclusive(&lock->mutex);
|
|
476
436
|
}
|
|
477
437
|
static inline void mi_lock_init(mi_lock_t* lock) {
|
|
478
|
-
|
|
438
|
+
InitializeSRWLock(&lock->mutex);
|
|
479
439
|
}
|
|
480
440
|
static inline void mi_lock_done(mi_lock_t* lock) {
|
|
481
|
-
|
|
441
|
+
(void)(lock);
|
|
482
442
|
}
|
|
483
443
|
|
|
484
|
-
#endif
|
|
485
|
-
|
|
486
444
|
#elif defined(MI_USE_PTHREADS)
|
|
487
445
|
|
|
488
446
|
#include <string.h> // memcpy
|
|
489
447
|
void _mi_error_message(int err, const char* fmt, ...);
|
|
490
448
|
|
|
491
|
-
|
|
449
|
+
typedef struct mi_lock_s {
|
|
450
|
+
pthread_mutex_t mutex;
|
|
451
|
+
} mi_lock_t;
|
|
452
|
+
|
|
453
|
+
#define MI_LOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
|
|
492
454
|
|
|
493
455
|
static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
|
|
494
|
-
return (pthread_mutex_trylock(lock) == 0);
|
|
456
|
+
return (pthread_mutex_trylock(&lock->mutex) == 0);
|
|
495
457
|
}
|
|
496
458
|
static inline void mi_lock_acquire(mi_lock_t* lock) {
|
|
497
|
-
const int err = pthread_mutex_lock(lock);
|
|
459
|
+
const int err = pthread_mutex_lock(&lock->mutex);
|
|
498
460
|
if (err != 0) {
|
|
499
461
|
_mi_error_message(err, "internal error: lock cannot be acquired (err %i)\n", err);
|
|
500
462
|
}
|
|
501
463
|
}
|
|
502
464
|
static inline void mi_lock_release(mi_lock_t* lock) {
|
|
503
|
-
pthread_mutex_unlock(lock);
|
|
465
|
+
pthread_mutex_unlock(&lock->mutex);
|
|
504
466
|
}
|
|
505
467
|
static inline void mi_lock_init(mi_lock_t* lock) {
|
|
506
468
|
if(lock==NULL) return;
|
|
507
|
-
// use instead of pthread_mutex_init since that can cause allocation on some platforms (and recursively initialize)
|
|
508
|
-
const
|
|
509
|
-
memcpy(lock,&
|
|
469
|
+
// use this instead of pthread_mutex_init since that can cause allocation on some platforms (and recursively initialize)
|
|
470
|
+
const pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
471
|
+
memcpy(&lock->mutex,&mutex,sizeof(mutex));
|
|
510
472
|
}
|
|
511
473
|
static inline void mi_lock_done(mi_lock_t* lock) {
|
|
512
|
-
pthread_mutex_destroy(lock);
|
|
474
|
+
pthread_mutex_destroy(&lock->mutex);
|
|
513
475
|
}
|
|
514
476
|
|
|
515
477
|
#elif defined(__cplusplus)
|
|
516
478
|
|
|
479
|
+
#include <thread>
|
|
517
480
|
#include <mutex>
|
|
518
|
-
#
|
|
481
|
+
#include <new>
|
|
482
|
+
|
|
483
|
+
typedef struct mi_lock_s {
|
|
484
|
+
std::mutex mutex;
|
|
485
|
+
} mi_lock_t;
|
|
486
|
+
|
|
487
|
+
#define MI_LOCK_INITIALIZER { }
|
|
519
488
|
|
|
520
489
|
static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
|
|
521
|
-
return lock->try_lock();
|
|
490
|
+
return lock->mutex.try_lock();
|
|
522
491
|
}
|
|
523
492
|
static inline void mi_lock_acquire(mi_lock_t* lock) {
|
|
524
|
-
lock->lock();
|
|
493
|
+
lock->mutex.lock();
|
|
525
494
|
}
|
|
526
495
|
static inline void mi_lock_release(mi_lock_t* lock) {
|
|
527
|
-
lock->unlock();
|
|
496
|
+
lock->mutex.unlock();
|
|
528
497
|
}
|
|
529
498
|
static inline void mi_lock_init(mi_lock_t* lock) {
|
|
530
|
-
(
|
|
499
|
+
new(&lock->mutex) std::mutex();
|
|
531
500
|
}
|
|
532
501
|
static inline void mi_lock_done(mi_lock_t* lock) {
|
|
533
502
|
(void)(lock);
|
|
@@ -537,21 +506,32 @@ static inline void mi_lock_done(mi_lock_t* lock) {
|
|
|
537
506
|
|
|
538
507
|
// fall back to poor man's locks.
|
|
539
508
|
// this should only be the case in a single-threaded environment (like __wasi__)
|
|
509
|
+
#include <errno.h>
|
|
510
|
+
#ifndef EFAULT
|
|
511
|
+
#define EFAULT (14)
|
|
512
|
+
#endif
|
|
513
|
+
void _mi_error_message(int err, const char* fmt, ...);
|
|
514
|
+
void _mi_prim_thread_yield(void);
|
|
515
|
+
|
|
516
|
+
typedef struct mi_lock_s {
|
|
517
|
+
_Atomic(uintptr_t) mutex;
|
|
518
|
+
} mi_lock_t;
|
|
540
519
|
|
|
541
|
-
#define
|
|
520
|
+
#define MI_LOCK_INITIALIZER { MI_ATOMIC_VAR_INIT(0) }
|
|
542
521
|
|
|
543
522
|
static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
|
|
544
523
|
uintptr_t expected = 0;
|
|
545
|
-
return mi_atomic_cas_strong_acq_rel(lock, &expected, (uintptr_t)1);
|
|
524
|
+
return mi_atomic_cas_strong_acq_rel(&lock->mutex, &expected, (uintptr_t)1);
|
|
546
525
|
}
|
|
547
526
|
static inline void mi_lock_acquire(mi_lock_t* lock) {
|
|
548
|
-
for (int i = 0; i <
|
|
527
|
+
for (int i = 0; i < 10000; i++) { // for at most 10000 tries?
|
|
549
528
|
if (mi_lock_try_acquire(lock)) return;
|
|
550
|
-
|
|
529
|
+
_mi_prim_thread_yield();
|
|
551
530
|
}
|
|
531
|
+
_mi_error_message(EFAULT, "internal error: lock cannot be acquired (due to lack of native lock primitives)\n");
|
|
552
532
|
}
|
|
553
533
|
static inline void mi_lock_release(mi_lock_t* lock) {
|
|
554
|
-
mi_atomic_store_release(lock, (uintptr_t)0);
|
|
534
|
+
mi_atomic_store_release(&lock->mutex, (uintptr_t)0);
|
|
555
535
|
}
|
|
556
536
|
static inline void mi_lock_init(mi_lock_t* lock) {
|
|
557
537
|
mi_lock_release(lock);
|
|
@@ -563,4 +543,20 @@ static inline void mi_lock_done(mi_lock_t* lock) {
|
|
|
563
543
|
#endif
|
|
564
544
|
|
|
565
545
|
|
|
566
|
-
|
|
546
|
+
typedef struct mi_atomic_once_s {
|
|
547
|
+
_Atomic(uintptr_t) tid;
|
|
548
|
+
mi_lock_t lock;
|
|
549
|
+
} mi_atomic_once_t;
|
|
550
|
+
|
|
551
|
+
// Returns `true` only on the first invocation, signifying we can execute an action once.
|
|
552
|
+
// If it returns `true`, the caller should call `_mi_atomic_once_release` after performing the action.
|
|
553
|
+
// Other threads (than the initial thread that entered) will block until `_mi_atomic_once_release` has been called.
|
|
554
|
+
bool _mi_atomic_once_enter(mi_atomic_once_t* once); // defined in `libc.c`
|
|
555
|
+
void _mi_atomic_once_release(mi_atomic_once_t* once); // defined in `libc.c`
|
|
556
|
+
|
|
557
|
+
#define mi_atomic_do_once \
|
|
558
|
+
static mi_atomic_once_t _mi_once = { MI_ATOMIC_VAR_INIT(0), MI_LOCK_INITIALIZER }; \
|
|
559
|
+
for(bool _mi_exec = _mi_atomic_once_enter(&_mi_once); _mi_exec; (_mi_atomic_once_release(&_mi_once),_mi_exec=false))
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
#endif // __MIMALLOC_ATOMIC_H
|
|
@@ -108,6 +108,9 @@ typedef int32_t mi_ssize_t;
|
|
|
108
108
|
#if MI_ARCH_X64 && (defined(__AVX2__) || defined(__BMI2__)) && !defined(__BMI1__) // msvc
|
|
109
109
|
#define __BMI1__ 1
|
|
110
110
|
#endif
|
|
111
|
+
#if MI_ARCH_X64 && defined(__AVX2__) && !defined(__LZCNT__) // msvc
|
|
112
|
+
#define __LZCNT__ 1
|
|
113
|
+
#endif
|
|
111
114
|
|
|
112
115
|
// Define big endian if needed
|
|
113
116
|
// #define MI_BIG_ENDIAN 1
|
|
@@ -123,9 +126,9 @@ typedef int32_t mi_ssize_t;
|
|
|
123
126
|
#define MI_MAX_VABITS (32)
|
|
124
127
|
#endif
|
|
125
128
|
|
|
126
|
-
// use a flat page-map
|
|
129
|
+
// use a flat page-map or a 2-level one
|
|
127
130
|
#ifndef MI_PAGE_MAP_FLAT
|
|
128
|
-
#if MI_MAX_VABITS <= 40 && !defined(__APPLE__)
|
|
131
|
+
#if MI_MAX_VABITS <= 40 && !defined(__APPLE__) && MI_SECURE==0 && !MI_PAGE_META_IS_SEPARATED
|
|
129
132
|
#define MI_PAGE_MAP_FLAT 1
|
|
130
133
|
#else
|
|
131
134
|
#define MI_PAGE_MAP_FLAT 0
|
|
@@ -222,11 +225,11 @@ static inline size_t mi_ctz(size_t x) {
|
|
|
222
225
|
}
|
|
223
226
|
|
|
224
227
|
static inline size_t mi_clz(size_t x) {
|
|
225
|
-
#if defined(__GNUC__) && MI_ARCH_X64 && defined(
|
|
228
|
+
#if defined(__GNUC__) && MI_ARCH_X64 && defined(__LZCNT__) // on x64 lzcnt is defined for 0
|
|
226
229
|
size_t r;
|
|
227
230
|
__asm ("lzcnt\t%1, %0" : "=r"(r) : "r"(x) : "cc");
|
|
228
231
|
return r;
|
|
229
|
-
#elif defined(_MSC_VER) && MI_ARCH_X64 && defined(
|
|
232
|
+
#elif defined(_MSC_VER) && MI_ARCH_X64 && defined(__LZCNT__)
|
|
230
233
|
return _lzcnt_u64(x);
|
|
231
234
|
#elif defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
|
|
232
235
|
unsigned long idx;
|
|
@@ -273,12 +276,7 @@ static inline bool mi_bsf(size_t x, size_t* idx) {
|
|
|
273
276
|
// return false if `x==0` (with `*idx` undefined) and true otherwise,
|
|
274
277
|
// with the `idx` is set to the bit index (`0 <= *idx < MI_BFIELD_BITS`).
|
|
275
278
|
static inline bool mi_bsr(size_t x, size_t* idx) {
|
|
276
|
-
#if
|
|
277
|
-
// on x64 the carry flag is set on zero which gives better codegen
|
|
278
|
-
bool is_zero;
|
|
279
|
-
__asm ("lzcnt\t%2, %1" : "=@ccc"(is_zero), "=r"(*idx) : "r"(x) : "cc");
|
|
280
|
-
return !is_zero;
|
|
281
|
-
#elif 0 && defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
|
|
279
|
+
#if 0 && defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
|
|
282
280
|
unsigned long i;
|
|
283
281
|
return (mi_msc_builtinz(_BitScanReverse)(&i, x) ? (*idx = (size_t)i, true) : false);
|
|
284
282
|
#else
|