@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.
Files changed (88) hide show
  1. package/.github/skills/yo-async-effects/async-effects-recipes.md +74 -1
  2. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +115 -0
  3. package/.github/skills/yo-syntax/syntax-cheatsheet.md +626 -6
  4. package/out/cjs/index.cjs +563 -564
  5. package/out/cjs/yo-cli.cjs +722 -715
  6. package/out/cjs/yo-lsp.cjs +601 -602
  7. package/out/esm/index.mjs +506 -507
  8. package/out/types/src/codegen/utils/index.d.ts +1 -0
  9. package/out/types/src/expr.d.ts +1 -0
  10. package/out/types/src/parser.d.ts +1 -0
  11. package/out/types/src/test-runner.d.ts +1 -0
  12. package/out/types/tsconfig.tsbuildinfo +1 -1
  13. package/package.json +1 -1
  14. package/std/build.yo +2 -2
  15. package/std/collections/array_list.yo +26 -0
  16. package/std/imm/map.yo +15 -15
  17. package/std/imm/sorted_map.yo +14 -14
  18. package/std/imm/string.yo +4 -4
  19. package/std/prelude.yo +18 -23
  20. package/std/process/command.yo +8 -8
  21. package/std/string/string.yo +76 -55
  22. package/std/string/unicode.yo +6 -6
  23. package/std/sys/signal.yo +6 -6
  24. package/vendor/mimalloc/.github/workflows/release.yaml +55 -0
  25. package/vendor/mimalloc/.github/workflows/stale.yaml +27 -0
  26. package/vendor/mimalloc/.github/workflows/test.yaml +163 -0
  27. package/vendor/mimalloc/CMakeLists.txt +52 -33
  28. package/vendor/mimalloc/azure-pipelines.yml +4 -3
  29. package/vendor/mimalloc/bin/bundle.bat +74 -0
  30. package/vendor/mimalloc/bin/bundle.sh +232 -0
  31. package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +2 -2
  32. package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +1 -1
  33. package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +2 -2
  34. package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +1 -1
  35. package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +1 -1
  36. package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +4 -3
  37. package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +1 -1
  38. package/vendor/mimalloc/doc/mimalloc-doc.h +42 -4
  39. package/vendor/mimalloc/doc/release-notes.md +15 -0
  40. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +3 -3
  41. package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj +511 -0
  42. package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj.filters +117 -0
  43. package/vendor/mimalloc/ide/vs2022/mimalloc-test-dep.vcxproj +360 -0
  44. package/vendor/mimalloc/ide/vs2022/mimalloc-test-override-static.vcxproj +310 -0
  45. package/vendor/mimalloc/ide/vs2022/mimalloc.sln +92 -35
  46. package/vendor/mimalloc/include/mimalloc/atomic.h +178 -182
  47. package/vendor/mimalloc/include/mimalloc/bits.h +8 -10
  48. package/vendor/mimalloc/include/mimalloc/internal.h +76 -32
  49. package/vendor/mimalloc/include/mimalloc/prim.h +25 -18
  50. package/vendor/mimalloc/include/mimalloc/track.h +7 -2
  51. package/vendor/mimalloc/include/mimalloc/types.h +57 -29
  52. package/vendor/mimalloc/include/mimalloc-override.h +10 -10
  53. package/vendor/mimalloc/include/mimalloc-stats.h +18 -6
  54. package/vendor/mimalloc/include/mimalloc.h +22 -12
  55. package/vendor/mimalloc/readme.md +42 -17
  56. package/vendor/mimalloc/src/alloc-aligned.c +13 -11
  57. package/vendor/mimalloc/src/alloc-override.c +97 -17
  58. package/vendor/mimalloc/src/alloc-posix.c +44 -27
  59. package/vendor/mimalloc/src/alloc.c +73 -23
  60. package/vendor/mimalloc/src/arena-meta.c +3 -3
  61. package/vendor/mimalloc/src/arena.c +380 -192
  62. package/vendor/mimalloc/src/bitmap.c +68 -18
  63. package/vendor/mimalloc/src/bitmap.h +8 -4
  64. package/vendor/mimalloc/src/free.c +83 -47
  65. package/vendor/mimalloc/src/heap.c +94 -40
  66. package/vendor/mimalloc/src/init.c +273 -102
  67. package/vendor/mimalloc/src/libc.c +53 -8
  68. package/vendor/mimalloc/src/options.c +43 -40
  69. package/vendor/mimalloc/src/os.c +110 -45
  70. package/vendor/mimalloc/src/page-map.c +14 -8
  71. package/vendor/mimalloc/src/page-queue.c +9 -6
  72. package/vendor/mimalloc/src/page.c +26 -16
  73. package/vendor/mimalloc/src/prim/emscripten/prim.c +10 -1
  74. package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +35 -16
  75. package/vendor/mimalloc/src/prim/unix/prim.c +26 -22
  76. package/vendor/mimalloc/src/prim/wasi/prim.c +7 -4
  77. package/vendor/mimalloc/src/prim/windows/prim.c +247 -44
  78. package/vendor/mimalloc/src/random.c +8 -3
  79. package/vendor/mimalloc/src/stats.c +59 -48
  80. package/vendor/mimalloc/src/theap.c +85 -44
  81. package/vendor/mimalloc/src/threadlocal.c +102 -41
  82. package/vendor/mimalloc/test/main-override-static.c +31 -2
  83. package/vendor/mimalloc/test/main-override.c +27 -14
  84. package/vendor/mimalloc/test/main-static-dep.cpp +46 -0
  85. package/vendor/mimalloc/test/main-static-dep.h +11 -0
  86. package/vendor/mimalloc/test/test-api-fill.c +2 -2
  87. package/vendor/mimalloc/test/test-stress.c +3 -3
  88. 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 start;
