@shd101wyy/yo 0.0.2

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 (339) hide show
  1. package/LICENSE.md +17 -0
  2. package/README.md +80 -0
  3. package/out/cjs/index.cjs +51 -0
  4. package/out/cjs/yo-cli.cjs +2158 -0
  5. package/out/esm/index.mjs +51 -0
  6. package/out/types/src/codegen/async/runtime.d.ts +2 -0
  7. package/out/types/src/codegen/async/state-code-gen.d.ts +10 -0
  8. package/out/types/src/codegen/async/state-machine.d.ts +13 -0
  9. package/out/types/src/codegen/c/collection.d.ts +3 -0
  10. package/out/types/src/codegen/codegen-c.d.ts +12 -0
  11. package/out/types/src/codegen/constants.d.ts +3 -0
  12. package/out/types/src/codegen/expressions/array.d.ts +4 -0
  13. package/out/types/src/codegen/expressions/generation.d.ts +11 -0
  14. package/out/types/src/codegen/expressions/index.d.ts +2 -0
  15. package/out/types/src/codegen/functions/collection.d.ts +5 -0
  16. package/out/types/src/codegen/functions/context.d.ts +57 -0
  17. package/out/types/src/codegen/functions/generation.d.ts +25 -0
  18. package/out/types/src/codegen/functions/index.d.ts +2 -0
  19. package/out/types/src/codegen/index.d.ts +20 -0
  20. package/out/types/src/codegen/parallelism/runtime.d.ts +2 -0
  21. package/out/types/src/codegen/types/collection.d.ts +8 -0
  22. package/out/types/src/codegen/types/generation.d.ts +13 -0
  23. package/out/types/src/codegen/types/index.d.ts +2 -0
  24. package/out/types/src/codegen/utils/fixup.d.ts +2 -0
  25. package/out/types/src/codegen/utils/index.d.ts +77 -0
  26. package/out/types/src/codegen/values/index.d.ts +1 -0
  27. package/out/types/src/emitter.d.ts +11 -0
  28. package/out/types/src/env.d.ts +85 -0
  29. package/out/types/src/error.d.ts +45 -0
  30. package/out/types/src/evaluator/async/await-analysis-types.d.ts +23 -0
  31. package/out/types/src/evaluator/async/await-analysis.d.ts +5 -0
  32. package/out/types/src/evaluator/builtins/alignof.d.ts +8 -0
  33. package/out/types/src/evaluator/builtins/and_or.d.ts +8 -0
  34. package/out/types/src/evaluator/builtins/arc_fns.d.ts +58 -0
  35. package/out/types/src/evaluator/builtins/array_fns.d.ts +0 -0
  36. package/out/types/src/evaluator/builtins/as.d.ts +8 -0
  37. package/out/types/src/evaluator/builtins/async_fns.d.ts +8 -0
  38. package/out/types/src/evaluator/builtins/compt_assert.d.ts +8 -0
  39. package/out/types/src/evaluator/builtins/compt_boolean_fns.d.ts +8 -0
  40. package/out/types/src/evaluator/builtins/compt_expect_error.d.ts +8 -0
  41. package/out/types/src/evaluator/builtins/compt_list_fns.d.ts +33 -0
  42. package/out/types/src/evaluator/builtins/compt_print.d.ts +8 -0
  43. package/out/types/src/evaluator/builtins/compt_string_fns.d.ts +8 -0
  44. package/out/types/src/evaluator/builtins/consume.d.ts +8 -0
  45. package/out/types/src/evaluator/builtins/drop.d.ts +8 -0
  46. package/out/types/src/evaluator/builtins/dup.d.ts +8 -0
  47. package/out/types/src/evaluator/builtins/expr_fns.d.ts +33 -0
  48. package/out/types/src/evaluator/builtins/future_fns.d.ts +8 -0
  49. package/out/types/src/evaluator/builtins/gc.d.ts +8 -0
  50. package/out/types/src/evaluator/builtins/gensym.d.ts +8 -0
  51. package/out/types/src/evaluator/builtins/impl_constraint.d.ts +8 -0
  52. package/out/types/src/evaluator/builtins/macro_expand.d.ts +8 -0
  53. package/out/types/src/evaluator/builtins/numeric_fns.d.ts +8 -0
  54. package/out/types/src/evaluator/builtins/panic.d.ts +8 -0
  55. package/out/types/src/evaluator/builtins/ptr_fns.d.ts +8 -0
  56. package/out/types/src/evaluator/builtins/quote.d.ts +13 -0
  57. package/out/types/src/evaluator/builtins/rc.d.ts +8 -0
  58. package/out/types/src/evaluator/builtins/sizeof.d.ts +8 -0
  59. package/out/types/src/evaluator/builtins/the.d.ts +8 -0
  60. package/out/types/src/evaluator/builtins/type_fns.d.ts +28 -0
  61. package/out/types/src/evaluator/builtins/va_start.d.ts +8 -0
  62. package/out/types/src/evaluator/builtins/var_fns.d.ts +18 -0
  63. package/out/types/src/evaluator/calls/array.d.ts +13 -0
  64. package/out/types/src/evaluator/calls/array_type.d.ts +11 -0
  65. package/out/types/src/evaluator/calls/closure_type.d.ts +11 -0
  66. package/out/types/src/evaluator/calls/compt_function.d.ts +19 -0
  67. package/out/types/src/evaluator/calls/compt_list_type.d.ts +11 -0
  68. package/out/types/src/evaluator/calls/function.d.ts +16 -0
  69. package/out/types/src/evaluator/calls/function_type.d.ts +15 -0
  70. package/out/types/src/evaluator/calls/helper.d.ts +42 -0
  71. package/out/types/src/evaluator/calls/iso.d.ts +15 -0
  72. package/out/types/src/evaluator/calls/module_type.d.ts +11 -0
  73. package/out/types/src/evaluator/calls/numeric_type.d.ts +15 -0
  74. package/out/types/src/evaluator/calls/pointer.d.ts +8 -0
  75. package/out/types/src/evaluator/calls/pointer_type.d.ts +14 -0
  76. package/out/types/src/evaluator/calls/type.d.ts +12 -0
  77. package/out/types/src/evaluator/context.d.ts +169 -0
  78. package/out/types/src/evaluator/exprs/_expr.d.ts +8 -0
  79. package/out/types/src/evaluator/exprs/assignment.d.ts +9 -0
  80. package/out/types/src/evaluator/exprs/begin.d.ts +10 -0
  81. package/out/types/src/evaluator/exprs/binding.d.ts +12 -0
  82. package/out/types/src/evaluator/exprs/c_include.d.ts +8 -0
  83. package/out/types/src/evaluator/exprs/cond.d.ts +8 -0
  84. package/out/types/src/evaluator/exprs/destructuring_assignment.d.ts +33 -0
  85. package/out/types/src/evaluator/exprs/exists.d.ts +0 -0
  86. package/out/types/src/evaluator/exprs/expr.d.ts +9 -0
  87. package/out/types/src/evaluator/exprs/extern.d.ts +8 -0
  88. package/out/types/src/evaluator/exprs/identifer_and_operator.d.ts +9 -0
  89. package/out/types/src/evaluator/exprs/import.d.ts +9 -0
  90. package/out/types/src/evaluator/exprs/initialization_assignment.d.ts +8 -0
  91. package/out/types/src/evaluator/exprs/match.d.ts +8 -0
  92. package/out/types/src/evaluator/exprs/open.d.ts +8 -0
  93. package/out/types/src/evaluator/exprs/property_access.d.ts +8 -0
  94. package/out/types/src/evaluator/exprs/recur.d.ts +8 -0
  95. package/out/types/src/evaluator/exprs/subtype_of.d.ts +21 -0
  96. package/out/types/src/evaluator/exprs/test.d.ts +8 -0
  97. package/out/types/src/evaluator/exprs/typeof.d.ts +8 -0
  98. package/out/types/src/evaluator/exprs/while.d.ts +8 -0
  99. package/out/types/src/evaluator/index.d.ts +26 -0
  100. package/out/types/src/evaluator/types/array.d.ts +8 -0
  101. package/out/types/src/evaluator/types/closure.d.ts +8 -0
  102. package/out/types/src/evaluator/types/compt_list.d.ts +8 -0
  103. package/out/types/src/evaluator/types/concrete_module.d.ts +8 -0
  104. package/out/types/src/evaluator/types/dyn.d.ts +8 -0
  105. package/out/types/src/evaluator/types/enum.d.ts +8 -0
  106. package/out/types/src/evaluator/types/expr_synthesizer.d.ts +14 -0
  107. package/out/types/src/evaluator/types/field.d.ts +14 -0
  108. package/out/types/src/evaluator/types/fn_module.d.ts +8 -0
  109. package/out/types/src/evaluator/types/function.d.ts +58 -0
  110. package/out/types/src/evaluator/types/future_module.d.ts +8 -0
  111. package/out/types/src/evaluator/types/module.d.ts +19 -0
  112. package/out/types/src/evaluator/types/newtype.d.ts +8 -0
  113. package/out/types/src/evaluator/types/object.d.ts +8 -0
  114. package/out/types/src/evaluator/types/proofs.d.ts +0 -0
  115. package/out/types/src/evaluator/types/slice.d.ts +8 -0
  116. package/out/types/src/evaluator/types/struct.d.ts +8 -0
  117. package/out/types/src/evaluator/types/synthesizer.d.ts +16 -0
  118. package/out/types/src/evaluator/types/tuple.d.ts +18 -0
  119. package/out/types/src/evaluator/types/union.d.ts +8 -0
  120. package/out/types/src/evaluator/types/utils.d.ts +71 -0
  121. package/out/types/src/evaluator/types/validation.d.ts +3 -0
  122. package/out/types/src/evaluator/utils/array-utils.d.ts +15 -0
  123. package/out/types/src/evaluator/utils/closure.d.ts +35 -0
  124. package/out/types/src/evaluator/utils.d.ts +4 -0
  125. package/out/types/src/evaluator/values/anonymous_function.d.ts +8 -0
  126. package/out/types/src/evaluator/values/anonymous_module.d.ts +17 -0
  127. package/out/types/src/evaluator/values/anonymous_struct.d.ts +8 -0
  128. package/out/types/src/evaluator/values/array.d.ts +8 -0
  129. package/out/types/src/evaluator/values/boolean.d.ts +3 -0
  130. package/out/types/src/evaluator/values/char.d.ts +3 -0
  131. package/out/types/src/evaluator/values/compt_list.d.ts +8 -0
  132. package/out/types/src/evaluator/values/dyn.d.ts +8 -0
  133. package/out/types/src/evaluator/values/float.d.ts +4 -0
  134. package/out/types/src/evaluator/values/integer.d.ts +4 -0
  135. package/out/types/src/evaluator/values/module.d.ts +58 -0
  136. package/out/types/src/evaluator/values/string.d.ts +3 -0
  137. package/out/types/src/evaluator/values/tuple.d.ts +32 -0
  138. package/out/types/src/expr.d.ts +456 -0
  139. package/out/types/src/function-value.d.ts +42 -0
  140. package/out/types/src/index.d.ts +4 -0
  141. package/out/types/src/lexer.d.ts +2 -0
  142. package/out/types/src/logger.d.ts +1 -0
  143. package/out/types/src/module-manager.d.ts +30 -0
  144. package/out/types/src/naming-checker.d.ts +4 -0
  145. package/out/types/src/parser.d.ts +33 -0
  146. package/out/types/src/test-runner.d.ts +30 -0
  147. package/out/types/src/tests/codegen.test.d.ts +1 -0
  148. package/out/types/src/tests/fixme.test.d.ts +1 -0
  149. package/out/types/src/tests/module-manager.test.d.ts +1 -0
  150. package/out/types/src/tests/parser.test.d.ts +1 -0
  151. package/out/types/src/tests/sample.test.d.ts +0 -0
  152. package/out/types/src/tests/std.test.d.ts +1 -0
  153. package/out/types/src/token.d.ts +40 -0
  154. package/out/types/src/type-value.d.ts +7 -0
  155. package/out/types/src/types/compatibility.d.ts +16 -0
  156. package/out/types/src/types/creators.d.ts +73 -0
  157. package/out/types/src/types/definitions.d.ts +218 -0
  158. package/out/types/src/types/guards.d.ts +70 -0
  159. package/out/types/src/types/hierarchy.d.ts +4 -0
  160. package/out/types/src/types/index.d.ts +7 -0
  161. package/out/types/src/types/module_field.d.ts +2 -0
  162. package/out/types/src/types/tags.d.ts +45 -0
  163. package/out/types/src/types/utils.d.ts +50 -0
  164. package/out/types/src/unit-value.d.ts +7 -0
  165. package/out/types/src/utils.d.ts +6 -0
  166. package/out/types/src/value-tag.d.ts +29 -0
  167. package/out/types/src/value.d.ts +110 -0
  168. package/out/types/src/yo-cli.d.ts +1 -0
  169. package/out/types/tsconfig.tsbuildinfo +1 -0
  170. package/package.json +57 -0
  171. package/scripts/check-liburing.js +76 -0
  172. package/std/alg/hash.yo +50 -0
  173. package/std/allocator.yo +113 -0
  174. package/std/allocators/c_allocator.yo +118 -0
  175. package/std/async.yo +13 -0
  176. package/std/collections/array_list.yo +415 -0
  177. package/std/collections/hash_map.yo +482 -0
  178. package/std/collections/hash_set.yo +706 -0
  179. package/std/collections/index.yo +11 -0
  180. package/std/collections/linked_list.yo +439 -0
  181. package/std/error.yo +0 -0
  182. package/std/gc.yo +10 -0
  183. package/std/index.yo +12 -0
  184. package/std/io/file.yo +191 -0
  185. package/std/io/index.yo +5 -0
  186. package/std/libc/assert.yo +39 -0
  187. package/std/libc/ctype.yo +57 -0
  188. package/std/libc/errno.yo +182 -0
  189. package/std/libc/float.yo +87 -0
  190. package/std/libc/index.yo +29 -0
  191. package/std/libc/limits.yo +65 -0
  192. package/std/libc/math.yo +679 -0
  193. package/std/libc/signal.yo +101 -0
  194. package/std/libc/stdatomic.yo +213 -0
  195. package/std/libc/stdint.yo +214 -0
  196. package/std/libc/stdio.yo +225 -0
  197. package/std/libc/stdlib.yo +204 -0
  198. package/std/libc/string.yo +151 -0
  199. package/std/libc/time.yo +92 -0
  200. package/std/libc/unistd.yo +130 -0
  201. package/std/monad.yo +152 -0
  202. package/std/prelude.yo +3094 -0
  203. package/std/string/index.yo +8 -0
  204. package/std/string/rune.yo +82 -0
  205. package/std/string/string.yo +288 -0
  206. package/std/sync.yo +95 -0
  207. package/std/thread.yo +36 -0
  208. package/std/time.yo +13 -0
  209. package/std/worker.yo +36 -0
  210. package/vendor/mimalloc/.gitattributes +12 -0
  211. package/vendor/mimalloc/CMakeLists.txt +763 -0
  212. package/vendor/mimalloc/LICENSE +21 -0
  213. package/vendor/mimalloc/SECURITY.md +41 -0
  214. package/vendor/mimalloc/azure-pipelines.yml +251 -0
  215. package/vendor/mimalloc/bin/mimalloc-redirect-arm64.dll +0 -0
  216. package/vendor/mimalloc/bin/mimalloc-redirect-arm64.lib +0 -0
  217. package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.dll +0 -0
  218. package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.lib +0 -0
  219. package/vendor/mimalloc/bin/mimalloc-redirect.dll +0 -0
  220. package/vendor/mimalloc/bin/mimalloc-redirect.lib +0 -0
  221. package/vendor/mimalloc/bin/mimalloc-redirect32.dll +0 -0
  222. package/vendor/mimalloc/bin/mimalloc-redirect32.lib +0 -0
  223. package/vendor/mimalloc/bin/minject-arm64.exe +0 -0
  224. package/vendor/mimalloc/bin/minject.exe +0 -0
  225. package/vendor/mimalloc/bin/minject32.exe +0 -0
  226. package/vendor/mimalloc/bin/readme.md +118 -0
  227. package/vendor/mimalloc/cmake/JoinPaths.cmake +23 -0
  228. package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +19 -0
  229. package/vendor/mimalloc/cmake/mimalloc-config.cmake +14 -0
  230. package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +23 -0
  231. package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +28 -0
  232. package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +28 -0
  233. package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +23 -0
  234. package/vendor/mimalloc/contrib/docker/readme.md +10 -0
  235. package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +64 -0
  236. package/vendor/mimalloc/contrib/vcpkg/readme.md +40 -0
  237. package/vendor/mimalloc/contrib/vcpkg/usage +20 -0
  238. package/vendor/mimalloc/contrib/vcpkg/vcpkg-cmake-wrapper.cmake +20 -0
  239. package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +48 -0
  240. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg +887 -0
  241. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg +1185 -0
  242. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg +757 -0
  243. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg +1028 -0
  244. package/vendor/mimalloc/doc/bench-2020/bench-r5a-1.svg +769 -0
  245. package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg +868 -0
  246. package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg +1157 -0
  247. package/vendor/mimalloc/doc/bench-2020/bench-r5a-2.svg +983 -0
  248. package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg +683 -0
  249. package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg +854 -0
  250. package/vendor/mimalloc/doc/bench-2020/bench-spec-rss.svg +713 -0
  251. package/vendor/mimalloc/doc/bench-2020/bench-spec.svg +713 -0
  252. package/vendor/mimalloc/doc/bench-2020/bench-z4-1.svg +890 -0
  253. package/vendor/mimalloc/doc/bench-2020/bench-z4-2.svg +1146 -0
  254. package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-1.svg +796 -0
  255. package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-2.svg +974 -0
  256. package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg +952 -0
  257. package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg +1255 -0
  258. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg +955 -0
  259. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg +1269 -0
  260. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg +836 -0
  261. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg +1131 -0
  262. package/vendor/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg +766 -0
  263. package/vendor/mimalloc/doc/doxyfile +2895 -0
  264. package/vendor/mimalloc/doc/ds-logo.jpg +0 -0
  265. package/vendor/mimalloc/doc/ds-logo.png +0 -0
  266. package/vendor/mimalloc/doc/mimalloc-doc.h +1452 -0
  267. package/vendor/mimalloc/doc/mimalloc-doxygen.css +60 -0
  268. package/vendor/mimalloc/doc/mimalloc-logo-100.png +0 -0
  269. package/vendor/mimalloc/doc/mimalloc-logo.png +0 -0
  270. package/vendor/mimalloc/doc/mimalloc-logo.svg +161 -0
  271. package/vendor/mimalloc/doc/spades-logo.png +0 -0
  272. package/vendor/mimalloc/doc/unreal-logo.svg +43 -0
  273. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +500 -0
  274. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj.filters +108 -0
  275. package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj +508 -0
  276. package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj.filters +111 -0
  277. package/vendor/mimalloc/ide/vs2022/mimalloc-override-test-dep.vcxproj +355 -0
  278. package/vendor/mimalloc/ide/vs2022/mimalloc-override-test.vcxproj +360 -0
  279. package/vendor/mimalloc/ide/vs2022/mimalloc-test-api.vcxproj +295 -0
  280. package/vendor/mimalloc/ide/vs2022/mimalloc-test-stress.vcxproj +292 -0
  281. package/vendor/mimalloc/ide/vs2022/mimalloc-test.vcxproj +289 -0
  282. package/vendor/mimalloc/ide/vs2022/mimalloc.sln +151 -0
  283. package/vendor/mimalloc/include/mimalloc/atomic.h +557 -0
  284. package/vendor/mimalloc/include/mimalloc/internal.h +1153 -0
  285. package/vendor/mimalloc/include/mimalloc/prim.h +421 -0
  286. package/vendor/mimalloc/include/mimalloc/track.h +145 -0
  287. package/vendor/mimalloc/include/mimalloc/types.h +685 -0
  288. package/vendor/mimalloc/include/mimalloc-new-delete.h +66 -0
  289. package/vendor/mimalloc/include/mimalloc-override.h +68 -0
  290. package/vendor/mimalloc/include/mimalloc-stats.h +103 -0
  291. package/vendor/mimalloc/include/mimalloc.h +612 -0
  292. package/vendor/mimalloc/mimalloc.pc.in +11 -0
  293. package/vendor/mimalloc/readme.md +946 -0
  294. package/vendor/mimalloc/src/alloc-aligned.c +360 -0
  295. package/vendor/mimalloc/src/alloc-override.c +316 -0
  296. package/vendor/mimalloc/src/alloc-posix.c +185 -0
  297. package/vendor/mimalloc/src/alloc.c +692 -0
  298. package/vendor/mimalloc/src/arena-abandon.c +346 -0
  299. package/vendor/mimalloc/src/arena.c +1043 -0
  300. package/vendor/mimalloc/src/bitmap.c +441 -0
  301. package/vendor/mimalloc/src/bitmap.h +119 -0
  302. package/vendor/mimalloc/src/free.c +572 -0
  303. package/vendor/mimalloc/src/heap.c +733 -0
  304. package/vendor/mimalloc/src/init.c +714 -0
  305. package/vendor/mimalloc/src/libc.c +334 -0
  306. package/vendor/mimalloc/src/options.c +663 -0
  307. package/vendor/mimalloc/src/os.c +770 -0
  308. package/vendor/mimalloc/src/page-queue.c +390 -0
  309. package/vendor/mimalloc/src/page.c +1049 -0
  310. package/vendor/mimalloc/src/prim/emscripten/prim.c +249 -0
  311. package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +461 -0
  312. package/vendor/mimalloc/src/prim/osx/prim.c +9 -0
  313. package/vendor/mimalloc/src/prim/prim.c +76 -0
  314. package/vendor/mimalloc/src/prim/readme.md +9 -0
  315. package/vendor/mimalloc/src/prim/unix/prim.c +934 -0
  316. package/vendor/mimalloc/src/prim/wasi/prim.c +284 -0
  317. package/vendor/mimalloc/src/prim/windows/etw-mimalloc.wprp +61 -0
  318. package/vendor/mimalloc/src/prim/windows/etw.h +905 -0
  319. package/vendor/mimalloc/src/prim/windows/etw.man +0 -0
  320. package/vendor/mimalloc/src/prim/windows/prim.c +878 -0
  321. package/vendor/mimalloc/src/prim/windows/readme.md +17 -0
  322. package/vendor/mimalloc/src/random.c +258 -0
  323. package/vendor/mimalloc/src/segment-map.c +142 -0
  324. package/vendor/mimalloc/src/segment.c +1702 -0
  325. package/vendor/mimalloc/src/static.c +41 -0
  326. package/vendor/mimalloc/src/stats.c +635 -0
  327. package/vendor/mimalloc/test/CMakeLists.txt +56 -0
  328. package/vendor/mimalloc/test/main-override-dep.cpp +51 -0
  329. package/vendor/mimalloc/test/main-override-dep.h +11 -0
  330. package/vendor/mimalloc/test/main-override-static.c +539 -0
  331. package/vendor/mimalloc/test/main-override.c +36 -0
  332. package/vendor/mimalloc/test/main-override.cpp +497 -0
  333. package/vendor/mimalloc/test/main.c +46 -0
  334. package/vendor/mimalloc/test/readme.md +16 -0
  335. package/vendor/mimalloc/test/test-api-fill.c +343 -0
  336. package/vendor/mimalloc/test/test-api.c +466 -0
  337. package/vendor/mimalloc/test/test-stress.c +428 -0
  338. package/vendor/mimalloc/test/test-wrong.c +92 -0
  339. package/vendor/mimalloc/test/testhelper.h +49 -0
