@shd101wyy/yo 0.1.24 → 0.1.26
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 +6 -6
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +34 -0
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +441 -2
- package/out/cjs/index.cjs +563 -567
- package/out/cjs/yo-cli.cjs +656 -651
- package/out/cjs/yo-lsp.cjs +614 -618
- package/out/esm/index.mjs +582 -586
- package/out/types/src/codegen/codegen-c.d.ts +2 -2
- package/out/types/src/codegen/functions/collection.d.ts +2 -2
- package/out/types/src/codegen/functions/context.d.ts +3 -2
- package/out/types/src/codegen/types/collection.d.ts +2 -2
- package/out/types/src/codegen/utils/index.d.ts +4 -1
- package/out/types/src/doc/builder.d.ts +2 -2
- package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
- package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
- package/out/types/src/evaluator/context.d.ts +8 -9
- package/out/types/src/evaluator/index.d.ts +3 -3
- package/out/types/src/evaluator/types/record.d.ts +14 -0
- package/out/types/src/evaluator/types/validation.d.ts +2 -2
- package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
- package/out/types/src/evaluator/values/impl.d.ts +1 -1
- package/out/types/src/expr.d.ts +2 -4
- package/out/types/src/function-value.d.ts +1 -1
- package/out/types/src/lsp/document-manager.d.ts +1 -1
- package/out/types/src/module-manager.d.ts +3 -3
- package/out/types/src/test-runner.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +3 -4
- package/out/types/src/types/definitions.d.ts +8 -19
- package/out/types/src/types/guards.d.ts +3 -3
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +1 -1
- package/out/types/src/value-tag.d.ts +0 -1
- package/out/types/src/value.d.ts +6 -13
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/error.yo +6 -6
- package/std/prelude.yo +1 -7
- 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
- package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
- package/out/types/src/evaluator/types/module.d.ts +0 -19
|
@@ -67,17 +67,11 @@ const mi_page_t _mi_page_empty = {
|
|
|
67
67
|
#define MI_STAT_COUNT_NULL() {0,0,0}
|
|
68
68
|
|
|
69
69
|
// Empty statistics
|
|
70
|
+
#define MI_STAT_COUNT(stat) {0,0,0},
|
|
71
|
+
#define MI_STAT_COUNTER(stat) {0},
|
|
72
|
+
|
|
70
73
|
#define MI_STATS_NULL \
|
|
71
|
-
|
|
72
|
-
{ 0 }, { 0 }, \
|
|
73
|
-
MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
|
|
74
|
-
MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
|
|
75
|
-
{ 0 }, { 0 }, { 0 }, { 0 }, \
|
|
76
|
-
{ 0 }, { 0 }, { 0 }, { 0 }, \
|
|
77
|
-
\
|
|
78
|
-
{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, \
|
|
79
|
-
MI_INIT5(MI_STAT_COUNT_NULL), \
|
|
80
|
-
{ 0 }, { 0 }, { 0 }, { 0 }, \
|
|
74
|
+
MI_STAT_FIELDS() \
|
|
81
75
|
\
|
|
82
76
|
{ MI_INIT4(MI_STAT_COUNT_NULL) }, \
|
|
83
77
|
{ { 0 }, { 0 }, { 0 }, { 0 } }, \
|
|
@@ -97,9 +91,9 @@ const mi_page_t _mi_page_empty = {
|
|
|
97
91
|
|
|
98
92
|
static mi_decl_cache_align mi_subproc_t subproc_main
|
|
99
93
|
#if __cplusplus
|
|
100
|
-
= { }; // empty initializer to prevent running the constructor (with msvc)
|
|
94
|
+
= { }; // empty initializer to prevent running the constructor (with msvc)
|
|
101
95
|
#else
|
|
102
|
-
= { 0 }; // C zero initialize
|
|
96
|
+
= { 0 }; // C zero initialize
|
|
103
97
|
#endif
|
|
104
98
|
|
|
105
99
|
static mi_subproc_t* subprocs = &subproc_main;
|
|
@@ -111,6 +105,7 @@ static mi_decl_cache_align mi_tld_t tld_empty = {
|
|
|
111
105
|
0, // default numa node
|
|
112
106
|
&subproc_main, // subproc
|
|
113
107
|
NULL, // theaps list
|
|
108
|
+
MI_LOCK_INITIALIZER, // theaps lock
|
|
114
109
|
false, // recurse
|
|
115
110
|
false, // is_in_threadpool
|
|
116
111
|
MI_MEMID_STATIC // memid
|
|
@@ -118,12 +113,14 @@ static mi_decl_cache_align mi_tld_t tld_empty = {
|
|
|
118
113
|
|
|
119
114
|
mi_decl_cache_align const mi_theap_t _mi_theap_empty = {
|
|
120
115
|
&tld_empty, // tld
|
|
121
|
-
NULL,
|
|
116
|
+
MI_ATOMIC_VAR_INIT(NULL), // heap
|
|
117
|
+
MI_ATOMIC_VAR_INIT(1), // refcount
|
|
122
118
|
0, // heartbeat
|
|
123
119
|
0, // cookie
|
|
124
120
|
{ {0}, {0}, 0, true }, // random
|
|
125
121
|
0, // page count
|
|
126
122
|
MI_BIN_FULL, 0, // page retired min/max
|
|
123
|
+
0, // pages_full_size
|
|
127
124
|
0, 0, // generic count
|
|
128
125
|
NULL, NULL, // tnext, tprev
|
|
129
126
|
NULL, NULL, // hnext, hprev
|
|
@@ -141,12 +138,14 @@ mi_decl_cache_align const mi_theap_t _mi_theap_empty = {
|
|
|
141
138
|
|
|
142
139
|
mi_decl_cache_align const mi_theap_t _mi_theap_empty_wrong = {
|
|
143
140
|
&tld_empty, // tld
|
|
144
|
-
NULL,
|
|
141
|
+
MI_ATOMIC_VAR_INIT(NULL), // heap
|
|
142
|
+
MI_ATOMIC_VAR_INIT(1), // refcount
|
|
145
143
|
0, // heartbeat
|
|
146
144
|
0, // cookie
|
|
147
145
|
{ {0}, {0}, 0, true }, // random
|
|
148
146
|
0, // page count
|
|
149
147
|
MI_BIN_FULL, 0, // page retired min/max
|
|
148
|
+
0, // pages_full_size
|
|
150
149
|
0, 0, // generic count
|
|
151
150
|
NULL, NULL, // tnext, tprev
|
|
152
151
|
NULL, NULL, // hnext, hprev
|
|
@@ -173,6 +172,7 @@ static mi_decl_cache_align mi_tld_t tld_main = {
|
|
|
173
172
|
0, // numa node
|
|
174
173
|
&subproc_main, // subproc
|
|
175
174
|
&theap_main, // theaps list
|
|
175
|
+
MI_LOCK_INITIALIZER, // theaps lock
|
|
176
176
|
false, // recurse
|
|
177
177
|
false, // is_in_threadpool
|
|
178
178
|
MI_MEMID_STATIC // memid
|
|
@@ -180,12 +180,14 @@ static mi_decl_cache_align mi_tld_t tld_main = {
|
|
|
180
180
|
|
|
181
181
|
mi_decl_cache_align mi_theap_t theap_main = {
|
|
182
182
|
&tld_main, // thread local data
|
|
183
|
-
&heap_main,
|
|
183
|
+
MI_ATOMIC_VAR_INIT(&heap_main), // main heap
|
|
184
|
+
MI_ATOMIC_VAR_INIT(1), // refcount
|
|
184
185
|
0, // heartbeat
|
|
185
186
|
0, // initial cookie
|
|
186
187
|
{ {0x846ca68b}, {0}, 0, true }, // random
|
|
187
188
|
0, // page count
|
|
188
189
|
MI_BIN_FULL, 0, // page retired min/max
|
|
190
|
+
0, // pages_full_size
|
|
189
191
|
0, 0, // generic count
|
|
190
192
|
NULL, NULL, // tnext, tprev
|
|
191
193
|
NULL, NULL, // hnext, hprev
|
|
@@ -208,13 +210,15 @@ mi_decl_cache_align mi_heap_t heap_main
|
|
|
208
210
|
= { 0 }; // C zero initialize
|
|
209
211
|
#endif
|
|
210
212
|
|
|
211
|
-
mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
|
|
212
|
-
return _mi_prim_thread_id();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
213
|
// the theap belonging to the main heap
|
|
216
214
|
mi_decl_hidden mi_decl_thread mi_theap_t* __mi_theap_main = NULL;
|
|
217
215
|
|
|
216
|
+
mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
|
|
217
|
+
mi_threadid_t tid = _mi_prim_thread_id();
|
|
218
|
+
mi_assert_internal( (tid & 0x03) == 0 ); // mimalloc reserves the bottom 2 bits
|
|
219
|
+
return tid;
|
|
220
|
+
}
|
|
221
|
+
|
|
218
222
|
#if MI_TLS_MODEL_THREAD_LOCAL
|
|
219
223
|
// the thread-local main theap for allocation
|
|
220
224
|
mi_decl_hidden mi_decl_thread mi_theap_t* __mi_theap_default = (mi_theap_t*)&_mi_theap_empty;
|
|
@@ -226,6 +230,10 @@ bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`.
|
|
|
226
230
|
|
|
227
231
|
mi_stats_t _mi_stats_main = { sizeof(mi_stats_t), MI_STAT_VERSION, MI_STATS_NULL };
|
|
228
232
|
|
|
233
|
+
#undef MI_STAT_COUNT
|
|
234
|
+
#undef MI_STAT_COUNTER
|
|
235
|
+
|
|
236
|
+
|
|
229
237
|
#if MI_GUARDED
|
|
230
238
|
mi_decl_export void mi_theap_guarded_set_sample_rate(mi_theap_t* theap, size_t sample_rate, size_t seed) {
|
|
231
239
|
theap->guarded_sample_rate = sample_rate;
|
|
@@ -280,9 +288,11 @@ static void mi_subproc_main_init(void) {
|
|
|
280
288
|
subproc_main.heap_count = 1;
|
|
281
289
|
mi_atomic_store_ptr_release(mi_heap_t, &subproc_main.heap_main, &heap_main);
|
|
282
290
|
__mi_stat_increase_mt(&subproc_main.stats.heaps, 1);
|
|
291
|
+
mi_stats_header_init(&subproc_main.stats);
|
|
283
292
|
mi_lock_init(&subproc_main.arena_reserve_lock);
|
|
284
293
|
mi_lock_init(&subproc_main.heaps_lock);
|
|
285
294
|
mi_lock_init(&subprocs_lock);
|
|
295
|
+
mi_lock_init(&tld_empty.theaps_lock);
|
|
286
296
|
}
|
|
287
297
|
}
|
|
288
298
|
|
|
@@ -290,6 +300,7 @@ static void mi_subproc_main_init(void) {
|
|
|
290
300
|
static void mi_tld_main_init(void) {
|
|
291
301
|
if (tld_main.thread_id == 0) {
|
|
292
302
|
tld_main.thread_id = _mi_prim_thread_id();
|
|
303
|
+
mi_lock_init(&tld_main.theaps_lock);
|
|
293
304
|
}
|
|
294
305
|
}
|
|
295
306
|
|
|
@@ -354,6 +365,7 @@ static mi_tld_t* mi_tld_alloc(void) {
|
|
|
354
365
|
}
|
|
355
366
|
tld->memid = memid;
|
|
356
367
|
tld->theaps = NULL;
|
|
368
|
+
mi_lock_init(&tld->theaps_lock);
|
|
357
369
|
tld->subproc = &subproc_main;
|
|
358
370
|
tld->numa_node = _mi_os_numa_node();
|
|
359
371
|
tld->thread_id = _mi_prim_thread_id();
|
|
@@ -367,6 +379,7 @@ static mi_tld_t* mi_tld_alloc(void) {
|
|
|
367
379
|
#define MI_TLD_INVALID ((mi_tld_t*)1)
|
|
368
380
|
|
|
369
381
|
mi_decl_noinline static void mi_tld_free(mi_tld_t* tld) {
|
|
382
|
+
mi_lock_done(&tld->theaps_lock);
|
|
370
383
|
if (tld != NULL && tld != MI_TLD_INVALID) {
|
|
371
384
|
mi_atomic_decrement_relaxed(&tld->subproc->thread_count);
|
|
372
385
|
_mi_meta_free(tld, sizeof(mi_tld_t), tld->memid);
|
|
@@ -388,6 +401,22 @@ mi_theap_t* _mi_theap_default_safe(void) {
|
|
|
388
401
|
return _mi_theap_default();
|
|
389
402
|
}
|
|
390
403
|
|
|
404
|
+
// return the main theap ensuring it is initialized.
|
|
405
|
+
mi_theap_t* _mi_theap_main_safe(void) {
|
|
406
|
+
mi_theap_t* theap = __mi_theap_main;
|
|
407
|
+
if mi_unlikely(theap==NULL) { // if thread_init or default_set was never called
|
|
408
|
+
mi_thread_init(); // sets the default slot to the main theap
|
|
409
|
+
theap = _mi_theap_default();
|
|
410
|
+
mi_assert_internal(theap!=NULL);
|
|
411
|
+
mi_assert_internal(_mi_is_theap_main(theap));
|
|
412
|
+
if (_mi_is_theap_main(theap)) {
|
|
413
|
+
__mi_theap_main = theap;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
mi_assert_internal(theap!=NULL && _mi_is_theap_main(theap));
|
|
417
|
+
return theap;
|
|
418
|
+
}
|
|
419
|
+
|
|
391
420
|
|
|
392
421
|
mi_subproc_t* _mi_subproc_main(void) {
|
|
393
422
|
return &subproc_main;
|
|
@@ -420,7 +449,7 @@ mi_heap_t* _mi_subproc_heap_main(mi_subproc_t* subproc) {
|
|
|
420
449
|
}
|
|
421
450
|
|
|
422
451
|
mi_heap_t* mi_heap_main(void) {
|
|
423
|
-
return _mi_subproc_heap_main(_mi_subproc()); // don't use
|
|
452
|
+
return _mi_subproc_heap_main(_mi_subproc()); // don't use mi_theap_main_init_get() so this call works during process_init
|
|
424
453
|
}
|
|
425
454
|
|
|
426
455
|
bool _mi_is_heap_main(const mi_heap_t* heap) {
|
|
@@ -428,25 +457,40 @@ bool _mi_is_heap_main(const mi_heap_t* heap) {
|
|
|
428
457
|
return (_mi_subproc_heap_main(heap->subproc) == heap);
|
|
429
458
|
}
|
|
430
459
|
|
|
460
|
+
bool _mi_is_theap_main(const mi_theap_t* theap) {
|
|
461
|
+
return (mi_theap_is_initialized(theap) && _mi_is_heap_main(_mi_theap_heap(theap)));
|
|
462
|
+
}
|
|
463
|
+
|
|
431
464
|
/* -----------------------------------------------------------
|
|
432
465
|
Sub process
|
|
433
466
|
----------------------------------------------------------- */
|
|
434
467
|
|
|
468
|
+
|
|
469
|
+
mi_subproc_t* _mi_subproc_from_id(mi_subproc_id_t subproc_id) {
|
|
470
|
+
return (mi_subproc_t*)(subproc_id._mi_subproc_id);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
mi_subproc_id_t _mi_subproc_to_id(mi_subproc_t* subproc) {
|
|
474
|
+
mi_subproc_id_t id = { subproc };
|
|
475
|
+
return id;
|
|
476
|
+
}
|
|
477
|
+
|
|
435
478
|
mi_subproc_id_t mi_subproc_main(void) {
|
|
436
|
-
return _mi_subproc_main();
|
|
479
|
+
return _mi_subproc_to_id(_mi_subproc_main());
|
|
437
480
|
}
|
|
438
481
|
|
|
439
482
|
mi_subproc_id_t mi_subproc_current(void) {
|
|
440
|
-
return _mi_subproc();
|
|
483
|
+
return _mi_subproc_to_id(_mi_subproc());
|
|
441
484
|
}
|
|
442
485
|
|
|
443
486
|
mi_subproc_id_t mi_subproc_new(void) {
|
|
444
487
|
static _Atomic(size_t) subproc_total_count;
|
|
445
488
|
mi_memid_t memid;
|
|
446
489
|
mi_subproc_t* subproc = (mi_subproc_t*)_mi_meta_zalloc(sizeof(mi_subproc_t),&memid);
|
|
447
|
-
if (subproc == NULL) return NULL;
|
|
490
|
+
if (subproc == NULL) return _mi_subproc_to_id(NULL);
|
|
448
491
|
subproc->memid = memid;
|
|
449
492
|
subproc->subproc_seq = mi_atomic_increment_relaxed(&subproc_total_count) + 1;
|
|
493
|
+
mi_stats_header_init(&subproc->stats);
|
|
450
494
|
mi_lock_init(&subproc->arena_reserve_lock);
|
|
451
495
|
mi_lock_init(&subproc->heaps_lock);
|
|
452
496
|
mi_lock(&subprocs_lock) {
|
|
@@ -455,18 +499,16 @@ mi_subproc_id_t mi_subproc_new(void) {
|
|
|
455
499
|
if (subprocs!=NULL) { subprocs->prev = subproc; }
|
|
456
500
|
subprocs = subproc;
|
|
457
501
|
}
|
|
458
|
-
return subproc;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
mi_subproc_t* _mi_subproc_from_id(mi_subproc_id_t subproc_id) {
|
|
462
|
-
return (subproc_id == NULL ? &subproc_main : (mi_subproc_t*)subproc_id);
|
|
502
|
+
return _mi_subproc_to_id(subproc);
|
|
463
503
|
}
|
|
464
504
|
|
|
465
505
|
// destroy all subproc resources including arena's, heap's etc.
|
|
466
|
-
static void mi_subproc_unsafe_destroy(mi_subproc_t* subproc)
|
|
506
|
+
static void mi_subproc_unsafe_destroy(mi_subproc_t* subproc, bool acquire_subprocs_lock)
|
|
467
507
|
{
|
|
508
|
+
if (subproc==NULL) return;
|
|
509
|
+
|
|
468
510
|
// remove from the subproc list
|
|
469
|
-
|
|
511
|
+
mi_lock_maybe(&subprocs_lock, acquire_subprocs_lock) {
|
|
470
512
|
if (subproc->next!=NULL) { subproc->next->prev = subproc->prev; }
|
|
471
513
|
if (subproc->prev!=NULL) { subproc->prev->next = subproc->next; }
|
|
472
514
|
else { mi_assert_internal(subprocs==subproc); subprocs = subproc->next; }
|
|
@@ -477,29 +519,38 @@ static void mi_subproc_unsafe_destroy(mi_subproc_t* subproc)
|
|
|
477
519
|
mi_heap_t* heap = subproc->heaps;
|
|
478
520
|
while (heap != NULL) {
|
|
479
521
|
mi_heap_t* next = heap->next;
|
|
480
|
-
if (heap!=subproc->heap_main) {mi_heap_destroy(heap); }
|
|
522
|
+
if (heap!=subproc->heap_main) { mi_heap_destroy(heap); }
|
|
481
523
|
heap = next;
|
|
482
524
|
}
|
|
483
525
|
mi_assert_internal(subproc->heaps == subproc->heap_main);
|
|
484
|
-
|
|
526
|
+
_mi_heap_force_destroy(subproc->heap_main); // no warning if destroying the main heap
|
|
485
527
|
}
|
|
486
528
|
|
|
529
|
+
// remove associated arenas
|
|
530
|
+
_mi_arenas_unsafe_destroy_all(subproc);
|
|
531
|
+
|
|
487
532
|
// merge stats back into the main subproc?
|
|
488
533
|
if (subproc!=&subproc_main) {
|
|
489
|
-
_mi_arenas_unsafe_destroy_all(subproc);
|
|
490
534
|
_mi_stats_merge_into(&subproc_main.stats, &subproc->stats);
|
|
535
|
+
}
|
|
491
536
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
537
|
+
// safe to release
|
|
538
|
+
// todo: should we refcount subprocesses?
|
|
539
|
+
mi_lock_done(&subproc->arena_reserve_lock);
|
|
540
|
+
mi_lock_done(&subproc->heaps_lock);
|
|
541
|
+
if (subproc!=&subproc_main) {
|
|
496
542
|
_mi_meta_free(subproc, sizeof(mi_subproc_t), subproc->memid);
|
|
497
543
|
}
|
|
544
|
+
else {
|
|
545
|
+
// for the main subproc, also release the global page map
|
|
546
|
+
_mi_page_map_unsafe_destroy(&subproc_main);
|
|
547
|
+
}
|
|
498
548
|
}
|
|
499
549
|
|
|
500
550
|
void mi_subproc_destroy(mi_subproc_id_t subproc_id) {
|
|
501
|
-
|
|
502
|
-
|
|
551
|
+
mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id);
|
|
552
|
+
if (subproc==NULL || subproc==&subproc_main) return;
|
|
553
|
+
mi_subproc_unsafe_destroy(subproc, true /* take lock */);
|
|
503
554
|
}
|
|
504
555
|
|
|
505
556
|
static void mi_subprocs_unsafe_destroy_all(void) {
|
|
@@ -508,12 +559,12 @@ static void mi_subprocs_unsafe_destroy_all(void) {
|
|
|
508
559
|
while (subproc!=NULL) {
|
|
509
560
|
mi_subproc_t* next = subproc->next;
|
|
510
561
|
if (subproc!=&subproc_main) {
|
|
511
|
-
mi_subproc_unsafe_destroy(subproc);
|
|
562
|
+
mi_subproc_unsafe_destroy(subproc, false /* take subprocs lock */);
|
|
512
563
|
}
|
|
513
564
|
subproc = next;
|
|
514
565
|
}
|
|
515
|
-
}
|
|
516
|
-
mi_subproc_unsafe_destroy(&subproc_main);
|
|
566
|
+
}
|
|
567
|
+
mi_subproc_unsafe_destroy(&subproc_main, true /* take subprocs lock */);
|
|
517
568
|
}
|
|
518
569
|
|
|
519
570
|
|
|
@@ -562,6 +613,7 @@ static mi_theap_t* _mi_thread_init_theap_default(void) {
|
|
|
562
613
|
// note: we cannot access thread-locals yet as that can cause (recursive) allocation
|
|
563
614
|
// (on macOS <= 14 for example where the loader allocates thread-local data on demand).
|
|
564
615
|
mi_tld_t* tld = mi_tld_alloc();
|
|
616
|
+
if (tld==NULL) return NULL; // things are very wrong if this fails (out of memory)
|
|
565
617
|
// allocate and initialize the theap for the main heap
|
|
566
618
|
theap = _mi_theap_create(mi_heap_main(), tld);
|
|
567
619
|
}
|
|
@@ -576,19 +628,50 @@ static mi_theap_t* _mi_thread_init_theap_default(void) {
|
|
|
576
628
|
static void mi_thread_theaps_done(mi_tld_t* tld)
|
|
577
629
|
{
|
|
578
630
|
// reset the thread local theaps
|
|
579
|
-
__mi_theap_main = NULL;
|
|
580
631
|
_mi_theap_default_set((mi_theap_t*)&_mi_theap_empty);
|
|
581
632
|
_mi_theap_cached_set((mi_theap_t*)&_mi_theap_empty);
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
mi_theap_t*
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
633
|
+
__mi_theap_main = NULL;
|
|
634
|
+
|
|
635
|
+
// abandon the pages of all theaps in this thread
|
|
636
|
+
mi_lock(&tld->theaps_lock) {
|
|
637
|
+
mi_theap_t* theap = tld->theaps;
|
|
638
|
+
while (theap != NULL) {
|
|
639
|
+
mi_theap_t* next = theap->tnext;
|
|
640
|
+
// never destroy theaps; if a dll is linked statically with mimalloc,
|
|
641
|
+
// there may still be delete/free calls after the mi_fls_done is called. Issue #207
|
|
642
|
+
_mi_theap_collect_abandon(theap);
|
|
643
|
+
mi_assert_internal(theap->page_count==0);
|
|
644
|
+
theap = next;
|
|
645
|
+
}
|
|
591
646
|
}
|
|
647
|
+
|
|
648
|
+
// free the theaps of this thread.
|
|
649
|
+
// This can run concurrently with a `mi_heap_free_theaps` and we need to ensure we free theaps atomically.
|
|
650
|
+
// We do this in a loop where we release the theaps_lock at every potential re-iteration to unblock
|
|
651
|
+
// potential concurrent `mi_heap_free_theaps` which tries to remove the theap from our theaps list.
|
|
652
|
+
bool all_freed;
|
|
653
|
+
do {
|
|
654
|
+
all_freed = true;
|
|
655
|
+
mi_lock(&tld->theaps_lock) {
|
|
656
|
+
mi_theap_t* theap = tld->theaps;
|
|
657
|
+
while (theap != NULL) {
|
|
658
|
+
mi_theap_t* next = theap->tnext;
|
|
659
|
+
mi_assert_internal(theap->page_count==0);
|
|
660
|
+
if (!_mi_theap_free(theap, true /* acquire heap->theaps_lock */, false /* dont re-acquire the tld->theaps_lock*/ )) {
|
|
661
|
+
all_freed = false;
|
|
662
|
+
}
|
|
663
|
+
theap = next;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
if (!all_freed) {
|
|
667
|
+
mi_subproc_stat_counter_increase(tld->subproc,heaps_delete_wait,1);
|
|
668
|
+
_mi_prim_thread_yield();
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
mi_assert_internal(tld->theaps==NULL);
|
|
672
|
+
}
|
|
673
|
+
} while (!all_freed);
|
|
674
|
+
|
|
592
675
|
mi_assert(_mi_theap_default()==(mi_theap_t*)&_mi_theap_empty); // careful to not re-initialize the default theap during theap_delete
|
|
593
676
|
mi_assert(!mi_theap_is_initialized(_mi_theap_default()));
|
|
594
677
|
}
|
|
@@ -613,11 +696,10 @@ static void mi_thread_theaps_done(mi_tld_t* tld)
|
|
|
613
696
|
|
|
614
697
|
// Set up handlers so `mi_thread_done` is called automatically
|
|
615
698
|
static void mi_process_setup_auto_thread_done(void) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
_mi_theap_default_set(&theap_main);
|
|
699
|
+
mi_atomic_do_once {
|
|
700
|
+
_mi_prim_thread_init_auto_done();
|
|
701
|
+
_mi_theap_default_set(&theap_main);
|
|
702
|
+
}
|
|
621
703
|
}
|
|
622
704
|
|
|
623
705
|
|
|
@@ -635,7 +717,7 @@ void mi_thread_init(void) mi_attr_noexcept
|
|
|
635
717
|
if (_mi_thread_is_initialized()) return;
|
|
636
718
|
|
|
637
719
|
// initialize the default theap
|
|
638
|
-
_mi_thread_init_theap_default();
|
|
720
|
+
if (_mi_thread_init_theap_default() == NULL) return; // out-of-memory on tld/theap allocation
|
|
639
721
|
|
|
640
722
|
mi_heap_stat_increase(mi_heap_main(), threads, 1);
|
|
641
723
|
// _mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
|
@@ -649,7 +731,11 @@ void _mi_thread_done(mi_theap_t* _theap_main)
|
|
|
649
731
|
{
|
|
650
732
|
// NULL can be passed on some platforms
|
|
651
733
|
if (_theap_main==NULL) {
|
|
652
|
-
_theap_main = __mi_theap_main;
|
|
734
|
+
_theap_main = __mi_theap_main; // don't call `mi_theap_main_safe` as that re-initializes the thread
|
|
735
|
+
if (_theap_main==NULL) { // can happen if `mi_theap_main_safe` is never called; but then the default is main
|
|
736
|
+
_theap_main = _mi_theap_default();
|
|
737
|
+
mi_assert_internal(_theap_main==NULL || _mi_is_theap_main(_theap_main));
|
|
738
|
+
}
|
|
653
739
|
}
|
|
654
740
|
|
|
655
741
|
// prevent re-entrancy through theap_done/theap_set_default_direct (issue #699)
|
|
@@ -699,8 +785,8 @@ mi_decl_cold mi_decl_noinline mi_theap_t* _mi_theap_empty_get(void) {
|
|
|
699
785
|
#else
|
|
700
786
|
// with only direct entries, use the "arbitrary user data" field
|
|
701
787
|
// and assume it is NULL (see also <http://www.nynaeve.net/?p=98>)
|
|
702
|
-
#define MI_TLS_INITIAL_EXPANSION_SLOT (0)
|
|
703
788
|
#define MI_TLS_INITIAL_SLOT (5)
|
|
789
|
+
#define MI_TLS_INITIAL_EXPANSION_SLOT (0)
|
|
704
790
|
#endif
|
|
705
791
|
|
|
706
792
|
// we initially use the last of the expansion slots as the default NULL.
|
|
@@ -710,38 +796,62 @@ mi_decl_hidden size_t _mi_theap_default_expansion_slot = MI_TLS_INITIAL_EXPANSIO
|
|
|
710
796
|
mi_decl_hidden size_t _mi_theap_cached_slot = MI_TLS_INITIAL_SLOT;
|
|
711
797
|
mi_decl_hidden size_t _mi_theap_cached_expansion_slot = MI_TLS_INITIAL_EXPANSION_SLOT;
|
|
712
798
|
|
|
713
|
-
static
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
799
|
+
static DWORD mi_tls_raw_index_default = TLS_OUT_OF_INDEXES;
|
|
800
|
+
static DWORD mi_tls_raw_index_cached = TLS_OUT_OF_INDEXES;
|
|
801
|
+
|
|
802
|
+
static bool mi_win_tls_slot_alloc(size_t* slot, size_t* extended, DWORD* raw_index) {
|
|
803
|
+
const DWORD index = TlsAlloc();
|
|
804
|
+
*raw_index = index;
|
|
805
|
+
if (index==TLS_OUT_OF_INDEXES) {
|
|
717
806
|
*extended = 0;
|
|
718
|
-
|
|
807
|
+
*slot = 0;
|
|
808
|
+
return false;
|
|
719
809
|
}
|
|
720
|
-
else if (
|
|
810
|
+
else if (index<MI_TLS_DIRECT_SLOTS) {
|
|
721
811
|
*extended = 0;
|
|
722
|
-
|
|
812
|
+
*slot = index + MI_TLS_DIRECT_FIRST;
|
|
813
|
+
return true;
|
|
814
|
+
}
|
|
815
|
+
#if !MI_WIN_DIRECT_TLS
|
|
816
|
+
else if (index < MI_TLS_DIRECT_SLOTS + MI_TLS_EXPANSION_SLOTS - 1) { // check maximum number of expansion slots - 1 (as we use the last one as the default)
|
|
817
|
+
*extended = index - MI_TLS_DIRECT_SLOTS;
|
|
818
|
+
*slot = MI_TLS_EXPANSION_SLOT;
|
|
819
|
+
return true;
|
|
723
820
|
}
|
|
821
|
+
#endif
|
|
724
822
|
else {
|
|
725
|
-
|
|
823
|
+
// to high an index for us
|
|
824
|
+
_mi_error_message(EFAULT, "returned tls index was too high (%u)\n", index);
|
|
825
|
+
TlsFree(index);
|
|
826
|
+
*raw_index = TLS_OUT_OF_INDEXES;
|
|
726
827
|
*extended = 0;
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
828
|
+
*slot = 0;
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
static void mi_win_tls_slot_free(DWORD* raw_index) {
|
|
834
|
+
if (*raw_index != TLS_OUT_OF_INDEXES) {
|
|
835
|
+
TlsFree(*raw_index);
|
|
836
|
+
*raw_index = TLS_OUT_OF_INDEXES;
|
|
732
837
|
}
|
|
733
838
|
}
|
|
734
839
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
840
|
+
static void mi_tls_slots_init(void) {
|
|
841
|
+
mi_atomic_do_once {
|
|
842
|
+
bool ok = mi_win_tls_slot_alloc(&_mi_theap_default_slot, &_mi_theap_default_expansion_slot, &mi_tls_raw_index_default);
|
|
843
|
+
if (ok) {
|
|
844
|
+
ok = mi_win_tls_slot_alloc(&_mi_theap_cached_slot, &_mi_theap_cached_expansion_slot, &mi_tls_raw_index_cached);
|
|
845
|
+
}
|
|
846
|
+
if (!ok) {
|
|
741
847
|
_mi_error_message(EFAULT, "unable to allocate fast TLS user slot (0x%zx)\n", _mi_theap_cached_slot);
|
|
742
848
|
}
|
|
743
849
|
}
|
|
744
|
-
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
static void mi_tls_slots_done(void) {
|
|
853
|
+
mi_win_tls_slot_free(&mi_tls_raw_index_default);
|
|
854
|
+
mi_win_tls_slot_free(&mi_tls_raw_index_cached );
|
|
745
855
|
}
|
|
746
856
|
|
|
747
857
|
static void mi_win_tls_slot_set(size_t slot, size_t extended_slot, void* value) {
|
|
@@ -761,43 +871,90 @@ static void mi_win_tls_slot_set(size_t slot, size_t extended_slot, void* value)
|
|
|
761
871
|
mi_decl_hidden pthread_key_t _mi_theap_default_key = 0;
|
|
762
872
|
mi_decl_hidden pthread_key_t _mi_theap_cached_key = 0;
|
|
763
873
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
874
|
+
// create a non-zero pthread key
|
|
875
|
+
static int mi_pthread_key_create( pthread_key_t* pkey ) {
|
|
876
|
+
pthread_key_t key;
|
|
877
|
+
int err = pthread_key_create(&key, NULL);
|
|
878
|
+
if (err!=0) return err;
|
|
879
|
+
if (key==0) {
|
|
880
|
+
// if we get a zero key, create another one as we use 0 for an invalid key
|
|
881
|
+
pthread_key_t key2;
|
|
882
|
+
err = pthread_key_create(&key2, NULL);
|
|
883
|
+
pthread_key_delete(key); // delete the old key
|
|
884
|
+
if (err!=0) return err;
|
|
885
|
+
key = key2;
|
|
886
|
+
}
|
|
887
|
+
mi_assert_internal(key!=0);
|
|
888
|
+
*pkey = key;
|
|
889
|
+
return 0;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
static void mi_tls_slots_init(void) {
|
|
893
|
+
mi_atomic_do_once {
|
|
894
|
+
int err = mi_pthread_key_create(&_mi_theap_default_key);
|
|
895
|
+
if (err==0) {
|
|
896
|
+
err = mi_pthread_key_create(&_mi_theap_cached_key);
|
|
897
|
+
}
|
|
898
|
+
if (err!=0) {
|
|
899
|
+
_mi_error_message(EFAULT, "unable to allocate pthread keys (error %d)\n", err);
|
|
900
|
+
}
|
|
769
901
|
}
|
|
770
|
-
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
static void mi_tls_slots_done(void) {
|
|
905
|
+
if (_mi_theap_default_key != 0) {
|
|
906
|
+
pthread_key_delete(_mi_theap_default_key);
|
|
907
|
+
_mi_theap_default_key = 0;
|
|
908
|
+
}
|
|
909
|
+
if (_mi_theap_cached_key != 0) {
|
|
910
|
+
pthread_key_delete(_mi_theap_cached_key);
|
|
911
|
+
_mi_theap_cached_key = 0;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
#else
|
|
916
|
+
|
|
917
|
+
static void mi_tls_slots_init(void) {
|
|
918
|
+
// nothing
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
static void mi_tls_slots_done(void) {
|
|
922
|
+
// nothing
|
|
771
923
|
}
|
|
772
924
|
|
|
773
925
|
#endif
|
|
774
926
|
|
|
775
927
|
void _mi_theap_cached_set(mi_theap_t* theap) {
|
|
928
|
+
mi_theap_t* prev = _mi_theap_cached();
|
|
929
|
+
if (prev==theap) return;
|
|
930
|
+
// set
|
|
931
|
+
mi_tls_slots_init();
|
|
776
932
|
#if MI_TLS_MODEL_THREAD_LOCAL
|
|
777
933
|
__mi_theap_cached = theap;
|
|
778
934
|
#elif MI_TLS_MODEL_FIXED_SLOT
|
|
779
935
|
mi_prim_tls_slot_set(MI_TLS_MODEL_FIXED_SLOT_CACHED, theap);
|
|
780
936
|
#elif MI_TLS_MODEL_DYNAMIC_WIN32
|
|
781
|
-
_mi_win_tls_slots_init();
|
|
782
937
|
mi_win_tls_slot_set(_mi_theap_cached_slot, _mi_theap_cached_expansion_slot, theap);
|
|
783
938
|
#elif MI_TLS_MODEL_DYNAMIC_PTHREADS
|
|
784
|
-
_mi_tls_keys_init();
|
|
785
939
|
if (_mi_theap_cached_key!=0) pthread_setspecific(_mi_theap_cached_key, theap);
|
|
786
940
|
#endif
|
|
941
|
+
// update refcounts (so cached theap memory keeps available until no longer cached)
|
|
942
|
+
_mi_theap_incref(theap);
|
|
943
|
+
_mi_theap_decref(prev);
|
|
787
944
|
}
|
|
788
945
|
|
|
789
946
|
void _mi_theap_default_set(mi_theap_t* theap) {
|
|
947
|
+
mi_theap_t* const theap_old = _mi_theap_default();
|
|
790
948
|
mi_assert_internal(theap != NULL);
|
|
791
949
|
mi_assert_internal(theap->tld->thread_id==0 || theap->tld->thread_id==_mi_thread_id());
|
|
950
|
+
mi_tls_slots_init();
|
|
792
951
|
#if MI_TLS_MODEL_THREAD_LOCAL
|
|
793
952
|
__mi_theap_default = theap;
|
|
794
953
|
#elif MI_TLS_MODEL_FIXED_SLOT
|
|
795
954
|
mi_prim_tls_slot_set(MI_TLS_MODEL_FIXED_SLOT_DEFAULT, theap);
|
|
796
955
|
#elif MI_TLS_MODEL_DYNAMIC_WIN32
|
|
797
|
-
_mi_win_tls_slots_init();
|
|
798
956
|
mi_win_tls_slot_set(_mi_theap_default_slot, _mi_theap_default_expansion_slot, theap);
|
|
799
957
|
#elif MI_TLS_MODEL_DYNAMIC_PTHREADS
|
|
800
|
-
_mi_tls_keys_init();
|
|
801
958
|
if (_mi_theap_default_key!=0) pthread_setspecific(_mi_theap_default_key, theap);
|
|
802
959
|
#endif
|
|
803
960
|
|
|
@@ -805,10 +962,15 @@ void _mi_theap_default_set(mi_theap_t* theap) {
|
|
|
805
962
|
if (mi_theap_is_initialized(theap)) {
|
|
806
963
|
// ensure the default theap is passed to `_mi_thread_done` as on some platforms we cannot access TLS at thread termination (as it would allocate again)
|
|
807
964
|
_mi_prim_thread_associate_default_theap(theap);
|
|
808
|
-
if (_mi_is_heap_main(theap
|
|
965
|
+
if (_mi_is_heap_main(_mi_theap_heap(theap))) {
|
|
809
966
|
__mi_theap_main = theap;
|
|
810
967
|
}
|
|
811
968
|
}
|
|
969
|
+
|
|
970
|
+
// ensure either the default slot contains the main theap, or __mi_theap_main is initialized
|
|
971
|
+
if (mi_theap_is_initialized(theap_old) && _mi_is_heap_main(_mi_theap_heap(theap_old))) {
|
|
972
|
+
__mi_theap_main = theap_old;
|
|
973
|
+
}
|
|
812
974
|
}
|
|
813
975
|
|
|
814
976
|
void mi_thread_set_in_threadpool(void) mi_attr_noexcept {
|
|
@@ -932,13 +1094,8 @@ static void mi_detect_cpu_features(void) {
|
|
|
932
1094
|
|
|
933
1095
|
|
|
934
1096
|
// Initialize the process; called by thread_init or the process loader
|
|
935
|
-
void
|
|
936
|
-
|
|
937
|
-
static mi_atomic_once_t process_init;
|
|
938
|
-
// #if _MSC_VER < 1920
|
|
939
|
-
// mi_heap_main_init(); // vs2017 can dynamically re-initialize theap_main
|
|
940
|
-
// #endif
|
|
941
|
-
if (!mi_atomic_once(&process_init)) return;
|
|
1097
|
+
static void mi_process_init_once(void) mi_attr_noexcept {
|
|
1098
|
+
_mi_process_is_initialized = true;
|
|
942
1099
|
_mi_verbose_message("process init: 0x%zx\n", _mi_thread_id());
|
|
943
1100
|
|
|
944
1101
|
mi_detect_cpu_features();
|
|
@@ -978,6 +1135,16 @@ void mi_process_init(void) mi_attr_noexcept {
|
|
|
978
1135
|
}
|
|
979
1136
|
}
|
|
980
1137
|
|
|
1138
|
+
// Initialize the process; called by thread_init or the process loader
|
|
1139
|
+
void mi_process_init(void) mi_attr_noexcept {
|
|
1140
|
+
// #if _MSC_VER < 1920
|
|
1141
|
+
// mi_heap_main_init(); // vs2017 can dynamically re-initialize _mi_heap_main
|
|
1142
|
+
// #endif
|
|
1143
|
+
mi_atomic_do_once {
|
|
1144
|
+
mi_process_init_once();
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
981
1148
|
// Called when the process is done (cdecl as it is used with `at_exit` on some platforms)
|
|
982
1149
|
void mi_cdecl mi_process_done(void) mi_attr_noexcept {
|
|
983
1150
|
// only shutdown if we were initialized
|
|
@@ -1002,21 +1169,25 @@ void mi_cdecl mi_process_done(void) mi_attr_noexcept {
|
|
|
1002
1169
|
#endif
|
|
1003
1170
|
#endif
|
|
1004
1171
|
|
|
1172
|
+
// done with tracking tools
|
|
1173
|
+
mi_track_done()
|
|
1174
|
+
|
|
1005
1175
|
// Forcefully release all retained memory; this can be dangerous in general if overriding regular malloc/free
|
|
1006
1176
|
// since after process_done there might still be other code running that calls `free` (like at_exit routines,
|
|
1007
1177
|
// or C-runtime termination code.
|
|
1008
1178
|
if (mi_option_is_enabled(mi_option_destroy_on_exit)) {
|
|
1009
|
-
mi_subprocs_unsafe_destroy_all();
|
|
1010
|
-
_mi_page_map_unsafe_destroy(_mi_subproc_main());
|
|
1179
|
+
mi_subprocs_unsafe_destroy_all(); // destroys all subprocs, arenas, and the page_map!
|
|
1011
1180
|
}
|
|
1012
1181
|
else {
|
|
1013
1182
|
mi_heap_stats_merge_to_subproc(mi_heap_main());
|
|
1014
1183
|
}
|
|
1015
|
-
|
|
1184
|
+
|
|
1185
|
+
// careful now to no longer access any allocator functionality
|
|
1016
1186
|
if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) {
|
|
1017
|
-
mi_subproc_stats_print_out(
|
|
1187
|
+
mi_subproc_stats_print_out(mi_subproc_main(), NULL, NULL);
|
|
1018
1188
|
}
|
|
1019
1189
|
mi_lock_done(&subprocs_lock);
|
|
1190
|
+
mi_tls_slots_done();
|
|
1020
1191
|
_mi_allocator_done();
|
|
1021
1192
|
_mi_verbose_message("process done: 0x%zx\n", tld_main.thread_id);
|
|
1022
1193
|
os_preloading = true; // don't call the C runtime anymore
|