@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.
- package/LICENSE.md +17 -0
- package/README.md +80 -0
- package/out/cjs/index.cjs +51 -0
- package/out/cjs/yo-cli.cjs +2158 -0
- package/out/esm/index.mjs +51 -0
- package/out/types/src/codegen/async/runtime.d.ts +2 -0
- package/out/types/src/codegen/async/state-code-gen.d.ts +10 -0
- package/out/types/src/codegen/async/state-machine.d.ts +13 -0
- package/out/types/src/codegen/c/collection.d.ts +3 -0
- package/out/types/src/codegen/codegen-c.d.ts +12 -0
- package/out/types/src/codegen/constants.d.ts +3 -0
- package/out/types/src/codegen/expressions/array.d.ts +4 -0
- package/out/types/src/codegen/expressions/generation.d.ts +11 -0
- package/out/types/src/codegen/expressions/index.d.ts +2 -0
- package/out/types/src/codegen/functions/collection.d.ts +5 -0
- package/out/types/src/codegen/functions/context.d.ts +57 -0
- package/out/types/src/codegen/functions/generation.d.ts +25 -0
- package/out/types/src/codegen/functions/index.d.ts +2 -0
- package/out/types/src/codegen/index.d.ts +20 -0
- package/out/types/src/codegen/parallelism/runtime.d.ts +2 -0
- package/out/types/src/codegen/types/collection.d.ts +8 -0
- package/out/types/src/codegen/types/generation.d.ts +13 -0
- package/out/types/src/codegen/types/index.d.ts +2 -0
- package/out/types/src/codegen/utils/fixup.d.ts +2 -0
- package/out/types/src/codegen/utils/index.d.ts +77 -0
- package/out/types/src/codegen/values/index.d.ts +1 -0
- package/out/types/src/emitter.d.ts +11 -0
- package/out/types/src/env.d.ts +85 -0
- package/out/types/src/error.d.ts +45 -0
- package/out/types/src/evaluator/async/await-analysis-types.d.ts +23 -0
- package/out/types/src/evaluator/async/await-analysis.d.ts +5 -0
- package/out/types/src/evaluator/builtins/alignof.d.ts +8 -0
- package/out/types/src/evaluator/builtins/and_or.d.ts +8 -0
- package/out/types/src/evaluator/builtins/arc_fns.d.ts +58 -0
- package/out/types/src/evaluator/builtins/array_fns.d.ts +0 -0
- package/out/types/src/evaluator/builtins/as.d.ts +8 -0
- package/out/types/src/evaluator/builtins/async_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_assert.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_boolean_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_expect_error.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_list_fns.d.ts +33 -0
- package/out/types/src/evaluator/builtins/compt_print.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_string_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/consume.d.ts +8 -0
- package/out/types/src/evaluator/builtins/drop.d.ts +8 -0
- package/out/types/src/evaluator/builtins/dup.d.ts +8 -0
- package/out/types/src/evaluator/builtins/expr_fns.d.ts +33 -0
- package/out/types/src/evaluator/builtins/future_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/gc.d.ts +8 -0
- package/out/types/src/evaluator/builtins/gensym.d.ts +8 -0
- package/out/types/src/evaluator/builtins/impl_constraint.d.ts +8 -0
- package/out/types/src/evaluator/builtins/macro_expand.d.ts +8 -0
- package/out/types/src/evaluator/builtins/numeric_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/panic.d.ts +8 -0
- package/out/types/src/evaluator/builtins/ptr_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/quote.d.ts +13 -0
- package/out/types/src/evaluator/builtins/rc.d.ts +8 -0
- package/out/types/src/evaluator/builtins/sizeof.d.ts +8 -0
- package/out/types/src/evaluator/builtins/the.d.ts +8 -0
- package/out/types/src/evaluator/builtins/type_fns.d.ts +28 -0
- package/out/types/src/evaluator/builtins/va_start.d.ts +8 -0
- package/out/types/src/evaluator/builtins/var_fns.d.ts +18 -0
- package/out/types/src/evaluator/calls/array.d.ts +13 -0
- package/out/types/src/evaluator/calls/array_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/closure_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/compt_function.d.ts +19 -0
- package/out/types/src/evaluator/calls/compt_list_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/function.d.ts +16 -0
- package/out/types/src/evaluator/calls/function_type.d.ts +15 -0
- package/out/types/src/evaluator/calls/helper.d.ts +42 -0
- package/out/types/src/evaluator/calls/iso.d.ts +15 -0
- package/out/types/src/evaluator/calls/module_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/numeric_type.d.ts +15 -0
- package/out/types/src/evaluator/calls/pointer.d.ts +8 -0
- package/out/types/src/evaluator/calls/pointer_type.d.ts +14 -0
- package/out/types/src/evaluator/calls/type.d.ts +12 -0
- package/out/types/src/evaluator/context.d.ts +169 -0
- package/out/types/src/evaluator/exprs/_expr.d.ts +8 -0
- package/out/types/src/evaluator/exprs/assignment.d.ts +9 -0
- package/out/types/src/evaluator/exprs/begin.d.ts +10 -0
- package/out/types/src/evaluator/exprs/binding.d.ts +12 -0
- package/out/types/src/evaluator/exprs/c_include.d.ts +8 -0
- package/out/types/src/evaluator/exprs/cond.d.ts +8 -0
- package/out/types/src/evaluator/exprs/destructuring_assignment.d.ts +33 -0
- package/out/types/src/evaluator/exprs/exists.d.ts +0 -0
- package/out/types/src/evaluator/exprs/expr.d.ts +9 -0
- package/out/types/src/evaluator/exprs/extern.d.ts +8 -0
- package/out/types/src/evaluator/exprs/identifer_and_operator.d.ts +9 -0
- package/out/types/src/evaluator/exprs/import.d.ts +9 -0
- package/out/types/src/evaluator/exprs/initialization_assignment.d.ts +8 -0
- package/out/types/src/evaluator/exprs/match.d.ts +8 -0
- package/out/types/src/evaluator/exprs/open.d.ts +8 -0
- package/out/types/src/evaluator/exprs/property_access.d.ts +8 -0
- package/out/types/src/evaluator/exprs/recur.d.ts +8 -0
- package/out/types/src/evaluator/exprs/subtype_of.d.ts +21 -0
- package/out/types/src/evaluator/exprs/test.d.ts +8 -0
- package/out/types/src/evaluator/exprs/typeof.d.ts +8 -0
- package/out/types/src/evaluator/exprs/while.d.ts +8 -0
- package/out/types/src/evaluator/index.d.ts +26 -0
- package/out/types/src/evaluator/types/array.d.ts +8 -0
- package/out/types/src/evaluator/types/closure.d.ts +8 -0
- package/out/types/src/evaluator/types/compt_list.d.ts +8 -0
- package/out/types/src/evaluator/types/concrete_module.d.ts +8 -0
- package/out/types/src/evaluator/types/dyn.d.ts +8 -0
- package/out/types/src/evaluator/types/enum.d.ts +8 -0
- package/out/types/src/evaluator/types/expr_synthesizer.d.ts +14 -0
- package/out/types/src/evaluator/types/field.d.ts +14 -0
- package/out/types/src/evaluator/types/fn_module.d.ts +8 -0
- package/out/types/src/evaluator/types/function.d.ts +58 -0
- package/out/types/src/evaluator/types/future_module.d.ts +8 -0
- package/out/types/src/evaluator/types/module.d.ts +19 -0
- package/out/types/src/evaluator/types/newtype.d.ts +8 -0
- package/out/types/src/evaluator/types/object.d.ts +8 -0
- package/out/types/src/evaluator/types/proofs.d.ts +0 -0
- package/out/types/src/evaluator/types/slice.d.ts +8 -0
- package/out/types/src/evaluator/types/struct.d.ts +8 -0
- package/out/types/src/evaluator/types/synthesizer.d.ts +16 -0
- package/out/types/src/evaluator/types/tuple.d.ts +18 -0
- package/out/types/src/evaluator/types/union.d.ts +8 -0
- package/out/types/src/evaluator/types/utils.d.ts +71 -0
- package/out/types/src/evaluator/types/validation.d.ts +3 -0
- package/out/types/src/evaluator/utils/array-utils.d.ts +15 -0
- package/out/types/src/evaluator/utils/closure.d.ts +35 -0
- package/out/types/src/evaluator/utils.d.ts +4 -0
- package/out/types/src/evaluator/values/anonymous_function.d.ts +8 -0
- package/out/types/src/evaluator/values/anonymous_module.d.ts +17 -0
- package/out/types/src/evaluator/values/anonymous_struct.d.ts +8 -0
- package/out/types/src/evaluator/values/array.d.ts +8 -0
- package/out/types/src/evaluator/values/boolean.d.ts +3 -0
- package/out/types/src/evaluator/values/char.d.ts +3 -0
- package/out/types/src/evaluator/values/compt_list.d.ts +8 -0
- package/out/types/src/evaluator/values/dyn.d.ts +8 -0
- package/out/types/src/evaluator/values/float.d.ts +4 -0
- package/out/types/src/evaluator/values/integer.d.ts +4 -0
- package/out/types/src/evaluator/values/module.d.ts +58 -0
- package/out/types/src/evaluator/values/string.d.ts +3 -0
- package/out/types/src/evaluator/values/tuple.d.ts +32 -0
- package/out/types/src/expr.d.ts +456 -0
- package/out/types/src/function-value.d.ts +42 -0
- package/out/types/src/index.d.ts +4 -0
- package/out/types/src/lexer.d.ts +2 -0
- package/out/types/src/logger.d.ts +1 -0
- package/out/types/src/module-manager.d.ts +30 -0
- package/out/types/src/naming-checker.d.ts +4 -0
- package/out/types/src/parser.d.ts +33 -0
- package/out/types/src/test-runner.d.ts +30 -0
- package/out/types/src/tests/codegen.test.d.ts +1 -0
- package/out/types/src/tests/fixme.test.d.ts +1 -0
- package/out/types/src/tests/module-manager.test.d.ts +1 -0
- package/out/types/src/tests/parser.test.d.ts +1 -0
- package/out/types/src/tests/sample.test.d.ts +0 -0
- package/out/types/src/tests/std.test.d.ts +1 -0
- package/out/types/src/token.d.ts +40 -0
- package/out/types/src/type-value.d.ts +7 -0
- package/out/types/src/types/compatibility.d.ts +16 -0
- package/out/types/src/types/creators.d.ts +73 -0
- package/out/types/src/types/definitions.d.ts +218 -0
- package/out/types/src/types/guards.d.ts +70 -0
- package/out/types/src/types/hierarchy.d.ts +4 -0
- package/out/types/src/types/index.d.ts +7 -0
- package/out/types/src/types/module_field.d.ts +2 -0
- package/out/types/src/types/tags.d.ts +45 -0
- package/out/types/src/types/utils.d.ts +50 -0
- package/out/types/src/unit-value.d.ts +7 -0
- package/out/types/src/utils.d.ts +6 -0
- package/out/types/src/value-tag.d.ts +29 -0
- package/out/types/src/value.d.ts +110 -0
- package/out/types/src/yo-cli.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +57 -0
- package/scripts/check-liburing.js +76 -0
- package/std/alg/hash.yo +50 -0
- package/std/allocator.yo +113 -0
- package/std/allocators/c_allocator.yo +118 -0
- package/std/async.yo +13 -0
- package/std/collections/array_list.yo +415 -0
- package/std/collections/hash_map.yo +482 -0
- package/std/collections/hash_set.yo +706 -0
- package/std/collections/index.yo +11 -0
- package/std/collections/linked_list.yo +439 -0
- package/std/error.yo +0 -0
- package/std/gc.yo +10 -0
- package/std/index.yo +12 -0
- package/std/io/file.yo +191 -0
- package/std/io/index.yo +5 -0
- package/std/libc/assert.yo +39 -0
- package/std/libc/ctype.yo +57 -0
- package/std/libc/errno.yo +182 -0
- package/std/libc/float.yo +87 -0
- package/std/libc/index.yo +29 -0
- package/std/libc/limits.yo +65 -0
- package/std/libc/math.yo +679 -0
- package/std/libc/signal.yo +101 -0
- package/std/libc/stdatomic.yo +213 -0
- package/std/libc/stdint.yo +214 -0
- package/std/libc/stdio.yo +225 -0
- package/std/libc/stdlib.yo +204 -0
- package/std/libc/string.yo +151 -0
- package/std/libc/time.yo +92 -0
- package/std/libc/unistd.yo +130 -0
- package/std/monad.yo +152 -0
- package/std/prelude.yo +3094 -0
- package/std/string/index.yo +8 -0
- package/std/string/rune.yo +82 -0
- package/std/string/string.yo +288 -0
- package/std/sync.yo +95 -0
- package/std/thread.yo +36 -0
- package/std/time.yo +13 -0
- package/std/worker.yo +36 -0
- package/vendor/mimalloc/.gitattributes +12 -0
- package/vendor/mimalloc/CMakeLists.txt +763 -0
- package/vendor/mimalloc/LICENSE +21 -0
- package/vendor/mimalloc/SECURITY.md +41 -0
- package/vendor/mimalloc/azure-pipelines.yml +251 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect32.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect32.lib +0 -0
- package/vendor/mimalloc/bin/minject-arm64.exe +0 -0
- package/vendor/mimalloc/bin/minject.exe +0 -0
- package/vendor/mimalloc/bin/minject32.exe +0 -0
- package/vendor/mimalloc/bin/readme.md +118 -0
- package/vendor/mimalloc/cmake/JoinPaths.cmake +23 -0
- package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +19 -0
- package/vendor/mimalloc/cmake/mimalloc-config.cmake +14 -0
- package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +23 -0
- package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +28 -0
- package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +28 -0
- package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +23 -0
- package/vendor/mimalloc/contrib/docker/readme.md +10 -0
- package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +64 -0
- package/vendor/mimalloc/contrib/vcpkg/readme.md +40 -0
- package/vendor/mimalloc/contrib/vcpkg/usage +20 -0
- package/vendor/mimalloc/contrib/vcpkg/vcpkg-cmake-wrapper.cmake +20 -0
- package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +48 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg +887 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg +1185 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg +757 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg +1028 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-1.svg +769 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg +868 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg +1157 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-2.svg +983 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg +683 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg +854 -0
- package/vendor/mimalloc/doc/bench-2020/bench-spec-rss.svg +713 -0
- package/vendor/mimalloc/doc/bench-2020/bench-spec.svg +713 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-1.svg +890 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-2.svg +1146 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-1.svg +796 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-2.svg +974 -0
- package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg +952 -0
- package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg +1255 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg +955 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg +1269 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg +836 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg +1131 -0
- package/vendor/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg +766 -0
- package/vendor/mimalloc/doc/doxyfile +2895 -0
- package/vendor/mimalloc/doc/ds-logo.jpg +0 -0
- package/vendor/mimalloc/doc/ds-logo.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-doc.h +1452 -0
- package/vendor/mimalloc/doc/mimalloc-doxygen.css +60 -0
- package/vendor/mimalloc/doc/mimalloc-logo-100.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-logo.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-logo.svg +161 -0
- package/vendor/mimalloc/doc/spades-logo.png +0 -0
- package/vendor/mimalloc/doc/unreal-logo.svg +43 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +500 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj.filters +108 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj +508 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj.filters +111 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-test-dep.vcxproj +355 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-test.vcxproj +360 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-api.vcxproj +295 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-stress.vcxproj +292 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test.vcxproj +289 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc.sln +151 -0
- package/vendor/mimalloc/include/mimalloc/atomic.h +557 -0
- package/vendor/mimalloc/include/mimalloc/internal.h +1153 -0
- package/vendor/mimalloc/include/mimalloc/prim.h +421 -0
- package/vendor/mimalloc/include/mimalloc/track.h +145 -0
- package/vendor/mimalloc/include/mimalloc/types.h +685 -0
- package/vendor/mimalloc/include/mimalloc-new-delete.h +66 -0
- package/vendor/mimalloc/include/mimalloc-override.h +68 -0
- package/vendor/mimalloc/include/mimalloc-stats.h +103 -0
- package/vendor/mimalloc/include/mimalloc.h +612 -0
- package/vendor/mimalloc/mimalloc.pc.in +11 -0
- package/vendor/mimalloc/readme.md +946 -0
- package/vendor/mimalloc/src/alloc-aligned.c +360 -0
- package/vendor/mimalloc/src/alloc-override.c +316 -0
- package/vendor/mimalloc/src/alloc-posix.c +185 -0
- package/vendor/mimalloc/src/alloc.c +692 -0
- package/vendor/mimalloc/src/arena-abandon.c +346 -0
- package/vendor/mimalloc/src/arena.c +1043 -0
- package/vendor/mimalloc/src/bitmap.c +441 -0
- package/vendor/mimalloc/src/bitmap.h +119 -0
- package/vendor/mimalloc/src/free.c +572 -0
- package/vendor/mimalloc/src/heap.c +733 -0
- package/vendor/mimalloc/src/init.c +714 -0
- package/vendor/mimalloc/src/libc.c +334 -0
- package/vendor/mimalloc/src/options.c +663 -0
- package/vendor/mimalloc/src/os.c +770 -0
- package/vendor/mimalloc/src/page-queue.c +390 -0
- package/vendor/mimalloc/src/page.c +1049 -0
- package/vendor/mimalloc/src/prim/emscripten/prim.c +249 -0
- package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +461 -0
- package/vendor/mimalloc/src/prim/osx/prim.c +9 -0
- package/vendor/mimalloc/src/prim/prim.c +76 -0
- package/vendor/mimalloc/src/prim/readme.md +9 -0
- package/vendor/mimalloc/src/prim/unix/prim.c +934 -0
- package/vendor/mimalloc/src/prim/wasi/prim.c +284 -0
- package/vendor/mimalloc/src/prim/windows/etw-mimalloc.wprp +61 -0
- package/vendor/mimalloc/src/prim/windows/etw.h +905 -0
- package/vendor/mimalloc/src/prim/windows/etw.man +0 -0
- package/vendor/mimalloc/src/prim/windows/prim.c +878 -0
- package/vendor/mimalloc/src/prim/windows/readme.md +17 -0
- package/vendor/mimalloc/src/random.c +258 -0
- package/vendor/mimalloc/src/segment-map.c +142 -0
- package/vendor/mimalloc/src/segment.c +1702 -0
- package/vendor/mimalloc/src/static.c +41 -0
- package/vendor/mimalloc/src/stats.c +635 -0
- package/vendor/mimalloc/test/CMakeLists.txt +56 -0
- package/vendor/mimalloc/test/main-override-dep.cpp +51 -0
- package/vendor/mimalloc/test/main-override-dep.h +11 -0
- package/vendor/mimalloc/test/main-override-static.c +539 -0
- package/vendor/mimalloc/test/main-override.c +36 -0
- package/vendor/mimalloc/test/main-override.cpp +497 -0
- package/vendor/mimalloc/test/main.c +46 -0
- package/vendor/mimalloc/test/readme.md +16 -0
- package/vendor/mimalloc/test/test-api-fill.c +343 -0
- package/vendor/mimalloc/test/test-api.c +466 -0
- package/vendor/mimalloc/test/test-stress.c +428 -0
- package/vendor/mimalloc/test/test-wrong.c +92 -0
- package/vendor/mimalloc/test/testhelper.h +49 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/* ----------------------------------------------------------------------------
|
|
2
|
+
Copyright (c) 2019-2023 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
|
+
/* ----------------------------------------------------------------------------
|
|
9
|
+
Concurrent bitmap that can set/reset sequences of bits atomically,
|
|
10
|
+
represented as an array of fields where each field is a machine word (`size_t`)
|
|
11
|
+
|
|
12
|
+
There are two api's; the standard one cannot have sequences that cross
|
|
13
|
+
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
|
|
14
|
+
|
|
15
|
+
The `_across` postfixed functions do allow sequences that can cross over
|
|
16
|
+
between the fields. (This is used in arena allocation)
|
|
17
|
+
---------------------------------------------------------------------------- */
|
|
18
|
+
|
|
19
|
+
#include "mimalloc.h"
|
|
20
|
+
#include "mimalloc/internal.h"
|
|
21
|
+
#include "bitmap.h"
|
|
22
|
+
|
|
23
|
+
/* -----------------------------------------------------------
|
|
24
|
+
Bitmap definition
|
|
25
|
+
----------------------------------------------------------- */
|
|
26
|
+
|
|
27
|
+
// The bit mask for a given number of blocks at a specified bit index.
|
|
28
|
+
static inline size_t mi_bitmap_mask_(size_t count, size_t bitidx) {
|
|
29
|
+
mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS);
|
|
30
|
+
mi_assert_internal(count > 0);
|
|
31
|
+
if (count >= MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL;
|
|
32
|
+
if (count == 0) return 0;
|
|
33
|
+
return ((((size_t)1 << count) - 1) << bitidx);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/* -----------------------------------------------------------
|
|
38
|
+
Claim a bit sequence atomically
|
|
39
|
+
----------------------------------------------------------- */
|
|
40
|
+
|
|
41
|
+
// Try to atomically claim a sequence of `count` bits in a single
|
|
42
|
+
// field at `idx` in `bitmap`. Returns `true` on success.
|
|
43
|
+
inline bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx)
|
|
44
|
+
{
|
|
45
|
+
mi_assert_internal(bitmap_idx != NULL);
|
|
46
|
+
mi_assert_internal(count <= MI_BITMAP_FIELD_BITS);
|
|
47
|
+
mi_assert_internal(count > 0);
|
|
48
|
+
mi_bitmap_field_t* field = &bitmap[idx];
|
|
49
|
+
size_t map = mi_atomic_load_relaxed(field);
|
|
50
|
+
if (map==MI_BITMAP_FIELD_FULL) return false; // short cut
|
|
51
|
+
|
|
52
|
+
// search for 0-bit sequence of length count
|
|
53
|
+
const size_t mask = mi_bitmap_mask_(count, 0);
|
|
54
|
+
const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count;
|
|
55
|
+
|
|
56
|
+
#ifdef MI_HAVE_FAST_BITSCAN
|
|
57
|
+
size_t bitidx = mi_ctz(~map); // quickly find the first zero bit if possible
|
|
58
|
+
#else
|
|
59
|
+
size_t bitidx = 0; // otherwise start at 0
|
|
60
|
+
#endif
|
|
61
|
+
size_t m = (mask << bitidx); // invariant: m == mask shifted by bitidx
|
|
62
|
+
|
|
63
|
+
// scan linearly for a free range of zero bits
|
|
64
|
+
while (bitidx <= bitidx_max) {
|
|
65
|
+
const size_t mapm = (map & m);
|
|
66
|
+
if (mapm == 0) { // are the mask bits free at bitidx?
|
|
67
|
+
mi_assert_internal((m >> bitidx) == mask); // no overflow?
|
|
68
|
+
const size_t newmap = (map | m);
|
|
69
|
+
mi_assert_internal((newmap^map) >> bitidx == mask);
|
|
70
|
+
if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { // TODO: use weak cas here?
|
|
71
|
+
// no success, another thread claimed concurrently.. keep going (with updated `map`)
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// success, we claimed the bits!
|
|
76
|
+
*bitmap_idx = mi_bitmap_index_create(idx, bitidx);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// on to the next bit range
|
|
82
|
+
#ifdef MI_HAVE_FAST_BITSCAN
|
|
83
|
+
mi_assert_internal(mapm != 0);
|
|
84
|
+
const size_t shift = (count == 1 ? 1 : (MI_SIZE_BITS - mi_clz(mapm) - bitidx));
|
|
85
|
+
mi_assert_internal(shift > 0 && shift <= count);
|
|
86
|
+
#else
|
|
87
|
+
const size_t shift = 1;
|
|
88
|
+
#endif
|
|
89
|
+
bitidx += shift;
|
|
90
|
+
m <<= shift;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// no bits found
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success.
|
|
98
|
+
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
|
99
|
+
// `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields.
|
|
100
|
+
bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
|
101
|
+
size_t idx = start_field_idx;
|
|
102
|
+
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
|
103
|
+
if (idx >= bitmap_fields) { idx = 0; } // wrap
|
|
104
|
+
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Like _mi_bitmap_try_find_from_claim but with an extra predicate that must be fullfilled
|
|
112
|
+
bool _mi_bitmap_try_find_from_claim_pred(mi_bitmap_t bitmap, const size_t bitmap_fields,
|
|
113
|
+
const size_t start_field_idx, const size_t count,
|
|
114
|
+
mi_bitmap_pred_fun_t pred_fun, void* pred_arg,
|
|
115
|
+
mi_bitmap_index_t* bitmap_idx) {
|
|
116
|
+
size_t idx = start_field_idx;
|
|
117
|
+
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
|
118
|
+
if (idx >= bitmap_fields) idx = 0; // wrap
|
|
119
|
+
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
|
120
|
+
if (pred_fun == NULL || pred_fun(*bitmap_idx, pred_arg)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
// predicate returned false, unclaim and look further
|
|
124
|
+
_mi_bitmap_unclaim(bitmap, bitmap_fields, count, *bitmap_idx);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Set `count` bits at `bitmap_idx` to 0 atomically
|
|
131
|
+
// Returns `true` if all `count` bits were 1 previously.
|
|
132
|
+
bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
133
|
+
const size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
134
|
+
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
|
135
|
+
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
|
136
|
+
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
|
137
|
+
// mi_assert_internal((bitmap[idx] & mask) == mask);
|
|
138
|
+
const size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
|
|
139
|
+
return ((prev & mask) == mask);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
// Set `count` bits at `bitmap_idx` to 1 atomically
|
|
144
|
+
// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
|
|
145
|
+
bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) {
|
|
146
|
+
const size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
147
|
+
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
|
148
|
+
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
|
149
|
+
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
|
150
|
+
//mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
|
|
151
|
+
size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
|
|
152
|
+
if (any_zero != NULL) { *any_zero = ((prev & mask) != mask); }
|
|
153
|
+
return ((prev & mask) == 0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one.
|
|
157
|
+
static bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) {
|
|
158
|
+
const size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
159
|
+
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
|
160
|
+
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
|
161
|
+
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
|
162
|
+
const size_t field = mi_atomic_load_relaxed(&bitmap[idx]);
|
|
163
|
+
if (any_ones != NULL) { *any_ones = ((field & mask) != 0); }
|
|
164
|
+
return ((field & mask) == mask);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Try to set `count` bits at `bitmap_idx` from 0 to 1 atomically.
|
|
168
|
+
// Returns `true` if successful when all previous `count` bits were 0.
|
|
169
|
+
bool _mi_bitmap_try_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
170
|
+
const size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
171
|
+
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
|
172
|
+
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
|
173
|
+
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
|
174
|
+
size_t expected = mi_atomic_load_relaxed(&bitmap[idx]);
|
|
175
|
+
do {
|
|
176
|
+
if ((expected & mask) != 0) return false;
|
|
177
|
+
}
|
|
178
|
+
while (!mi_atomic_cas_strong_acq_rel(&bitmap[idx], &expected, expected | mask));
|
|
179
|
+
mi_assert_internal((expected & mask) == 0);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
185
|
+
return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
189
|
+
bool any_ones;
|
|
190
|
+
mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones);
|
|
191
|
+
return any_ones;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
//--------------------------------------------------------------------------
|
|
196
|
+
// the `_across` functions work on bitmaps where sequences can cross over
|
|
197
|
+
// between the fields. This is used in arena allocation
|
|
198
|
+
//--------------------------------------------------------------------------
|
|
199
|
+
|
|
200
|
+
// Try to atomically claim a sequence of `count` bits starting from the field
|
|
201
|
+
// at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success.
|
|
202
|
+
// Only needs to consider crossing into the next fields (see `mi_bitmap_try_find_from_claim_across`)
|
|
203
|
+
static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx)
|
|
204
|
+
{
|
|
205
|
+
mi_assert_internal(bitmap_idx != NULL);
|
|
206
|
+
|
|
207
|
+
// check initial trailing zeros
|
|
208
|
+
mi_bitmap_field_t* field = &bitmap[idx];
|
|
209
|
+
size_t map = mi_atomic_load_relaxed(field);
|
|
210
|
+
const size_t initial = mi_clz(map); // count of initial zeros starting at idx
|
|
211
|
+
mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS);
|
|
212
|
+
if (initial == 0) return false;
|
|
213
|
+
if (initial >= count) return _mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx); // no need to cross fields (this case won't happen for us)
|
|
214
|
+
if (_mi_divide_up(count - initial, MI_BITMAP_FIELD_BITS) >= (bitmap_fields - idx)) return false; // not enough entries
|
|
215
|
+
|
|
216
|
+
// scan ahead
|
|
217
|
+
size_t found = initial;
|
|
218
|
+
size_t mask = 0; // mask bits for the final field
|
|
219
|
+
while(found < count) {
|
|
220
|
+
field++;
|
|
221
|
+
map = mi_atomic_load_relaxed(field);
|
|
222
|
+
const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
|
|
223
|
+
mi_assert_internal(mask_bits > 0 && mask_bits <= MI_BITMAP_FIELD_BITS);
|
|
224
|
+
mask = mi_bitmap_mask_(mask_bits, 0);
|
|
225
|
+
if ((map & mask) != 0) return false; // some part is already claimed
|
|
226
|
+
found += mask_bits;
|
|
227
|
+
}
|
|
228
|
+
mi_assert_internal(field < &bitmap[bitmap_fields]);
|
|
229
|
+
|
|
230
|
+
// we found a range of contiguous zeros up to the final field; mask contains mask in the final field
|
|
231
|
+
// now try to claim the range atomically
|
|
232
|
+
mi_bitmap_field_t* const final_field = field;
|
|
233
|
+
const size_t final_mask = mask;
|
|
234
|
+
mi_bitmap_field_t* const initial_field = &bitmap[idx];
|
|
235
|
+
const size_t initial_idx = MI_BITMAP_FIELD_BITS - initial;
|
|
236
|
+
const size_t initial_mask = mi_bitmap_mask_(initial, initial_idx);
|
|
237
|
+
|
|
238
|
+
// initial field
|
|
239
|
+
size_t newmap;
|
|
240
|
+
field = initial_field;
|
|
241
|
+
map = mi_atomic_load_relaxed(field);
|
|
242
|
+
do {
|
|
243
|
+
newmap = (map | initial_mask);
|
|
244
|
+
if ((map & initial_mask) != 0) { goto rollback; };
|
|
245
|
+
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
|
246
|
+
|
|
247
|
+
// intermediate fields
|
|
248
|
+
while (++field < final_field) {
|
|
249
|
+
newmap = MI_BITMAP_FIELD_FULL;
|
|
250
|
+
map = 0;
|
|
251
|
+
if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { goto rollback; }
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// final field
|
|
255
|
+
mi_assert_internal(field == final_field);
|
|
256
|
+
map = mi_atomic_load_relaxed(field);
|
|
257
|
+
do {
|
|
258
|
+
newmap = (map | final_mask);
|
|
259
|
+
if ((map & final_mask) != 0) { goto rollback; }
|
|
260
|
+
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
|
261
|
+
|
|
262
|
+
// claimed!
|
|
263
|
+
*bitmap_idx = mi_bitmap_index_create(idx, initial_idx);
|
|
264
|
+
return true;
|
|
265
|
+
|
|
266
|
+
rollback:
|
|
267
|
+
// roll back intermediate fields
|
|
268
|
+
// (we just failed to claim `field` so decrement first)
|
|
269
|
+
while (--field > initial_field) {
|
|
270
|
+
newmap = 0;
|
|
271
|
+
map = MI_BITMAP_FIELD_FULL;
|
|
272
|
+
mi_assert_internal(mi_atomic_load_relaxed(field) == map);
|
|
273
|
+
mi_atomic_store_release(field, newmap);
|
|
274
|
+
}
|
|
275
|
+
if (field == initial_field) { // (if we failed on the initial field, `field + 1 == initial_field`)
|
|
276
|
+
map = mi_atomic_load_relaxed(field);
|
|
277
|
+
do {
|
|
278
|
+
mi_assert_internal((map & initial_mask) == initial_mask);
|
|
279
|
+
newmap = (map & ~initial_mask);
|
|
280
|
+
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
|
281
|
+
}
|
|
282
|
+
mi_stat_counter_increase(_mi_stats_main.arena_rollback_count,1);
|
|
283
|
+
// retry? (we make a recursive call instead of goto to be able to use const declarations)
|
|
284
|
+
if (retries <= 2) {
|
|
285
|
+
return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success.
|
|
294
|
+
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
|
295
|
+
bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
|
296
|
+
mi_assert_internal(count > 0);
|
|
297
|
+
if (count <= 2) {
|
|
298
|
+
// we don't bother with crossover fields for small counts
|
|
299
|
+
return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, start_field_idx, count, bitmap_idx);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// visit the fields
|
|
303
|
+
size_t idx = start_field_idx;
|
|
304
|
+
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
|
305
|
+
if (idx >= bitmap_fields) { idx = 0; } // wrap
|
|
306
|
+
// first try to claim inside a field
|
|
307
|
+
/*
|
|
308
|
+
if (count <= MI_BITMAP_FIELD_BITS) {
|
|
309
|
+
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
*/
|
|
314
|
+
// if that fails, then try to claim across fields
|
|
315
|
+
if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Helper for masks across fields; returns the mid count, post_mask may be 0
|
|
323
|
+
static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_fields, size_t count, size_t* pre_mask, size_t* mid_mask, size_t* post_mask) {
|
|
324
|
+
MI_UNUSED(bitmap_fields);
|
|
325
|
+
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
|
326
|
+
if mi_likely(bitidx + count <= MI_BITMAP_FIELD_BITS) {
|
|
327
|
+
*pre_mask = mi_bitmap_mask_(count, bitidx);
|
|
328
|
+
*mid_mask = 0;
|
|
329
|
+
*post_mask = 0;
|
|
330
|
+
mi_assert_internal(mi_bitmap_index_field(bitmap_idx) < bitmap_fields);
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
const size_t pre_bits = MI_BITMAP_FIELD_BITS - bitidx;
|
|
335
|
+
mi_assert_internal(pre_bits < count);
|
|
336
|
+
*pre_mask = mi_bitmap_mask_(pre_bits, bitidx);
|
|
337
|
+
count -= pre_bits;
|
|
338
|
+
const size_t mid_count = (count / MI_BITMAP_FIELD_BITS);
|
|
339
|
+
*mid_mask = MI_BITMAP_FIELD_FULL;
|
|
340
|
+
count %= MI_BITMAP_FIELD_BITS;
|
|
341
|
+
*post_mask = (count==0 ? 0 : mi_bitmap_mask_(count, 0));
|
|
342
|
+
mi_assert_internal(mi_bitmap_index_field(bitmap_idx) + mid_count + (count==0 ? 0 : 1) < bitmap_fields);
|
|
343
|
+
return mid_count;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Set `count` bits at `bitmap_idx` to 0 atomically
|
|
348
|
+
// Returns `true` if all `count` bits were 1 previously.
|
|
349
|
+
bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
350
|
+
size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
351
|
+
size_t pre_mask;
|
|
352
|
+
size_t mid_mask;
|
|
353
|
+
size_t post_mask;
|
|
354
|
+
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
|
|
355
|
+
bool all_one = true;
|
|
356
|
+
mi_bitmap_field_t* field = &bitmap[idx];
|
|
357
|
+
size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask); // clear first part
|
|
358
|
+
if ((prev & pre_mask) != pre_mask) all_one = false;
|
|
359
|
+
while(mid_count-- > 0) {
|
|
360
|
+
prev = mi_atomic_and_acq_rel(field++, ~mid_mask); // clear mid part
|
|
361
|
+
if ((prev & mid_mask) != mid_mask) all_one = false;
|
|
362
|
+
}
|
|
363
|
+
if (post_mask!=0) {
|
|
364
|
+
prev = mi_atomic_and_acq_rel(field, ~post_mask); // clear end part
|
|
365
|
+
if ((prev & post_mask) != post_mask) all_one = false;
|
|
366
|
+
}
|
|
367
|
+
return all_one;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Set `count` bits at `bitmap_idx` to 1 atomically
|
|
371
|
+
// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
|
|
372
|
+
bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero, size_t* already_set) {
|
|
373
|
+
size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
374
|
+
size_t pre_mask;
|
|
375
|
+
size_t mid_mask;
|
|
376
|
+
size_t post_mask;
|
|
377
|
+
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
|
|
378
|
+
bool all_zero = true;
|
|
379
|
+
bool any_zero = false;
|
|
380
|
+
size_t one_count = 0;
|
|
381
|
+
_Atomic(size_t)*field = &bitmap[idx];
|
|
382
|
+
size_t prev = mi_atomic_or_acq_rel(field++, pre_mask);
|
|
383
|
+
if ((prev & pre_mask) != 0) { all_zero = false; one_count += mi_popcount(prev & pre_mask); }
|
|
384
|
+
if ((prev & pre_mask) != pre_mask) any_zero = true;
|
|
385
|
+
while (mid_count-- > 0) {
|
|
386
|
+
prev = mi_atomic_or_acq_rel(field++, mid_mask);
|
|
387
|
+
if ((prev & mid_mask) != 0) { all_zero = false; one_count += mi_popcount(prev & mid_mask); }
|
|
388
|
+
if ((prev & mid_mask) != mid_mask) any_zero = true;
|
|
389
|
+
}
|
|
390
|
+
if (post_mask!=0) {
|
|
391
|
+
prev = mi_atomic_or_acq_rel(field, post_mask);
|
|
392
|
+
if ((prev & post_mask) != 0) { all_zero = false; one_count += mi_popcount(prev & post_mask); }
|
|
393
|
+
if ((prev & post_mask) != post_mask) any_zero = true;
|
|
394
|
+
}
|
|
395
|
+
if (pany_zero != NULL) { *pany_zero = any_zero; }
|
|
396
|
+
if (already_set != NULL) { *already_set = one_count; };
|
|
397
|
+
mi_assert_internal(all_zero ? one_count == 0 : one_count <= count);
|
|
398
|
+
return all_zero;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
// Returns `true` if all `count` bits were 1.
|
|
403
|
+
// `any_ones` is `true` if there was at least one bit set to one.
|
|
404
|
+
static bool mi_bitmap_is_claimedx_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_ones, size_t* already_set) {
|
|
405
|
+
size_t idx = mi_bitmap_index_field(bitmap_idx);
|
|
406
|
+
size_t pre_mask;
|
|
407
|
+
size_t mid_mask;
|
|
408
|
+
size_t post_mask;
|
|
409
|
+
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
|
|
410
|
+
bool all_ones = true;
|
|
411
|
+
bool any_ones = false;
|
|
412
|
+
size_t one_count = 0;
|
|
413
|
+
mi_bitmap_field_t* field = &bitmap[idx];
|
|
414
|
+
size_t prev = mi_atomic_load_relaxed(field++);
|
|
415
|
+
if ((prev & pre_mask) != pre_mask) all_ones = false;
|
|
416
|
+
if ((prev & pre_mask) != 0) { any_ones = true; one_count += mi_popcount(prev & pre_mask); }
|
|
417
|
+
while (mid_count-- > 0) {
|
|
418
|
+
prev = mi_atomic_load_relaxed(field++);
|
|
419
|
+
if ((prev & mid_mask) != mid_mask) all_ones = false;
|
|
420
|
+
if ((prev & mid_mask) != 0) { any_ones = true; one_count += mi_popcount(prev & mid_mask); }
|
|
421
|
+
}
|
|
422
|
+
if (post_mask!=0) {
|
|
423
|
+
prev = mi_atomic_load_relaxed(field);
|
|
424
|
+
if ((prev & post_mask) != post_mask) all_ones = false;
|
|
425
|
+
if ((prev & post_mask) != 0) { any_ones = true; one_count += mi_popcount(prev & post_mask); }
|
|
426
|
+
}
|
|
427
|
+
if (pany_ones != NULL) { *pany_ones = any_ones; }
|
|
428
|
+
if (already_set != NULL) { *already_set = one_count; }
|
|
429
|
+
mi_assert_internal(all_ones ? one_count == count : one_count < count);
|
|
430
|
+
return all_ones;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, size_t* already_set) {
|
|
434
|
+
return mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, NULL, already_set);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
|
|
438
|
+
bool any_ones;
|
|
439
|
+
mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, &any_ones, NULL);
|
|
440
|
+
return any_ones;
|
|
441
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* ----------------------------------------------------------------------------
|
|
2
|
+
Copyright (c) 2019-2023 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
|
+
/* ----------------------------------------------------------------------------
|
|
9
|
+
Concurrent bitmap that can set/reset sequences of bits atomically,
|
|
10
|
+
represented as an array of fields where each field is a machine word (`size_t`)
|
|
11
|
+
|
|
12
|
+
There are two api's; the standard one cannot have sequences that cross
|
|
13
|
+
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
|
|
14
|
+
(this is used in region allocation)
|
|
15
|
+
|
|
16
|
+
The `_across` postfixed functions do allow sequences that can cross over
|
|
17
|
+
between the fields. (This is used in arena allocation)
|
|
18
|
+
---------------------------------------------------------------------------- */
|
|
19
|
+
#pragma once
|
|
20
|
+
#ifndef MI_BITMAP_H
|
|
21
|
+
#define MI_BITMAP_H
|
|
22
|
+
|
|
23
|
+
/* -----------------------------------------------------------
|
|
24
|
+
Bitmap definition
|
|
25
|
+
----------------------------------------------------------- */
|
|
26
|
+
|
|
27
|
+
#define MI_BITMAP_FIELD_BITS (8*MI_SIZE_SIZE)
|
|
28
|
+
#define MI_BITMAP_FIELD_FULL (~((size_t)0)) // all bits set
|
|
29
|
+
|
|
30
|
+
// An atomic bitmap of `size_t` fields
|
|
31
|
+
typedef _Atomic(size_t) mi_bitmap_field_t;
|
|
32
|
+
typedef mi_bitmap_field_t* mi_bitmap_t;
|
|
33
|
+
|
|
34
|
+
// A bitmap index is the index of the bit in a bitmap.
|
|
35
|
+
typedef size_t mi_bitmap_index_t;
|
|
36
|
+
|
|
37
|
+
// Create a bit index.
|
|
38
|
+
static inline mi_bitmap_index_t mi_bitmap_index_create_ex(size_t idx, size_t bitidx) {
|
|
39
|
+
mi_assert_internal(bitidx <= MI_BITMAP_FIELD_BITS);
|
|
40
|
+
return (idx*MI_BITMAP_FIELD_BITS) + bitidx;
|
|
41
|
+
}
|
|
42
|
+
static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) {
|
|
43
|
+
mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS);
|
|
44
|
+
return mi_bitmap_index_create_ex(idx,bitidx);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create a bit index.
|
|
48
|
+
static inline mi_bitmap_index_t mi_bitmap_index_create_from_bit(size_t full_bitidx) {
|
|
49
|
+
return mi_bitmap_index_create(full_bitidx / MI_BITMAP_FIELD_BITS, full_bitidx % MI_BITMAP_FIELD_BITS);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Get the field index from a bit index.
|
|
53
|
+
static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) {
|
|
54
|
+
return (bitmap_idx / MI_BITMAP_FIELD_BITS);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Get the bit index in a bitmap field
|
|
58
|
+
static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) {
|
|
59
|
+
return (bitmap_idx % MI_BITMAP_FIELD_BITS);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Get the full bit index
|
|
63
|
+
static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) {
|
|
64
|
+
return bitmap_idx;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* -----------------------------------------------------------
|
|
68
|
+
Claim a bit sequence atomically
|
|
69
|
+
----------------------------------------------------------- */
|
|
70
|
+
|
|
71
|
+
// Try to atomically claim a sequence of `count` bits in a single
|
|
72
|
+
// field at `idx` in `bitmap`. Returns `true` on success.
|
|
73
|
+
bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
|
|
74
|
+
|
|
75
|
+
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
|
76
|
+
// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields.
|
|
77
|
+
bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
|
|
78
|
+
|
|
79
|
+
// Like _mi_bitmap_try_find_from_claim but with an extra predicate that must be fullfilled
|
|
80
|
+
typedef bool (mi_cdecl *mi_bitmap_pred_fun_t)(mi_bitmap_index_t bitmap_idx, void* pred_arg);
|
|
81
|
+
bool _mi_bitmap_try_find_from_claim_pred(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_pred_fun_t pred_fun, void* pred_arg, mi_bitmap_index_t* bitmap_idx);
|
|
82
|
+
|
|
83
|
+
// Set `count` bits at `bitmap_idx` to 0 atomically
|
|
84
|
+
// Returns `true` if all `count` bits were 1 previously.
|
|
85
|
+
bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
86
|
+
|
|
87
|
+
// Try to set `count` bits at `bitmap_idx` from 0 to 1 atomically.
|
|
88
|
+
// Returns `true` if successful when all previous `count` bits were 0.
|
|
89
|
+
bool _mi_bitmap_try_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
90
|
+
|
|
91
|
+
// Set `count` bits at `bitmap_idx` to 1 atomically
|
|
92
|
+
// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
|
|
93
|
+
bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero);
|
|
94
|
+
|
|
95
|
+
bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
96
|
+
bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
//--------------------------------------------------------------------------
|
|
100
|
+
// the `_across` functions work on bitmaps where sequences can cross over
|
|
101
|
+
// between the fields. This is used in arena allocation
|
|
102
|
+
//--------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success.
|
|
105
|
+
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
|
106
|
+
bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
|
|
107
|
+
|
|
108
|
+
// Set `count` bits at `bitmap_idx` to 0 atomically
|
|
109
|
+
// Returns `true` if all `count` bits were 1 previously.
|
|
110
|
+
bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
111
|
+
|
|
112
|
+
// Set `count` bits at `bitmap_idx` to 1 atomically
|
|
113
|
+
// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
|
|
114
|
+
bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero, size_t* already_set);
|
|
115
|
+
|
|
116
|
+
bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, size_t* already_set);
|
|
117
|
+
bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
|
|
118
|
+
|
|
119
|
+
#endif
|