@@ -0,0 +1,934 @@
1
+ /* ----------------------------------------------------------------------------
2
+ Copyright (c) 2018-2025, Microsoft Research, Daan Leijen
3
+ This is free software; you can redistribute it and/or modify it under the
4
+ terms of the MIT license. A copy of the license can be found in the file
5
+ "LICENSE" at the root of this distribution.
6
+ -----------------------------------------------------------------------------*/
7
+
8
+ // This file is included in `src/prim/prim.c`
9
+
10
+ #ifndef _DEFAULT_SOURCE
11
+ #define _DEFAULT_SOURCE // ensure mmap flags and syscall are defined
12
+ #endif
13
+
14
+ #if defined(__sun)
15
+ // illumos provides new mman.h api when any of these are defined
16
+ // otherwise the old api based on caddr_t which predates the void pointers one.
17
+ // stock solaris provides only the former, chose to atomically to discard those
18
+ // flags only here rather than project wide tough.
19
+ #undef _XOPEN_SOURCE
20
+ #undef _POSIX_C_SOURCE
21
+ #endif
22
+
23
+ #include "mimalloc.h"
24
+ #include "mimalloc/internal.h"
25
+ #include "mimalloc/prim.h"
26
+
27
+ #include <sys/mman.h> // mmap
28
+ #include <unistd.h> // sysconf
29
+ #include <fcntl.h> // open, close, read, access
30
+ #include <stdlib.h> // getenv, arc4random_buf
31
+
32
+ #if defined(__linux__)
33
+ #include <features.h>
34
+ #include <sys/prctl.h> // THP disable, PR_SET_VMA
35
+ #if defined(__GLIBC__) && !defined(PR_SET_VMA)
36
+ #include <linux/prctl.h>
37
+ #endif
38
+ #if defined(__GLIBC__)
39
+ #include <linux/mman.h> // linux mmap flags
40
+ #else
41
+ #include <sys/mman.h>
42
+ #endif
43
+ #elif defined(__APPLE__)
44
+ #include <AvailabilityMacros.h>
45
+ #include <TargetConditionals.h>
46
+ #if !defined(TARGET_OS_OSX) || TARGET_OS_OSX // see issue #879, used to be (!TARGET_IOS_IPHONE && !TARGET_IOS_SIMULATOR)
47
+ #include <mach/vm_statistics.h> // VM_MAKE_TAG, VM_FLAGS_SUPERPAGE_SIZE_2MB, etc.
48
+ #endif
49
+ #if !defined(MAC_OS_X_VERSION_10_7)
50
+ #define MAC_OS_X_VERSION_10_7 1070
51
+ #endif
52
+ #elif defined(__FreeBSD__) || defined(__DragonFly__)
53
+ #include <sys/param.h>
54
+ #if __FreeBSD_version >= 1200000
55
+ #include <sys/cpuset.h>
56
+ #include <sys/domainset.h>
57
+ #endif
58
+ #include <sys/sysctl.h>
59
+ #endif
60
+
61
+ #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__)
62
+ #define MI_HAS_SYSCALL_H
63
+ #include <sys/syscall.h>
64
+ #endif
65
+
66
+ #if !defined(MADV_DONTNEED) && defined(POSIX_MADV_DONTNEED) // QNX
67
+ #define MADV_DONTNEED POSIX_MADV_DONTNEED
68
+ #endif
69
+ #if !defined(MADV_FREE) && defined(POSIX_MADV_FREE) // QNX
70
+ #define MADV_FREE POSIX_MADV_FREE
71
+ #endif
72
+
73
+ #define MI_UNIX_LARGE_PAGE_SIZE (2*MI_MiB) // TODO: can we query the OS for this?
74
+
75
+ //------------------------------------------------------------------------------------
76
+ // Use syscalls for some primitives to allow for libraries that override open/read/close etc.
77
+ // and do allocation themselves; using syscalls prevents recursion when mimalloc is
78
+ // still initializing (issue #713)
79
+ // Declare inline to avoid unused function warnings.
80
+ //------------------------------------------------------------------------------------
81
+
82
+ #if defined(MI_HAS_SYSCALL_H) && defined(SYS_open) && defined(SYS_close) && defined(SYS_read) && defined(SYS_access)
83
+
84
+ static inline int mi_prim_open(const char* fpath, int open_flags) {
85
+ return syscall(SYS_open,fpath,open_flags,0);
86
+ }
87
+ static inline ssize_t mi_prim_read(int fd, void* buf, size_t bufsize) {
88
+ return syscall(SYS_read,fd,buf,bufsize);
89
+ }
90
+ static inline int mi_prim_close(int fd) {
91
+ return syscall(SYS_close,fd);
92
+ }
93
+ static inline int mi_prim_access(const char *fpath, int mode) {
94
+ return syscall(SYS_access,fpath,mode);
95
+ }
96
+
97
+ #else
98
+
99
+ static inline int mi_prim_open(const char* fpath, int open_flags) {
100
+ return open(fpath,open_flags);
101
+ }
102
+ static inline ssize_t mi_prim_read(int fd, void* buf, size_t bufsize) {
103
+ return read(fd,buf,bufsize);
104
+ }
105
+ static inline int mi_prim_close(int fd) {
106
+ return close(fd);
107
+ }
108
+ static inline int mi_prim_access(const char *fpath, int mode) {
109
+ return access(fpath,mode);
110
+ }
111
+
112
+ #endif
113
+
114
+
115
+
116
+ //---------------------------------------------
117
+ // init
118
+ //---------------------------------------------
119
+
120
+ static bool unix_detect_overcommit(void) {
121
+ bool os_overcommit = true;
122
+ #if defined(__linux__)
123
+ int fd = mi_prim_open("/proc/sys/vm/overcommit_memory", O_RDONLY);
124
+ if (fd >= 0) {
125
+ char buf[32];
126
+ ssize_t nread = mi_prim_read(fd, &buf, sizeof(buf));
127
+ mi_prim_close(fd);
128
+ // <https://www.kernel.org/doc/Documentation/vm/overcommit-accounting>
129
+ // 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE)
130
+ if (nread >= 1) {
131
+ os_overcommit = (buf[0] == '0' || buf[0] == '1');
132
+ }
133
+ }
134
+ #elif defined(__FreeBSD__)
135
+ int val = 0;
136
+ size_t olen = sizeof(val);
137
+ if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) {
138
+ os_overcommit = (val != 0);
139
+ }
140
+ #else
141
+ // default: overcommit is true
142
+ #endif
143
+ return os_overcommit;
144
+ }
145
+
146
+ void _mi_prim_mem_init( mi_os_mem_config_t* config )
147
+ {
148
+ long psize = sysconf(_SC_PAGESIZE);
149
+ if (psize > 0) {
150
+ config->page_size = (size_t)psize;
151
+ config->alloc_granularity = (size_t)psize;
152
+ #if defined(_SC_PHYS_PAGES)
153
+ long pphys = sysconf(_SC_PHYS_PAGES);
154
+ const size_t psize_in_kib = (size_t)psize / MI_KiB;
155
+ if (psize_in_kib > 0 && pphys > 0 && (size_t)pphys <= (SIZE_MAX/psize_in_kib)) {
156
+ config->physical_memory_in_kib = (size_t)pphys * psize_in_kib;
157
+ }
158
+ #endif
159
+ }
160
+ config->large_page_size = MI_UNIX_LARGE_PAGE_SIZE;
161
+ config->has_overcommit = unix_detect_overcommit();
162
+ config->has_partial_free = true; // mmap can free in parts
163
+ config->has_virtual_reserve = true; // todo: check if this true for NetBSD? (for anonymous mmap with PROT_NONE)
164
+
165
+ // disable transparent huge pages for this process?
166
+ #if (defined(__linux__) || defined(__ANDROID__)) && defined(PR_GET_THP_DISABLE)
167
+ #if defined(MI_NO_THP)
168
+ if (true)
169
+ #else
170
+ if (!mi_option_is_enabled(mi_option_allow_large_os_pages)) // disable THP also if large OS pages are not allowed in the options
171
+ #endif
172
+ {
173
+ int val = 0;
174
+ if (prctl(PR_GET_THP_DISABLE, &val, 0, 0, 0) != 0) {
175
+ // Most likely since distros often come with always/madvise settings.
176
+ val = 1;
177
+ // Disabling only for mimalloc process rather than touching system wide settings
178
+ (void)prctl(PR_SET_THP_DISABLE, &val, 0, 0, 0);
179
+ }
180
+ }
181
+ #endif
182
+ }
183
+
184
+
185
+ //---------------------------------------------
186
+ // free
187
+ //---------------------------------------------
188
+
189
+ int _mi_prim_free(void* addr, size_t size ) {
190
+ if (size==0) return 0;
191
+ bool err = (munmap(addr, size) == -1);
192
+ return (err ? errno : 0);
193
+ }
194
+
195
+
196
+ //---------------------------------------------
197
+ // mmap
198
+ //---------------------------------------------
199
+
200
+ static int unix_madvise(void* addr, size_t size, int advice) {
201
+ #if defined(__sun)
202
+ int res = madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520)
203
+ #elif defined(__QNX__)
204
+ int res = posix_madvise(addr, size, advice);
205
+ #else
206
+ int res = madvise(addr, size, advice);
207
+ #endif
208
+ return (res==0 ? 0 : errno);
209
+ }
210
+
211
+ static void* unix_mmap_prim(void* addr, size_t size, int protect_flags, int flags, int fd) {
212
+ void* p = mmap(addr, size, protect_flags, flags, fd, 0 /* offset */);
213
+ #if defined(__linux__) && defined(PR_SET_VMA)
214
+ if (p!=MAP_FAILED && p!=NULL) {
215
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, size, "mimalloc");
216
+ }
217
+ #endif
218
+ return p;
219
+ }
220
+
221
+ static void* unix_mmap_prim_aligned(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) {
222
+ MI_UNUSED(try_alignment);
223
+ void* p = NULL;
224
+ #if defined(MAP_ALIGNED) // BSD
225
+ if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) {
226
+ size_t n = mi_bsr(try_alignment);
227
+ if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) { // alignment is a power of 2 and 4096 <= alignment <= 1GiB
228
+ p = unix_mmap_prim(addr, size, protect_flags, flags | MAP_ALIGNED(n), fd);
229
+ if (p==MAP_FAILED || !_mi_is_aligned(p,try_alignment)) {
230
+ int err = errno;
231
+ _mi_trace_message("unable to directly request aligned OS memory (error: %d (0x%x), size: 0x%zx bytes, alignment: 0x%zx, hint address: %p)\n", err, err, size, try_alignment, addr);
232
+ }
233
+ if (p!=MAP_FAILED) return p;
234
+ // fall back to regular mmap
235
+ }
236
+ }
237
+ #elif defined(MAP_ALIGN) // Solaris
238
+ if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) {
239
+ p = unix_mmap_prim((void*)try_alignment, size, protect_flags, flags | MAP_ALIGN, fd); // addr parameter is the required alignment
240
+ if (p!=MAP_FAILED) return p;
241
+ // fall back to regular mmap
242
+ }
243
+ #endif
244
+ #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
245
+ // on 64-bit systems, use the virtual address area after 2TiB for 4MiB aligned allocations
246
+ if (addr == NULL) {
247
+ void* hint = _mi_os_get_aligned_hint(try_alignment, size);
248
+ if (hint != NULL) {
249
+ p = unix_mmap_prim(hint, size, protect_flags, flags, fd);
250
+ if (p==MAP_FAILED || !_mi_is_aligned(p,try_alignment)) {
251
+ #if MI_TRACK_ENABLED // asan sometimes does not instrument errno correctly?
252
+ int err = 0;
253
+ #else
254
+ int err = errno;
255
+ #endif
256
+ _mi_trace_message("unable to directly request hinted aligned OS memory (error: %d (0x%x), size: 0x%zx bytes, alignment: 0x%zx, hint address: %p)\n", err, err, size, try_alignment, hint);
257
+ }
258
+ if (p!=MAP_FAILED) return p;
259
+ // fall back to regular mmap
260
+ }
261
+ }
262
+ #endif
263
+ // regular mmap
264
+ p = unix_mmap_prim(addr, size, protect_flags, flags, fd);
265
+ if (p!=MAP_FAILED) return p;
266
+ // failed to allocate
267
+ return NULL;
268
+ }
269
+
270
+ static int unix_mmap_fd(void) {
271
+ #if defined(VM_MAKE_TAG)
272
+ // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99)
273
+ int os_tag = (int)mi_option_get(mi_option_os_tag);
274
+ if (os_tag < 100 || os_tag > 255) { os_tag = 254; }
275
+ return VM_MAKE_TAG(os_tag);
276
+ #else
277
+ return -1;
278
+ #endif
279
+ }
280
+
281
+ static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) {
282
+ #if !defined(MAP_ANONYMOUS)
283
+ #define MAP_ANONYMOUS MAP_ANON
284
+ #endif
285
+ #if !defined(MAP_NORESERVE)
286
+ #define MAP_NORESERVE 0
287
+ #endif
288
+ void* p = NULL;
289
+ const int fd = unix_mmap_fd();
290
+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
291
+ if (_mi_os_has_overcommit()) {
292
+ flags |= MAP_NORESERVE;
293
+ }
294
+ #if defined(PROT_MAX)
295
+ protect_flags |= PROT_MAX(PROT_READ | PROT_WRITE); // BSD
296
+ #endif
297
+ // huge page allocation
298
+ if (allow_large && (large_only || (_mi_os_use_large_page(size, try_alignment) && mi_option_get(mi_option_allow_large_os_pages) == 1))) {
299
+ static _Atomic(size_t) large_page_try_ok; // = 0;
300
+ size_t try_ok = mi_atomic_load_acquire(&large_page_try_ok);
301
+ if (!large_only && try_ok > 0) {
302
+ // If the OS is not configured for large OS pages, or the user does not have
303
+ // enough permission, the `mmap` will always fail (but it might also fail for other reasons).
304
+ // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times
305
+ // to avoid too many failing calls to mmap.
306
+ mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1);
307
+ }
308
+ else {
309
+ int lflags = flags & ~MAP_NORESERVE; // using NORESERVE on huge pages seems to fail on Linux
310
+ int lfd = fd;
311
+ #ifdef MAP_ALIGNED_SUPER
312
+ lflags |= MAP_ALIGNED_SUPER;
313
+ #endif
314
+ #ifdef MAP_HUGETLB
315
+ lflags |= MAP_HUGETLB;
316
+ #endif
317
+ #ifdef MAP_HUGE_1GB
318
+ static bool mi_huge_pages_available = true;
319
+ if (large_only && (size % MI_GiB) == 0 && mi_huge_pages_available) {
320
+ lflags |= MAP_HUGE_1GB;
321
+ }
322
+ else
323
+ #endif
324
+ {
325
+ #ifdef MAP_HUGE_2MB
326
+ lflags |= MAP_HUGE_2MB;
327
+ #endif
328
+ }
329
+ #ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB
330
+ lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB;
331
+ #endif
332
+ if (large_only || lflags != flags) {
333
+ // try large OS page allocation
334
+ *is_large = true;
335
+ p = unix_mmap_prim_aligned(addr, size, try_alignment, protect_flags, lflags, lfd);
336
+ #ifdef MAP_HUGE_1GB
337
+ if (p == NULL && (lflags & MAP_HUGE_1GB) == MAP_HUGE_1GB) {
338
+ mi_huge_pages_available = false; // don't try huge 1GiB pages again
339
+ if (large_only) {
340
+ _mi_warning_message("unable to allocate huge (1GiB) page, trying large (2MiB) pages instead (errno: %i)\n", errno);
341
+ }
342
+ lflags = ((lflags & ~MAP_HUGE_1GB) | MAP_HUGE_2MB);
343
+ p = unix_mmap_prim_aligned(addr, size, try_alignment, protect_flags, lflags, lfd);
344
+ }
345
+ #endif
346
+ if (large_only) return p;
347
+ if (p == NULL) {
348
+ mi_atomic_store_release(&large_page_try_ok, (size_t)8); // on error, don't try again for the next N allocations
349
+ }
350
+ }
351
+ }
352
+ }
353
+ // regular allocation
354
+ if (p == NULL) {
355
+ *is_large = false;
356
+ p = unix_mmap_prim_aligned(addr, size, try_alignment, protect_flags, flags, fd);
357
+ if (p != NULL) {
358
+ #if defined(MADV_HUGEPAGE)
359
+ // Many Linux systems don't allow MAP_HUGETLB but they support instead
360
+ // transparent huge pages (THP). Generally, it is not required to call `madvise` with MADV_HUGE
361
+ // though since properly aligned allocations will already use large pages if available
362
+ // in that case -- in particular for our large regions (in `memory.c`).
363
+ // However, some systems only allow THP if called with explicit `madvise`, so
364
+ // when large OS pages are enabled for mimalloc, we call `madvise` anyways.
365
+ if (allow_large && _mi_os_use_large_page(size, try_alignment)) {
366
+ if (unix_madvise(p, size, MADV_HUGEPAGE) == 0) {
367
+ // *is_large = true; // possibly
368
+ };
369
+ }
370
+ #elif defined(__sun)
371
+ if (allow_large && _mi_os_use_large_page(size, try_alignment)) {
372
+ struct memcntl_mha cmd = {0};
373
+ cmd.mha_pagesize = _mi_os_large_page_size();
374
+ cmd.mha_cmd = MHA_MAPSIZE_VA;
375
+ if (memcntl((caddr_t)p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) {
376
+ // *is_large = true; // possibly
377
+ }
378
+ }
379
+ #endif
380
+ }
381
+ }
382
+ return p;
383
+ }
384
+
385
+ // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
386
+ int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
387
+ mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
388
+ mi_assert_internal(commit || !allow_large);
389
+ mi_assert_internal(try_alignment > 0);
390
+ 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) {
391
+ try_alignment = MI_UNIX_LARGE_PAGE_SIZE; // try to align along large page size for larger allocations
392
+ }
393
+
394
+ *is_zero = true;
395
+ int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
396
+ *addr = unix_mmap(hint_addr, size, try_alignment, protect_flags, false, allow_large, is_large);
397
+ return (*addr != NULL ? 0 : errno);
398
+ }
399
+
400
+
401
+ //---------------------------------------------
402
+ // Commit/Reset
403
+ //---------------------------------------------
404
+
405
+ static void unix_mprotect_hint(int err) {
406
+ #if defined(__linux__) && (MI_SECURE>=2) // guard page around every mimalloc page
407
+ if (err == ENOMEM) {
408
+ _mi_warning_message("The next warning may be caused by a low memory map limit.\n"
409
+ " On Linux this is controlled by the vm.max_map_count -- maybe increase it?\n"
410
+ " For example: sudo sysctl -w vm.max_map_count=262144\n");
411
+ }
412
+ #else
413
+ MI_UNUSED(err);
414
+ #endif
415
+ }
416
+
417
+ int _mi_prim_commit(void* start, size_t size, bool* is_zero) {
418
+ // commit: ensure we can access the area
419
+ // note: we may think that *is_zero can be true since the memory
420
+ // was either from mmap PROT_NONE, or from decommit MADV_DONTNEED, but
421
+ // we sometimes call commit on a range with still partially committed
422
+ // memory and `mprotect` does not zero the range.
423
+ *is_zero = false;
424
+ int err = mprotect(start, size, (PROT_READ | PROT_WRITE));
425
+ if (err != 0) {
426
+ err = errno;
427
+ unix_mprotect_hint(err);
428
+ }
429
+ return err;
430
+ }
431
+
432
+ int _mi_prim_reuse(void* start, size_t size) {
433
+ MI_UNUSED(start); MI_UNUSED(size);
434
+ #if defined(__APPLE__) && defined(MADV_FREE_REUSE)
435
+ return unix_madvise(start, size, MADV_FREE_REUSE);
436
+ #endif
437
+ return 0;
438
+ }
439
+
440
+ int _mi_prim_decommit(void* start, size_t size, bool* needs_recommit) {
441
+ int err = 0;
442
+ #if defined(__APPLE__) && defined(MADV_FREE_REUSABLE)
443
+ // decommit on macOS: use MADV_FREE_REUSABLE as it does immediate rss accounting (issue #1097)
444
+ err = unix_madvise(start, size, MADV_FREE_REUSABLE);
445
+ if (err) { err = unix_madvise(start, size, MADV_DONTNEED); }
446
+ #else
447
+ // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
448
+ err = unix_madvise(start, size, MADV_DONTNEED);
449
+ #endif
450
+ #if !MI_DEBUG && MI_SECURE<=2
451
+ *needs_recommit = false;
452
+ #else
453
+ *needs_recommit = true;
454
+ mprotect(start, size, PROT_NONE);
455
+ #endif
456
+ /*
457
+ // decommit: use mmap with MAP_FIXED and PROT_NONE to discard the existing memory (and reduce rss)
458
+ *needs_recommit = true;
459
+ const int fd = unix_mmap_fd();
460
+ void* p = mmap(start, size, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), fd, 0);
461
+ if (p != start) { err = errno; }
462
+ */
463
+ return err;
464
+ }
465
+
466
+ int _mi_prim_reset(void* start, size_t size) {
467
+ int err = 0;
468
+
469
+ // on macOS can use MADV_FREE_REUSABLE (but we disable this for now as it seems slower)
470
+ #if 0 && defined(__APPLE__) && defined(MADV_FREE_REUSABLE)
471
+ err = unix_madvise(start, size, MADV_FREE_REUSABLE);
472
+ if (err==0) return 0;
473
+ // fall through
474
+ #endif
475
+
476
+ #if defined(MADV_FREE)
477
+ // Otherwise, we try to use `MADV_FREE` as that is the fastest. A drawback though is that it
478
+ // will not reduce the `rss` stats in tools like `top` even though the memory is available
479
+ // to other processes. With the default `MIMALLOC_PURGE_DECOMMITS=1` we ensure that by
480
+ // default `MADV_DONTNEED` is used though.
481
+ static _Atomic(size_t) advice = MI_ATOMIC_VAR_INIT(MADV_FREE);
482
+ int oadvice = (int)mi_atomic_load_relaxed(&advice);
483
+ while ((err = unix_madvise(start, size, oadvice)) != 0 && errno == EAGAIN) { errno = 0; };
484
+ if (err != 0 && errno == EINVAL && oadvice == MADV_FREE) {
485
+ // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
486
+ mi_atomic_store_release(&advice, (size_t)MADV_DONTNEED);
487
+ err = unix_madvise(start, size, MADV_DONTNEED);
488
+ }
489
+ #else
490
+ err = unix_madvise(start, size, MADV_DONTNEED);
491
+ #endif
492
+ return err;
493
+ }
494
+
495
+ int _mi_prim_protect(void* start, size_t size, bool protect) {
496
+ int err = mprotect(start, size, protect ? PROT_NONE : (PROT_READ | PROT_WRITE));
497
+ if (err != 0) { err = errno; }
498
+ unix_mprotect_hint(err);
499
+ return err;
500
+ }
501
+
502
+
503
+
504
+ //---------------------------------------------
505
+ // Huge page allocation
506
+ //---------------------------------------------
507
+
508
+ #if (MI_INTPTR_SIZE >= 8) && !defined(__HAIKU__) && !defined(__CYGWIN__)
509
+
510
+ #ifndef MPOL_PREFERRED
511
+ #define MPOL_PREFERRED 1
512
+ #endif
513
+
514
+ #if defined(MI_HAS_SYSCALL_H) && defined(SYS_mbind)
515
+ static long mi_prim_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) {
516
+ return syscall(SYS_mbind, start, len, mode, nmask, maxnode, flags);
517
+ }
518
+ #else
519
+ static long mi_prim_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) {
520
+ MI_UNUSED(start); MI_UNUSED(len); MI_UNUSED(mode); MI_UNUSED(nmask); MI_UNUSED(maxnode); MI_UNUSED(flags);
521
+ return 0;
522
+ }
523
+ #endif
524
+
525
+ int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) {
526
+ bool is_large = true;
527
+ *is_zero = true;
528
+ *addr = unix_mmap(hint_addr, size, MI_SEGMENT_SIZE, PROT_READ | PROT_WRITE, true, true, &is_large);
529
+ if (*addr != NULL && numa_node >= 0 && numa_node < 8*MI_INTPTR_SIZE) { // at most 64 nodes
530
+ unsigned long numa_mask = (1UL << numa_node);
531
+ // TODO: does `mbind` work correctly for huge OS pages? should we
532
+ // use `set_mempolicy` before calling mmap instead?
533
+ // see: <https://lkml.org/lkml/2017/2/9/875>
534
+ long err = mi_prim_mbind(*addr, size, MPOL_PREFERRED, &numa_mask, 8*MI_INTPTR_SIZE, 0);
535
+ if (err != 0) {
536
+ err = errno;
537
+ _mi_warning_message("failed to bind huge (1GiB) pages to numa node %d (error: %d (0x%x))\n", numa_node, err, err);
538
+ }
539
+ }
540
+ return (*addr != NULL ? 0 : errno);
541
+ }
542
+
543
+ #else
544
+
545
+ int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) {
546
+ MI_UNUSED(hint_addr); MI_UNUSED(size); MI_UNUSED(numa_node);
547
+ *is_zero = false;
548
+ *addr = NULL;
549
+ return ENOMEM;
550
+ }
551
+
552
+ #endif
553
+
554
+ //---------------------------------------------
555
+ // NUMA nodes
556
+ //---------------------------------------------
557
+
558
+ #if defined(__linux__)
559
+
560
+ size_t _mi_prim_numa_node(void) {
561
+ #if defined(MI_HAS_SYSCALL_H) && defined(SYS_getcpu)
562
+ unsigned long node = 0;
563
+ unsigned long ncpu = 0;
564
+ long err = syscall(SYS_getcpu, &ncpu, &node, NULL);
565
+ if (err != 0) return 0;
566
+ return node;
567
+ #else
568
+ return 0;
569
+ #endif
570
+ }
571
+
572
+ size_t _mi_prim_numa_node_count(void) {
573
+ char buf[128];
574
+ unsigned node = 0;
575
+ for(node = 0; node < 256; node++) {
576
+ // enumerate node entries -- todo: it there a more efficient way to do this? (but ensure there is no allocation)
577
+ _mi_snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1);
578
+ if (mi_prim_access(buf,R_OK) != 0) break;
579
+ }
580
+ return (node+1);
581
+ }
582
+
583
+ #elif defined(__FreeBSD__) && __FreeBSD_version >= 1200000
584
+
585
+ size_t _mi_prim_numa_node(void) {
586
+ domainset_t dom;
587
+ size_t node;
588
+ int policy;
589
+ if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul;
590
+ for (node = 0; node < MAXMEMDOM; node++) {
591
+ if (DOMAINSET_ISSET(node, &dom)) return node;
592
+ }
593
+ return 0ul;
594
+ }
595
+
596
+ size_t _mi_prim_numa_node_count(void) {
597
+ size_t ndomains = 0;
598
+ size_t len = sizeof(ndomains);
599
+ if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul;
600
+ return ndomains;
601
+ }
602
+
603
+ #elif defined(__DragonFly__)
604
+
605
+ size_t _mi_prim_numa_node(void) {
606
+ // TODO: DragonFly does not seem to provide any userland means to get this information.
607
+ return 0ul;
608
+ }
609
+
610
+ size_t _mi_prim_numa_node_count(void) {
611
+ size_t ncpus = 0, nvirtcoresperphys = 0;
612
+ size_t len = sizeof(size_t);
613
+ if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul;
614
+ if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul;
615
+ return nvirtcoresperphys * ncpus;
616
+ }
617
+
618
+ #else
619
+
620
+ size_t _mi_prim_numa_node(void) {
621
+ return 0;
622
+ }
623
+
624
+ size_t _mi_prim_numa_node_count(void) {
625
+ return 1;
626
+ }
627
+
628
+ #endif
629
+
630
+ // ----------------------------------------------------------------
631
+ // Clock
632
+ // ----------------------------------------------------------------
633
+
634
+ #include <time.h>
635
+
636
+ #if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC)
637
+
638
+ mi_msecs_t _mi_prim_clock_now(void) {
639
+ struct timespec t;
640
+ #ifdef CLOCK_MONOTONIC
641
+ clock_gettime(CLOCK_MONOTONIC, &t);
642
+ #else
643
+ clock_gettime(CLOCK_REALTIME, &t);
644
+ #endif
645
+ return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000);
646
+ }
647
+
648
+ #else
649
+
650
+ // low resolution timer
651
+ mi_msecs_t _mi_prim_clock_now(void) {
652
+ #if !defined(CLOCKS_PER_SEC) || (CLOCKS_PER_SEC == 1000) || (CLOCKS_PER_SEC == 0)
653
+ return (mi_msecs_t)clock();
654
+ #elif (CLOCKS_PER_SEC < 1000)
655
+ return (mi_msecs_t)clock() * (1000 / (mi_msecs_t)CLOCKS_PER_SEC);
656
+ #else
657
+ return (mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000);
658
+ #endif
659
+ }
660
+
661
+ #endif
662
+
663
+
664
+
665
+
666
+ //----------------------------------------------------------------
667
+ // Process info
668
+ //----------------------------------------------------------------
669
+
670
+ #if defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__)
671
+ #include <stdio.h>
672
+ #include <unistd.h>
673
+ #include <sys/resource.h>
674
+
675
+ #if defined(__APPLE__)
676
+ #include <mach/mach.h>
677
+ #endif
678
+
679
+ #if defined(__HAIKU__)
680
+ #include <kernel/OS.h>
681
+ #endif
682
+
683
+ static mi_msecs_t timeval_secs(const struct timeval* tv) {
684
+ return ((mi_msecs_t)tv->tv_sec * 1000L) + ((mi_msecs_t)tv->tv_usec / 1000L);
685
+ }
686
+
687
+ void _mi_prim_process_info(mi_process_info_t* pinfo)
688
+ {
689
+ struct rusage rusage;
690
+ getrusage(RUSAGE_SELF, &rusage);
691
+ pinfo->utime = timeval_secs(&rusage.ru_utime);
692
+ pinfo->stime = timeval_secs(&rusage.ru_stime);
693
+ #if !defined(__HAIKU__)
694
+ pinfo->page_faults = rusage.ru_majflt;
695
+ #endif
696
+ #if defined(__HAIKU__)
697
+ // Haiku does not have (yet?) a way to
698
+ // get these stats per process
699
+ thread_info tid;
700
+ area_info mem;
701
+ ssize_t c;
702
+ get_thread_info(find_thread(0), &tid);
703
+ while (get_next_area_info(tid.team, &c, &mem) == B_OK) {
704
+ pinfo->peak_rss += mem.ram_size;
705
+ }
706
+ pinfo->page_faults = 0;
707
+ #elif defined(__APPLE__)
708
+ pinfo->peak_rss = rusage.ru_maxrss; // macos reports in bytes
709
+ #ifdef MACH_TASK_BASIC_INFO
710
+ struct mach_task_basic_info info;
711
+ mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
712
+ if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
713
+ pinfo->current_rss = (size_t)info.resident_size;
714
+ }
715
+ #else
716
+ struct task_basic_info info;
717
+ mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;
718
+ if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
719
+ pinfo->current_rss = (size_t)info.resident_size;
720
+ }
721
+ #endif
722
+ #else
723
+ pinfo->peak_rss = rusage.ru_maxrss * 1024; // Linux/BSD report in KiB
724
+ #endif
725
+ // use defaults for commit
726
+ }
727
+
728
+ #else
729
+
730
+ #ifndef __wasi__
731
+ // WebAssembly instances are not processes
732
+ #pragma message("define a way to get process info")
733
+ #endif
734
+
735
+ void _mi_prim_process_info(mi_process_info_t* pinfo)
736
+ {
737
+ // use defaults
738
+ MI_UNUSED(pinfo);
739
+ }
740
+
741
+ #endif
742
+
743
+
744
+ //----------------------------------------------------------------
745
+ // Output
746
+ //----------------------------------------------------------------
747
+
748
+ void _mi_prim_out_stderr( const char* msg ) {
749
+ fputs(msg,stderr);
750
+ }
751
+
752
+
753
+ //----------------------------------------------------------------
754
+ // Environment
755
+ //----------------------------------------------------------------
756
+
757
+ #if !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0)
758
+ // On Posix systemsr use `environ` to access environment variables
759
+ // even before the C runtime is initialized.
760
+ #if defined(__APPLE__) && defined(__has_include) && __has_include(<crt_externs.h>)
761
+ #include <crt_externs.h>
762
+ static char** mi_get_environ(void) {
763
+ return (*_NSGetEnviron());
764
+ }
765
+ #else
766
+ extern char** environ;
767
+ static char** mi_get_environ(void) {
768
+ return environ;
769
+ }
770
+ #endif
771
+ bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
772
+ if (name==NULL) return false;
773
+ const size_t len = _mi_strlen(name);
774
+ if (len == 0) return false;
775
+ char** env = mi_get_environ();
776
+ if (env == NULL) return false;
777
+ // compare up to 10000 entries
778
+ for (int i = 0; i < 10000 && env[i] != NULL; i++) {
779
+ const char* s = env[i];
780
+ if (_mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive
781
+ // found it
782
+ _mi_strlcpy(result, s + len + 1, result_size);
783
+ return true;
784
+ }
785
+ }
786
+ return false;
787
+ }
788
+ #else
789
+ // fallback: use standard C `getenv` but this cannot be used while initializing the C runtime
790
+ bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
791
+ // cannot call getenv() when still initializing the C runtime.
792
+ if (_mi_preloading()) return false;
793
+ const char* s = getenv(name);
794
+ if (s == NULL) {
795
+ // we check the upper case name too.
796
+ char buf[64+1];
797
+ size_t len = _mi_strnlen(name,sizeof(buf)-1);
798
+ for (size_t i = 0; i < len; i++) {
799
+ buf[i] = _mi_toupper(name[i]);
800
+ }
801
+ buf[len] = 0;
802
+ s = getenv(buf);
803
+ }
804
+ if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false;
805
+ _mi_strlcpy(result, s, result_size);
806
+ return true;
807
+ }
808
+ #endif // !MI_USE_ENVIRON
809
+
810
+
811
+ //----------------------------------------------------------------
812
+ // Random
813
+ //----------------------------------------------------------------
814
+
815
+ #if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_15) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15)
816
+ #include <CommonCrypto/CommonCryptoError.h>
817
+ #include <CommonCrypto/CommonRandom.h>
818
+
819
+ bool _mi_prim_random_buf(void* buf, size_t buf_len) {
820
+ // We prefer CCRandomGenerateBytes as it returns an error code while arc4random_buf
821
+ // may fail silently on macOS. See PR #390, and <https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen/FreeBSD/arc4random.c.auto.html>
822
+ return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess);
823
+ }
824
+
825
+ #elif defined(__ANDROID__) || defined(__DragonFly__) || \
826
+ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
827
+ defined(__sun) || \
828
+ (defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7))
829
+
830
+ bool _mi_prim_random_buf(void* buf, size_t buf_len) {
831
+ arc4random_buf(buf, buf_len);
832
+ return true;
833
+ }
834
+
835
+ #elif defined(__APPLE__) || defined(__linux__) || defined(__HAIKU__) // also for old apple versions < 10.7 (issue #829)
836
+
837
+ #include <sys/types.h>
838
+ #include <sys/stat.h>
839
+ #include <errno.h>
840
+
841
+ bool _mi_prim_random_buf(void* buf, size_t buf_len) {
842
+ // Modern Linux provides `getrandom` but different distributions either use `sys/random.h` or `linux/random.h`
843
+ // and for the latter the actual `getrandom` call is not always defined.
844
+ // (see <https://stackoverflow.com/questions/45237324/why-doesnt-getrandom-compile>)
845
+ // We therefore use a syscall directly and fall back dynamically to /dev/urandom when needed.
846
+ #if defined(MI_HAS_SYSCALL_H) && defined(SYS_getrandom)
847
+ #ifndef GRND_NONBLOCK
848
+ #define GRND_NONBLOCK (1)
849
+ #endif
850
+ static _Atomic(uintptr_t) no_getrandom; // = 0
851
+ if (mi_atomic_load_acquire(&no_getrandom)==0) {
852
+ ssize_t ret = syscall(SYS_getrandom, buf, buf_len, GRND_NONBLOCK);
853
+ if (ret >= 0) return (buf_len == (size_t)ret);
854
+ if (errno != ENOSYS) return false;
855
+ mi_atomic_store_release(&no_getrandom, (uintptr_t)1); // don't call again, and fall back to /dev/urandom
856
+ }
857
+ #endif
858
+ int flags = O_RDONLY;
859
+ #if defined(O_CLOEXEC)
860
+ flags |= O_CLOEXEC;
861
+ #endif
862
+ int fd = mi_prim_open("/dev/urandom", flags);
863
+ if (fd < 0) return false;
864
+ size_t count = 0;
865
+ while(count < buf_len) {
866
+ ssize_t ret = mi_prim_read(fd, (char*)buf + count, buf_len - count);
867
+ if (ret<=0) {
868
+ if (errno!=EAGAIN && errno!=EINTR) break;
869
+ }
870
+ else {
871
+ count += ret;
872
+ }
873
+ }
874
+ mi_prim_close(fd);
875
+ return (count==buf_len);
876
+ }
877
+
878
+ #else
879
+
880
+ bool _mi_prim_random_buf(void* buf, size_t buf_len) {
881
+ return false;
882
+ }
883
+
884
+ #endif
885
+
886
+
887
+ //----------------------------------------------------------------
888
+ // Thread init/done
889
+ //----------------------------------------------------------------
890
+
891
+ #if defined(MI_USE_PTHREADS)
892
+
893
+ // use pthread local storage keys to detect thread ending
894
+ // (and used with MI_TLS_PTHREADS for the default heap)
895
+ pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1);
896
+
897
+ static void mi_pthread_done(void* value) {
898
+ if (value!=NULL) {
899
+ _mi_thread_done((mi_heap_t*)value);
900
+ }
901
+ }
902
+
903
+ void _mi_prim_thread_init_auto_done(void) {
904
+ mi_assert_internal(_mi_heap_default_key == (pthread_key_t)(-1));
905
+ pthread_key_create(&_mi_heap_default_key, &mi_pthread_done);
906
+ }
907
+
908
+ void _mi_prim_thread_done_auto_done(void) {
909
+ if (_mi_heap_default_key != (pthread_key_t)(-1)) { // do not leak the key, see issue #809
910
+ pthread_key_delete(_mi_heap_default_key);
911
+ }
912
+ }
913
+
914
+ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
915
+ if (_mi_heap_default_key != (pthread_key_t)(-1)) { // can happen during recursive invocation on freeBSD
916
+ pthread_setspecific(_mi_heap_default_key, heap);
917
+ }
918
+ }
919
+
920
+ #else
921
+
922
+ void _mi_prim_thread_init_auto_done(void) {
923
+ // nothing
924
+ }
925
+
926
+ void _mi_prim_thread_done_auto_done(void) {
927
+ // nothing
928
+ }
929
+
930
+ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
931
+ MI_UNUSED(heap);
932
+ }
933
+
934
+ #endif