216
- size_t idx = _mi_wsize_from_size(size);
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 - (uint8_t*)page > (ptrdiff_t)MI_LARGE_PAGE_SIZE || page == _mi_ptr_page(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>=3)
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<3) { //!mi_option_is_enabled(mi_option_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->heap) ? NULL : theap->heap); // faster for `mi_page_associated_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>=3) // in secure mode, we extend half the time to increase randomness
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
- static mi_deferred_free_fun* volatile deferred_free = NULL;
882
- static _Atomic(void*) deferred_arg; // = NULL
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
- if (deferred_free != NULL && !theap->tld->recurse) {
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
- deferred_free(force, theap->heartbeat, mi_atomic_load_ptr_relaxed(void,&deferred_arg));
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
- // nothing to do
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
- MI_UNUSED(zone);
46
- if (!mi_is_in_heap_region(p)){ return 0; } // not our pointer, bail out
47
- return mi_usable_size(p);
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
- MI_UNUSED(zone);
67
- // mi_cfree(p); // checked free as `zone_free` may be called with invalid pointers
68
- mi_free(p); // with the page_map and pagemap_commit=1 we can use the regular free
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
- MI_UNUSED(zone);
73
- return mi_realloc(p, newsize);
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
- MI_UNUSED(zone);
83
- // todo: ignore for now?
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.totalram > 0 && info.totalram <= SIZE_MAX) {
189
- *physical_memory_in_kib = (size_t)info.totalram / MI_KiB;
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
- int val = 0;
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, &val, 0, 0, 0);
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
- int res = posix_madvise(addr, size, advice);
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>=2) // guard page around every mimalloc page
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 && errno == EAGAIN) { errno = 0; };
537
- if (err != 0 && errno == EINVAL && oadvice == MADV_FREE) {
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 = mi_align_up_ptr(current, try_alignment); // and align from there to minimize wasted space
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 = mi_align_up_ptr(base, try_alignment);
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
+ }