@shd101wyy/yo 0.1.24 → 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-core-patterns/core-patterns-cheatsheet.md +30 -0
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +436 -2
- package/out/cjs/index.cjs +551 -553
- package/out/cjs/yo-cli.cjs +638 -632
- package/out/cjs/yo-lsp.cjs +595 -597
- package/out/esm/index.mjs +487 -489
- package/out/types/src/codegen/utils/index.d.ts +1 -0
- package/out/types/src/expr.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/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
|
@@ -115,9 +115,12 @@ mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexce
|
|
|
115
115
|
if (size <= MI_LARGE_MAX_OBJ_SIZE) {
|
|
116
116
|
return _mi_bin_size(mi_bin(size + MI_PADDING_SIZE));
|
|
117
117
|
}
|
|
118
|
-
else {
|
|
118
|
+
else if (size <= MI_MAX_ALLOC_SIZE) {
|
|
119
119
|
return _mi_align_up(size + MI_PADDING_SIZE,_mi_os_page_size());
|
|
120
120
|
}
|
|
121
|
+
else {
|
|
122
|
+
return size;
|
|
123
|
+
}
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
#if (MI_DEBUG>1)
|
|
@@ -205,25 +208,25 @@ static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) {
|
|
|
205
208
|
// range of entries in `_mi_page_small_free`.
|
|
206
209
|
static inline void mi_theap_queue_first_update(mi_theap_t* theap, const mi_page_queue_t* pq) {
|
|
207
210
|
mi_assert_internal(mi_theap_contains_queue(theap,pq));
|
|
208
|
-
size_t size = pq->block_size;
|
|
211
|
+
const size_t size = pq->block_size;
|
|
209
212
|
if (size > MI_SMALL_SIZE_MAX) return;
|
|
210
213
|
|
|
211
214
|
mi_page_t* page = pq->first;
|
|
212
215
|
if (pq->first == NULL) page = (mi_page_t*)&_mi_page_empty;
|
|
213
216
|
|
|
214
217
|
// find index in the right direct page array
|
|
215
|
-
size_t
|
|
216
|
-
|
|
217
|
-
mi_page_t** pages_free = theap->pages_free_direct;
|
|
218
|
-
|
|
218
|
+
const size_t idx = _mi_wsize_from_size(size);
|
|
219
|
+
mi_page_t** const pages_free = theap->pages_free_direct;
|
|
219
220
|
if (pages_free[idx] == page) return; // already set
|
|
220
221
|
|
|
221
222
|
// find start slot
|
|
223
|
+
size_t start;
|
|
222
224
|
if (idx<=1) {
|
|
223
225
|
start = 0;
|
|
224
226
|
}
|
|
225
227
|
else {
|
|
226
228
|
// find previous size; due to minimal alignment upto 3 previous bins may need to be skipped
|
|
229
|
+
mi_assert_internal(pq > &theap->pages[0]); // since idx > 1
|
|
227
230
|
size_t bin = mi_bin(size);
|
|
228
231
|
const mi_page_queue_t* prev = pq - 1;
|
|
229
232
|
while( bin == mi_bin(prev->block_size) && prev > &theap->pages[0]) {
|
|
@@ -41,10 +41,12 @@ static bool mi_page_extend_free(mi_theap_t* theap, mi_page_t* page);
|
|
|
41
41
|
|
|
42
42
|
#if (MI_DEBUG>=3)
|
|
43
43
|
static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) {
|
|
44
|
-
mi_assert_internal(_mi_ptr_page(page) == page);
|
|
44
|
+
mi_assert_internal(_mi_ptr_page(page->page_start) == page);
|
|
45
|
+
const uint8_t* slice_start = mi_page_slice_start(page);
|
|
46
|
+
mi_assert_internal(_mi_is_aligned(slice_start,MI_PAGE_ALIGN));
|
|
45
47
|
size_t count = 0;
|
|
46
48
|
while (head != NULL) {
|
|
47
|
-
mi_assert_internal((uint8_t*)head -
|
|
49
|
+
mi_assert_internal((uint8_t*)head - slice_start > (ptrdiff_t)MI_LARGE_PAGE_SIZE || page == _mi_ptr_page(head));
|
|
48
50
|
count++;
|
|
49
51
|
head = mi_block_next(page, head);
|
|
50
52
|
}
|
|
@@ -152,10 +154,15 @@ static void mi_page_thread_collect_to_local(mi_page_t* page, mi_block_t* head)
|
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
// if `count > max_count` there was a memory corruption (possibly infinite list due to double multi-threaded free)
|
|
155
|
-
if (count > max_count) {
|
|
157
|
+
if mi_unlikely(count > max_count) {
|
|
156
158
|
_mi_error_message(EFAULT, "corrupted thread-free list\n");
|
|
157
159
|
return; // the thread-free items cannot be freed
|
|
158
160
|
}
|
|
161
|
+
// if `count > page->used` there was another kind memory corruption (either in the page meta-data or in the linked list)
|
|
162
|
+
else if mi_unlikely(count > page->used) {
|
|
163
|
+
_mi_error_message(EFAULT, "corrupted meta-data in thread-free list\n");
|
|
164
|
+
return; // the thread-free items cannot be freed
|
|
165
|
+
}
|
|
159
166
|
|
|
160
167
|
// and append the current local free list
|
|
161
168
|
mi_block_set_next(page, last, page->local_free);
|
|
@@ -279,8 +286,8 @@ void _mi_page_reclaim(mi_theap_t* theap, mi_page_t* page) {
|
|
|
279
286
|
// called from `mi_free` on a reclaim, and fresh_alloc if we get an abandoned page
|
|
280
287
|
void _mi_theap_page_reclaim(mi_theap_t* theap, mi_page_t* page)
|
|
281
288
|
{
|
|
282
|
-
mi_assert_internal(_mi_is_aligned(page, MI_PAGE_ALIGN));
|
|
283
|
-
mi_assert_internal(_mi_ptr_page(page)==page);
|
|
289
|
+
mi_assert_internal(_mi_is_aligned(mi_page_slice_start(page), MI_PAGE_ALIGN));
|
|
290
|
+
mi_assert_internal(_mi_ptr_page(mi_page_start(page))==page);
|
|
284
291
|
mi_assert_internal(mi_page_is_owned(page));
|
|
285
292
|
mi_assert_internal(mi_page_is_abandoned(page));
|
|
286
293
|
|
|
@@ -608,7 +615,7 @@ static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, co
|
|
|
608
615
|
----------------------------------------------------------- */
|
|
609
616
|
|
|
610
617
|
#define MI_MAX_EXTEND_SIZE (4*1024) // heuristic, one OS page seems to work well.
|
|
611
|
-
#if (MI_SECURE>=
|
|
618
|
+
#if (MI_SECURE>=2)
|
|
612
619
|
#define MI_MIN_EXTEND (8*MI_SECURE) // extend at least by this many
|
|
613
620
|
#else
|
|
614
621
|
#define MI_MIN_EXTEND (1)
|
|
@@ -667,7 +674,7 @@ static bool mi_page_extend_free(mi_theap_t* theap, mi_page_t* page) {
|
|
|
667
674
|
}
|
|
668
675
|
|
|
669
676
|
// and append the extend the free list
|
|
670
|
-
if (extend < MI_MIN_SLICES || MI_SECURE<
|
|
677
|
+
if (extend < MI_MIN_SLICES || MI_SECURE<2) { //!mi_option_is_enabled(mi_option_secure)) {
|
|
671
678
|
mi_page_free_list_extend(page, bsize, extend );
|
|
672
679
|
}
|
|
673
680
|
else {
|
|
@@ -686,7 +693,7 @@ static bool mi_page_extend_free(mi_theap_t* theap, mi_page_t* page) {
|
|
|
686
693
|
mi_decl_nodiscard bool _mi_page_init(mi_theap_t* theap, mi_page_t* page) {
|
|
687
694
|
mi_assert(page != NULL);
|
|
688
695
|
mi_assert(theap!=NULL);
|
|
689
|
-
page->heap = (_mi_is_heap_main(theap
|
|
696
|
+
page->heap = (_mi_is_heap_main(_mi_theap_heap(theap)) ? NULL : _mi_theap_heap(theap)); // faster for `mi_page_associated_theap`
|
|
690
697
|
mi_page_set_theap(page, theap);
|
|
691
698
|
|
|
692
699
|
size_t page_size;
|
|
@@ -856,7 +863,7 @@ static mi_page_t* mi_find_free_page(mi_theap_t* theap, mi_page_queue_t* pq) {
|
|
|
856
863
|
// check the first page: we even do this with candidate search or otherwise we re-search every time
|
|
857
864
|
mi_page_t* page = pq->first;
|
|
858
865
|
if mi_likely(page != NULL && mi_page_free_quick_collect(page)) {
|
|
859
|
-
#if (MI_SECURE>=
|
|
866
|
+
#if (MI_SECURE>=2) // in secure mode, we extend half the time to increase randomness
|
|
860
867
|
if (page->capacity < page->reserved && ((_mi_theap_random_next(theap) & 1) == 1)) {
|
|
861
868
|
(void)mi_page_extend_free(theap, page); // ok if this fails
|
|
862
869
|
mi_assert_internal(mi_page_immediate_available(page));
|
|
@@ -878,21 +885,24 @@ static mi_page_t* mi_find_free_page(mi_theap_t* theap, mi_page_queue_t* pq) {
|
|
|
878
885
|
a certain number of allocations.
|
|
879
886
|
----------------------------------------------------------- */
|
|
880
887
|
|
|
881
|
-
|
|
882
|
-
static _Atomic(void*)
|
|
888
|
+
// The program should only install a single deferred free handler before doing allocation.
|
|
889
|
+
static _Atomic(void*) deferred_free; // is `mi_deferred_free_fun*` (but some platforms don't support atomic function pointers)
|
|
890
|
+
static _Atomic(void*) deferred_arg;
|
|
883
891
|
|
|
884
892
|
void _mi_deferred_free(mi_theap_t* theap, bool force) {
|
|
885
893
|
theap->heartbeat++;
|
|
886
|
-
|
|
894
|
+
mi_deferred_free_fun* const fun = (mi_deferred_free_fun*)mi_atomic_load_ptr_acquire(void,&deferred_free);
|
|
895
|
+
if (fun != NULL && !theap->tld->recurse) {
|
|
887
896
|
theap->tld->recurse = true;
|
|
888
|
-
|
|
897
|
+
void* const arg = mi_atomic_load_ptr_acquire(void,&deferred_arg);
|
|
898
|
+
fun(force, theap->heartbeat, arg);
|
|
889
899
|
theap->tld->recurse = false;
|
|
890
900
|
}
|
|
891
901
|
}
|
|
892
902
|
|
|
893
903
|
void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noexcept {
|
|
894
|
-
deferred_free = fn;
|
|
895
904
|
mi_atomic_store_ptr_release(void,&deferred_arg, arg);
|
|
905
|
+
mi_atomic_store_ptr_release(void,&deferred_free, (void*)fn);
|
|
896
906
|
}
|
|
897
907
|
|
|
898
908
|
|
|
@@ -1013,8 +1023,8 @@ void* _mi_malloc_generic(mi_theap_t* theap, size_t size, size_t zero_huge_alignm
|
|
|
1013
1023
|
|
|
1014
1024
|
mi_assert_internal(mi_page_immediate_available(page));
|
|
1015
1025
|
mi_assert_internal(mi_page_block_size(page) >= size);
|
|
1016
|
-
mi_assert_internal(_mi_is_aligned(page, MI_PAGE_ALIGN));
|
|
1017
|
-
mi_assert_internal(_mi_ptr_page(page)==page);
|
|
1026
|
+
mi_assert_internal(_mi_is_aligned(mi_page_slice_start(page), MI_PAGE_ALIGN));
|
|
1027
|
+
mi_assert_internal(_mi_ptr_page(mi_page_start(page))==page);
|
|
1018
1028
|
|
|
1019
1029
|
// and try again, this time succeeding! (i.e. this should never recurse through _mi_page_malloc)
|
|
1020
1030
|
if (usable!=NULL) { *usable = mi_page_usable_block_size(page); }
|
|
@@ -12,6 +12,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
|
|
12
12
|
#include "mimalloc/atomic.h"
|
|
13
13
|
#include "mimalloc/prim.h"
|
|
14
14
|
|
|
15
|
+
#include <sched.h> // sched_yield
|
|
16
|
+
#include <unistd.h> // getentropy
|
|
17
|
+
|
|
15
18
|
// Design
|
|
16
19
|
// ======
|
|
17
20
|
//
|
|
@@ -223,7 +226,9 @@ void _mi_prim_thread_init_auto_done(void) {
|
|
|
223
226
|
}
|
|
224
227
|
|
|
225
228
|
void _mi_prim_thread_done_auto_done(void) {
|
|
226
|
-
//
|
|
229
|
+
if (_mi_heap_default_key != (pthread_key_t)(-1)) { // do not leak the key, see issue #809
|
|
230
|
+
pthread_key_delete(_mi_heap_default_key);
|
|
231
|
+
}
|
|
227
232
|
}
|
|
228
233
|
|
|
229
234
|
void _mi_prim_thread_associate_default_theap(mi_theap_t* theap) {
|
|
@@ -250,3 +255,7 @@ void _mi_prim_thread_associate_default_theap(mi_theap_t* theap) {
|
|
|
250
255
|
bool _mi_prim_thread_is_in_threadpool(void) {
|
|
251
256
|
return false;
|
|
252
257
|
}
|
|
258
|
+
|
|
259
|
+
void _mi_prim_thread_yield(void) {
|
|
260
|
+
sched_yield();
|
|
261
|
+
}
|
|
@@ -41,10 +41,18 @@ extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_im
|
|
|
41
41
|
malloc zone members
|
|
42
42
|
------------------------------------------------------ */
|
|
43
43
|
|
|
44
|
+
static bool is_mimalloc_zone( malloc_zone_t* zone );
|
|
45
|
+
|
|
44
46
|
static size_t zone_size(malloc_zone_t* zone, const void* p) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
if (mi_any_heap_contains(p)) {
|
|
48
|
+
return mi_usable_size(p);
|
|
49
|
+
}
|
|
50
|
+
else if (!is_mimalloc_zone(zone)) { // can happen due to interpose
|
|
51
|
+
return zone->size(zone,p);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
static void* zone_malloc(malloc_zone_t* zone, size_t size) {
|
|
@@ -63,14 +71,24 @@ static void* zone_valloc(malloc_zone_t* zone, size_t size) {
|
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
static void zone_free(malloc_zone_t* zone, void* p) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
if (mi_any_heap_contains(p)) {
|
|
75
|
+
mi_free(p); // with the page_map and pagemap_commit=1 we can use the regular free
|
|
76
|
+
}
|
|
77
|
+
else if (!is_mimalloc_zone(zone)) { // can happen due to interpose
|
|
78
|
+
zone->free(zone,p);
|
|
79
|
+
}
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) {
|
|
72
|
-
|
|
73
|
-
|
|
83
|
+
if (p == NULL || mi_any_heap_contains(p)) {
|
|
84
|
+
return mi_realloc(p, newsize);
|
|
85
|
+
}
|
|
86
|
+
else if (!is_mimalloc_zone(zone)) { // can happen due to interpose
|
|
87
|
+
return zone->realloc(zone,p,newsize);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
return NULL;
|
|
91
|
+
}
|
|
74
92
|
}
|
|
75
93
|
|
|
76
94
|
static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) {
|
|
@@ -79,8 +97,9 @@ static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) {
|
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
static void zone_destroy(malloc_zone_t* zone) {
|
|
82
|
-
|
|
83
|
-
|
|
100
|
+
if (!is_mimalloc_zone(zone)) {
|
|
101
|
+
zone->destroy(zone);
|
|
102
|
+
}
|
|
84
103
|
}
|
|
85
104
|
|
|
86
105
|
static unsigned zone_batch_malloc(malloc_zone_t* zone, size_t size, void** ps, unsigned count) {
|
|
@@ -241,6 +260,9 @@ static malloc_zone_t mi_malloc_zone = {
|
|
|
241
260
|
}
|
|
242
261
|
#endif
|
|
243
262
|
|
|
263
|
+
static bool is_mimalloc_zone( malloc_zone_t* zone ) {
|
|
264
|
+
return (zone==NULL || zone==&mi_malloc_zone);
|
|
265
|
+
}
|
|
244
266
|
|
|
245
267
|
#if defined(MI_OSX_INTERPOSE) && defined(MI_SHARED_LIB_EXPORT)
|
|
246
268
|
|
|
@@ -254,11 +276,8 @@ static malloc_zone_t mi_malloc_zone = {
|
|
|
254
276
|
// `malloc_zone_calloc` etc. see <https://github.com/aosm/libmalloc/blob/master/man/malloc_zone_malloc.3>
|
|
255
277
|
// ------------------------------------------------------
|
|
256
278
|
|
|
257
|
-
static inline malloc_zone_t* mi_get_default_zone(void)
|
|
258
|
-
{
|
|
259
|
-
static bool init;
|
|
260
|
-
if mi_unlikely(!init) {
|
|
261
|
-
init = true;
|
|
279
|
+
static inline malloc_zone_t* mi_get_default_zone(void) {
|
|
280
|
+
mi_atomic_do_once {
|
|
262
281
|
malloc_zone_register(&mi_malloc_zone); // by calling register we avoid a zone error on free (see <http://eatmyrandom.blogspot.com/2010/03/mallocfree-interception-on-mac-os-x.html>)
|
|
263
282
|
}
|
|
264
283
|
return &mi_malloc_zone;
|
|
@@ -329,7 +348,7 @@ static bool zone_check(malloc_zone_t* zone) {
|
|
|
329
348
|
|
|
330
349
|
static malloc_zone_t* zone_from_ptr(const void* p) {
|
|
331
350
|
MI_UNUSED(p);
|
|
332
|
-
return mi_get_default_zone();
|
|
351
|
+
return (mi_any_heap_contains(p) ? mi_get_default_zone() : NULL);
|
|
333
352
|
}
|
|
334
353
|
|
|
335
354
|
static void zone_log(malloc_zone_t* zone, void* p) {
|
|
@@ -25,7 +25,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|
|
25
25
|
#include "mimalloc/prim.h"
|
|
26
26
|
|
|
27
27
|
#include <sys/mman.h> // mmap
|
|
28
|
-
#include <unistd.h> // sysconf
|
|
28
|
+
#include <unistd.h> // sysconf, sleep
|
|
29
29
|
#include <fcntl.h> // open, close, read, access
|
|
30
30
|
#include <stdlib.h> // getenv, arc4random_buf
|
|
31
31
|
|
|
@@ -185,8 +185,16 @@ static void unix_detect_physical_memory( size_t page_size, size_t* physical_memo
|
|
|
185
185
|
MI_UNUSED(page_size);
|
|
186
186
|
struct sysinfo info; _mi_memzero_var(info);
|
|
187
187
|
const int err = sysinfo(&info);
|
|
188
|
-
if (err==0 && info.
|
|
189
|
-
|
|
188
|
+
if (err==0 && info.mem_unit > 0 && info.totalram <= SIZE_MAX) {
|
|
189
|
+
if (info.mem_unit==MI_KiB) {
|
|
190
|
+
*physical_memory_in_kib = (size_t)info.totalram;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
size_t total = 0;
|
|
194
|
+
if (!mi_mul_overflow((size_t)info.totalram, (size_t)info.mem_unit, &total)) {
|
|
195
|
+
*physical_memory_in_kib = (total / MI_KiB);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
190
198
|
}
|
|
191
199
|
#elif defined(_SC_PHYS_PAGES) // do not use by default as it might cause allocation (by using `fopen` to parse /proc/meminfo) (issue #1100)
|
|
192
200
|
const long pphys = sysconf(_SC_PHYS_PAGES);
|
|
@@ -213,19 +221,13 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config )
|
|
|
213
221
|
|
|
214
222
|
// disable transparent huge pages for this process?
|
|
215
223
|
#if (defined(__linux__) || defined(__ANDROID__)) && defined(PR_GET_THP_DISABLE)
|
|
216
|
-
#if defined(MI_NO_THP)
|
|
217
|
-
if (true)
|
|
218
|
-
#else
|
|
219
224
|
if (!mi_option_is_enabled(mi_option_allow_thp)) // disable THP if requested through an option
|
|
220
|
-
#endif
|
|
221
225
|
{
|
|
222
226
|
config->has_transparent_huge_pages = false;
|
|
223
|
-
|
|
224
|
-
if (prctl(PR_GET_THP_DISABLE, &val, 0, 0, 0) != 0) {
|
|
227
|
+
if (prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0) == 0) { // -1 on error, 1 if already disabled
|
|
225
228
|
// Most likely since distros often come with always/madvise settings.
|
|
226
|
-
val = 1;
|
|
227
229
|
// Disabling only for mimalloc process rather than touching system wide settings
|
|
228
|
-
(void)prctl(PR_SET_THP_DISABLE,
|
|
230
|
+
(void)prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0);
|
|
229
231
|
}
|
|
230
232
|
}
|
|
231
233
|
#endif
|
|
@@ -247,15 +249,17 @@ int _mi_prim_free(void* addr, size_t size ) {
|
|
|
247
249
|
// mmap
|
|
248
250
|
//---------------------------------------------
|
|
249
251
|
|
|
252
|
+
// return errno on failure
|
|
250
253
|
static int unix_madvise(void* addr, size_t size, int advice) {
|
|
251
254
|
#if defined(__sun)
|
|
252
|
-
int res = madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520)
|
|
255
|
+
const int res = madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520)
|
|
256
|
+
return (res==0 ? 0 : errno);
|
|
253
257
|
#elif defined(__QNX__)
|
|
254
|
-
|
|
258
|
+
return posix_madvise(addr, size, advice); // posix returns errno
|
|
255
259
|
#else
|
|
256
|
-
int res = madvise(addr, size, advice);
|
|
257
|
-
#endif
|
|
260
|
+
const int res = madvise(addr, size, advice); // linux returns -1 on failure and sets errno
|
|
258
261
|
return (res==0 ? 0 : errno);
|
|
262
|
+
#endif
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
static void* unix_mmap_prim(void* addr, size_t size, int protect_flags, int flags, int fd) {
|
|
@@ -436,10 +440,6 @@ int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool comm
|
|
|
436
440
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
|
437
441
|
mi_assert_internal(commit || !allow_large);
|
|
438
442
|
mi_assert_internal(try_alignment > 0);
|
|
439
|
-
if (hint_addr == NULL && size >= 8*MI_UNIX_LARGE_PAGE_SIZE && try_alignment > 1 && _mi_is_power_of_two(try_alignment) && try_alignment < MI_UNIX_LARGE_PAGE_SIZE) {
|
|
440
|
-
try_alignment = MI_UNIX_LARGE_PAGE_SIZE; // try to align along large page size for larger allocations
|
|
441
|
-
}
|
|
442
|
-
|
|
443
443
|
*is_zero = true;
|
|
444
444
|
int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
|
|
445
445
|
*addr = unix_mmap(hint_addr, size, try_alignment, protect_flags, false, allow_large, is_large);
|
|
@@ -452,7 +452,7 @@ int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool comm
|
|
|
452
452
|
//---------------------------------------------
|
|
453
453
|
|
|
454
454
|
static void unix_mprotect_hint(int err) {
|
|
455
|
-
#if defined(__linux__) && (MI_SECURE>=
|
|
455
|
+
#if defined(__linux__) && (MI_SECURE>=5) // guard page around every mimalloc page
|
|
456
456
|
if (err == ENOMEM) {
|
|
457
457
|
_mi_warning_message("The next warning may be caused by a low memory map limit.\n"
|
|
458
458
|
" On Linux this is controlled by the vm.max_map_count -- maybe increase it?\n"
|
|
@@ -533,8 +533,8 @@ int _mi_prim_reset(void* start, size_t size) {
|
|
|
533
533
|
// default `MADV_DONTNEED` is used though.
|
|
534
534
|
static _Atomic(size_t) advice = MI_ATOMIC_VAR_INIT(MADV_FREE);
|
|
535
535
|
int oadvice = (int)mi_atomic_load_relaxed(&advice);
|
|
536
|
-
while ((err = unix_madvise(start, size, oadvice)) != 0 &&
|
|
537
|
-
if (err
|
|
536
|
+
while ((err = unix_madvise(start, size, oadvice)) != 0 && err == EAGAIN) { /* try again */ };
|
|
537
|
+
if (err == EINVAL && oadvice == MADV_FREE) {
|
|
538
538
|
// if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
|
|
539
539
|
mi_atomic_store_release(&advice, (size_t)MADV_DONTNEED);
|
|
540
540
|
err = unix_madvise(start, size, MADV_DONTNEED);
|
|
@@ -989,3 +989,7 @@ void _mi_prim_thread_associate_default_theap(mi_theap_t* theap) {
|
|
|
989
989
|
bool _mi_prim_thread_is_in_threadpool(void) {
|
|
990
990
|
return false;
|
|
991
991
|
}
|
|
992
|
+
|
|
993
|
+
void _mi_prim_thread_yield(void) {
|
|
994
|
+
sleep(0);
|
|
995
|
+
}
|
|
@@ -13,6 +13,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|
|
13
13
|
|
|
14
14
|
#include <stdio.h> // fputs
|
|
15
15
|
#include <stdlib.h> // getenv
|
|
16
|
+
#include <unistd.h> // sbrk, sleep
|
|
16
17
|
|
|
17
18
|
//---------------------------------------------
|
|
18
19
|
// Initialize
|
|
@@ -42,8 +43,6 @@ int _mi_prim_free(void* addr, size_t size ) {
|
|
|
42
43
|
//---------------------------------------------
|
|
43
44
|
|
|
44
45
|
#if defined(MI_USE_SBRK)
|
|
45
|
-
#include <unistd.h> // for sbrk
|
|
46
|
-
|
|
47
46
|
static void* mi_memory_grow( size_t size ) {
|
|
48
47
|
void* p = sbrk(size);
|
|
49
48
|
if (p == (void*)(-1)) return NULL;
|
|
@@ -89,7 +88,7 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
|
|
89
88
|
{
|
|
90
89
|
void* current = mi_memory_grow(0); // get current size
|
|
91
90
|
if (current != NULL) {
|
|
92
|
-
void* aligned_current =
|
|
91
|
+
void* aligned_current = _mi_align_up_ptr(current, try_alignment); // and align from there to minimize wasted space
|
|
93
92
|
alloc_size = _mi_align_up( ((uint8_t*)aligned_current - (uint8_t*)current) + size, _mi_os_page_size());
|
|
94
93
|
base = mi_memory_grow(alloc_size);
|
|
95
94
|
}
|
|
@@ -98,7 +97,7 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
|
|
98
97
|
pthread_mutex_unlock(&mi_theap_grow_mutex);
|
|
99
98
|
#endif
|
|
100
99
|
if (base != NULL) {
|
|
101
|
-
p =
|
|
100
|
+
p = _mi_align_up_ptr(base, try_alignment);
|
|
102
101
|
if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
|
|
103
102
|
// another thread used wasm_memory_grow/sbrk in-between and we do not have enough
|
|
104
103
|
// space after alignment. Give up (and waste the space as we cannot shrink :-( )
|
|
@@ -286,3 +285,7 @@ void _mi_prim_thread_associate_default_theap(mi_theap_t* theap) {
|
|
|
286
285
|
bool _mi_prim_thread_is_in_threadpool(void) {
|
|
287
286
|
return false;
|
|
288
287
|
}
|
|
288
|
+
|
|
289
|
+
void _mi_prim_thread_yield(void) {
|
|
290
|
+
sleep(0);
|
|
291
|
+
}
|