From 82f7f866c8b0fd7a2c19cfdf34fc87f8d39ce22a Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Wed, 7 Oct 2020 10:35:14 +0800 Subject: [PATCH 1/2] First commit in adding mimalloc Signed-off-by: Hanif Bin Ariffin --- deps/mimalloc/.gitattributes | 10 + deps/mimalloc/.gitignore | 8 + deps/mimalloc/CMakeLists.txt | 367 +++ deps/mimalloc/LICENSE | 21 + deps/mimalloc/azure-pipelines.yml | 168 ++ deps/mimalloc/bin/mimalloc-redirect.dll | Bin 0 -> 55808 bytes deps/mimalloc/bin/mimalloc-redirect.lib | Bin 0 -> 2874 bytes deps/mimalloc/bin/mimalloc-redirect32.dll | Bin 0 -> 39424 bytes deps/mimalloc/bin/mimalloc-redirect32.lib | Bin 0 -> 2928 bytes .../cmake/mimalloc-config-version.cmake | 18 + deps/mimalloc/cmake/mimalloc-config.cmake | 2 + .../doc/bench-c5-18xlarge-2020-01-20-a.svg | 886 ++++++ .../doc/bench-c5-18xlarge-2020-01-20-b.svg | 1184 ++++++++ .../bench-c5-18xlarge-2020-01-20-rss-a.svg | 756 +++++ .../bench-c5-18xlarge-2020-01-20-rss-b.svg | 1027 +++++++ deps/mimalloc/doc/bench-r5a-1.svg | 768 +++++ .../doc/bench-r5a-12xlarge-2020-01-16-a.svg | 867 ++++++ .../doc/bench-r5a-12xlarge-2020-01-16-b.svg | 1156 ++++++++ deps/mimalloc/doc/bench-r5a-2.svg | 982 +++++++ deps/mimalloc/doc/bench-r5a-rss-1.svg | 682 +++++ deps/mimalloc/doc/bench-r5a-rss-2.svg | 853 ++++++ deps/mimalloc/doc/bench-spec-rss.svg | 713 +++++ deps/mimalloc/doc/bench-spec.svg | 713 +++++ deps/mimalloc/doc/bench-z4-1.svg | 890 ++++++ deps/mimalloc/doc/bench-z4-2.svg | 1146 ++++++++ deps/mimalloc/doc/bench-z4-rss-1.svg | 796 +++++ deps/mimalloc/doc/bench-z4-rss-2.svg | 974 +++++++ deps/mimalloc/doc/doxyfile | 2564 +++++++++++++++++ deps/mimalloc/doc/mimalloc-doc.h | 1221 ++++++++ deps/mimalloc/doc/mimalloc-doxygen.css | 49 + deps/mimalloc/doc/mimalloc-logo-100.png | Bin 0 -> 3532 bytes deps/mimalloc/doc/mimalloc-logo.png | Bin 0 -> 73097 bytes deps/mimalloc/doc/mimalloc-logo.svg | 161 ++ .../ide/vs2017/mimalloc-override-test.vcxproj | 190 ++ .../ide/vs2017/mimalloc-override.vcxproj | 254 ++ .../ide/vs2017/mimalloc-test-stress.vcxproj | 159 + .../mimalloc/ide/vs2017/mimalloc-test.vcxproj | 158 + deps/mimalloc/ide/vs2017/mimalloc.sln | 71 + deps/mimalloc/ide/vs2017/mimalloc.vcxproj | 260 ++ .../ide/vs2019/mimalloc-override-test.vcxproj | 190 ++ .../ide/vs2019/mimalloc-override.vcxproj | 257 ++ .../ide/vs2019/mimalloc-test-api.vcxproj | 155 + .../ide/vs2019/mimalloc-test-stress.vcxproj | 159 + .../mimalloc/ide/vs2019/mimalloc-test.vcxproj | 158 + deps/mimalloc/ide/vs2019/mimalloc.sln | 81 + deps/mimalloc/ide/vs2019/mimalloc.vcxproj | 253 ++ deps/mimalloc/include/mimalloc-atomic.h | 308 ++ deps/mimalloc/include/mimalloc-internal.h | 748 +++++ deps/mimalloc/include/mimalloc-new-delete.h | 52 + deps/mimalloc/include/mimalloc-override.h | 66 + deps/mimalloc/include/mimalloc-types.h | 498 ++++ deps/mimalloc/include/mimalloc.h | 429 +++ deps/mimalloc/readme.md | 608 ++++ deps/mimalloc/src/alloc-aligned.c | 205 ++ deps/mimalloc/src/alloc-override-osx.c | 260 ++ deps/mimalloc/src/alloc-override.c | 214 ++ deps/mimalloc/src/alloc-posix.c | 157 + deps/mimalloc/src/alloc.c | 855 ++++++ deps/mimalloc/src/arena.c | 357 +++ deps/mimalloc/src/bitmap.inc.c | 247 ++ deps/mimalloc/src/heap.c | 558 ++++ deps/mimalloc/src/init.c | 563 ++++ deps/mimalloc/src/options.c | 520 ++++ deps/mimalloc/src/os.c | 1193 ++++++++ deps/mimalloc/src/page-queue.c | 368 +++ deps/mimalloc/src/page.c | 843 ++++++ deps/mimalloc/src/random.c | 339 +++ deps/mimalloc/src/region.c | 500 ++++ deps/mimalloc/src/segment.c | 1373 +++++++++ deps/mimalloc/src/static.c | 38 + deps/mimalloc/src/stats.c | 570 ++++ deps/mimalloc/test/CMakeLists.txt | 46 + deps/mimalloc/test/main-override-static.c | 168 ++ deps/mimalloc/test/main-override.c | 30 + deps/mimalloc/test/main-override.cpp | 209 ++ deps/mimalloc/test/main.c | 46 + deps/mimalloc/test/readme.md | 16 + deps/mimalloc/test/test-api.c | 249 ++ deps/mimalloc/test/test-stress.c | 329 +++ src/Makefile | 11 + 80 files changed, 34300 insertions(+) create mode 100644 deps/mimalloc/.gitattributes create mode 100644 deps/mimalloc/.gitignore create mode 100644 deps/mimalloc/CMakeLists.txt create mode 100644 deps/mimalloc/LICENSE create mode 100644 deps/mimalloc/azure-pipelines.yml create mode 100644 deps/mimalloc/bin/mimalloc-redirect.dll create mode 100644 deps/mimalloc/bin/mimalloc-redirect.lib create mode 100644 deps/mimalloc/bin/mimalloc-redirect32.dll create mode 100644 deps/mimalloc/bin/mimalloc-redirect32.lib create mode 100644 deps/mimalloc/cmake/mimalloc-config-version.cmake create mode 100644 deps/mimalloc/cmake/mimalloc-config.cmake create mode 100644 deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-a.svg create mode 100644 deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-b.svg create mode 100644 deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-a.svg create mode 100644 deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-b.svg create mode 100644 deps/mimalloc/doc/bench-r5a-1.svg create mode 100644 deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-a.svg create mode 100644 deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-b.svg create mode 100644 deps/mimalloc/doc/bench-r5a-2.svg create mode 100644 deps/mimalloc/doc/bench-r5a-rss-1.svg create mode 100644 deps/mimalloc/doc/bench-r5a-rss-2.svg create mode 100644 deps/mimalloc/doc/bench-spec-rss.svg create mode 100644 deps/mimalloc/doc/bench-spec.svg create mode 100644 deps/mimalloc/doc/bench-z4-1.svg create mode 100644 deps/mimalloc/doc/bench-z4-2.svg create mode 100644 deps/mimalloc/doc/bench-z4-rss-1.svg create mode 100644 deps/mimalloc/doc/bench-z4-rss-2.svg create mode 100644 deps/mimalloc/doc/doxyfile create mode 100644 deps/mimalloc/doc/mimalloc-doc.h create mode 100644 deps/mimalloc/doc/mimalloc-doxygen.css create mode 100644 deps/mimalloc/doc/mimalloc-logo-100.png create mode 100644 deps/mimalloc/doc/mimalloc-logo.png create mode 100644 deps/mimalloc/doc/mimalloc-logo.svg create mode 100644 deps/mimalloc/ide/vs2017/mimalloc-override-test.vcxproj create mode 100644 deps/mimalloc/ide/vs2017/mimalloc-override.vcxproj create mode 100644 deps/mimalloc/ide/vs2017/mimalloc-test-stress.vcxproj create mode 100644 deps/mimalloc/ide/vs2017/mimalloc-test.vcxproj create mode 100644 deps/mimalloc/ide/vs2017/mimalloc.sln create mode 100644 deps/mimalloc/ide/vs2017/mimalloc.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc-override-test.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc-override.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc-test-api.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc-test-stress.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc-test.vcxproj create mode 100644 deps/mimalloc/ide/vs2019/mimalloc.sln create mode 100644 deps/mimalloc/ide/vs2019/mimalloc.vcxproj create mode 100644 deps/mimalloc/include/mimalloc-atomic.h create mode 100644 deps/mimalloc/include/mimalloc-internal.h create mode 100644 deps/mimalloc/include/mimalloc-new-delete.h create mode 100644 deps/mimalloc/include/mimalloc-override.h create mode 100644 deps/mimalloc/include/mimalloc-types.h create mode 100644 deps/mimalloc/include/mimalloc.h create mode 100644 deps/mimalloc/readme.md create mode 100644 deps/mimalloc/src/alloc-aligned.c create mode 100644 deps/mimalloc/src/alloc-override-osx.c create mode 100644 deps/mimalloc/src/alloc-override.c create mode 100644 deps/mimalloc/src/alloc-posix.c create mode 100644 deps/mimalloc/src/alloc.c create mode 100644 deps/mimalloc/src/arena.c create mode 100644 deps/mimalloc/src/bitmap.inc.c create mode 100644 deps/mimalloc/src/heap.c create mode 100644 deps/mimalloc/src/init.c create mode 100644 deps/mimalloc/src/options.c create mode 100644 deps/mimalloc/src/os.c create mode 100644 deps/mimalloc/src/page-queue.c create mode 100644 deps/mimalloc/src/page.c create mode 100644 deps/mimalloc/src/random.c create mode 100644 deps/mimalloc/src/region.c create mode 100644 deps/mimalloc/src/segment.c create mode 100644 deps/mimalloc/src/static.c create mode 100644 deps/mimalloc/src/stats.c create mode 100644 deps/mimalloc/test/CMakeLists.txt create mode 100644 deps/mimalloc/test/main-override-static.c create mode 100644 deps/mimalloc/test/main-override.c create mode 100644 deps/mimalloc/test/main-override.cpp create mode 100644 deps/mimalloc/test/main.c create mode 100644 deps/mimalloc/test/readme.md create mode 100644 deps/mimalloc/test/test-api.c create mode 100644 deps/mimalloc/test/test-stress.c diff --git a/deps/mimalloc/.gitattributes b/deps/mimalloc/.gitattributes new file mode 100644 index 000000000..acdbdbf4b --- /dev/null +++ b/deps/mimalloc/.gitattributes @@ -0,0 +1,10 @@ +# default behavior is to always use unix style line endings +* text eol=lf +*.png binary +*.pdn binary +*.sln binary +*.suo binary +*.vcproj binary +*.patch binary +*.dll binary +*.lib binary diff --git a/deps/mimalloc/.gitignore b/deps/mimalloc/.gitignore new file mode 100644 index 000000000..3639d3241 --- /dev/null +++ b/deps/mimalloc/.gitignore @@ -0,0 +1,8 @@ +ide/vs20??/*.db +ide/vs20??/*.opendb +ide/vs20??/*.user +ide/vs20??/*.vcxproj.filters +ide/vs20??/.vs +out/ +docs/ +*.zip diff --git a/deps/mimalloc/CMakeLists.txt b/deps/mimalloc/CMakeLists.txt new file mode 100644 index 000000000..35460e858 --- /dev/null +++ b/deps/mimalloc/CMakeLists.txt @@ -0,0 +1,367 @@ +cmake_minimum_required(VERSION 3.0) +project(libmimalloc C CXX) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +option(MI_SECURE "Use full security mitigations (like guard pages, allocation randomization, double-free mitigation, and free-list corruption detection)" OFF) +option(MI_DEBUG_FULL "Use full internal heap invariant checking in DEBUG mode (expensive)" OFF) +option(MI_PADDING "Enable padding to detect heap block overflow (used only in DEBUG mode)" ON) +option(MI_OVERRIDE "Override the standard malloc interface (e.g. define entry points for malloc() etc)" ON) +option(MI_XMALLOC "Enable abort() call on memory allocation failure by default" OFF) +option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF) +option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) +option(MI_SEE_ASM "Generate assembly files" OFF) +option(MI_INTERPOSE "Use interpose to override standard malloc on macOS" ON) +option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" OFF) # enables interpose as well +option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF) +option(MI_BUILD_SHARED "Build shared library" ON) +option(MI_BUILD_STATIC "Build static library" ON) +option(MI_BUILD_OBJECT "Build object library" ON) +option(MI_BUILD_TESTS "Build test executables" ON) +option(MI_DEBUG_TSAN "Build with thread sanitizer (needs clang)" OFF) +option(MI_DEBUG_UBSAN "Build with undefined-behavior sanitizer (needs clang++)" OFF) +option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF) + +include("cmake/mimalloc-config-version.cmake") + +set(mi_sources + src/stats.c + src/random.c + src/os.c + src/arena.c + src/region.c + src/segment.c + src/page.c + src/alloc.c + src/alloc-aligned.c + src/alloc-posix.c + src/heap.c + src/options.c + src/init.c) + +# ----------------------------------------------------------------------------- +# Converience: set default build type depending on the build directory +# ----------------------------------------------------------------------------- + +if (NOT CMAKE_BUILD_TYPE) + if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR MI_DEBUG_FULL MATCHES "ON") + message(STATUS "No build type selected, default to: Debug") + set(CMAKE_BUILD_TYPE "Debug") + else() + message(STATUS "No build type selected, default to: Release") + set(CMAKE_BUILD_TYPE "Release") + endif() +endif() + +if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$") + message(STATUS "Default to secure build") + set(MI_SECURE "ON") +endif() + +# ----------------------------------------------------------------------------- +# Process options +# ----------------------------------------------------------------------------- + +if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel") + set(MI_USE_CXX "ON") +endif() + +if(MI_OVERRIDE MATCHES "ON") + message(STATUS "Override standard malloc (MI_OVERRIDE=ON)") + if(APPLE) + if(MI_OSX_ZONE MATCHES "ON") + # use zone's on macOS + message(STATUS " Use malloc zone to override malloc (MI_OSX_ZONE=ON)") + list(APPEND mi_sources src/alloc-override-osx.c) + list(APPEND mi_defines MI_OSX_ZONE=1) + if(NOT MI_INTERPOSE MATCHES "ON") + message(STATUS " (enabling INTERPOSE as well since zone's require this)") + set(MI_INTERPOSE "ON") + endif() + endif() + if(MI_INTERPOSE MATCHES "ON") + # use interpose on macOS + message(STATUS " Use interpose to override malloc (MI_INTERPOSE=ON)") + list(APPEND mi_defines MI_INTERPOSE) + endif() + endif() +endif() + +if(MI_SECURE MATCHES "ON") + message(STATUS "Set full secure build (MI_SECURE=ON)") + list(APPEND mi_defines MI_SECURE=4) +endif() + +if(MI_SEE_ASM MATCHES "ON") + message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)") + list(APPEND mi_cflags -save-temps) +endif() + +if(MI_CHECK_FULL MATCHES "ON") + message(STATUS "The MI_CHECK_FULL option is deprecated, use MI_DEBUG_FULL instead") + set(MI_DEBUG_FULL "ON") +endif() + +if(MI_DEBUG_FULL MATCHES "ON") + message(STATUS "Set debug level to full internal invariant checking (MI_DEBUG_FULL=ON)") + list(APPEND mi_defines MI_DEBUG=3) # full invariant checking +endif() + +if(MI_PADDING MATCHES "OFF") + message(STATUS "Disable padding of heap blocks in debug mode (MI_PADDING=OFF)") + list(APPEND mi_defines MI_PADDING=0) +endif() + +if(MI_XMALLOC MATCHES "ON") + message(STATUS "Enable abort() calls on memory allocation failure (MI_XMALLOC=ON)") + list(APPEND mi_defines MI_XMALLOC=1) +endif() + +if(MI_SHOW_ERRORS MATCHES "ON") + message(STATUS "Enable printing of error and warning messages by default (MI_SHOW_ERRORS=ON)") + list(APPEND mi_defines MI_SHOW_ERRORS=1) +endif() + +if(MI_DEBUG_TSAN MATCHES "ON") + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + message(STATUS "Build with thread sanitizer (MI_DEBUG_TSAN=ON)") + list(APPEND mi_defines MI_TSAN=1) + list(APPEND mi_cflags -fsanitize=thread -g -O1) + list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=thread) + else() + message(WARNING "Can only use thread sanitizer with clang (MI_DEBUG_TSAN=ON but ignored)") + endif() +endif() + +if(MI_DEBUG_UBSAN MATCHES "ON") + if(CMAKE_BUILD_TYPE MATCHES "Debug") + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(STATUS "Build with undefined-behavior sanitizer (MI_DEBUG_UBSAN=ON)") + list(APPEND mi_cflags -fsanitize=undefined -g) + list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=undefined) + if (MI_USE_CXX MATCHES "OFF") + message(STATUS "(switch to use C++ due to MI_DEBUG_UBSAN)") + set(MI_USE_CXX "ON") + endif() + else() + message(WARNING "Can only use undefined-behavior sanitizer with clang++ (MI_DEBUG_UBSAN=ON but ignored)") + endif() + else() + message(WARNING "Can only use thread sanitizer with a debug build (CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})") + endif() +endif() + +if(MI_USE_CXX MATCHES "ON") + message(STATUS "Use the C++ compiler to compile (MI_USE_CXX=ON)") + set_source_files_properties(${mi_sources} PROPERTIES LANGUAGE CXX ) + set_source_files_properties(src/static.c test/test-api.c test/test-stress PROPERTIES LANGUAGE CXX ) + if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang|Clang") + list(APPEND mi_cflags -Wno-deprecated) + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + list(APPEND mi_cflags -Kc++) + endif() +endif() + +# Compiler flags +if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") + list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden) + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND mi_cflags -Wno-invalid-memory-model) + endif() +endif() + +if(CMAKE_C_COMPILER_ID MATCHES "Intel") + list(APPEND mi_cflags -Wall -fvisibility=hidden) +endif() + +if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM_NAME MATCHES "Haiku") + if(MI_LOCAL_DYNAMIC_TLS MATCHES "ON") + list(APPEND mi_cflags -ftls-model=local-dynamic) + else() + list(APPEND mi_cflags -ftls-model=initial-exec) + endif() +endif() + +# Architecture flags +if(${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm") + list(APPEND mi_cflags -march=native) +endif() + +# extra needed libraries +if(WIN32) + list(APPEND mi_libraries psapi shell32 user32 advapi32 bcrypt) +else() + if(NOT ${CMAKE_C_COMPILER} MATCHES "android") + list(APPEND mi_libraries pthread) + find_library(LIBRT rt) + if(LIBRT) + list(APPEND mi_libraries ${LIBRT}) + endif() + endif() +endif() + +# ----------------------------------------------------------------------------- +# Install and output names +# ----------------------------------------------------------------------------- + +set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}") +if(MI_SECURE MATCHES "ON") + set(mi_basename "mimalloc-secure") +else() + set(mi_basename "mimalloc") +endif() +string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC) +if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel)$")) + set(mi_basename "${mi_basename}-${CMAKE_BUILD_TYPE_LC}") #append build type (e.g. -debug) if not a release version +endif() +if(MI_BUILD_SHARED) + list(APPEND mi_build_targets "shared") +endif() +if(MI_BUILD_STATIC) + list(APPEND mi_build_targets "static") +endif() +if(MI_BUILD_OBJECT) + list(APPEND mi_build_targets "object") +endif() +if(MI_BUILD_TESTS) + list(APPEND mi_build_targets "tests") +endif() +message(STATUS "") +message(STATUS "Library base name: ${mi_basename}") +message(STATUS "Build type : ${CMAKE_BUILD_TYPE_LC}") +if(MI_USE_CXX MATCHES "ON") + message(STATUS "Compiler : ${CMAKE_CXX_COMPILER}") +else() + message(STATUS "Compiler : ${CMAKE_C_COMPILER}") +endif() +message(STATUS "Install directory: ${mi_install_dir}") +message(STATUS "Build targets : ${mi_build_targets}") +message(STATUS "") + +# ----------------------------------------------------------------------------- +# Main targets +# ----------------------------------------------------------------------------- + +# shared library +if(MI_BUILD_SHARED) + add_library(mimalloc SHARED ${mi_sources}) + set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} OUTPUT_NAME ${mi_basename} ) + target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_SHARED_LIB MI_SHARED_LIB_EXPORT) + target_compile_options(mimalloc PRIVATE ${mi_cflags}) + target_link_libraries(mimalloc PUBLIC ${mi_libraries}) + target_include_directories(mimalloc PUBLIC + $ + $ + ) + if(WIN32) + # On windows copy the mimalloc redirection dll too. + target_link_libraries(mimalloc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect.lib) + add_custom_command(TARGET mimalloc POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect.dll" $ + COMMENT "Copy mimalloc-redirect.dll to output directory") + endif() + + install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY) + install(EXPORT mimalloc DESTINATION ${mi_install_dir}/cmake) +endif() + +# static library +if (MI_BUILD_STATIC) + add_library(mimalloc-static STATIC ${mi_sources}) + set_property(TARGET mimalloc-static PROPERTY POSITION_INDEPENDENT_CODE ON) + target_compile_definitions(mimalloc-static PRIVATE ${mi_defines} MI_STATIC_LIB) + target_compile_options(mimalloc-static PRIVATE ${mi_cflags}) + target_link_libraries(mimalloc-static PUBLIC ${mi_libraries}) + target_include_directories(mimalloc-static PUBLIC + $ + $ + ) + if(WIN32) + # When building both static and shared libraries on Windows, a static library should use a + # different output name to avoid the conflict with the import library of a shared one. + string(REPLACE "mimalloc" "mimalloc-static" mi_output_name ${mi_basename}) + set_target_properties(mimalloc-static PROPERTIES OUTPUT_NAME ${mi_output_name}) + else() + set_target_properties(mimalloc-static PROPERTIES OUTPUT_NAME ${mi_basename}) + endif() + + install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_dir}) +endif() + +# install include files +install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include) +install(FILES include/mimalloc-override.h DESTINATION ${mi_install_dir}/include) +install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_dir}/include) +install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_dir}/cmake) +install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_dir}/cmake) + +if(NOT WIN32 AND MI_BUILD_SHARED) + # install a symlink in the /usr/local/lib to the versioned library + set(mi_symlink "${CMAKE_SHARED_MODULE_PREFIX}${mi_basename}${CMAKE_SHARED_LIBRARY_SUFFIX}") + set(mi_soname "mimalloc-${mi_version}/${mi_symlink}.${mi_version}") + install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${mi_soname} ${mi_symlink} WORKING_DIRECTORY ${mi_install_dir}/..)") + install(CODE "MESSAGE(\"-- Symbolic link: ${CMAKE_INSTALL_PREFIX}/lib/${mi_symlink} -> ${mi_soname}\")") +endif() + +# single object file for more predictable static overriding +if (MI_BUILD_OBJECT) + add_library(mimalloc-obj OBJECT src/static.c) + set_property(TARGET mimalloc-obj PROPERTY POSITION_INDEPENDENT_CODE ON) + target_compile_definitions(mimalloc-obj PRIVATE ${mi_defines}) + target_compile_options(mimalloc-obj PRIVATE ${mi_cflags}) + target_include_directories(mimalloc-obj PUBLIC + $ + $ + ) + + # the following seems to lead to cmake warnings/errors on some systems, disable for now :-( + # install(TARGETS mimalloc-obj EXPORT mimalloc DESTINATION ${mi_install_dir}) + + # the FILES expression can also be: $ + # but that fails cmake versions less than 3.10 so we leave it as is for now + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/mimalloc-obj.dir/src/static.c${CMAKE_C_OUTPUT_EXTENSION} + DESTINATION ${mi_install_dir} + RENAME ${mi_basename}${CMAKE_C_OUTPUT_EXTENSION} ) +endif() + +# ----------------------------------------------------------------------------- +# API surface testing +# ----------------------------------------------------------------------------- + +if (MI_BUILD_TESTS MATCHES "ON") + add_executable(mimalloc-test-api test/test-api.c) + target_compile_definitions(mimalloc-test-api PRIVATE ${mi_defines}) + target_compile_options(mimalloc-test-api PRIVATE ${mi_cflags}) + target_include_directories(mimalloc-test-api PRIVATE include) + target_link_libraries(mimalloc-test-api PRIVATE mimalloc-static ${mi_libraries}) + + add_executable(mimalloc-test-stress test/test-stress.c) + target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines}) + target_compile_options(mimalloc-test-stress PRIVATE ${mi_cflags}) + target_include_directories(mimalloc-test-stress PRIVATE include) + target_link_libraries(mimalloc-test-stress PRIVATE mimalloc ${mi_libraries}) + + enable_testing() + add_test(test_api, mimalloc-test-api) + add_test(test_stress, mimalloc-test-stress) +endif() + +# ----------------------------------------------------------------------------- +# Set override properties +# ----------------------------------------------------------------------------- +if (MI_OVERRIDE MATCHES "ON") + if (MI_BUILD_SHARED) + target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) + endif() + if(NOT WIN32) + # It is only possible to override malloc on Windows when building as a DLL. + if (MI_BUILD_STATIC) + target_compile_definitions(mimalloc-static PRIVATE MI_MALLOC_OVERRIDE) + endif() + if (MI_BUILD_OBJECT) + target_compile_definitions(mimalloc-obj PRIVATE MI_MALLOC_OVERRIDE) + endif() + endif() +endif() diff --git a/deps/mimalloc/LICENSE b/deps/mimalloc/LICENSE new file mode 100644 index 000000000..4151dbe4a --- /dev/null +++ b/deps/mimalloc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/deps/mimalloc/azure-pipelines.yml b/deps/mimalloc/azure-pipelines.yml new file mode 100644 index 000000000..85e89420e --- /dev/null +++ b/deps/mimalloc/azure-pipelines.yml @@ -0,0 +1,168 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- master +- dev + +jobs: +- job: + displayName: Windows + pool: + vmImage: + windows-2019 + strategy: + matrix: + Debug: + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + MSBuildConfiguration: Debug + Release: + BuildType: release + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + MSBuildConfiguration: Release + Secure: + BuildType: secure + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON + MSBuildConfiguration: Release + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - task: MSBuild@1 + inputs: + solution: $(BuildType)/libmimalloc.sln + configuration: '$(MSBuildConfiguration)' + msbuildArguments: -m + - script: ctest --verbose --timeout 120 + workingDirectory: $(BuildType) + displayName: CTest + #- script: $(BuildType)\$(BuildType)\mimalloc-test-stress + # displayName: TestStress + #- upload: $(Build.SourcesDirectory)/$(BuildType) + # artifact: mimalloc-windows-$(BuildType) + +- job: + displayName: Linux + pool: + vmImage: + ubuntu-18.04 + strategy: + matrix: + Debug: + CC: gcc + CXX: g++ + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Release: + CC: gcc + CXX: g++ + BuildType: release + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + Secure: + CC: gcc + CXX: g++ + BuildType: secure + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON + Debug++: + CC: gcc + CXX: g++ + BuildType: debug-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + Debug Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Release Clang: + CC: clang + CXX: clang++ + BuildType: release-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + Secure Clang: + CC: clang + CXX: clang++ + BuildType: secure-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON + Debug++ Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - script: make -j$(nproc) -C $(BuildType) + displayName: Make + - script: ctest --verbose --timeout 120 + workingDirectory: $(BuildType) + displayName: CTest +# - upload: $(Build.SourcesDirectory)/$(BuildType) +# artifact: mimalloc-ubuntu-$(BuildType) + +- job: + displayName: macOS + pool: + vmImage: + macOS-10.14 + strategy: + matrix: + Debug: + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Release: + BuildType: release + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + Secure: + BuildType: secure + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) + displayName: Make + - script: ctest --verbose --timeout 120 + workingDirectory: $(BuildType) + displayName: CTest +# - upload: $(Build.SourcesDirectory)/$(BuildType) +# artifact: mimalloc-macos-$(BuildType) + +# - job: +# displayName: Windows-2017 +# pool: +# vmImage: +# vs2017-win2016 +# strategy: +# matrix: +# Debug: +# BuildType: debug +# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON +# MSBuildConfiguration: Debug +# Release: +# BuildType: release +# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release +# MSBuildConfiguration: Release +# Secure: +# BuildType: secure +# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON +# MSBuildConfiguration: Release +# steps: +# - task: CMake@1 +# inputs: +# workingDirectory: $(BuildType) +# cmakeArgs: .. $(cmakeExtraArgs) +# - task: MSBuild@1 +# inputs: +# solution: $(BuildType)/libmimalloc.sln +# configuration: '$(MSBuildConfiguration)' +# - script: | +# cd $(BuildType) +# ctest --verbose --timeout 120 +# displayName: CTest diff --git a/deps/mimalloc/bin/mimalloc-redirect.dll b/deps/mimalloc/bin/mimalloc-redirect.dll new file mode 100644 index 0000000000000000000000000000000000000000..b7bf1d099681fc73d15ee8dd1b86a48de0aca1d1 GIT binary patch literal 55808 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 literal 0 HcmV?d00001 diff --git a/deps/mimalloc/cmake/mimalloc-config-version.cmake b/deps/mimalloc/cmake/mimalloc-config-version.cmake new file mode 100644 index 000000000..edffeea12 --- /dev/null +++ b/deps/mimalloc/cmake/mimalloc-config-version.cmake @@ -0,0 +1,18 @@ +set(mi_version_major 1) +set(mi_version_minor 6) +set(mi_version ${mi_version_major}.${mi_version_minor}) + +set(PACKAGE_VERSION ${mi_version}) +if(PACKAGE_FIND_VERSION_MAJOR) + if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "${mi_version_major}") + if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "${mi_version_minor}") + set(PACKAGE_VERSION_EXACT TRUE) + elseif("${PACKAGE_FIND_VERSION_MINOR}" LESS "${mi_version_minor}") + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_UNSUITABLE TRUE) + endif() + else() + set(PACKAGE_VERSION_UNSUITABLE TRUE) + endif() +endif() diff --git a/deps/mimalloc/cmake/mimalloc-config.cmake b/deps/mimalloc/cmake/mimalloc-config.cmake new file mode 100644 index 000000000..12da076e3 --- /dev/null +++ b/deps/mimalloc/cmake/mimalloc-config.cmake @@ -0,0 +1,2 @@ +include(${CMAKE_CURRENT_LIST_DIR}/mimalloc.cmake) +get_filename_component(MIMALLOC_TARGET_DIR "${CMAKE_CURRENT_LIST_DIR}" PATH) diff --git a/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-a.svg b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-a.svg new file mode 100644 index 000000000..0e5509352 --- /dev/null +++ b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-a.svg @@ -0,0 +1,886 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-b.svg b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-b.svg new file mode 100644 index 000000000..22bfa5c23 --- /dev/null +++ b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-b.svg @@ -0,0 +1,1184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-a.svg b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-a.svg new file mode 100644 index 000000000..6b15ebe57 --- /dev/null +++ b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-a.svg @@ -0,0 +1,756 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-b.svg b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-b.svg new file mode 100644 index 000000000..e3eb774c7 --- /dev/null +++ b/deps/mimalloc/doc/bench-c5-18xlarge-2020-01-20-rss-b.svg @@ -0,0 +1,1027 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-1.svg b/deps/mimalloc/doc/bench-r5a-1.svg new file mode 100644 index 000000000..127d6de82 --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-1.svg @@ -0,0 +1,768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-a.svg b/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-a.svg new file mode 100644 index 000000000..b110ff47c --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-a.svg @@ -0,0 +1,867 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-b.svg b/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-b.svg new file mode 100644 index 000000000..f7a3287ea --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-12xlarge-2020-01-16-b.svg @@ -0,0 +1,1156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-2.svg b/deps/mimalloc/doc/bench-r5a-2.svg new file mode 100644 index 000000000..8b7b2da42 --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-2.svg @@ -0,0 +1,982 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-rss-1.svg b/deps/mimalloc/doc/bench-r5a-rss-1.svg new file mode 100644 index 000000000..1c7f85663 --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-rss-1.svg @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-r5a-rss-2.svg b/deps/mimalloc/doc/bench-r5a-rss-2.svg new file mode 100644 index 000000000..e819884dd --- /dev/null +++ b/deps/mimalloc/doc/bench-r5a-rss-2.svg @@ -0,0 +1,853 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-spec-rss.svg b/deps/mimalloc/doc/bench-spec-rss.svg new file mode 100644 index 000000000..2c936166c --- /dev/null +++ b/deps/mimalloc/doc/bench-spec-rss.svg @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-spec.svg b/deps/mimalloc/doc/bench-spec.svg new file mode 100644 index 000000000..af2b41ba9 --- /dev/null +++ b/deps/mimalloc/doc/bench-spec.svg @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-z4-1.svg b/deps/mimalloc/doc/bench-z4-1.svg new file mode 100644 index 000000000..dacd8ab94 --- /dev/null +++ b/deps/mimalloc/doc/bench-z4-1.svg @@ -0,0 +1,890 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-z4-2.svg b/deps/mimalloc/doc/bench-z4-2.svg new file mode 100644 index 000000000..9990cdcc3 --- /dev/null +++ b/deps/mimalloc/doc/bench-z4-2.svg @@ -0,0 +1,1146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-z4-rss-1.svg b/deps/mimalloc/doc/bench-z4-rss-1.svg new file mode 100644 index 000000000..891f7d68f --- /dev/null +++ b/deps/mimalloc/doc/bench-z4-rss-1.svg @@ -0,0 +1,796 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/bench-z4-rss-2.svg b/deps/mimalloc/doc/bench-z4-rss-2.svg new file mode 100644 index 000000000..f4265378a --- /dev/null +++ b/deps/mimalloc/doc/bench-z4-rss-2.svg @@ -0,0 +1,974 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/doc/doxyfile b/deps/mimalloc/doc/doxyfile new file mode 100644 index 000000000..6c1e30a0d --- /dev/null +++ b/deps/mimalloc/doc/doxyfile @@ -0,0 +1,2564 @@ +# Doxyfile 1.8.15 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = mi-malloc + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.6 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = mimalloc-logo.svg + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = .. + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = YES + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = YES + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 0 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = mimalloc-doc.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = docs + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = mimalloc-doxygen.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 189 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 12 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 240 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 180 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /

!%kaPR9P3?F>D)&Dt=g&k|T*mVc2Ow3CW+rNH=%0tt z>aq*pG;JTffFaUm$KFWj&erR*NrA=-8jj(jNTOUt3^vKwI}j?!ENZvUZu1rzM9bJm zyK-09;G?-He0P_7ct)TlkuH%#EJm%Ay=ffQHcmY05^^(g;t&6GU zF9Z~UseTFPN5}FG+B1OIM-5rZInE0puLMqj0USvJN4j>5pUOqn`_3482xV?|S+2(F zvL*RnOxy82U(HEvV)%;x?AmrlX-OTFCyT)N&SVP#UUh-5Eoe|GPR&biPU@viDl%4l zC>eSTND%$ALaNAv=n^Bm1n$?jpzc0v29 z9%G-<|BID0f%W#pEUIPnw%biVyO}vdt~iAvAm-o4=k0Tx@5kfWXMbAvY|uwda=g$< zL;E{a^<4tXHm;~u!9Kzx)Jr^PI`j_91v%tj8edSQh(${dhAPg^2U0e6q6DO(c6;$Q zY0+fDjP3I zUbWza`M`Z>Hm<*YGncD;95m31J;k=D7TIq3{re>l`2!sKb$FCetG-|>kExBULMsu+ z|ML>bN!=}qk-I4h^ZUIQaa8y_%!p%%gGYP}UN6y*qWmI;P3#6>)Nl39A=;q|b}Lk2 ze*QUWV?K&hD#~-n(R=~4@BDKLm3vvicD?E7#N~nV7I~C8C{U<#sHl|k+{aSQ`4U;h zH|-y8D3{;hM1XkW1IK)Dipt|h4v$$_)H663?CqPdrr4H}!X#A`;7lI~PIhC@cKQ8-OmAil%*9tYWHA(B_yMd>x{9>t{U&AN6 z@(xmh>fvd>%{$||Iepgd?%ni%)mA&!GDJb=#Xz7!vKprnDT^JvZ`aHLrdnQOypB=wb zE62pI-G!U%GDA1*7j9Lc{9%Sd*p%R}+|C7t4vlbmQFVDAxmTAdHnX`Lr-R{O@?S=B zRgv?v=(4wDPCSh)Z1Rm3lgh}#7AQmb3lXwFwL__}Z2SVhk=nsLD)`%*mBCK%c$4UF z8a_>UznZgjja1~3P5@y6t-Ml;Rt*S_kfHp&2=j=ZM38Du7K39+6UNld>M|)lY+zlW zJD$JoZ1JLe_>4u|PGq&lG<4^cRleebl|7r_bCd9^cH%Z#NR2bwA|-fKb1SK3*v3oH zwzFLR)uS0YqLVDW9?Pie!Wi93XT)ELa#&-|3OS)}UJvy{96z_pQy%``ifU&L8Xd!_ zIzVtE4V+sW;S_13xuvLQ2tWn_@J!CsrBO{U=^LZG0o%ZFax9VkyW^@f-kmTcaIJnz zcCl!Kmdt0>91(&V0V02!i{q*p3F54`Kt$r7-$zKxVbPhlD|-0hyBb4%Sjkd3<6MP| zn(V5UI8x3czg!hBaoatJ*koh^&=dkfpSYsjvvzj}}p>sDHDWOa&ShG&5mdlt@LROW)#%ZzTNkR$H;RKoE8 z8me~ZwD`G1$*LO56Yp;~ebCYpFxj;pNL4(Fcgx8*-G{q@v*d z09>Ho0PpJnz-!@DFE1EhOaB6Q2sPN;KhA}oL#5A5X>SaJOGU@^sRz}GQkV0I+0i#| zuEwk0pBn0x-?WOOM22pmMBUkel>f0Kb3vQh&rPv@BcL}Hq7N4Mt$?%t_lYCi=H&U| z8Ft=m{|{!0b)2HnjdMB|b8NBL@ZpczpFgiVFhxa2CySlli+<9fW+2#qEC=SpqoAi-j9k`W3V8j43Ppw@{Fxp=G2X2OG4qq{>K`Tr0&k4Bphl{f+L5pE-3>hG(9@>Gi?X=XI|uR20X z`t#NQ{Q0B8@`ge;B{DcG83_CD!_N5dNUi6)O5jWJ`IAYYa+Dig4oT3Ez5tN+PG9Vd z1&vadxEbf}@p~oezRN;8jhMam%+$-mS!Xcu4x~}vDL=X#f<(<9!W(z6n1`~H1zJad zEtRQI$SES9Ip^bsyCn9AcT1U+->DB?z+`tfVS5U_C9Phj2rq^d$@ zU{h!pJY_2W4vy9lHU{_pd1%uRKpe2Vid8p8XAdrU{xobVE3(ei9_iv^m7@4S3x-HQ zyW&Ybq@|dLO+9L#C_Sz0tdP%nN;x5bj$%kp8rTEBVjfFb7+>a1mV1(HgDYqZ#4hpk zEbaw^CBWeHAxEY;6xy-9+3OUVW0aJ#`Y0a1G2a0zN~*yZE-UiazH*&Z`%*(!=}(EU zp&mzO6hEVvjgCV@(QJ&jDmc1GD*lYnaQ!YzJ%C3dny{LUEq+R&dE4i9MuoO)g?w8B zxl%~ieY9m#Jw;0)6-~+Ecy2oATGsNDFQK=fb9C-q}o~T=|P8quq>T=x4cFiL*7xVyJ5iH$2_) zbp!q?lEAUW+4@^kt8hE*&?1X}v>;A2*@+;f<21$1yL;pVm7HFB3wru)v5HHagAn>x zvx%|uY>I-EWTx4?{qC<+323_?SUdUoon3cw@uOg#dAG_J>zLKRrdUy|zR|LRgg{>))X{8Z<2? z;gFqRXhwoLNdTg%+*8%HXktP5BJ{1jGi>`c9lM(WI^Xcf^X$OyS`#8L6SUJp)r&Qz zHgANZ|A49BvotyzR`4BJuTQN@!=|pGY4+P38XN0yqOzF_JLgt~ZmxoR!D1F8;aZK) zd1|Sq#QBi>KT}Z69hg%KD5WS>hu0`Yq3eHTS*5D43AeE!;|wBf2~6VLiv`{j`D0I- zEv7)H+f){+`bWtq5PNqXmN(zhojMb9I8u( zQhFV4fx#74$w?txShV$NXd zLZavz*^9v#~nQ;~ihYHkL|4|GoRa?Y* zsYY-65NE_vya6D2H-ZfcdeMzcdq|QXphoD?8LpNnB|nc9{~}TJgAldnj`frz&*6W4 z#GFi!)>0Pc0eAw~8tpu*q^ zhE9SlRXsz|>XeE?vGY?~q3j_WtTQTkdgTbet0jw`V*}pW!alWC=9$Qd9p)f4^hD23 zFd;m*4j;S)fd=@0uEC7G8x!K6)iWNQ$;#M$VHNtkU2s7}M}6>A@Yn#_3ePwIU-Pq2&36K97U<8x>_2eR71==0i9BGk4rKJk2)D{8Uu) zrvII+e-X849)Ze>BnA^0aM(`epEWC)5rR*kDYV>&0qxjeFbhDt15=;-hjL1S|Mq`2 zOyv4kqDC3O>Z%ap|1hLm^$v6=zK{4Ld7~|KPMif19qFfYB7VrzK$|#dC&7;nx{|@> z&j&q%O@Sw3{`hE8C<_{(qlUsxLiAl8Ti~9<^J|spb3^DY`hG1IdA7p%{N?T%>^Gs$ zgDD4_N#<(j2!&rG#V~4GFAT1hZGt|{sWvCcBlwBAb1E&Dov8jJk^h3**%{kGQ|cV# zvuY4SIxkO0KpdZF!Ai_<&!4fy`wU=3ZpBkwVnYqK?Cop&^IJASx&H_V<1i7@yHn#o z(|UypPt*Q7eyPcfkt!kQ1+umqud(yjDUlIYX=^aNaZX)Im3p&)#mnUnLEHsYod1=7 zp2I+ZFM%+m1*kpvuU=SmUQYq4>HnVl3~=rz!9(15XksxZHi-#vwoE%a+1!97pBeu{ z_}(N#I+)~NDZOjfFi%3?^F&+KcD{4+2s}HVa;KUj%HEqEg}x)ecgq0dAN+piBoe#!|Izh2WE57B5g)LKB-{B@PwLK#ba{0)o(GK2 zU$Y%&)~f%y&m`JKN`5xhJ7$1hV!%_jpP#XL`a8_A<{P=fef?zjsN&Wtn0vi!5TrHcSmLqXJwrO?lkOBA$igCCGdiV zss$mI4a9lpZ}EV99YkJ-B#sQm#hgDLd?vE0<_|g39FVD5zBB`Nd#r@0iB$9H`vl z4ym!qNI**=DO0;eAK5{xh}ygi4c(GJ6v?m1Y=uiNF64^$tBfNXA}`FOTzdsdo_;0{7IH3qDM7X6b;Rl-EoXcEh1 zi|hX0*mo@vb9YCGUgp3|lO1R1V=&AK^vJ*5HD{_P_)RYzlmBJBMg{;0ny zOARTZowpaKhv|PR9B0uT8$J--DgGC-K@V@(0`I$tgXvf3MSpNDxbK7%l8u{~W7H3o?Vh@BJ#zp_{{5Hxt40Ig8xjgK0nb`N-Sh>_;+0t>js7i4siTZl2WS z7YnTPALra}@hPD=OgQ5#OxArGe+n%_*GotT`nJ>C*y;bs=o}-nE(C-gJw%@7g7h-z zT_Is0xtuWcWNfa@OriQ#$F&skL5Bh)HO z@t)W~D;lXDGDBI(JV{;;U>afrKc`%W@?(|I0xaJ}yNk4wPaH8PShhvlI8y5mPlMZk za(LfGK_ItJ#caam@G{~FiG+ISGc>yBCqt5$HLIl*)~!HyNs^38F?8IW4I9Wm!qzbK zKaKL5qov&lACrj13PNPm%W4kVV&D^>Khj*?mO&e8Z!{m4rFR1vin{|c1m|)rto*v> ztuBXtApf9{d{o%-pFcseuQ7}MG{J%Z@$|Qv+7W0;>I}o`n^QrNHKRmOxZ%UP!V7Ak zy3p@;o^HwNScR2EJLAvNBt|!c(Q`B7i^hDWsMcTOjgFh@>R_NE>URuX%GtA!C5_Gk zQ-2GKw$5q;O}P(KO+{yv+C-&(9oLtGVU5}%&|+kfAxl&;s^HN9t6W9h?c3+`W#WuL zx4b?}xml%*<`QI6+K=b*sr+0Z1AP21|j*1zi3>wI2Nc{!P za;eS+W^0h05UWu61WP*2Z~Xf^KTu98#7q}5k^Xi3-5n^o&oYW}P5j*dPwAv#-cn~N zIak)EfwhAze6;!Fht0b0AZw87rF5%1{op&|Kbu+HHp}WRCI?c?;N!#7Y!_fyEO^lr zWIjNx2}%Fri>R}VCJ5VVX51go{%__qwm|4z+*#g~B2_C7T9HGmr+LETrcoed8+-OQ z2>z>L4ke?7Yd=j0f3hp+Fh83=d=4o?BZTS`!uqRtX*fqgq02Wa8Cy_fGO`#*SLZbX z^3uPzvz^d&12&+4fktk@;$sFDjf`RjhmvNj zDYxo6srq((C_LH^yqyV>U@#<%=*Q5Bpk}d@<(r;PA~sMJxGVMJx~{M#I2ykV!koct zyQ5oYDRqwstHJ@#I@EL>+SQb1^dlZ{%FYt%v>>7G&M$ZlaVbI!E|v_Myn)tVF!t4T ziq68j6v#FZR5~jF`0#pBy-bHLqy-!CdH+St%`UyHp^Zmq8>-?!pREQGcyi2n{2<$5 zFNJ1pa-Vwt`@3=gykd2To#B&(i=_Qc;NUS=_o=P|H3QgF55T`tM>fIXAl`MhxR29l)(XCiX+1+tA}%}Fv$Qu_TXG}38HqG+J4%rRL45bYL_A}kB2^(aS6;z>Dp zrY6n7r)&eqw6{d|*?)v8R)vL9pDS~TDS1>7|28p`WC$U)&?e!3rQh3%=t-=fhRc; z(LpZ&z8CuQ&#mg@Iqf)Qk;<1|k8)nV%5=VthnCeAoccdZePvvf&-b=pa{;BKOX*x1 zX^^G6B$w`9B&8J=kp}6OZjf$}MY_9L=}wof=f>aj;{T4%4)>XJ&YYRKXYO;Ziy$7m z3?P#SQlOw)=dn!QH&l?GNB=)yDI2x|bph*YRsR6!!T^Shm)yD#r*B$(!1@2#<+w*P z-^zm`)&BiYBp~F(UUajOr`r7gI7zWO!_qbJPtGWu(k$7`9-GokWg_4qK_M{qqhAk@ z%xcm|WW2I8+J^DdE-;->^gb92?`%21SYAKy0un^EMBZcVP+7cyf&whDAu=1B z!<`^5Mj(moB`_NlbJ6FUy=oPz>psW(JJBND3_<0n*s)@DhsC$T1)+)8Ra=vc=S>UQ zfjE%O;Pg#?Eeq;(`!8@xA&Iua4@T38mc#K4OIkAWVhv;eO$Qz&&qAfjl^XWNQHiW3 zZdHLlzhB$fTF$mo#kK4&3hO#a1|3)euqFRe5Duh{DaQqeTjc`&h6b( zZtaSj<^WO{LXPXlK+19PIt4Y4no?wm-p@CbvD9r7qx z^-(XF0sE%em9VzyEN37WJO_UtNilCn$1%GvkD5XyAbv&mAf2+o6y(YxGe;7wycJ`C zrefq4UGyjukf>V&-{x2};|wxLb1GecDw+yzMaLBro$SrYmu=0s#f!s>8ULj}{&%IH zd*iw(>=ng+1!eKOPW(!Wiekkj2a@IUlgra6#xxLif*XPjNFTeyu&_Ry!=W%*4VNg( z^O^C7+{BcZ;ha#tj2n{imHyqVAeXqKgrwH5m$R16 z0ESJF=Af1j1wisGh2+%DvuTn0mq00+iPR`Ai6jU-muTy9Nu+~iV6@puK)~*!yXqx5 z34j)@Z2{X}62^Y99{0vpY{JzxU&%aDSIH#wksBdK^>1N5MrRn!B_5XQVO@;^xU4sqEwq&05 zM_jGP*76acEn8gK=f-P9dY-*qHsct!&gMA~isBe>j&E-FouZCZ%^R1>_yg;-&eI2* zw-8A&NXA+_MVJ2X(Z8s9o4Be&{!yvwRCB-2ZIf~Gd;%3Q20wJ4l?iEW%+;_DPyhV< zN=sy!MAh&k0V!Nf0y&f;S)`d2iqpjcFyd|1O)~8t@6{DqQTJCvm>1k}@))C4F#6vq zUb=7pr@wKcrPKPg!Vu1A(Hu>o2fkP0Rr+8Y#B47V1QN~sm#OP96whdb<#D=*x8Ii? z_~XN+hZgG}nTu!f71F1hfQYZ#A@Fx(RLyP;F%){G{@ub&JKvc(@7Ra6DbS%pp|@e{ zz3bdg%8~_#e9TZ=(91>WOyD{M}sUIzT^0*=fPGFJ3T8~Ig8mNpr+24V3zn%R} zt&cl0fpdfgMy-E`6Sx02+?tk^_VQYanQoEq6BQlqf!R#f-P}{*)ZIjT;Ac|%Sueh0 zY19$Z`a5I37P9H4Pnb9&^2VW-71)(}-`P#~eGf6aF4M1g8p>x|NEgI+wV#>FDn zA=EpT?@nB2PYz6p)gt@H<#Ew?j^Rh*5B3H|ZQ3O@TO1mErqV6Gk-wZ1nf`iowU*sS zXxQ0=GGfImQ)#`cuyw@iZdDzq2g|y|TJqhllxF*_ns|5`P^i7(*LW{4mLx#v*Uyer z6>d{Om#X@?lBn!jZf~B|73Y^b*ksax(j9G_Fh8RlyIsdZIdB=nc@X1gI zq&tl}%qsOx>7!6zzR@3_jvHLDm%~(&R>~X2NT1^C2w8ykcpem6use82~G0bu0_kv>pUJXu5;$4nguDW-^!QfDb6Io zP*clSIx-JaA|yBBWPxbgrkG$lIw3p2sTnV6aM4VHQW5UN`u=r4oCzk*tdS!`CLn9} z7u_XKw>iy`i07IAGPb+_aEkmdiyjEI;}eY?(-gRzw91~#-{;FHy3D>Rs+-cXrMF@B zxNb~~Gz*GYra{g&mQWBk00V{HTVJM>LF0;od9!GloSZbzSGal%5?XUGsCag*%b#6+ z%0_5hMpU8L%kY^D<;pd_6mgKAqu_==EHkBa-n;|R2H)Wi$8iugJXarBprK|vY=_~y=uZPGGXI$V+GvfOv&2ifYOtKY3eSE!S~_ z27%Y;eZwQ!p9^+ZYk(PNm|M_U_X)UYxK`<3y`J~`VFQx3$${5QZ|iB zR`hBQ(?ZN5esI=B4zJq`Rv|x>`5xSa^x05}N)NTWYvf2}q?Shs_T>j9ivd+8y^&g@ zX$2Zn?s4%Uyr;zgjetwObVRekwkk&=`%!)WFi}hAo@ND=?wrMa)9{|E%OmcsV4r6S z11*3R0O$*@3@##n+h9VsVtQ4peow{Gy56Z=PejnEP`v$e+M$Kw5VA~<7wb4J`KmSv zvX8P`W77jrnRjNEAV3O*#$u`)%%mLq{T;q!F^o(nX zKZc*iFRQVyN_S6C2q`lxo##I#tNf-nn%PrxQf$Y=LG3{e2vCmPC2(kvnouprYCJkm zab<&(WY>~nP)DR(P7AFA^8` z%t>DR=<#AH?~S9{!8_xmZmC*8*0#HgY@o-Ln5Rg%ezy4GE{K=LxDEulnAxxq>|0YWUNykuGSig*hj}N#l zJ4?5%EXK@H#n?Zq#v5BNCOpnNNo3Z$K+V_wDvEZ~eXh>rjw8QW}Fw__CCu{*Q#oGJWTn%v!az zzE3`Vp8gF?wwhI3JYZOqI&*~!EMS*>xn?AjK?8Ce9KKIuO^L{Jj zd{xyVqlc%|MNrYA_OGHpl;RS+>Z0{__9NJ8JtRMz&D3;qyDZ83G~4BkZeu-fLb{beSY;i1TY-1&T6KPAvL6sCGJ0=LW9A0$EYvvv}k~K3wx$!-?)uafU zT#a4dR|v{z5loAmHtdPpTD`?qzLyP0PG$)2qSbmh&<7Iw}>xBcCh9C{|A?yPt{Xy%q}*71+R~ z4lHDwk3O)aEIB4^mmnhqrgNG8cLQtdj6KLYVqbm?k=i$eQDF3VL%WjTIa3oIdELc8 z?`@mCeNd|EgbTqTX55m6fW!rEt{n~mK#}j<0d1Z7AW~#ktz5b-JFzXrSzjN09bGyg5ShU{zAh^;D%za|( zDJ0zVI6$SU21bMMg)l0eV$kLivcke z_r9;>Sqf)N(9`x8=RXiaz0KQHNxXj+CZWi0% zPEDbzQNL%Q1I5*UEJpmE6}sDae5s#M0?#wc-QDEU1HP(A}fl0Q&len?a?ocENb&BKuH3i#5yRXlvE7# z-yn?o;-4F*-8@9JuH^Ofu`0#!TC)eO1z^8a34LYPnaEa?mZ7% z|5r@E{H{^CGenU6^W#Uq_Nij54ahmoUoe`4RuKT-A4KpmxJ@2Cd-Qo;@_t$^4HHKf zI2(#VUjBIW$gypUF|Yl#CWiDqT}8;j2M)bFibuar5v2-VQs8i^YBB)Jp*-YPcURI5 z_wl28-8FcSONBZMPionSF7eFaSS?!H#}E{|EX2RBLKglsx~}@nF`bTp}h8Meb)> zQy%!6@!KLz4+4O{$FV|2box*5Fr!hg_N(Rc#K#76&VljxfEPw`yA#jCNMg%#Sb~7- z#wwFb@S$-G_CiC$elaNpcGkt3q#KiJ14R!LXn;$a} zk`E-`aTlDUuQN0DQ?8M`$Jy(chC0Sz3|>07-CZ$zmVe6~*=uwkD$8XfVxFVlwtUoh zeP@s-oXxlvey7Nqa-a(o)$64ZE_Cc+u-=SVPDYMIj^iX1KraG4WoH?^1D;BM3p+Fd zQhYj@`FAN7Am^ot20NiSS1$+NVVIK;9 z5$k0pp6cDkAHv55)o{o|oO_OI$;jxR?n@36j9qKg#QnpH0ixf15+GcD{KT=cN5#=% zK*F0JY@JGAF$ET&m0l-W#C)%1G0f@NROI$;%v=l|z*;}huUWy|BYn0Rs%O`mU+3c8 zK2e9vq7Nk`54LkL-DKDTJ4M?f_QN6>^$BvYA!Pw@UxnsZtd2f>GKX7F9}hCZaHR;4 zZwGp`6Nc_IABl`cOJWlBNIoFz%$MaiY3<*ONQA!p)xg>owfDsEV}yf^25PZ00$Ztr zfBHv*NEuokui8KS9_g(+4d!jc9l2v;kC}Sqs2Xh{X6C21Y^zb>Y>s^*$bY&RJRkRo zeUcF7l1!9qbG#&<@UErWx62~6=&v`RBk3!nM{N$6Bjt1-M3w5Ejf|d-j+q&5m}LT( zLSx}c&sEGmq~``c|MOvV^u+AV#jiG{c)KKRp_a9G}0k);I#%e62K>m7^3Ai~OPMu#-Rj z-&Q9C#6`+#kPn5vR-{01!m+st8nD;qxRMcng7L(AT%*{tZC+A7wXCX?ypRc@^nL^U z9s1H~pSZ^RlSy-O#yQ}G}IMmxBV~{9xgZglP0}?HP-Ps7ZB*9t ziFi7GLh~Q&*b#$pgp)=h7f$NShrV9^+$RALg6%6^@0I~ZU zmbb)nHC;K0dSA3|1n5otp!YXDqo&8>BzD!-fC3VDa<4N5S>Zh9!vs{Z;JBUvhA|t!-wVfXg+%5p z%qanrE+0Wa`HLmIgnq)BPah4BEsV{<2X2YK^{v;f zxDY$i0b#K4PG`t9!n}+5Un8Uy2)HgQ{>OY6fPD_6Ci8C2>R{D3cuEQXy?8JuxlD`LC;Oz}-Og53M+(3d3K(^j zuc#E-EK#t&nX~Zc$sDoRsV@Kp$LZu}pW~F}2<5WuV^^l}Cadzu^}qhb{}3RZd&*a3 zaU1Las;qTT6bxx4OZXMnf7J*G$iCd?wPNtc{Mml$-S6_2rauEA$M>Lu6J@0RuvK#Q zw&@raC9-w&MQiA|`7dig9Cio)w2%={hzA#74L7RGy<@uk+kC}$nI7ftgdwoH8?Cr|#%81_34L4q{j zRi8&#wRB&dX!}V6NVp!d#$pC`I6*g8m zVYT*@^ej!YrE0Mg3g58O8gCoOf1%f7sCNCE(O$GXVc6|mJbk^t*8+>D^{JU;gw}e-5a1+1pG4$6`Y~%Nef%0{r!RWK1->;fi+nBwom7C;k z3@JRDImMnF_AuG*_(b~t_dAhI`+}wqqAC|T1B3m@|FN{#r0?4}V5Ht#TFgf{c?MRy zbyT)5JB8^qG%e*Klmkx}ukUs!z^w&|)Lu-FQK>8p1%_tkKHGwk@goH8KbnQt z11206s9v7mkD_~$F+YwYe~n5Z0iEtMWzolnMMEcrgV7>7120$=Gb)0!Vks(s^7+kQ zKQzyb*-BB*HxJhIMv48XX;2W2z84wtXL<^!Ts}S}Ei98h*Y5k3w@x~%cm;b949PTOA&m{5 z5H-)=kPGHkbyNAK#U_|brH!#`-w?~EmW^LS?{&QvoZpZuu2cKu=C6dJQVI(N>{pi& z%(pfCC?Pe|*aPB>`{u#)%4de=&QP_v=8v-k%U;S$DH}n;b;~S^LH2ZKOVY}8`0^Mj zUl;w}OXWJM7a8V{TdI5?qai|sqgW=KkGDB*ZC6W89+NwZ!U@k~^X|*gz3m4~(8~?2 z8d7{2U#;K1%VkF)n(cRD*LYtJ>CBimtvu^4Ao`I3T`mG6M!WPH?_F3*we1YsY&Lqb zWg{`@R?7Dp;Dd;2MS>%HM*GZv*yqyQI_w3BO=V8uJ$FxciB?B-uJ`DY)%j5P%1WVe z#R5_%d)KnN$=)(_w;+( zUr^abh){XQ_Gz6xmimxG`=Pzgk~_semUR@{A$PO=$5eP#zr=I&t@X}|YL6oL#>MoS zcLir_!B{rol_8@B2AdG0DFIUUuWr45 zUyz5cF`@7tWO{h2Z$9#)m%1juv&zc&5QAL```}ckNNelHT8EHjy-6th4TN&B{AH^Y zqqC4U{sB1m1wnkxlkvNJmKzZAdFH2XU>PjUp-22!rUDzE*DqbsdVV}!6rS@cABg5_ z{rWT??pMy=qR#qSTTtS>c*e|Y#}dU>R8rUEGTIRysEPHu5y)c9(LG`Rnbl^t+l$4@ z-7BO{U5++Ro^PeM_OuwUG>a@(kqYjDk8?BEP}V+Pk!^ANjCd4LV3Ir4cttCli-Hp0k3#Q#D_B=RHAcO zUU^Z!X_Hmbx%}6!cF9;~k?8}yg?8V*%QIcC*8<+5M{?x@*#T9=@mN)PgJf6wp6rF* z__wUk{}|0$J1>s$QVi@vK7okyb(pQ(XI<5@DwRGd1h<)=#h-3PNF>B#Yh*dGCC+Lo zVRZ~lTiN>)Tf%U@>f)zw{nS6!9(Rn4vu+<(ZN{QzWI^v0wTqr9#>++p2LYi$Ise~t z)(u@x<7RI~_o3&0@@J#%I_N>$Vrv+#Ox{bOoUJzYUF^~@9Hj|H{m@%aQQ-(&!ud&I zk3EVSo2ZX_@U6E9A~fL8Is8?uSJr($88ln-4wi%aH6`w#tw+&Zsq%w@cg%5EbwgMm zrTh!Dv}Q@Z4|x|yO7E8go4QE1#bS@NxYDrq9RUik^ejBIC~Sn*)~utI<8*qkY_Dal z&RJlRJz|s`b+6GYfBgLwK{yX5gkk!*`gAO>(w^j(rNaltUG-ht=Eot%SS)~rr3Y=9!&8Z@PoEo^!3#;OsQzkDUeF5z8N&1uL+e06 ze)^MkUTDN@J;^*AsHcmx3E!1s*+r_tonKrlhC~tZQ{GHEd8)l!;PyvQ1NK5&z9Cm2 zUZ0d)^kcp1K;8cD_S}Z9;!_W6mL1OM?@8%7(%D%7rZdjxI9)R6%VM6IWK1vgt7Nz0 zur2WVFMzLwtqBK1N@a^wsUhVeWIR@Hu$(#|)a{Q5(k2jxZ9>swyfv3xf z+8(coEGOHle4>N5mX9+N7@f_#v;;RSG)fX((XBGVs)XMz>*8(vBp;t9#ec%E49R@E z%FDzU05UZLYJP;-Fa^IZo}9(tK{AF9htU;|uYGn}zZ12Zqxf|0%o$s!pI8F?f`@kC zMJ=1K8AOurl#Z`o9z1t-42<9odQaLqkkm;EZQO1>r@(m=%x)lg9`}8lw_23h_NpPj z>cl{^_`+XJ$?WdM(349j!}~0Nhll~_H1HZ5G4Fl%epFoXdWnLpg`HpIBtsy@pWpWx zI80c<_h)9Q?Vr7^i?zVax_R5sN;Mr^$H)h+_4Zp4XO-k84pQD={YM^k5p0p3+asQZh4Z_wB-8(=xBn5c8z7b#l@dDgt<`*zXVaX){WI{lgxS7H_zfQ(rfrf z$5n8T&{D~_hro#AlMhce`k9ta&pJIq5o9*Z!-|)o+L}NG!}+*rYud_bX~M-phKm`xX~Ia+udirnE2k9iS8No^B>MEa#imNJ^Myt=*}3-{n0& zo)Z`a(5-|$PZ)sFU;|tQ%%N#5!rGLU(zlfhJ4=!jT?_g~r}l5QswN_zO1X_KYOgYv zh`J{E@}vg?r~=%`pTJ8lH?ra;&?01+&AR1%8;SJqJ+G~@iK(yma%O#jy|I`S-Ra)_ z+AEz7m=o*yCkwZyt5k=!=ltFL{L!g8=6O9Bl$+a}0Nc_9NxU1#r(sgojb7h(%qa`^ zFChnr$dE)P}Ly zKj1`};XM6k7w^r-6G)F|qr%8T@93F042Sth!w)F$lgSN}N;h3W-WyL?X6|`wxyU6G z!!%psA zf1A0|J1Md!$>b_mlK9!-C|eHGgu|u${r6uHcvJG3Ewqd*FE5vyzrq;u!Up-`GwDVT>K* z&H_0U5NftS+j^i|g*y0MA7yBY21hideEz=qzC0|3J&@5n43YPDD#Lx?^Q3rcU4ug? z`-0tNz%H|*_1MgoHu^P<+&F29h{d-244$E?EjluNu-ztfxaG&-4h86(OK?noIY)e{ zkkd)L$D?r|VNQq`;`cMsck=s|wxU2#J16IX&8?`f%(<~-&TyYXWUK3TpyP_+C^^kK zvoNueeJ&oc4^5!Bg8D+Oq*bf!rBKemj#<9apk=KtQaE|a?8>-*+TdgnnKm~Mt8Sl* z_?wz{jt#-Ra`N0wLG=h~NI8HaNB){tm?p-z#N-k|sLS~~PrXqtIy=(soMBlX&ebKs z`k!doO2^Sz-JxmHV}uH(1Z%xhhQR5!!9JAzgSqQsoJPh~o^o||&(7GOoGF2bbI%Sz zPo$3uToM%*yd=MWp=J763cN6IL~BgG%~EGg z*L|nzIYYvB0{xT9CRC(zon&yyJYI2FWhMkg-;E~_TI)krQRaM z-)F24Ajo7rHSM7+Cd@s*KX~7F*dkLf*e6ImVzs^iAm?g1I$+BQX-GMN_$?E93!K}% z>lgz^?o~(tyer^}?`jF9m8Q5FaNDL+&rnlN7moe)e0{u}K3XFUVLUj?Dw-sRre7<` zr(^eqqc&cQ}LIbX*ooWfivZQyuEe(y>@|u-KY?c6O@?+hh<_ z1Be?H0fwprkM>KzQ22;p!qg^MKn3D%6y0Vll(t{HW!kIdZm1nCRrnR0PH|XXNl?It z@KR^UY^nu;GZv%fA#Kq`GS%f1D`WZzJJ=ziai|p83+Caxzv=07g1S+thJ>@6s@y#( zts;J2ka;>2H9tJVIh{2|HDf2*>lXMDa9@Uc9wsqR8@rUI13t{Hb!uIA!ddK~a#9`- zFU1hG-ZvxgGrw9rEe~{uww?I{{nCS_nDUc+DP5yUVbB(n%lSf|I-WMgwuIl6FNSg^ z+h-nU*vU5LXOF$IWS05()!B`wFuzX*bGh6gXR`-LY+2<+D-9Y!Mjia>-FnY7?TVGt zl0iS0EL8tx;)Tjft?@(Fq4UqVvd?iFE?)Hqsp;29S{+o?iVrg7sf{(aHsi?lxHam7z&*Hj?CPB|``91#hClJ`2^El9-!a52ht z0n@%j4z+i81G6bB)`dU@LETy?qcZF3C0pwN$8DHTs4u0WX%ou7C^m4s%r8 z_X}!wKD!bxKoZcBG%dsEzA25Fu~E}(t8$qa`p>FAf8jmIcV+WLs3zOb5=2o)!q zXfnvuxH%_@+I&pbn@|9@_gm@@a$%_PF}C6l@wF7m9Qw-_#*!hsIsN*Y8znkwGXnSM z6@|MMpQ;BGq3}#6=3Un8i8*Ei2^zbPbvic~c3tM_RW1qqiXY2`taR4o&Z!PxQm17W zA8@Cx4B(km7V=d-jAZS|U$c*gP)xtqx)_-s+eYv&sgbbS+K_Y6_&eWG#^p6=`ZLCZ z!PXI(w)%q9uN;|dx8nng1kXSJuD1#uxv9qN z3mHw7xrjFWB-H0w2at?r@nlzOWE_u72jH)LHI;k(ts_z$ieWtZL;Dc6SLdQioUuhK zm3^Ojz*w>HC6)r=J>NGIIS?XtjA_vHP7`J=ni*OP>WHWN(|`5VNH$OMn&s81j(|j+ zvIC-zkkHUk=As3M7^dKOG2a72@Fezpt2vDR-a{^k1B|Aqf%0%{;5b`|H6z?`2iH4# zR0M;Xlr!v)b-RXCHRE=?rIDXpB+eDx?UG5@cUJYTB7rf&>dN)KEHFZqS+FV$J-WCX zNzh=t&u&~bsjfW0dKKPD^vr81e;(r-O`_XGUDh*l8jI{xc|N(H(Vo=dd)Rk7{GNF% zVR z9VW=EvF$G1ia7?a&eiN@?rYYHhL%KNVrq@RSh@_EH&afuotORTVP9jW?)eu(M53+CYP&&JgiosLp~`S zrb_z7&)kH*SOvVtTN1RsxlCDeVXu9E#iGyAyHfaPgC9eA$-OP-yz5k6f1TfXiA?^6 zc91o3O_f0X&se^7l#m;hlqbl8p6rx||4O?i5PKu7wzZh~i%bE>wp@o*6ua|L=NhG* zf_W#m!}^CLuQSha5|8FEH?mFT9X@!CggM*B*?tv!I*DrATJc|=#=R8 zCtx+a>vVSc+o{i#JI{vD5}`btHEbdfsj4&9w>}o`%#91zH|_buVo?=$$T!wQ0fdt% zyqTK8dr)bKrWzYjov)d)?s>8;h0#h&4VOJPyDC!WbEj-(yQJ&?zQWpA^D=sAEdWg) z@Np&kVUjBAF@yG6*Q(}MTOn(6Ok3w~4lRi{i?~Cv!QxZzD!sy>{N&0Mv!?VWc<`gA zyPy!GzG;WiZ*kbZ84k>E=Z5eQIoU{`I7XqcIN@vnhQWgrUcpCmZ?PK>hExqh;!YaP z%23%cSlWC)wH(Y9VrL7w*u5skwLgKq@r@u(_FH&HWyFu8+gaKxTR!Y@f@Q-) zQ*`68DoXEl-mThRomnoMlDG!3Py2INNXBe0r5-SFpI~~zRw5O+Fir*At6;BdfWZO1 z9mm?#OIG%6-hqr;gT1Vx|3--b5g`WhbDcp(aQGd0@wck6aNfcfv;4z*$?e*7;#WAbR2UDL_?mg0ryrUXe#I z>kqdPYmqhw`SYw)BWAZP&#CBG49w+mF9GjLbW(5WJkeFv;vUqC1*al;uTnJ?>?#x1SmZzy7O{8NiZgNjx|s z5gx6e2=Y5+*)=fDP-laD0ptv{uH|c##I;&ZZ~e3r4D-vZn6CA#`!iF)w@j{-DM%^nMfBcUpQPbjOHw;3RQxm);ngeQFj%j;{| zpeOc~ymk2!;SIV!>>z7nPlKc>6=O4XJcJ>6&gNi;mCHu% z4lvXz^=ZDe6$^Q?mO&$3U_|eldNW>YF%^9J4oNUXx|n2ETd?*z{K_9!gg0tIXQ^Mw zj4bn4PaYE-#*$AzwAxxn-XQznA36X*g0><{>C)CF(hf(r;i-C3a^%Ey+P#*SJ1Ks5 z+y>fRpIDAY3QeAj;}eKf;L%5Cg=v&dW8pr&E=tYQnz9J{mD@y{dc6m%aXX`X=95Cv^hFytUSwS zv25{G%phvpZ8rC>Ikc2ah)+XU_CMYPmtVZv^^*0>p_-`Oy`yps06$xvK%p%b!*l7E z)cjhb4G0a-Ec)p&j4gvXWzr+!gp2rK-uBgiTSa0T`>8HZFrFTMgah#0$C6-WZf#yPk!s)|) z8j26_W2?o+Hf9xGCJ$_<5>T;A`L{g>&(g`eT&Y8_1oBz*SQKS{)T|(Q-Bu_3XMz?xeSLvN*w_OZK z`3E@VE$oE0EpJ-azER#U(|D!WH_QMZc|%eX_wjxCotSmJuKcLU6ViaAXO{Aa8_Y{N z2w)HVj_X#!TT=hsOE-!_kn+ydyc~YZgwyzwMy?b)eFUBDEvo3^u_6d^9f+cz0h_D4 z*ATyZp4s6urM(aG5jlAeIMz3Rw0aD1P8}BkyxY}Xc|iwupv>jqx#D{T`|a+Bc)ORS z)tOM$`PKG`!)SIJ@uZqts)Ao!xEPU#oV#1UT7#5QEdd5F*h(T2qBsfVS%znC*EDf# z^cy3$$5LM1GRGV%`zhUrUpOg^+iq6J8Q@PhH!D5O+=s+r62jlPYNZ%kVjHmJ_{xh7t#Z%>gnj!Us;EBpSqlg<@5---&6=%O z5tt@MG`nvnOSF*eSeo=%1*hwy!Tl#ssGIVqT&fAt^rhOx*Xru`dikQPG(vt^UkvaP z)NX3+Pg$aRoq*w4*9pOg&XB-^Ft(6?qWXNV!py#euw(AmA5^%uccGD{n|J`hD=N=3 z-RiZy*fw=rUS;gLpZabrbVW^$4jb+^UxdsZR>NS_*fX}p7Fe(h&lPnLv*AO-HzsR4 zm{g43+mI!FE*SX%{;H9=@$Vkg(``BbO56$&kmzEG5vzuAKq6zMcYlLxyPvI65!52K z<(R>vIVGR*odz%^^E7r$`FEWCZDF%2Fv`3;2H2Npt~QN7CH<~-va)N3cZUcVa#3nO z6+?Y>V2tx~_QRFDAo7E%t_@y#JvT7f2lz)KzIfhz4ROg&f~H~xek`z7AN@VH>fIN{ zSx=-+Q{tG+3G@b|dK{xWo-I3s;HAuv!G{I)aN~PiA#6+tzG_|U|1h$Gf5vcx2bf~HDI z;SJEOn)nkL$pR#9PERW=wvE3CX$n@|G*WaIZ@nS}LA*{kN1^+%X?P576@nlvfqBbt zaD37EyNCV{sIG$Ro$BV;xpv}09MgQU$K>tVZGl!|1ntW-Z@60U>@w{g&x8!- zF(C6m|KC++8Pv0R9&ATLv}I1~_EFn5*l`jx&}yKY_zVAw@RTHX@O)ZJYnUSFL` z6ctM$bEo~u(?4EZ(AMr?guI@gp@2uXU?#xZOV3K(t4IKw!|XDCi69z?Fd$Fn>Gz-*gTkJvA9m}Zi>x-K@;`g6TCPZU-c&7r_5_xd z6jZ=S*^`}Yv6(z%X#=kqwu!i~rTv5E%%b`16_K}M7ftzOtZ3uVoLP-XAm~e#&!K)l zWv>WqZNmXTgVNn?x&C(GmzD-_V;4p|OhT$jH!Sftm7jhskYaSb5?It5bpQPQw-V;l%+(jDzVU|v73#nmQU1MNP7);y zy3~Lx10tGgXH;Oro?7R`Z~oH1L=bpt==J$i0IWmbMt4xV9=727SpVNjN>7)0G2e{z z$10*(YW@Zmg>;U^4z0-(k=cMKs3hN{GhvGmt6z-0SV7zE7cieqbF)S^@#!sf;0KSE&{zY{@A0CfvA`K=l8ba`4?Kp&tn{V}X)2RH|ooi-H-9F z?L$DU!Vi>0auH?ucH=&c`+sM!hDSm-x!(hVM!u1s)`DQJo@_0LI&wH({J8Mw4y6S6 z7fr@m6(C-vxsK@PM_uPh@s~fyw9Q*q=nG;4(_6WWhwdg)dCRvv-O#kd?mq>^G$z;j zJmY?mOzesTF0qSA)_kN0|NlhnPLPA`XJxjcLyi{QU12?XO}h9bv%(cT%h|6K-QQ%X zNwGbXPrI)e_u7uTjir3&Ob4Q71Lyc9s82`{yWwV1g>}D=ta)Gh>Y83i4Tof_f?zLa zT6Z6Ue@lqFB})cxoc^jNWY^*HWi#;l@MB|^4vIta+aMV_f^Ayh<~frjCz-;x5OxY+ z(I)Xa^?JubdMYDnWhC9wHk;0Xro7`eY$~@>HBo(vYOIgFnJ#I2_x3}!;Q&;ARvOKO zH^`sespnzMU{}aU{{<|%Jk8O*G-ZMzP4}cNGXe&MAVC+uXkBw{oz}|pG?-ris_|mtaL)bbPsI{GobEDY;@)q-EHJo(j@fPxN`)%;wA^4q}=TzojZ_%9j zv&)DqgZ}bYkr-Hun<(r9J+Uo4Y$;5B1Kg$i#;slR2N8cHAcD0MUck<}av{HeKU-HzA+BnCCYGqmKh+nb%Rii z&*$w#kTM}Ilz7L7e_M9^hX=^We~!}XH>=Ufpk0<-bPudJ^&IA|rbhK$Onk?o$&8~b z{wL%G282FfSnmVMyP7 z^Ywace=k!WVJmU&Z^3V$NLr&(FPyTZ-F=asx8~>{04#gG+Y#9;GZtcDGa$gWx!tQ` zCjW5F47J0gkfT&z7;*f(rH`ulAJO7w$@1{S)I07pU0N~eSJrUlxNSd20_cW{dJ?hH z^JOhTa*?8R#&wfAGD%4y3 zhf%3S=SoDae+@%XFsV?m`x+UdnCuk-mhRF>V|FPm(WmzOBZ|3|7GF*6kiawn8(wIs$K8@UYQKV~e+D?YEJ8IdZl{e}Acy#i^zX9-UCJ79UawE+05m7G3)4;UEEv0 z&^Jx>@kxAH#>)>ldeSYA5Ck9w1-*bRE;Cr_36K2J2A5{ITTCR0w(NFt$dPwObjMRU zu;3I|iEz&Shwl}-rjeXs1L2ja-P@CeB(@>Q$Ic za{VSpCY6HBF1sUkf$owxo3f63;g>(IijsV;Quj|oth9H@gUx1K5~3~Q?j z3+gyZ;Ur9>ebV5|^h_QS-H)R-C{NzX{B%Z-ebfmaoc{lj^wa@SK20Bel$>;XC=$|0 zO5P#e(kV!tbW7(^($dY*NQ!g{NH-|mlF}U#-}8IFKksIDpV^t6*_oZ$S$aj$*Xom- z>ly)4ZZSFSKY8EhRXfIX6^|=oA}F6CK)})IO9qOL;nzm^B^`wU+?JY3KueL>T-KewwPU=Gurp8 z-P3B?Lj5<;sJr2lFL4$QWM`fNui$iM(K4ZbTmG^OS(sPP_xle{LN|<_W=mKia?Y1j z3&c^p!0Vag9?b*Sl`AgF=dW?GtTl{<-{_X0Er0*s`lPSB~*0`uCacJ9{n1h2eW`n-Rb5Iq^8UXZhe!A$zqHuCA!Til{TjXxRxGIV9*h-oTb}_*R&h zl}Hk^4$KV$>)gRTM&Is^wbccf9QCAxCui^biL9>u#AzdY#1?0-2PAn4aP_pUYM$Rw z+(X#~E*drWxV1~Ms8tHNCv$v@!u?`n+&c1dxS2HNB~ns>Q~vls9D-IUJ>_B}Dx}7O zOBNRxey~(bbaJUb38TWw1a89%gCPjDf zUb)}7wAn*A>G>`M?rIiiE3OZEH!@R1SF# zCy|+Y$$H6>f2SHQJ$!tLs3=u_RXP>7gFCVK*xE;%~THzPWlEc>DiKhRBzz=i&S z>7o{DI^4TXq3pbZXDB)zZQ`2pf|hp(S&~|drU9Z6KOHf%az^uq4q7?R5|uj2c?11l z_MJwrvenu;BfAwM#S7vb$#bB0&c$a-d%p;i-IQwyUcrslzSD*F<{`w?FJ#_z$4|G6 z%E_jcMd6_Q(waJLAp$%0_M^|ZuiRE$Lpr(c=SBwX%8A;n&rfXXceO3%X?kV;irnob z%&&4!fAtO?Wg)pnW^9CroMz@UogL&yIa1~TdlB%GW?K~20#YOmLWV+n5nAsndy_(| z{9*4?N#D;_MB*A$^u~86_;^WX2|E1R6H+&Ahv0vwnJXT#l)g4VC$k5eHhFjuHQUGK z&DefFV z%xBGYdLAVu?4u^2KHKI=hb_jh?FGPYY`KOBz&@V#CcoRrYsBFEb!Z5)pLGdJNvVAR zxG54t6MZ5w^j@$jU4iB!&vnDfZ=v|b;j-~sY>d7@eU3j+Eaa327V4~zN1844O=R~5%(^ct>S`iyIe}f z(GHI|`LLc}IZQ5vVbr^QZl#5?N)?C+Z0cx^sSo8FCHPh{#VrKyDaf7M7X;P-)3$9? zP~S{=fnAP_4fUK4?mac$gvFy^ER_>6rt96}893Ln(n|n)~ zO@9PWtEL?5lHX^)!Em+Mhfjevg9&fCU^D`vXJ0w(=}5wMLa{u6JDr{V)^ zr10dM=RLuH8nGC{WNg?g4675m)t*v2TeeIbZAD?dilsDO7MjzrX%9@CfD**+HUyS( z3rnBaM;?B7@Z7o@j;30KKP9o{rmtmgpcanLHfL@s`L{^Y`(5B#GN*G_-Oe`b1jqcU z`NZ6~f_2B|yB+7qZ%ZfquKux1huYpd|0HJ|V?|(+mW|8T%_?qA8aXKb*Yl1BybA>c zIBSg$>t`L@!m*wxW&fg+j`Sy_6^adMTW){9SVjGoDE9t4>@$Q=a%W!t_`*v2%Z-1% zS)w01YWze-O3dC0lSaedl`VT$Q0QFS4BwMaC!>c8Tvfhttg?Lo`8!1O3T{?QzvONq z2==M6le{vT>TR|r%xZIF>xKzUl+a*W^zHUw8zIJK+CD1TE5zdRr{2IJKDmni8$@&t z0{mZ+nc5ED?M<~sRBAZ?ZFZxmM@Sj4MdfsED_V+u-RUy3te@5oQFW=)y9?qz%{+^q zPSt1l#Y0*GCQM)akcTj3w^_OjL~5Y~F7>725B;u$sh)IAjWojytew9;2+E#QaJw>{ zjC}n0a|5C2XZC5GUq0d9ZnG$xd(-vhGbWV4YqNU&yM$$=%Qgx{$8XurKo)tiG*6xW zK-)@4Zj^^u4KRcF)u(q)&7RA|Gs&tyrRFbR(b$wxxNM$Y{^k+9w-FH&_BkPyEXz~~ z%xvJ6W1D{9&bQ>7WAD|#{4M3(p1^Ev01N)#>~I5D8|L>8H`z@ZBfpC@>#rYb(*2@& z9=<$Y&&y?A8D;D&=-YXqY@$S%WxNTmavLDUTh`x&uuV5YLe8HEmC6<5|F@L(Wdmi^|#V!LP56E@W#z zMm_{t(Xe+Yb^gE@gKkV9qD%Lbj_~S;yW+8K2avxX3 ztUK>nGjp7UT!Sn`m79KG0SHbaqOsC@K4JuZ9&hBim$i418+uhadu*cNviFBW;$yji zPI}6zj!`$P#BH~ot~2@dR*<8dzq)^2T9)4o;=XVo%GcU{x4AjAD0zB%t2dNT@pF{B zc%yu^*l+pt0a>L!k8=m2WXxsSwTRR)OTXi=*KjIXb2h|Xph1BL<@h4#_-1R~4 z0*NXCBd^<3r|sR{SMCI=5^%JLM2SCT4oMV_X{^1CP{)8W#!;sJ*MIU4p3W^Tbt>I$ zY+xm>iX8487sctTWX(!INEqLqvRfd`(sqyKOHCuuT!iR3=#>-<$3 zc*#SH)bPEUiv8b?zISQGpMNK^j)BMT1TRRmzTaO`MB5-lh zyoXZMsZFIoqyt1Id#k!E8!Nq6;~vlYsV34A*{mSU*V34@2F;|OT)Asp-bkWc&NUz_ zCb~;Eww*M`NcsFv^@}*)l?-Y|Ndm5-_sR+uX>&`N5}_XBy=&$81kTy=H!1H$P&wdZ zA_h0yw`E%vD2ckBF1`4x7t&9WyaK9OTi2lcchVfs3g0s4Fa{0HkZz2TlX1<_6Wr$JjFInE- z3>ApHw`M*c`_-WT@S5BQsLfmI&l^@a`MIIV5jC7Ro!&K_x8d|A<>AdT?7D~gi2;kQ zWSrea30Rrhj<;@M?n!U3;~m4&8UATQ#)5>CY2?FMMp40~>Q6-9AT2$nOMR+=Kt_LR zL}+cP#^?DjemPhIO9owLANYc&n$BlV0N+WP-hgEmork(N|2dycW8l=67@H`ZHS>#fRhRwP^n~I@JDbkwTlMHRNsXT?*<{0|Hqs?M_ybE z!esm1-=VLvZvQ0RZ57npd{*&}8v2RoJR`-vJ0|LiO+NG3o1#(C^CV)zB}0AG_s^QZ z&^Ry^1s8jrkNsg2Y)G>5Du-X?XQmA5_xihX;|52QS1nK9ro1`pW5d@sObeb`x_a}F zD5S9ViC~TYE||L}r<;}Z^-{&o)Haw5<+;7W>o%IT2~1lg`1T+3aAk7Z*9m_}@?`B} z(+icCrqvUt+L?aE1IlfxCc)-&dg}DHB=OgtN<(In zd*WX|H+xSH@)%d;1E5i~oCTkLsz2OrP>|_jk(u(=cFHVa#O#}if}?3iyss=1hGZJ{ zo{jvIw8p{6I^g~E#?<-rS=~#eS|E+zMojvl#{JWlNn>PR>3I}KG3}}X5*l?Z6!QGd zr9++LfW9-6t6;dnyQjw75TuwkChE{h$Xfa@U?}~nl1=yI?~TG*GmzoRP-{7)01oa3 zEb_6Rd{C%7xOCI6@{^s?By;$-yETPvw+x{#*;iWsDT}MrF;X02+Ur7!VTk(_nUXx= zz0Oh>^=|_qCkUQ;=oa>}!{gi^Z|jQmssO{6w$lH;!GCzIZkCZCt}Cde@H=3Qp;hNo zozfw>3)z~4@=mPwMXC6Y$y*!SCntKOX{PWO@4e} z8^ZVeM^QUP+9yw4#sHo2?AJ(1@-LC>D1rI8F01x7ZK#zr3_26f$ z>tBMg!dNh`iC+Mo-s&mUMy*peZPv6AL6!c*=MzD(=I;4hb+({t*pV4QtsW`h;bl{c zN6Jp6`$_u;abghR4&5sGwcirqCh2gbDoZR`uB=aFDl>_cr}H=cX}P>Rd8py2Toic9 zFP7WE)A!`LZC3cx7vL9TPIK^hZEN+u6?5giOWEQ2^&j7N1CMqI2}a0=f2f3rTpSke zix0JXA~2K<+qvx@Y=)v5S)NgTU0-;Ar{GocyfGNP6#?R5ZS= z(8VjYi)JmmdXn)_>Wh}!)BjiX9;hhC3+#eZG;FK_Ah#W8Zf@DbWBAs|L zE%w;JCH=uQMP*exT9+6(#ee>9U9Q2_(zSQajEGEc5%)#)`M-!1{cCFFU$2j%rWyUd z=$(+aO*Zas{q)c6SopjyzUAs&_}lGw>%a8S-G&9*ytc0Su>Q`AtiwhAr?2lVsQ{JF zQ?K$f960D__N=9~IQx9)%9DxO`LnLk&QL+>3$Zx#wWn|_2O*|7<(|7b` z`oYY$-lfw9?ys~o@?dYS!V9rXqo!9ht$z#pzig=A)6vl1_Qkct{BEE+}e$P;t`tAlWvM*5*>xQ?-&f$;lBR=;zh==3(ZlJSQFBT5SHY z#V(7#%;ooFkzZJci*>hz(TC2B$}bvqzM9BxYuhtxo>=3BC^Ecp^TcoxWX_2mSGTj^ z*^-n~Iq!0Z$n1xulz+$O28$0?o4)7I*?vlpa*mr%rTje^ZC+2T%37VAE>mRaP5<-K z)T?5yM{Di%!Bwxf)aQEUtI$>#_QOA1{!-QlzqfJ;>-E)iOJ5R-(bB{3x=)HuNw-In zOnU0ry0bhEGELf-_%87!Goc%G#xhMgXY`-{IC;T0`3hA(Nf#P&DreNzh>Sgr7RYr$h8^>buT>Nn)Br1BFwr>kAFO>NLax)v=cP< zc`N1@A7m1G7X}?X|K_tVpW_d8EZF#7G}yz4G;8(5Qv}GG?dIBQR?!xQ4hPyFTTwsn z<^}nS@76{q3?3WR#)_~6RVi47wZ<5mo*L31SX*ug)q^ae`!qbIy39nr);K({-}msl zbMB<>SbuHZC=7smMtO!jWqZKV9q zbH4B5GC$${Ez^=dlY*(_lc6xgTD3AMXyudXl~;MLA5n^_U|r9s^#^Nu7k! zK!x>z^356D{5u2cR&8?Z!Sp;Q`)w`SCxqftYVi)%;{?gm^{xv7FYJQ^CZ^tLe0YwZ zw3D+uZ*u@#B~y;oEIw6ZzzRu0%u)oY!6@~*t=giRHz<#|{N{he_x%;roDz-$B3f8leSWd1XGc({w^$6`?WLZ%?}(-zcEYcy=y&fp3df3 zHVY!@vU+&a_ft?7-(tTI_MYGa)>@DBIj1nYFUgD;skyW5#@ol$e&mQ?uDh4(&d-Q7 zo)+2B@!5XK$5q66&L2cmMf8=MsD48&qu@haalv+q_H+Y1-FSwAsEB~;`gKGDhgTV# zIltrJI$}b8Pu#@L_WJGP$%AQ2RoY%{{9#2j|7K4oW+6)A_R`*3c+z28W6c~v;wzH= ztc0aqoYk3zzpSLS{$n2xvn4ljymL?VI~m^=KD->d;Yv?p)>M%>h61sDBw=n|c;=0e zvd|k4Yl3yCM*Hn*Y5Lz92}{59*VdaFugUjTt5w&3KEIQZWv86+l}#b?>}d3~?7Kr1 zmsqNf=DYSvf!oV=ahAXL1Wxz8|8Yp{CAA*Vk`w zYjwB%(KM(JK8l*LI-zp(4a#hHjWz)`+xRIjszm8Dj6r*ymbFO4C7&0nTAN;+;a zjh=%*hwk>Tt8kF*S$xy@Z(9M`-KsSX#X3%ffLhn;{t1gg&4&;L6cGV{J33H&BVcx8 z@E>f^;r8cyXD>;X@o(pX5FW5Fo%Wcn{;rLO5*TEEHL5EH3@PpuQ`iw04tQXil1FJ% zcUmgX@(4kzwQ6j|-%~Ib;X+dV(2e@EIN;oPG6@~D`p&4;9e9`Hp07VrdKl{C|Fo)# z&C~9GBML0N7tX;JEyisOaSToU&!@9-=Bub3I$(Z>5s;#s^HtDS>6;ebM*rLTf54ps5KN~vZaa91Mrn&r?C(PE}0G# z(TD3#1;96M`eqLbqD+_|3Ov<%M{h|Ma|izC_7E9&mke6MUv0`MgrER#1l=7ygq$`H zWh9A?v)0Gvp&V1Qzva|y57b0^es{IJooHvLLr$xpaEi%de=B-`92I-{H+w^Z;25_H23HRW{Z@?0UqX!yiI&`uCmfpy* z+EW9TKL*PA&8bMh!^CfWQ^7-C@(eYE1CsQcf9i*Cfjp>?`S}Fy*Qdsve3rwsbBhLw zGito@Udihm@uV7?jN@eK431l%YEzd!U|>&01L>sFf0Zvrjd~Ld%PA82w8`VNBL{+;R#|yw+vDX*07VO*V zv;&x+$-kRTYP}7iGEU#*f%u3NEwk*L*aFjT5IQJsNCbm6*7%G02hC)_eA^Nd{<^qA zm1lzol4P37zktP%SW|ILKsbfugN{$}VsZ-g0}Jy(P}J^8&W01Mh_A>;Oo}Wb4$cWr&Qn zvyW20b9&#-Ab`qSRbW}?4>x3BJDd!VAj3RWVruRx{_Dhxo1;7C(#c{VW7dGV0mMLD zM44rih}r3|KoLr@zpR`LSzb*1EYSo6r^m%v(tuk(i^Z@qpbiup|F2J&3!NcFR1G?H-6m8EA~SuONoyfI zvhyDbLMs}hZnfv~j^H)I4Lo?ZEQ!pfL+7MADDKC}t4e&Cq&hxJMR+B2!;6o>?CkR= zlU){2IOp(%+%1c|m)-jpdVorE;kcSoXc?VI!UjQ$b|)VBGkV#@c@eG2p|<~_?&eH- z-+(6RcoZeLeX`Fz=;QsdF*(!~cCEnBHsf<$7W)DhP15jNGzoy?V4cec07NPL!;J{5 zrOf_##Uj2@5N_NO}>1WB6Ky5yiPzdoibKJNk1>Kb0#sQ!&$6N-HjrIj8&H(!I zfaoP0UD1=5&5{K%Hyx!Uke&ta2pE)fpDHdx`;CJ=z}|657tK zN$9oO?WYEkdW4TqCc-1LDqv9F_=Ej`4|S%8o=pCCp8`Vop*M@JG27@a7KjJY_e$6S zYM#a?peP3v%r4)&OO4xXP#)(8gMN@*MV~8qW`|nh0%=jtPW+VmKhHaT5CeftazoE# zyo&bo;`L;RaZEP~L(Xv>H5LO&_Rs=aP|fVriH-4BXr_t7z$Te|W!6-oudXh zlF~bjZf6DC3Puln`62=&bDbFdG7Q^qS zVi_?(;(#1}78Xp5zXwp+2R6T<`xdoadk~;Q43(T6xCc|=`QKU#h`PqK$E`Y5r=<`g zcpy>a8&5&X=y|FC2lbmCw&3a=$3Ja;g$BxWIjnPDCY0Iqm!y2@55YSINX3_vw?_>6 z!K$x{b<}Hpnho=KK>;W^E?;_D6q+DNNO|vG{E;^C5kP?^NG+fbiTFVXdNOr8eKrQG zkL@)rZDIgsbmp(rf7$>AHalT`f44V;60{Ws>bmxofQCbRh{e@=sGoB6MF-6)d+*_( zZ>++pgI{jP0P5;bdq&(hZ$}mqkdTE5#!+xeo(~`T(CACp_2#QvLyxW#VC#ts)JJoU zqbqo->&^*i4xFK#;I+~nDnXlvmxEvIq5Z%%Q-*KkW{?m5Y-9(A=yH=N!iQtf12%ipPv7>#F4?0S z?bm9cQHI2(odg;~fY6!nt2>Wt;ahxI1dKH)taEjz5Mb?;;qr3*tqI}fslBy`9M#AgbSXH35Sn5dv z1cx(0oUc9c1Hh*Od)@FerabZq$~|5n+}|($%-7b3wI@rclmhgQvG*oeJ&mucIa)DT zEv_&>ibI@NK7|(~`7Tt@Vj`d`jfNs>)X@g=dBTR{YY7Ixj)AGrznB9s9Xgl?Ndq>D zGK{2mF_;lEpx~nv4F+H8aebJK&XtoLkc~$%8P>NTrV6Y}sPMc=1&eTFdapKxGY~O& z68_CK@f#LUPn(|*WD+V+4NIhT-3^+c;`}d%h@m+~=07E(1;8?=bvP8BG*@@;xY+|R zdsuQzO>44Kb0r!mYSL?_cnaE;Ve=n~Zh);dVbyP>GDT@L2LkmXmK1@<5*@EZ3BMk0 z976BRg?+;pEd-+`>wr;zHsx;u#4@JVFdAF}h-LBAH);{<86|MZRuB|Wsn*v)k}swG zi<(+}X>b$RBv^h1Uho7yBd~T2!~pGp>rzViJRG;%U+g-pT>|?v$Ka&;)_cJKfb&vJ z4W#%9!T2Bf+_+|NOwD7tzvDlA_5;{J$vvmfsPx2gT=(yXLn6TTP!~|I78!cv0$@Ao z*Ak~8R1Kum@=L=Qu+1Jjw`Gp9WBEDl1!}av?%em}6Ad>JjLyhjEd-{eEBEXh zq#6YQRSK)Kjo0H|d;i2;eRz>D}NrlVSkoNdTIrDh0 zS8q`CA6E)cK+4A@GIYBP;1%oWRO7X8fLeTtF!SZZ6^xnm1%Z|e=~y#VgMl};5Uu9~ zRamCxDUvjMREky9T>^NZSds4s;(_(b9_x(D1|FQ?7b4R7xx-s2|B0ih-TI05BtjAr z6eckFezOhO9m!td{{B}Tjs9auhMs)qypx5?uApNu7~nVFZEH{NhC?SX<`}W<0;bv6 zgxu~+dO%t&;`N8$Zt?*%4iNk(wuhV-=$sX&W)|y-{4a+uO57QSDX_|i2jY6;{kC9= z>BHqX%PvPY(2?yqzd_`w&J#fVM6H}%zNrmKQ+a>sm5V*G1e7)L*EwplzxO+xgsc2P zZgVlG+GcfoqQJ%d#wXO~# z+BM*sbyly>l#x9;u?2#F;;M0jYTa1njZSzf9!e#*AMPe6iQqMDs-K6=tl z1NJH*>XNuKd7!#07J)d25&z!EdGXR^(&%`ce!SING(0=AIn7ycny_zQ6N05=^O%CUSR_mjO*d zJ<*>0&18vki5;{mqraUKQLhww!#NqZqfSo*M@txg?}QFuYPjc`fmkxn6TZeH3^(4q z0GL$72BWo>r}zT-Q7A({N_My)xS-mNvhoxMOOWsPJ(YI`f#~ey-@-ImKC`^6!ZNZ1 z8Os0Y3!b386C(`E-URa7d>D<1YfL!kNzof)16p?SFYjZprH-20WizH^p< zAtk(P5AO8fM+GTV7z4ORB%51?Tu01SJC|r6 z3L)bJ{#bj5!2O%_P?)L|q_>sJgt&%Xlm*j~utM=?A7JG;b7RAV{^Xg+PLCaPbq2$M zqO6P0*Z;uk_Y|qo#h$=~_NxDbsVN!*22kSf=7d7Az$A0p}H zD>0nstwjx=y0)Dj=j@3ih#;P&|DJTRrC$3q=n3Y9? zG9MtC0!F0swT)4xM0o)0jhZAygzlY1-*GNP5>Ap40>lbNI#m(l!IYS5%GqSEaewC> zc&LG)S%J5-48_uOgRvj`gQ>t>8Dh+q#5I}9e_U8A2QdHAspLaO5cTL>>F#?W9wDN=b%DCetS64xrUfYjP-x99YoA{fF#%$RGL zNYTg-GF~?st_^4b;Yl4ARr~Ong zXcq}!lwpnXlp^U7_QD{@(A?;$YqNS!@EOh@7^L^Crcr)}OHAPt9SF=QdZ`;AifZ_(9y?HrGe5U;E#1?a*U_D!WK3*6r!dhZ}OR`BDMfwhu2bLCt8~ zIrLBpv|7?3V6Ynh{Esm8C=|FLlbs~qocfmZ`oXFBDOx~6^=z5>e?I>(lpYgRsr8&0 zrGKtbo`$w+T`jJ&s>RDrB3yzGD{-jnmoG8bBAPe=gGTY)l5uwIN#Avz@x{S>z;KLd z%kh^l3vPN0)JV}Cc~AfN#1Fyhk0FF+aiE~_@GLkpinyGnFoPJBN&5FI7~HB5`mL** zFC6w943~1p&q5BrKP6a70j;JU>ka|;f?@Uh&k0TAAVK4)zG<$e5%MFY64F;pAR(!} zQsTxs#PF#iUjXa_7#@5{F<$txNaW7qk$EW#v>I^y)*#}C_l}vik6bs!4sc1$O>&>n z+p7X%q9))B|arCykF1!(q6NcJMuLIhslL`DFV&y33GLtZ)s%TbXC8OWA6dy&Zp z2>vMslT!vl`7F{_iLg@Bum0c;$D+^5i5Ro}2b7f}rwoGf$!?gXSr+EAU{v>7IBi|ewS`< z0ID9>wfT0u2{i~8Sg>ROD|^4YV^kWFxl#uWeH7Eu%afopw|zPvnH~z|bEujEHi3QDH7VI_YU0Gkc16bIr(NkN#_ggY~ae->cbgjM^H{&=%Z=s7Su&Q zFfmPeImsubnQLx(76AV0n%6eT?FTbiR@_8kvvOm=QZuEAefTwNtg+Qe(F-_f-@LkR z3jXfnjR-(@fgt7eIXk=21v++4&T)2b_I2r*^rR9#n|N7pzYdzbNMf(Ez`&BN*Bwp!P%@x8h zh!G0bIL4t8Anh%=84*fA|G|Fn*0+)%(mYRlo$po?fI91*fA^|V;M(gdf`c@A7k)}u zeMoj-j+Tp~#Wb~Erg%WY^DG_S7E^)#e2A8Q+0^pdeaZt<9u6tmsUclp`LM-hpHW~y z3vwlpaE@hfaA#6^rbHIRt(8*|zv-@yo}|l%Ve)e$hWAml+3Bs$HF~sk93Q6XVEgim zK7r3H{KfW&^g~xrxRi)CNuqf?L2{%%It&q*Vy?$avY^U^e@n$Wi3rXK>AaZY--ua_=*_r$OV--yeLj93U_| zn^b%=I$1#kGA}E9A zT}lo@kki7oYDFz_Bc6_!v3O|V(;e#B93<-P{CtN2SP&$6GmBzJo!-Ox!K?xrBtM#u zBUM!}l$1BSKpm$%09rd4#>S}6OJc*XF%eur3eq4sDEyLH|CaY^A{8SUnBHIfkGB;g z?}D{_`A9(?S|u&-zJ>)yafr&jc%q8|Lsa-D6|c;*^B0?9p5?EazPr%KsM{xw7BqQ^ ziTZ6EXFZ^lDAD0bpbn-lB;?6vJal92CcH1Wkg!c z3sVMn2H*D?<2jZNj5-g@myQh1%ID+FqQMZ%tj|b!iA<)|2f+B@VT?o?3Jt@+lA*9#z09CMuC_)euHIkih0y9la z*AkKI#tEQ7dX?2|M8U9PaSlSEwHZ+&cvg#4<#c%rn3C@L{uKp0;jcaD0P-$vmu+Oy zM{9@75$5wnf%=tbN`{j8u=SWm>1&?_jiaerO}^yFx@l52<4XkfE6|jWrKzUW+9q!D zeGbTiAXPj{)h2h0@IIeb!+D$#b?a((kikCe`MklS@qAJq50&af zKiZ`fpBY2V=Qcpqm$%usOFd1mcD7RwSn{t`SGw*F(N zgCbopg6R)CCMsY2OWg>8`jP%hEDL65*4{r$FZ;VK#lVjA<_Q zK_ko@mHleKERL-8?H?>5OxR9s&VZO0b!3-w<_Ds@H&c3?-UNARQGi7n0~EIwc+JSs z=8BUC!F2Ufl=q@GDyr$KWx)Z%w|zPOog->rom12)jn860!y~49{N_3=KIkXnV=@ro zyc8=q#y$fG{lY^R+%+Cb~|8d3MuWCKDpkS;AatBQK2RY0Os`G z`I(#(2LJu?NCKZYnh^At@%m@kU>+UCa&9*9lc z*3X$eWleQIb!y-s$qGqedK(NS9qF?dj$daQymQbI4K7+Vf$uoX;P@P}Vdo2WC%9Gx z19^VybGyBHjzybFzR#kaKyPlTPYv}5cW%nOSy zU6U2le$oxXU`!Yb;|#5a2b(mZcH8I5#W=~5{H`pGJRW?BTmxEU5R^2*CbBDybyB&F zZwqZPuY+MmS**_C+m>Q;CyX5oS3hvJQKu{{qG*Uhe%!!l{Htm6?R{HtCGi#OTVa-0 zn5b$)L();Dcx`bWSobr@U$d7T;1c^R;^=qo{>lvkU>q0=x6UDJtIP=woBQ1tY}j$* z6rGm+qL6>Ebjof$HW~w1+Px>q8?Q>^zKP$+3c-Roh6h}+&OVyf$^)#cc2oxSTO^cp zVXBf7FF#MO5k)g3C&qsM$*qZViN|B9CU!Rzn}-36b(MzS61xn)px~$No(RbsR?7y!w(cEHleHQ!!g5>q+#E>?%Rh0H}dhr*|1#X+Goh4!IpB+@) zWx|eU0B=?g;!B&dED!6|_J=iafuF!wqL=7(wIwzEjW0;db~?9s*G@*$Gj9&<7`@866kYd%jv>g? zYjcJr6XV?Bu~OS-(&Wv3vm}p-dN$BcpB}oiaKS|7QS{Zq3KB!KH`3) zu=4PQS4)!4P7xLr6ueo}tD){8Ys>J__X-nFDoy#4&!_LGg47&~Yl;xxSrVeK^^R%D zIvaKCGGphNfvpucbkoqFg>AGf~KQWN!xg!7!F$<~BizH!r5Wikf{X73D(;2^(~_N3Rfg zHE`E2@gzZN?{x5XrqAf52}x(3^{|%)$b9-m=2=G?b$W37*g?wa%W`g2wQXP z;7j8`7sYNpCN2Zm!hKFrd1i~)+gx`l=J2&>NQ{K>)AN0)&N3g>589fRV0aVV>G2&) zgk5=w^?``gA6_ArUo-k?e{LXA`X^79;-G*|+rMPMv+CmZ9x!Y3u-wU=@}JRkPic6D zXRH+-YF#4*8FYBr9@oe6_s&G`kIf%Gm0;i6Zm>wfzgBv-N2pHv zJEx_f)C&D$DzRN_ODQc4qy4tQKj9@Gs0b#?+k~x$mQ+ib>#O}<-`kJx;P)9b{x~74 znbj6u(!dZkH0nad2x{yhdfTJEOT0g|5!ut}>$=#>u%qXTCCA)LuB+H!_$R&SszWE1 z2|fb$O8Z^<9;MPJcIP{0za#Uh!o`A4NKJ;2El}{1B~~7HAcFe#ELp&fz~rl|$~N|! z^j9_8W}JKsE2CUH_82LWkmgZShwOQqpf5#Vg*ORBxV5}6?8=MXx_!U#La0(xYyRRb zS+7z9MD#+7#k=S!Qn>eA@kT6sbBY~Hl6m2{5WLyMf)TBEDZXU63M^3_FFbWbKizAm zR1NK!=|4U8eDiXu21a`06w#9AxjeJNJ1Ss!ihgkXNcEi1Fh`Zcp73V85CNg9z)WI6 zS-7M|wM=gX1X&rP^_riNrC1dl6p(MR+BX;VWF=PN^@t_{A|r#b1K-`dE(QnTpSpg#Vy z!I)G^%ck0&n>asWi^TZWK|ci3&~S^ZT%`=^aq_)&(8j-b3#z zxVT17M|z)$JF;1bD+>}gQUs0TYnz(a_WV}5yZkgbEjE6QFzB=C!&aH=__4M4Q_f#? z`*OPIHvQ#G;fFK{hIGH{xP!Q+So`OWuQ5@A<+%&gw#4{(X>Z^8KJ4dBe!g&v<}jES zY4N(f4U=Jp%ZHf(w{^@{Jshr9#J^S4?RF9-S@bjorZscbKcczhxDWk|!F7;?c=b3p z*LC84Gc0g+N|s2~aee>M(?aXw_Svs#yRT*5)hF??)EWBv1NjnujJFaqGt!T$G+)cg zX0#HMNViw$QaP?HNA6U5t52tRs9JWn&>Ey5UVXgHZGkBwTO&w4rFp`~Bf?4h>y>dL zH0E}#S)m;&Fq}v@Q@%k6#8_nVCpQHO7Tbj6K_qi(Xswhy@Pfw8#%-}B$MU*eTLNSO zpp`@(1R4muGpLO=2H-ocp&Nzz{@;8hJhID-D+p?%;9CnU)Z zg`U^@dp}hN8yB;Cryb%PvtXiT?iV7l_-H{M@iqHo%@jWX8y3=}DJO*lZH@YG7MjX!}tPcuBXR;6B&m=F;C}SQPYE3p=R3@uDik84B)kN zu9-YsR*$#6hgCZ@IFgXA==SB{QJYmXtbgq&MS3V63@q45@9ij3cpM@zzWD?=a{)Ja zJ!@h8(UvG3_84913JQWE7ff+k8xtKinO);C48x$vCKKSdTJPxCE;>%*(;&#!%e&^Lw07R|P3uE0M?BAsz= z3@Gn#L=Y<&&b_%;{B4LHGv$VKlp0e57-Je|=wmAyB(~;`*r)^~1N3OE8uuamnHcDo z7l(<-z_>}QVvRn*GF1H$@&zCVqi-F>KUPU7m8u^sg(*ND43}H}$AS+d7|e@wRYy++ zD5U8VAye=p$6?!HHwaS>I|%aboHxcAJv-6jXsQq#$B4;LaHz-r97~1w(qs%;KmY@4 zH`ZvN0&#!v41OJQMMEz@2htrqu`~)+OQgegCozE25=i-(ArqlGNML9-a)j7~3X?&1 zcZ!)u8t>BJ{;828NE--Y^>BW0VVK3!$TQ&wz(=4WxlSgkf8$D|?7;F6@d?r@FcGt0 zj-kR7fr2}kQf9_?uuLMfo{bk`nebpT%x>Q&@gdO)5HD4zF#iE9w2#(E-^g+h9 zS7QZ1_T4FmY3;ASB)c=-bmKgZ#z zSz~ah#bNOf_J6Lc<0RT}d=MJGf2cl$7T|YSTe!w6C<=JKv=jt5k>F8p2P{HQP=oFz zuMs0?6b3=3c$RxauxPpY&(#wo1T5B8L*r<_0>>q5S2YY{2=d2-m547NUQjWs&A2j+ z5FCR3zGEqvFqFRG7-WPG%7lUgJ9Ne~7rtv77DR#qo?!waF|{;ncO*1Z6+xMhC{}^%hV~G z-}R~_20@{~fPdFt?en;jS-fm64$Orhq1D??jctnTT|O*efUQB^)XakNl_rAj@&U5| zwDs{QnBT*kr8J6v2a2~Y1qmYc^Y_4_r&5s7J0bS<0(}7f;`96DLH0^Y-n{&cQVw;% zHPA0>v$vVoE5DfkX+|mpJ&wLV9T}a*xhcl zIQ$^U#>Hl!h0umEc(5jTWjqWW3Xq`xV2?uQ4~jtttA+DETbuwS46Jx8afwFaJ$d2d z3ZZK3XLh!f`4(wdy;qowJzU@ zE*?H~VE^9TyLRndvnp!kvZzH13knJ{W9x8~jOhQbpfL8oToL;}ui3e4=dL|ZKYQ@S zSKj~dlh1Gh5`euBga82GX$V390Pr*fApih)8iEi206Yyr2mk<{h9Cq008c{@0sw%A bMI!${0bO36huu=@00000NkvXXu0mjfmW0V> literal 0 HcmV?d00001 diff --git a/deps/mimalloc/doc/mimalloc-logo.svg b/deps/mimalloc/doc/mimalloc-logo.svg new file mode 100644 index 000000000..672c7e41a --- /dev/null +++ b/deps/mimalloc/doc/mimalloc-logo.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deps/mimalloc/ide/vs2017/mimalloc-override-test.vcxproj b/deps/mimalloc/ide/vs2017/mimalloc-override-test.vcxproj new file mode 100644 index 000000000..faaa00e35 --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc-override-test.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7868F-750E-4C21-A04D-22707CC66879} + mimalloc-override-test + 10.0.17134.0 + mimalloc-override-test + + + + Application + true + v141 + + + Application + false + v141 + true + + + Application + true + v141 + + + Application + false + v141 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + false + Default + false + + + Console + kernel32.lib;%(AdditionalDependencies) + + + + + + + + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + Sync + Default + false + + + Console + + + kernel32.lib;%(AdditionalDependencies) + + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + MultiThreadedDLL + + + true + true + Console + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + MultiThreadedDLL + + + true + true + Console + + + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + {abb5eae7-b3e6-432e-b636-333449892ea7} + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2017/mimalloc-override.vcxproj b/deps/mimalloc/ide/vs2017/mimalloc-override.vcxproj new file mode 100644 index 000000000..990d6ca97 --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc-override.vcxproj @@ -0,0 +1,254 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {ABB5EAE7-B3E6-432E-B636-333449892EA7} + mimalloc-override + 10.0.17134.0 + mimalloc-override + + + + DynamicLibrary + true + v141 + + + DynamicLibrary + false + v141 + + + DynamicLibrary + true + v141 + + + DynamicLibrary + false + v141 + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + + Level3 + Disabled + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); + MultiThreadedDebugDLL + false + Default + + + $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath) + + + Copy mimalloc-redirect32.dll to the output directory + + + + + Level3 + Disabled + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); + MultiThreadedDebugDLL + false + Default + + + $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath) + + + copy mimalloc-redirect.dll to the output directory + + + + + Level3 + MaxSpeed + true + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + MultiThreadedDLL + Default + false + + + true + true + $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath) + + + Copy mimalloc-redirect32.dll to the output directory + + + + + Level3 + MaxSpeed + true + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + MultiThreadedDLL + Default + false + + + true + true + $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath) + + + copy mimalloc-redirect.dll to the output directory + + + + + + + + + + + + + false + false + false + false + + + true + true + true + true + + + + + + + + + + + true + true + true + true + + + + + + + + + + diff --git a/deps/mimalloc/ide/vs2017/mimalloc-test-stress.vcxproj b/deps/mimalloc/ide/vs2017/mimalloc-test-stress.vcxproj new file mode 100644 index 000000000..b8267d0b3 --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc-test-stress.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7958F-750E-4C21-A04D-22707CC66878} + mimalloc-test-stress + 10.0.17134.0 + mimalloc-test-stress + + + + Application + true + v141 + + + Application + false + v141 + true + + + Application + true + v141 + + + Application + false + v141 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + false + false + false + false + + + + + {abb5eae7-b3e6-432e-b636-333449892ea6} + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2017/mimalloc-test.vcxproj b/deps/mimalloc/ide/vs2017/mimalloc-test.vcxproj new file mode 100644 index 000000000..27c7bb6ea --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc-test.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7858F-750E-4C21-A04D-22707CC66878} + mimalloctest + 10.0.17134.0 + mimalloc-test + + + + Application + true + v141 + + + Application + false + v141 + true + + + Application + true + v141 + + + Application + false + v141 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + stdcpp17 + + + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + stdcpp17 + + + true + true + Console + + + + + {abb5eae7-b3e6-432e-b636-333449892ea6} + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2017/mimalloc.sln b/deps/mimalloc/ide/vs2017/mimalloc.sln new file mode 100644 index 000000000..aeab6b88f --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc.sln @@ -0,0 +1,71 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2016 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} + EndGlobalSection +EndGlobal diff --git a/deps/mimalloc/ide/vs2017/mimalloc.vcxproj b/deps/mimalloc/ide/vs2017/mimalloc.vcxproj new file mode 100644 index 000000000..1ff1af9c2 --- /dev/null +++ b/deps/mimalloc/ide/vs2017/mimalloc.vcxproj @@ -0,0 +1,260 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {ABB5EAE7-B3E6-432E-B636-333449892EA6} + mimalloc + 10.0.17134.0 + mimalloc + + + + StaticLibrary + true + v141 + + + StaticLibrary + false + v141 + true + + + StaticLibrary + true + v141 + + + StaticLibrary + false + v141 + true + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + false + + + false + + + false + + + false + + + + Level3 + Disabled + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions); + CompileAsC + false + stdcpp17 + + + + + + + + + + + Level4 + Disabled + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions); + CompileAsC + false + stdcpp17 + + + + + + + + + + + + + + + + + + + Level3 + MaxSpeed + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + false + Default + CompileAsC + true + + + true + true + + + + + + + + + + + Level4 + MaxSpeed + true + true + ../../include + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + false + Default + CompileAsC + true + + + true + true + + + + + + + + + + + + + + + + + false + false + false + false + + + true + true + true + true + + + true + true + true + true + + + + + + + + + + true + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2019/mimalloc-override-test.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc-override-test.vcxproj new file mode 100644 index 000000000..7a9202f1b --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc-override-test.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7868F-750E-4C21-A04D-22707CC66879} + mimalloc-override-test + 10.0 + mimalloc-override-test + + + + Application + true + v142 + + + Application + false + v142 + true + + + Application + true + v142 + + + Application + false + v142 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + Sync + Default + false + + + Console + kernel32.lib;%(AdditionalDependencies) + + + + + + + + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + Sync + Default + false + + + Console + + + kernel32.lib;%(AdditionalDependencies) + + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + MultiThreadedDLL + + + true + true + Console + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + MultiThreadedDLL + + + true + true + Console + + + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + + + + {abb5eae7-b3e6-432e-b636-333449892ea7} + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2019/mimalloc-override.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc-override.vcxproj new file mode 100644 index 000000000..a0e79fb06 --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc-override.vcxproj @@ -0,0 +1,257 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {ABB5EAE7-B3E6-432E-B636-333449892EA7} + mimalloc-override + 10.0 + mimalloc-override + + + + DynamicLibrary + true + v142 + + + DynamicLibrary + false + v142 + + + DynamicLibrary + true + v142 + + + DynamicLibrary + false + v142 + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + + + + Level3 + Disabled + true + true + ../../include + MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); + MultiThreadedDebugDLL + false + Default + + + $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath) + + + Copy mimalloc-redirect32.dll to the output directory + + + + + Level3 + Disabled + true + true + ../../include + MI_DEBUG=3;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); + MultiThreadedDebugDLL + false + Default + + + $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath) + + + copy mimalloc-redirect.dll to the output directory + + + + + Level3 + MaxSpeed + true + true + true + ../../include + MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + MultiThreadedDLL + Default + false + + + true + true + $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath) + + + Copy mimalloc-redirect32.dll to the output directory + + + + + Level3 + MaxSpeed + true + true + true + ../../include + MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + MultiThreadedDLL + Default + false + + + true + true + $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath) + + + copy mimalloc-redirect.dll to the output directory + + + + + + + + + + + + + false + false + false + false + + + true + true + true + true + + + + + + true + + + + + + + + true + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2019/mimalloc-test-api.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc-test-api.vcxproj new file mode 100644 index 000000000..812a9cb11 --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc-test-api.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FFF7958F-750E-4C21-A04D-22707CC66878} + mimalloc-test-api + 10.0 + mimalloc-test-api + + + + Application + true + v142 + + + Application + false + v142 + true + + + Application + true + v142 + + + Application + false + v142 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + + + + + {abb5eae7-b3e6-432e-b636-333449892ea6} + + + + + + diff --git a/deps/mimalloc/ide/vs2019/mimalloc-test-stress.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc-test-stress.vcxproj new file mode 100644 index 000000000..afbb66666 --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc-test-stress.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7958F-750E-4C21-A04D-22707CC66878} + mimalloc-test-stress + 10.0 + mimalloc-test-stress + + + + Application + true + v142 + + + Application + false + v142 + true + + + Application + true + v142 + + + Application + false + v142 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + + + + false + false + false + false + + + + + {abb5eae7-b3e6-432e-b636-333449892ea7} + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2019/mimalloc-test.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc-test.vcxproj new file mode 100644 index 000000000..13af6ab49 --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc-test.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FEF7858F-750E-4C21-A04D-22707CC66878} + mimalloctest + 10.0 + mimalloc-test + + + + Application + true + v142 + + + Application + false + v142 + true + + + Application + true + v142 + + + Application + false + v142 + true + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + stdcpp17 + + + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + stdcpp17 + + + true + true + Console + + + + + {abb5eae7-b3e6-432e-b636-333449892ea6} + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/ide/vs2019/mimalloc.sln b/deps/mimalloc/ide/vs2019/mimalloc.sln new file mode 100644 index 000000000..fcb938a4f --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc.sln @@ -0,0 +1,81 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-api", "mimalloc-test-api.vcxproj", "{FFF7958F-750E-4C21-A04D-22707CC66878}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} + EndGlobalSection +EndGlobal diff --git a/deps/mimalloc/ide/vs2019/mimalloc.vcxproj b/deps/mimalloc/ide/vs2019/mimalloc.vcxproj new file mode 100644 index 000000000..e18db0c5c --- /dev/null +++ b/deps/mimalloc/ide/vs2019/mimalloc.vcxproj @@ -0,0 +1,253 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {ABB5EAE7-B3E6-432E-B636-333449892EA6} + mimalloc + 10.0 + mimalloc + + + + StaticLibrary + true + v142 + + + StaticLibrary + false + v142 + true + + + StaticLibrary + true + v142 + + + StaticLibrary + false + v142 + true + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + + + + Level3 + Disabled + true + true + ../../include + MI_DEBUG=3;%(PreprocessorDefinitions); + CompileAsCpp + false + Default + + + + + + + + + + + Level4 + Disabled + true + true + ../../include + MI_DEBUG=3;%(PreprocessorDefinitions); + CompileAsCpp + false + Default + + + + + + + + + + + + + + + + + + + Level3 + MaxSpeed + true + true + ../../include + %(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + false + Default + CompileAsCpp + true + Default + + + true + true + + + + + + + + + + + Level3 + MaxSpeed + true + true + ../../include + %(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + false + Default + CompileAsCpp + true + Default + + + true + true + + + + + + + + + + + + + + + + + false + false + false + false + + + true + true + true + true + + + true + true + true + true + + + + + + true + + + + + + + true + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deps/mimalloc/include/mimalloc-atomic.h b/deps/mimalloc/include/mimalloc-atomic.h new file mode 100644 index 000000000..b65060755 --- /dev/null +++ b/deps/mimalloc/include/mimalloc-atomic.h @@ -0,0 +1,308 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2020 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_ATOMIC_H +#define MIMALLOC_ATOMIC_H + +// -------------------------------------------------------------------------------------------- +// Atomics +// We need to be portable between C, C++, and MSVC. +// We base the primitives on the C/C++ atomics and create a mimimal wrapper for MSVC in C compilation mode. +// This is why we try to use only `uintptr_t` and `*` as atomic types. +// To gain better insight in the range of used atomics, we use explicitly named memory order operations +// instead of passing the memory order as a parameter. +// ----------------------------------------------------------------------------------------------- + +#if defined(__cplusplus) +// Use C++ atomics +#include +#define _Atomic(tp) std::atomic +#define mi_atomic(name) std::atomic_##name +#define mi_memory_order(name) std::memory_order_##name +#elif defined(_MSC_VER) +// Use MSVC C wrapper for C11 atomics +#define _Atomic(tp) tp +#define ATOMIC_VAR_INIT(x) x +#define mi_atomic(name) mi_atomic_##name +#define mi_memory_order(name) mi_memory_order_##name +#else +// Use C11 atomics +#include +#define mi_atomic(name) atomic_##name +#define mi_memory_order(name) memory_order_##name +#endif + +// Various defines for all used memory orders in mimalloc +#define mi_atomic_cas_weak(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_weak_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_cas_strong(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_strong_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_load_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_load_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_store_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_store_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_exchange_release(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_exchange_acq_rel(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_cas_weak_release(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_weak_acq_rel(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) +#define mi_atomic_cas_strong_release(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_strong_acq_rel(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) + +#define mi_atomic_add_relaxed(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_sub_relaxed(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_add_acq_rel(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_sub_acq_rel(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_and_acq_rel(p,x) mi_atomic(fetch_and_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_or_acq_rel(p,x) mi_atomic(fetch_or_explicit)(p,x,mi_memory_order(acq_rel)) + +#define mi_atomic_increment_relaxed(p) mi_atomic_add_relaxed(p,(uintptr_t)1) +#define mi_atomic_decrement_relaxed(p) mi_atomic_sub_relaxed(p,(uintptr_t)1) +#define mi_atomic_increment_acq_rel(p) mi_atomic_add_acq_rel(p,(uintptr_t)1) +#define mi_atomic_decrement_acq_rel(p) mi_atomic_sub_acq_rel(p,(uintptr_t)1) + +static inline void mi_atomic_yield(void); +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add); +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); + + +#if defined(__cplusplus) || !defined(_MSC_VER) + +// In C++/C11 atomics we have polymorphic atomics so can use the typed `ptr` variants (where `tp` is the type of atomic value) +// We use these macros so we can provide a typed wrapper in MSVC in C compilation mode as well +#define mi_atomic_load_ptr_acquire(tp,p) mi_atomic_load_acquire(p) +#define mi_atomic_load_ptr_relaxed(tp,p) mi_atomic_load_relaxed(p) + +// In C++ we need to add casts to help resolve templates if NULL is passed +#if defined(__cplusplus) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,(tp*)x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,(tp*)x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,(tp*)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,(tp*)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,(tp*)x) +#else +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,x) +#endif + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile int64_t* p, int64_t add) { + return mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed)); +} +static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) { + int64_t current = mi_atomic_load_relaxed((_Atomic(int64_t)*)p); + while (current < x && !mi_atomic_cas_weak_release((_Atomic(int64_t)*)p, ¤t, x)) { /* nothing */ }; +} + +// Used by timers +#define mi_atomic_loadi64_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) + + + +#elif defined(_MSC_VER) + +// MSVC C compilation wrapper that uses Interlocked operations to model C11 atomics. +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifdef _WIN64 +typedef LONG64 msc_intptr_t; +#define MI_64(f) f##64 +#else +typedef LONG msc_intptr_t; +#define MI_64(f) f +#endif + +typedef enum mi_memory_order_e { + mi_memory_order_relaxed, + mi_memory_order_consume, + mi_memory_order_acquire, + mi_memory_order_release, + mi_memory_order_acq_rel, + mi_memory_order_seq_cst +} mi_memory_order; + +static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add); +} +static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub)); +} +static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + (void)(mo1); (void)(mo2); + uintptr_t read = (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected)); + if (read == *expected) { + return true; + } + else { + *expected = read; + return false; + } +} +static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + return mi_atomic_compare_exchange_strong_explicit(p, expected, desired, mo1, mo2); +} +static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange); +} +static inline void mi_atomic_thread_fence(mi_memory_order mo) { + (void)(mo); + _Atomic(uintptr_t)x = 0; + mi_atomic_exchange_explicit(&x, 1, mo); +} +static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + return *p; +#else + uintptr_t x = *p; + if (mo > mi_memory_order_relaxed) { + while (!mi_atomic_compare_exchange_weak_explicit(p, &x, x, mo, mi_memory_order_relaxed)) { /* nothing */ }; + } + return x; +#endif +} +static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + *p = x; +#else + mi_atomic_exchange_explicit(p, x, mo); +#endif +} +static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_X64) + return *p; +#else + int64_t old = *p; + int64_t x = old; + while ((old = InterlockedCompareExchange64(p, x, old)) != x) { + x = old; + } + return x; +#endif +} +static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) { + (void)(mo); +#if defined(x_M_IX86) || defined(_M_X64) + *p = x; +#else + InterlockedExchange64(p, x); +#endif +} + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) { +#ifdef _WIN64 + return (int64_t)mi_atomic_addi((int64_t*)p, add); +#else + int64_t current; + int64_t sum; + do { + current = *p; + sum = current + add; + } while (_InterlockedCompareExchange64(p, sum, current) != current); + return current; +#endif +} +static inline void mi_atomic_maxi64_relaxed(volatile _Atomic(int64_t)*p, int64_t x) { + int64_t current; + do { + current = *p; + } while (current < x && _InterlockedCompareExchange64(p, x, current) != current); +} + +// The pointer macros cast to `uintptr_t`. +#define mi_atomic_load_ptr_acquire(tp,p) (tp*)mi_atomic_load_acquire((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_load_ptr_relaxed(tp,p) (tp*)mi_atomic_load_relaxed((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) (tp*)mi_atomic_exchange_release((_Atomic(uintptr_t)*)(p),(uintptr_t)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) (tp*)mi_atomic_exchange_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t)x) + +#define mi_atomic_loadi64_acquire(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(relaxed)) + + +#endif + + +// Atomically add a signed value; returns the previous value. +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add) { + return (intptr_t)mi_atomic_add_acq_rel((_Atomic(uintptr_t)*)p, (uintptr_t)add); +} + +// Atomically subtract a signed value; returns the previous value. +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) { + return (intptr_t)mi_atomic_addi(p, -sub); +} + +// Yield +#if defined(__cplusplus) +#include +static inline void mi_atomic_yield(void) { + std::this_thread::yield(); +} +#elif defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +static inline void mi_atomic_yield(void) { + YieldProcessor(); +} +#elif (defined(__GNUC__) || defined(__clang__)) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)) +#if defined(__x86_64__) || defined(__i386__) +static inline void mi_atomic_yield(void) { + __asm__ volatile ("pause" ::: "memory"); +} +#elif defined(__arm__) || defined(__aarch64__) +static inline void mi_atomic_yield(void) { + __asm__ volatile("yield"); +} +#endif +#elif defined(__wasi__) +#include +static inline void mi_atomic_yield(void) { + sched_yield(); +} +#else +#include +static inline void mi_atomic_yield(void) { + sleep(0); +} +#endif + + +#endif // __MIMALLOC_ATOMIC_H \ No newline at end of file diff --git a/deps/mimalloc/include/mimalloc-internal.h b/deps/mimalloc/include/mimalloc-internal.h new file mode 100644 index 000000000..145f6f921 --- /dev/null +++ b/deps/mimalloc/include/mimalloc-internal.h @@ -0,0 +1,748 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_INTERNAL_H +#define MIMALLOC_INTERNAL_H + +#include "mimalloc-types.h" + +#if (MI_DEBUG>0) +#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__) +#else +#define mi_trace_message(...) +#endif + +#define MI_CACHE_LINE 64 +#if defined(_MSC_VER) +#pragma warning(disable:4127) // suppress constant conditional warning (due to MI_SECURE paths) +#define mi_decl_noinline __declspec(noinline) +#define mi_decl_thread __declspec(thread) +#define mi_decl_cache_align __declspec(align(MI_CACHE_LINE)) +#elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc +#define mi_decl_noinline __attribute__((noinline)) +#define mi_decl_thread __thread +#define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE))) +#else +#define mi_decl_noinline +#define mi_decl_thread __thread // hope for the best :-) +#define mi_decl_cache_align +#endif + + +// "options.c" +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message); +void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...); +void _mi_warning_message(const char* fmt, ...); +void _mi_verbose_message(const char* fmt, ...); +void _mi_trace_message(const char* fmt, ...); +void _mi_options_init(void); +void _mi_error_message(int err, const char* fmt, ...); + +// random.c +void _mi_random_init(mi_random_ctx_t* ctx); +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx); +uintptr_t _mi_random_next(mi_random_ctx_t* ctx); +uintptr_t _mi_heap_random_next(mi_heap_t* heap); +uintptr_t _os_random_weak(uintptr_t extra_seed); +static inline uintptr_t _mi_random_shuffle(uintptr_t x); + +// init.c +extern mi_stats_t _mi_stats_main; +extern const mi_page_t _mi_page_empty; +bool _mi_is_main_thread(void); +bool _mi_preloading(); // true while the C runtime is not ready + +// os.c +size_t _mi_os_page_size(void); +void _mi_os_init(void); // called from process init +void* _mi_os_alloc(size_t size, mi_stats_t* stats); // to allocate thread local data +void _mi_os_free(void* p, size_t size, mi_stats_t* stats); // to free thread local data +size_t _mi_os_good_alloc_size(size_t size); + +// memory.c +void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld); +void _mi_mem_free(void* p, size_t size, size_t id, bool fully_committed, bool any_reset, mi_os_tld_t* tld); + +bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld); +bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld); +bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld); +bool _mi_mem_protect(void* addr, size_t size); +bool _mi_mem_unprotect(void* addr, size_t size); + +void _mi_mem_collect(mi_os_tld_t* tld); + +// "segment.c" +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld); +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size); // page start for any page +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); + +void _mi_segment_thread_collect(mi_segments_tld_t* tld); +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld); +void _mi_abandoned_await_readers(void); + + + +// "page.c" +void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc; + +void _mi_page_retire(mi_page_t* page); // free the page if there are no other pages with many free blocks +void _mi_page_unfull(mi_page_t* page); +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... +void _mi_heap_delayed_free(mi_heap_t* heap); +void _mi_heap_collect_retired(mi_heap_t* heap, bool force); + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); +void _mi_deferred_free(mi_heap_t* heap, bool force); + +void _mi_page_free_collect(mi_page_t* page,bool force); +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments + +size_t _mi_bin_size(uint8_t bin); // for stats +uint8_t _mi_bin(size_t size); // for stats +uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD in "os.c" + +// "heap.c" +void _mi_heap_destroy_pages(mi_heap_t* heap); +void _mi_heap_collect_abandon(mi_heap_t* heap); +void _mi_heap_set_default_direct(mi_heap_t* heap); + +// "stats.c" +void _mi_stats_done(mi_stats_t* stats); + +mi_msecs_t _mi_clock_now(void); +mi_msecs_t _mi_clock_end(mi_msecs_t start); +mi_msecs_t _mi_clock_start(void); + +// "alloc.c" +void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept; // called from `_mi_malloc_generic` +void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero); +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero); +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p); +bool _mi_free_delayed_block(mi_block_t* block); +void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size); + +#if MI_DEBUG>1 +bool _mi_page_is_valid(mi_page_t* page); +#endif + + +// ------------------------------------------------------ +// Branches +// ------------------------------------------------------ + +#if defined(__GNUC__) || defined(__clang__) +#define mi_unlikely(x) __builtin_expect((x),0) +#define mi_likely(x) __builtin_expect((x),1) +#else +#define mi_unlikely(x) (x) +#define mi_likely(x) (x) +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + + +/* ----------------------------------------------------------- + Error codes passed to `_mi_fatal_error` + All are recoverable but EFAULT is a serious error and aborts by default in secure mode. + For portability define undefined error codes using common Unix codes: + +----------------------------------------------------------- */ +#include +#ifndef EAGAIN // double free +#define EAGAIN (11) +#endif +#ifndef ENOMEM // out of memory +#define ENOMEM (12) +#endif +#ifndef EFAULT // corrupted free-list or meta-data +#define EFAULT (14) +#endif +#ifndef EINVAL // trying to free an invalid pointer +#define EINVAL (22) +#endif +#ifndef EOVERFLOW // count*size overflow +#define EOVERFLOW (75) +#endif + + +/* ----------------------------------------------------------- + Inlined definitions +----------------------------------------------------------- */ +#define UNUSED(x) (void)(x) +#if (MI_DEBUG>0) +#define UNUSED_RELEASE(x) +#else +#define UNUSED_RELEASE(x) UNUSED(x) +#endif + +#define MI_INIT4(x) x(),x(),x(),x() +#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x) +#define MI_INIT16(x) MI_INIT8(x),MI_INIT8(x) +#define MI_INIT32(x) MI_INIT16(x),MI_INIT16(x) +#define MI_INIT64(x) MI_INIT32(x),MI_INIT32(x) +#define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x) +#define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x) + + +// Is `x` a power of two? (0 is considered a power of two) +static inline bool _mi_is_power_of_two(uintptr_t x) { + return ((x & (x - 1)) == 0); +} + +// Align upwards +static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) { + mi_assert_internal(alignment != 0); + uintptr_t mask = alignment - 1; + if ((alignment & mask) == 0) { // power of two? + return ((sz + mask) & ~mask); + } + else { + return (((sz + mask)/alignment)*alignment); + } +} + +// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`. +static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) { + mi_assert_internal(divider != 0); + return (divider == 0 ? size : ((size + divider - 1) / divider)); +} + +// Is memory zero initialized? +static inline bool mi_mem_is_zero(void* p, size_t size) { + for (size_t i = 0; i < size; i++) { + if (((uint8_t*)p)[i] != 0) return false; + } + return true; +} + +// Align a byte size to a size in _machine words_, +// i.e. byte size == `wsize*sizeof(void*)`. +static inline size_t _mi_wsize_from_size(size_t size) { + mi_assert_internal(size <= SIZE_MAX - sizeof(uintptr_t)); + return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); +} + +// Does malloc satisfy the alignment constraints already? +static inline bool mi_malloc_satisfies_alignment(size_t alignment, size_t size) { + return (alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2))); +} + +// Overflow detecting multiply +#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5 +#include // UINT_MAX, ULONG_MAX +#if defined(_CLOCK_T) // for Illumos +#undef _CLOCK_T +#endif +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { + #if (SIZE_MAX == UINT_MAX) + return __builtin_umul_overflow(count, size, total); + #elif (SIZE_MAX == ULONG_MAX) + return __builtin_umull_overflow(count, size, total); + #else + return __builtin_umulll_overflow(count, size, total); + #endif +} +#else /* __builtin_umul_overflow is unavailable */ +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { + #define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX) + *total = count * size; + return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW) + && size > 0 && (SIZE_MAX / size) < count); +} +#endif + +// Safe multiply `count*size` into `total`; return `true` on overflow. +static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* total) { + if (count==1) { // quick check for the case where count is one (common for C++ allocators) + *total = size; + return false; + } + else if (mi_unlikely(mi_mul_overflow(count, size, total))) { + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu * %zu bytes)\n", count, size); + *total = SIZE_MAX; + return true; + } + else return false; +} + + +/* ---------------------------------------------------------------------------------------- +The thread local default heap: `_mi_get_default_heap` returns the thread local heap. +On most platforms (Windows, Linux, FreeBSD, NetBSD, etc), this just returns a +__thread local variable (`_mi_heap_default`). With the initial-exec TLS model this ensures +that the storage will always be available (allocated on the thread stacks). +On some platforms though we cannot use that when overriding `malloc` since the underlying +TLS implementation (or the loader) will call itself `malloc` on a first access and recurse. +We try to circumvent this in an efficient way: +- macOSX : we use an unused TLS slot from the OS allocated slots (MI_TLS_SLOT). On OSX, the + loader itself calls `malloc` even before the modules are initialized. +- OpenBSD: we use an unused slot from the pthread block (MI_TLS_PTHREAD_SLOT_OFS). +- DragonFly: not yet working. +------------------------------------------------------------------------------------------- */ + +extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap +extern bool _mi_process_is_initialized; +mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing heap + +#if defined(MI_MALLOC_OVERRIDE) +#if defined(__MACH__) // OSX +#define MI_TLS_SLOT 89 // seems unused? +// other possible unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89) +// see +#elif defined(__OpenBSD__) +// use end bytes of a name; goes wrong if anyone uses names > 23 characters (ptrhread specifies 16) +// see +#define MI_TLS_PTHREAD_SLOT_OFS (6*sizeof(int) + 4*sizeof(void*) + 24) +#elif defined(__DragonFly__) +#warning "mimalloc is not working correctly on DragonFly yet." +#define MI_TLS_PTHREAD_SLOT_OFS (4 + 1*sizeof(void*)) // offset `uniqueid` (also used by gdb?) +#endif +#endif + +#if defined(MI_TLS_SLOT) +static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept; // forward declaration +#elif defined(MI_TLS_PTHREAD_SLOT_OFS) +#include +static inline mi_heap_t** mi_tls_pthread_heap_slot(void) { + pthread_t self = pthread_self(); + #if defined(__DragonFly__) + if (self==NULL) { + static mi_heap_t* pheap_main = _mi_heap_main_get(); + return &pheap_main; + } + #endif + return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS); +} +#elif defined(MI_TLS_PTHREAD) +#include +extern pthread_key_t _mi_heap_default_key; +#else +extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from +#endif + +static inline mi_heap_t* mi_get_default_heap(void) { +#if defined(MI_TLS_SLOT) + mi_heap_t* heap = (mi_heap_t*)mi_tls_slot(MI_TLS_SLOT); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#elif defined(MI_TLS_PTHREAD_SLOT_OFS) + mi_heap_t* heap = *mi_tls_pthread_heap_slot(); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#elif defined(MI_TLS_PTHREAD) + mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? _mi_heap_main_get() : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key)); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#else + #if defined(MI_TLS_RECURSE_GUARD) + if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get(); + #endif + return _mi_heap_default; +#endif +} + +static inline bool mi_heap_is_default(const mi_heap_t* heap) { + return (heap == mi_get_default_heap()); +} + +static inline bool mi_heap_is_backing(const mi_heap_t* heap) { + return (heap->tld->heap_backing == heap); +} + +static inline bool mi_heap_is_initialized(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + return (heap != &_mi_heap_empty); +} + +static inline uintptr_t _mi_ptr_cookie(const void* p) { + extern mi_heap_t _mi_heap_main; + mi_assert_internal(_mi_heap_main.cookie != 0); + return ((uintptr_t)p ^ _mi_heap_main.cookie); +} + +/* ----------------------------------------------------------- + Pages +----------------------------------------------------------- */ + +static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) { + mi_assert_internal(size <= (MI_SMALL_SIZE_MAX + MI_PADDING_SIZE)); + const size_t idx = _mi_wsize_from_size(size); + mi_assert_internal(idx < MI_PAGES_DIRECT); + return heap->pages_free_direct[idx]; +} + +// Get the page belonging to a certain size class +static inline mi_page_t* _mi_get_free_small_page(size_t size) { + return _mi_heap_get_free_small_page(mi_get_default_heap(), size); +} + +// Segment that contains the pointer +static inline mi_segment_t* _mi_ptr_segment(const void* p) { + // mi_assert_internal(p != NULL); + return (mi_segment_t*)((uintptr_t)p & ~MI_SEGMENT_MASK); +} + +// Segment belonging to a page +static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) { + mi_segment_t* segment = _mi_ptr_segment(page); + mi_assert_internal(segment == NULL || page == &segment->pages[page->segment_idx]); + return segment; +} + +// used internally +static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) { + // if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages + ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment; + mi_assert_internal(diff >= 0 && (size_t)diff < MI_SEGMENT_SIZE); + uintptr_t idx = (uintptr_t)diff >> segment->page_shift; + mi_assert_internal(idx < segment->capacity); + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0); + return idx; +} + +// Get the page containing the pointer +static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) { + uintptr_t idx = _mi_segment_page_idx_of(segment, p); + return &((mi_segment_t*)segment)->pages[idx]; +} + +// Quick page start for initialized pages +static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { + const size_t bsize = page->xblock_size; + mi_assert_internal(bsize > 0 && (bsize%sizeof(void*)) == 0); + return _mi_segment_page_start(segment, page, bsize, page_size, NULL); +} + +// Get the page containing the pointer +static inline mi_page_t* _mi_ptr_page(void* p) { + return _mi_segment_page_of(_mi_ptr_segment(p), p); +} + +// Get the block size of a page (special cased for huge objects) +static inline size_t mi_page_block_size(const mi_page_t* page) { + const size_t bsize = page->xblock_size; + mi_assert_internal(bsize > 0); + if (mi_likely(bsize < MI_HUGE_BLOCK_SIZE)) { + return bsize; + } + else { + size_t psize; + _mi_segment_page_start(_mi_page_segment(page), page, bsize, &psize, NULL); + return psize; + } +} + +// Get the usable block size of a page without fixed padding. +// This may still include internal padding due to alignment and rounding up size classes. +static inline size_t mi_page_usable_block_size(const mi_page_t* page) { + return mi_page_block_size(page) - MI_PADDING_SIZE; +} + + +// Thread free access +static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) { + return (mi_block_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & ~3); +} + +static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) { + return (mi_delayed_t)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & 3); +} + +// Heap access +static inline mi_heap_t* mi_page_heap(const mi_page_t* page) { + return (mi_heap_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xheap)); +} + +static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) { + mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING); + mi_atomic_store_release(&page->xheap,(uintptr_t)heap); +} + +// Thread free flag helpers +static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) { + return (mi_block_t*)(tf & ~0x03); +} +static inline mi_delayed_t mi_tf_delayed(mi_thread_free_t tf) { + return (mi_delayed_t)(tf & 0x03); +} +static inline mi_thread_free_t mi_tf_make(mi_block_t* block, mi_delayed_t delayed) { + return (mi_thread_free_t)((uintptr_t)block | (uintptr_t)delayed); +} +static inline mi_thread_free_t mi_tf_set_delayed(mi_thread_free_t tf, mi_delayed_t delayed) { + return mi_tf_make(mi_tf_block(tf),delayed); +} +static inline mi_thread_free_t mi_tf_set_block(mi_thread_free_t tf, mi_block_t* block) { + return mi_tf_make(block, mi_tf_delayed(tf)); +} + +// are all blocks in a page freed? +// note: needs up-to-date used count, (as the `xthread_free` list may not be empty). see `_mi_page_collect_free`. +static inline bool mi_page_all_free(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->used == 0); +} + +// are there any available blocks? +static inline bool mi_page_has_any_available(const mi_page_t* page) { + mi_assert_internal(page != NULL && page->reserved > 0); + return (page->used < page->reserved || (mi_page_thread_free(page) != NULL)); +} + +// are there immediately available blocks, i.e. blocks available on the free list. +static inline bool mi_page_immediate_available(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->free != NULL); +} + +// is more than 7/8th of a page in use? +static inline bool mi_page_mostly_used(const mi_page_t* page) { + if (page==NULL) return true; + uint16_t frac = page->reserved / 8U; + return (page->reserved - page->used <= frac); +} + +static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) { + return &((mi_heap_t*)heap)->pages[_mi_bin(size)]; +} + + + +//----------------------------------------------------------- +// Page flags +//----------------------------------------------------------- +static inline bool mi_page_is_in_full(const mi_page_t* page) { + return page->flags.x.in_full; +} + +static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) { + page->flags.x.in_full = in_full; +} + +static inline bool mi_page_has_aligned(const mi_page_t* page) { + return page->flags.x.has_aligned; +} + +static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { + page->flags.x.has_aligned = has_aligned; +} + + +/* ------------------------------------------------------------------- +Encoding/Decoding the free list next pointers + +This is to protect against buffer overflow exploits where the +free list is mutated. Many hardened allocators xor the next pointer `p` +with a secret key `k1`, as `p^k1`. This prevents overwriting with known +values but might be still too weak: if the attacker can guess +the pointer `p` this can reveal `k1` (since `p^k1^p == k1`). +Moreover, if multiple blocks can be read as well, the attacker can +xor both as `(p1^k1) ^ (p2^k1) == p1^p2` which may reveal a lot +about the pointers (and subsequently `k1`). + +Instead mimalloc uses an extra key `k2` and encodes as `((p^k2)<<> (MI_INTPTR_BITS - shift)))); +} +static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) { + shift %= MI_INTPTR_BITS; + return (shift==0 ? x : ((x >> shift) | (x << (MI_INTPTR_BITS - shift)))); +} + +static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) { + void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]); + return (mi_unlikely(p==null) ? NULL : p); +} + +static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) { + uintptr_t x = (uintptr_t)(mi_unlikely(p==NULL) ? null : p); + return mi_rotl(x ^ keys[1], keys[0]) + keys[0]; +} + +static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) { + #ifdef MI_ENCODE_FREELIST + return (mi_block_t*)mi_ptr_decode(null, block->next, keys); + #else + UNUSED(keys); UNUSED(null); + return (mi_block_t*)block->next; + #endif +} + +static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) { + #ifdef MI_ENCODE_FREELIST + block->next = mi_ptr_encode(null, next, keys); + #else + UNUSED(keys); UNUSED(null); + block->next = (mi_encoded_t)next; + #endif +} + +static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) { + #ifdef MI_ENCODE_FREELIST + mi_block_t* next = mi_block_nextx(page,block,page->keys); + // check for free list corruption: is `next` at least in the same page? + // TODO: check if `next` is `page->block_size` aligned? + if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) { + _mi_error_message(EFAULT, "corrupted free list entry of size %zub at %p: value 0x%zx\n", mi_page_block_size(page), block, (uintptr_t)next); + next = NULL; + } + return next; + #else + UNUSED(page); + return mi_block_nextx(page,block,NULL); + #endif +} + +static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) { + #ifdef MI_ENCODE_FREELIST + mi_block_set_nextx(page,block,next, page->keys); + #else + UNUSED(page); + mi_block_set_nextx(page,block,next,NULL); + #endif +} + +// ------------------------------------------------------------------- +// Fast "random" shuffle +// ------------------------------------------------------------------- + +static inline uintptr_t _mi_random_shuffle(uintptr_t x) { + if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros +#if (MI_INTPTR_SIZE==8) + // by Sebastiano Vigna, see: + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9UL; + x ^= x >> 27; + x *= 0x94d049bb133111ebUL; + x ^= x >> 31; +#elif (MI_INTPTR_SIZE==4) + // by Chris Wellons, see: + x ^= x >> 16; + x *= 0x7feb352dUL; + x ^= x >> 15; + x *= 0x846ca68bUL; + x ^= x >> 16; +#endif + return x; +} + +// ------------------------------------------------------------------- +// Optimize numa node access for the common case (= one node) +// ------------------------------------------------------------------- + +int _mi_os_numa_node_get(mi_os_tld_t* tld); +size_t _mi_os_numa_node_count_get(void); + +extern size_t _mi_numa_node_count; +static inline int _mi_os_numa_node(mi_os_tld_t* tld) { + if (mi_likely(_mi_numa_node_count == 1)) return 0; + else return _mi_os_numa_node_get(tld); +} +static inline size_t _mi_os_numa_node_count(void) { + if (mi_likely(_mi_numa_node_count>0)) return _mi_numa_node_count; + else return _mi_os_numa_node_count_get(); +} + + +// ------------------------------------------------------------------- +// Getting the thread id should be performant as it is called in the +// fast path of `_mi_free` and we specialize for various platforms. +// ------------------------------------------------------------------- +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + // Windows: works on Intel and ARM in both 32- and 64-bit + return (uintptr_t)NtCurrentTeb(); +} + +#elif defined(__GNUC__) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)) + +// TLS register on x86 is in the FS or GS register, see: https://akkadia.org/drepper/tls.pdf +static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept { + void* res; + const size_t ofs = (slot*sizeof(void*)); +#if defined(__i386__) + __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + res = tcb[slot]; +#elif defined(__aarch64__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + res = tcb[slot]; +#endif + return res; +} + +// setting is only used on macOSX for now +static inline void mi_tls_slot_set(size_t slot, void* value) mi_attr_noexcept { + const size_t ofs = (slot*sizeof(void*)); +#if defined(__i386__) + __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("movq %1,%%fs:%1" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + tcb[slot] = value; +#elif defined(__aarch64__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + tcb[slot] = value; +#endif +} + +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + // in all our targets, slot 0 is the pointer to the thread control block + return (uintptr_t)mi_tls_slot(0); +} +#else +// otherwise use standard C +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + return (uintptr_t)&_mi_heap_default; +} +#endif + + +#endif diff --git a/deps/mimalloc/include/mimalloc-new-delete.h b/deps/mimalloc/include/mimalloc-new-delete.h new file mode 100644 index 000000000..fded0c04f --- /dev/null +++ b/deps/mimalloc/include/mimalloc-new-delete.h @@ -0,0 +1,52 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_NEW_DELETE_H +#define MIMALLOC_NEW_DELETE_H + +// ---------------------------------------------------------------------------- +// This header provides convenient overrides for the new and +// delete operations in C++. +// +// This header should be included in only one source file! +// +// On Windows, or when linking dynamically with mimalloc, these +// can be more performant than the standard new-delete operations. +// See +// --------------------------------------------------------------------------- +#if defined(__cplusplus) + #include + #include + + void operator delete(void* p) noexcept { mi_free(p); }; + void operator delete[](void* p) noexcept { mi_free(p); }; + + void* operator new(std::size_t n) noexcept(false) { return mi_new(n); } + void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); } + + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); }; + void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); }; + #endif + + #if (__cplusplus > 201402L || defined(__cpp_aligned_new)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + #endif +#endif + +#endif // MIMALLOC_NEW_DELETE_H diff --git a/deps/mimalloc/include/mimalloc-override.h b/deps/mimalloc/include/mimalloc-override.h new file mode 100644 index 000000000..201fb8b49 --- /dev/null +++ b/deps/mimalloc/include/mimalloc-override.h @@ -0,0 +1,66 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_OVERRIDE_H +#define MIMALLOC_OVERRIDE_H + +/* ---------------------------------------------------------------------------- +This header can be used to statically redirect malloc/free and new/delete +to the mimalloc variants. This can be useful if one can include this file on +each source file in a project (but be careful when using external code to +not accidentally mix pointers from different allocators). +-----------------------------------------------------------------------------*/ + +#include + +// Standard C allocation +#define malloc(n) mi_malloc(n) +#define calloc(n,c) mi_calloc(n,c) +#define realloc(p,n) mi_realloc(p,n) +#define free(p) mi_free(p) + +#define strdup(s) mi_strdup(s) +#define strndup(s) mi_strndup(s) +#define realpath(f,n) mi_realpath(f,n) + +// Microsoft extensions +#define _expand(p,n) mi_expand(p,n) +#define _msize(p) mi_usable_size(p) +#define _recalloc(p,n,c) mi_recalloc(p,n,c) + +#define _strdup(s) mi_strdup(s) +#define _strndup(s) mi_strndup(s) +#define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) +#define _mbsdup(s) mi_mbsdup(s) +#define _dupenv_s(b,n,v) mi_dupenv_s(b,n,v) +#define _wdupenv_s(b,n,v) mi_wdupenv_s((unsigned short*)(b),n,(const unsigned short*)(v)) + +// Various Posix and Unix variants +#define reallocf(p,n) mi_reallocf(p,n) +#define malloc_size(p) mi_usable_size(p) +#define malloc_usable_size(p) mi_usable_size(p) +#define cfree(p) mi_free(p) + +#define valloc(n) mi_valloc(n) +#define pvalloc(n) mi_pvalloc(n) +#define reallocarray(p,s,n) mi_reallocarray(p,s,n) +#define memalign(a,n) mi_memalign(a,n) +#define aligned_alloc(a,n) mi_aligned_alloc(a,n) +#define posix_memalign(p,a,n) mi_posix_memalign(p,a,n) +#define _posix_memalign(p,a,n) mi_posix_memalign(p,a,n) + +// Microsoft aligned variants +#define _aligned_malloc(n,a) mi_malloc_aligned(n,a) +#define _aligned_realloc(p,n,a) mi_realloc_aligned(p,n,a) +#define _aligned_recalloc(p,s,n,a) mi_aligned_recalloc(p,s,n,a) +#define _aligned_msize(p,a,o) mi_usable_size(p) +#define _aligned_free(p) mi_free(p) +#define _aligned_offset_malloc(n,a,o) mi_malloc_aligned_at(n,a,o) +#define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o) +#define _aligned_offset_recalloc(p,s,n,a,o) mi_recalloc_aligned_at(p,s,n,a,o) + +#endif // MIMALLOC_OVERRIDE_H diff --git a/deps/mimalloc/include/mimalloc-types.h b/deps/mimalloc/include/mimalloc-types.h new file mode 100644 index 000000000..d9bd14eb8 --- /dev/null +++ b/deps/mimalloc/include/mimalloc-types.h @@ -0,0 +1,498 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_TYPES_H +#define MIMALLOC_TYPES_H + +#include // ptrdiff_t +#include // uintptr_t, uint16_t, etc +#include // _Atomic + +#ifdef _MSC_VER +#pragma warning(disable:4214) // bitfield is not int +#endif + +// Minimal alignment necessary. On most platforms 16 bytes are needed +// due to SSE registers for example. This must be at least `MI_INTPTR_SIZE` +#ifndef MI_MAX_ALIGN_SIZE +#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t) +#endif + +// ------------------------------------------------------ +// Variants +// ------------------------------------------------------ + +// Define NDEBUG in the release version to disable assertions. +// #define NDEBUG + +// Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance). +// #define MI_STAT 1 + +// Define MI_SECURE to enable security mitigations +// #define MI_SECURE 1 // guard page around metadata +// #define MI_SECURE 2 // guard page around each mimalloc page +// #define MI_SECURE 3 // encode free lists (detect corrupted free list (buffer overflow), and invalid pointer free) +// #define MI_SECURE 4 // checks for double free. (may be more expensive) + +#if !defined(MI_SECURE) +#define MI_SECURE 0 +#endif + +// Define MI_DEBUG for debug mode +// #define MI_DEBUG 1 // basic assertion checks and statistics, check double free, corrupted free list, and invalid pointer free. +// #define MI_DEBUG 2 // + internal assertion checks +// #define MI_DEBUG 3 // + extensive internal invariant checking (cmake -DMI_DEBUG_FULL=ON) +#if !defined(MI_DEBUG) +#if !defined(NDEBUG) || defined(_DEBUG) +#define MI_DEBUG 2 +#else +#define MI_DEBUG 0 +#endif +#endif + +// Reserve extra padding at the end of each block to be more resilient against heap block overflows. +// The padding can detect byte-precise buffer overflow on free. +#if !defined(MI_PADDING) && (MI_DEBUG>=1) +#define MI_PADDING 1 +#endif + + +// Encoded free lists allow detection of corrupted free lists +// and can detect buffer overflows, modify after free, and double `free`s. +#if (MI_SECURE>=3 || MI_DEBUG>=1 || MI_PADDING > 0) +#define MI_ENCODE_FREELIST 1 +#endif + +// ------------------------------------------------------ +// Platform specific values +// ------------------------------------------------------ + +// ------------------------------------------------------ +// Size of a pointer. +// We assume that `sizeof(void*)==sizeof(intptr_t)` +// and it holds for all platforms we know of. +// +// However, the C standard only requires that: +// p == (void*)((intptr_t)p)) +// but we also need: +// i == (intptr_t)((void*)i) +// or otherwise one might define an intptr_t type that is larger than a pointer... +// ------------------------------------------------------ + +#if INTPTR_MAX == 9223372036854775807LL +# define MI_INTPTR_SHIFT (3) +#elif INTPTR_MAX == 2147483647LL +# define MI_INTPTR_SHIFT (2) +#else +#error platform must be 32 or 64 bits +#endif + +#define MI_INTPTR_SIZE (1<= 655360) +#error "define more bins" +#endif + +// Used as a special value to encode block sizes in 32 bits. +#define MI_HUGE_BLOCK_SIZE ((uint32_t)MI_HUGE_OBJ_SIZE_MAX) + +// The free lists use encoded next fields +// (Only actually encodes when MI_ENCODED_FREELIST is defined.) +typedef uintptr_t mi_encoded_t; + +// free lists contain blocks +typedef struct mi_block_s { + mi_encoded_t next; +} mi_block_t; + + +// The delayed flags are used for efficient multi-threaded free-ing +typedef enum mi_delayed_e { + MI_USE_DELAYED_FREE = 0, // push on the owning heap thread delayed list + MI_DELAYED_FREEING = 1, // temporary: another thread is accessing the owning heap + MI_NO_DELAYED_FREE = 2, // optimize: push on page local thread free queue if another block is already in the heap thread delayed free list + MI_NEVER_DELAYED_FREE = 3 // sticky, only resets on page reclaim +} mi_delayed_t; + + +// The `in_full` and `has_aligned` page flags are put in a union to efficiently +// test if both are false (`full_aligned == 0`) in the `mi_free` routine. +#if !MI_TSAN +typedef union mi_page_flags_s { + uint8_t full_aligned; + struct { + uint8_t in_full : 1; + uint8_t has_aligned : 1; + } x; +} mi_page_flags_t; +#else +// under thread sanitizer, use a byte for each flag to suppress warning, issue #130 +typedef union mi_page_flags_s { + uint16_t full_aligned; + struct { + uint8_t in_full; + uint8_t has_aligned; + } x; +} mi_page_flags_t; +#endif + +// Thread free list. +// We use the bottom 2 bits of the pointer for mi_delayed_t flags +typedef uintptr_t mi_thread_free_t; + +// A page contains blocks of one specific size (`block_size`). +// Each page has three list of free blocks: +// `free` for blocks that can be allocated, +// `local_free` for freed blocks that are not yet available to `mi_malloc` +// `thread_free` for freed blocks by other threads +// The `local_free` and `thread_free` lists are migrated to the `free` list +// when it is exhausted. The separate `local_free` list is necessary to +// implement a monotonic heartbeat. The `thread_free` list is needed for +// avoiding atomic operations in the common case. +// +// +// `used - |thread_free|` == actual blocks that are in use (alive) +// `used - |thread_free| + |free| + |local_free| == capacity` +// +// We don't count `freed` (as |free|) but use `used` to reduce +// the number of memory accesses in the `mi_page_all_free` function(s). +// +// Notes: +// - Access is optimized for `mi_free` and `mi_page_alloc` (in `alloc.c`) +// - Using `uint16_t` does not seem to slow things down +// - The size is 8 words on 64-bit which helps the page index calculations +// (and 10 words on 32-bit, and encoded free lists add 2 words. Sizes 10 +// and 12 are still good for address calculation) +// - To limit the structure size, the `xblock_size` is 32-bits only; for +// blocks > MI_HUGE_BLOCK_SIZE the size is determined from the segment page size +// - `thread_free` uses the bottom bits as a delayed-free flags to optimize +// concurrent frees where only the first concurrent free adds to the owning +// heap `thread_delayed_free` list (see `alloc.c:mi_free_block_mt`). +// The invariant is that no-delayed-free is only set if there is +// at least one block that will be added, or as already been added, to +// the owning heap `thread_delayed_free` list. This guarantees that pages +// will be freed correctly even if only other threads free blocks. +typedef struct mi_page_s { + // "owned" by the segment + uint8_t segment_idx; // index in the segment `pages` array, `page == &segment->pages[page->segment_idx]` + uint8_t segment_in_use:1; // `true` if the segment allocated this page + uint8_t is_reset:1; // `true` if the page memory was reset + uint8_t is_committed:1; // `true` if the page virtual memory is committed + uint8_t is_zero_init:1; // `true` if the page was zero initialized + + // layout like this to optimize access in `mi_malloc` and `mi_free` + uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear` + uint16_t reserved; // number of blocks reserved in memory + mi_page_flags_t flags; // `in_full` and `has_aligned` flags (8 bits) + uint8_t is_zero:1; // `true` if the blocks in the free list are zero initialized + uint8_t retire_expire:7; // expiration count for retired blocks + + mi_block_t* free; // list of available free blocks (`malloc` allocates from this list) + #ifdef MI_ENCODE_FREELIST + uintptr_t keys[2]; // two random keys to encode the free lists (see `_mi_block_next`) + #endif + uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`) + uint32_t xblock_size; // size available in each block (always `>0`) + + mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`) + _Atomic(mi_thread_free_t) xthread_free; // list of deferred free blocks freed by other threads + _Atomic(uintptr_t) xheap; + + struct mi_page_s* next; // next page owned by this thread with the same `block_size` + struct mi_page_s* prev; // previous page owned by this thread with the same `block_size` +} mi_page_t; + + + +typedef enum mi_page_kind_e { + MI_PAGE_SMALL, // small blocks go into 64kb pages inside a segment + MI_PAGE_MEDIUM, // medium blocks go into 512kb pages inside a segment + MI_PAGE_LARGE, // larger blocks go into a single page spanning a whole segment + MI_PAGE_HUGE // huge blocks (>512kb) are put into a single page in a segment of the exact size (but still 2mb aligned) +} mi_page_kind_t; + +// Segments are large allocated memory blocks (2mb on 64 bit) from +// the OS. Inside segments we allocated fixed size _pages_ that +// contain blocks. +typedef struct mi_segment_s { + // memory fields + size_t memid; // id for the os-level memory manager + bool mem_is_fixed; // `true` if we cannot decommit/reset/protect in this memory (i.e. when allocated using large OS pages) + bool mem_is_committed; // `true` if the whole segment is eagerly committed + + // segment fields + _Atomic(struct mi_segment_s*) abandoned_next; + struct mi_segment_s* next; // must be the first segment field after abandoned_next -- see `segment.c:segment_init` + struct mi_segment_s* prev; + + size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) + size_t abandoned_visits; // count how often this segment is visited in the abandoned list (to force reclaim it it is too long) + + size_t used; // count of pages in use (`used <= capacity`) + size_t capacity; // count of available pages (`#free + used`) + size_t segment_size; // for huge pages this may be different from `MI_SEGMENT_SIZE` + size_t segment_info_size;// space we are using from the first page for segment meta-data and possible guard pages. + uintptr_t cookie; // verify addresses in secure mode: `_mi_ptr_cookie(segment) == segment->cookie` + + // layout like this to optimize access in `mi_free` + size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`). + _Atomic(uintptr_t) thread_id; // unique id of the thread owning this segment + mi_page_kind_t page_kind; // kind of pages: small, large, or huge + mi_page_t pages[1]; // up to `MI_SMALL_PAGES_PER_SEGMENT` pages +} mi_segment_t; + + +// ------------------------------------------------------ +// Heaps +// Provide first-class heaps to allocate from. +// A heap just owns a set of pages for allocation and +// can only be allocate/reallocate from the thread that created it. +// Freeing blocks can be done from any thread though. +// Per thread, the segments are shared among its heaps. +// Per thread, there is always a default heap that is +// used for allocation; it is initialized to statically +// point to an empty heap to avoid initialization checks +// in the fast path. +// ------------------------------------------------------ + +// Thread local data +typedef struct mi_tld_s mi_tld_t; + +// Pages of a certain block size are held in a queue. +typedef struct mi_page_queue_s { + mi_page_t* first; + mi_page_t* last; + size_t block_size; +} mi_page_queue_t; + +#define MI_BIN_FULL (MI_BIN_HUGE+1) + +// Random context +typedef struct mi_random_cxt_s { + uint32_t input[16]; + uint32_t output[16]; + int output_available; +} mi_random_ctx_t; + + +// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows +#if (MI_PADDING) +typedef struct mi_padding_s { + uint32_t canary; // encoded block value to check validity of the padding (in case of overflow) + uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes) +} mi_padding_t; +#define MI_PADDING_SIZE (sizeof(mi_padding_t)) +#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE) +#else +#define MI_PADDING_SIZE 0 +#define MI_PADDING_WSIZE 0 +#endif + +#define MI_PAGES_DIRECT (MI_SMALL_WSIZE_MAX + MI_PADDING_WSIZE + 1) + + +// A heap owns a set of pages. +struct mi_heap_s { + mi_tld_t* tld; + mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. + mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") + _Atomic(mi_block_t*) thread_delayed_free; + uintptr_t thread_id; // thread this heap belongs too + uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`) + uintptr_t keys[2]; // two random keys used to encode the `thread_delayed_free` list + mi_random_ctx_t random; // random number context used for secure allocation + size_t page_count; // total number of pages in the `pages` queues. + size_t page_retired_min; // smallest retired index (retired pages are fully free, but still in the page queues) + size_t page_retired_max; // largest retired index into the `pages` array. + mi_heap_t* next; // list of heaps per thread + bool no_reclaim; // `true` if this heap should not reclaim abandoned pages +}; + + + +// ------------------------------------------------------ +// Debug +// ------------------------------------------------------ + +#define MI_DEBUG_UNINIT (0xD0) +#define MI_DEBUG_FREED (0xDF) +#define MI_DEBUG_PADDING (0xDE) + +#if (MI_DEBUG) +// use our own assertion to print without memory allocation +void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line, const char* func ); +#define mi_assert(expr) ((expr) ? (void)0 : _mi_assert_fail(#expr,__FILE__,__LINE__,__func__)) +#else +#define mi_assert(x) +#endif + +#if (MI_DEBUG>1) +#define mi_assert_internal mi_assert +#else +#define mi_assert_internal(x) +#endif + +#if (MI_DEBUG>2) +#define mi_assert_expensive mi_assert +#else +#define mi_assert_expensive(x) +#endif + +// ------------------------------------------------------ +// Statistics +// ------------------------------------------------------ + +#ifndef MI_STAT +#if (MI_DEBUG>0) +#define MI_STAT 2 +#else +#define MI_STAT 0 +#endif +#endif + +typedef struct mi_stat_count_s { + int64_t allocated; + int64_t freed; + int64_t peak; + int64_t current; +} mi_stat_count_t; + +typedef struct mi_stat_counter_s { + int64_t total; + int64_t count; +} mi_stat_counter_t; + +typedef struct mi_stats_s { + mi_stat_count_t segments; + mi_stat_count_t pages; + mi_stat_count_t reserved; + mi_stat_count_t committed; + mi_stat_count_t reset; + mi_stat_count_t page_committed; + mi_stat_count_t segments_abandoned; + mi_stat_count_t pages_abandoned; + mi_stat_count_t threads; + mi_stat_count_t huge; + mi_stat_count_t giant; + mi_stat_count_t malloc; + mi_stat_count_t segments_cache; + mi_stat_counter_t pages_extended; + mi_stat_counter_t mmap_calls; + mi_stat_counter_t commit_calls; + mi_stat_counter_t page_no_retire; + mi_stat_counter_t searches; + mi_stat_counter_t huge_count; + mi_stat_counter_t giant_count; +#if MI_STAT>1 + mi_stat_count_t normal[MI_BIN_HUGE+1]; +#endif +} mi_stats_t; + + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount); +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount); +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount); + +#if (MI_STAT) +#define mi_stat_increase(stat,amount) _mi_stat_increase( &(stat), amount) +#define mi_stat_decrease(stat,amount) _mi_stat_decrease( &(stat), amount) +#define mi_stat_counter_increase(stat,amount) _mi_stat_counter_increase( &(stat), amount) +#else +#define mi_stat_increase(stat,amount) (void)0 +#define mi_stat_decrease(stat,amount) (void)0 +#define mi_stat_counter_increase(stat,amount) (void)0 +#endif + +#define mi_heap_stat_increase(heap,stat,amount) mi_stat_increase( (heap)->tld->stats.stat, amount) +#define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount) + +// ------------------------------------------------------ +// Thread Local data +// ------------------------------------------------------ + +typedef int64_t mi_msecs_t; + +// Queue of segments +typedef struct mi_segment_queue_s { + mi_segment_t* first; + mi_segment_t* last; +} mi_segment_queue_t; + +// OS thread local data +typedef struct mi_os_tld_s { + size_t region_idx; // start point for next allocation + mi_stats_t* stats; // points to tld stats +} mi_os_tld_t; + +// Segments thread local data +typedef struct mi_segments_tld_s { + mi_segment_queue_t small_free; // queue of segments with free small pages + mi_segment_queue_t medium_free; // queue of segments with free medium pages + mi_page_queue_t pages_reset; // queue of freed pages that can be reset + size_t count; // current number of segments; + size_t peak_count; // peak number of segments + size_t current_size; // current size of all segments + size_t peak_size; // peak size of all segments + size_t cache_count; // number of segments in the cache + size_t cache_size; // total size of all segments in the cache + mi_segment_t* cache; // (small) cache of segments + mi_stats_t* stats; // points to tld stats + mi_os_tld_t* os; // points to os stats +} mi_segments_tld_t; + +// Thread local data +struct mi_tld_s { + unsigned long long heartbeat; // monotonic heartbeat count + bool recurse; // true if deferred was called; used to prevent infinite recursion. + mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) + mi_heap_t* heaps; // list of heaps in this thread (so we can abandon all when the thread terminates) + mi_segments_tld_t segments; // segment tld + mi_os_tld_t os; // os tld + mi_stats_t stats; // statistics +}; + +#endif diff --git a/deps/mimalloc/include/mimalloc.h b/deps/mimalloc/include/mimalloc.h new file mode 100644 index 000000000..254a7d9cd --- /dev/null +++ b/deps/mimalloc/include/mimalloc.h @@ -0,0 +1,429 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_H +#define MIMALLOC_H + +#define MI_MALLOC_VERSION 167 // major + 2 digits minor + +// ------------------------------------------------------ +// Compiler specific attributes +// ------------------------------------------------------ + +#ifdef __cplusplus + #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 + #define mi_attr_noexcept noexcept + #else + #define mi_attr_noexcept throw() + #endif +#else + #define mi_attr_noexcept +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201703) + #define mi_decl_nodiscard [[nodiscard]] +#elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl + #define mi_decl_nodiscard __attribute__((warn_unused_result)) +#elif (_MSC_VER >= 1700) + #define mi_decl_nodiscard _Check_return_ +#else + #define mi_decl_nodiscard +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) + #if !defined(MI_SHARED_LIB) + #define mi_decl_export + #elif defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __declspec(dllexport) + #else + #define mi_decl_export __declspec(dllimport) + #endif + #if defined(__MINGW32__) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #else + #if (_MSC_VER >= 1900) && !defined(__EDG__) + #define mi_decl_restrict __declspec(allocator) __declspec(restrict) + #else + #define mi_decl_restrict __declspec(restrict) + #endif + #define mi_attr_malloc + #endif + #define mi_cdecl __cdecl + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#elif defined(__GNUC__) // includes clang and icc + #define mi_cdecl // leads to warnings... __attribute__((cdecl)) + #define mi_decl_export __attribute__((visibility("default"))) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5) + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) + #elif defined(__INTEL_COMPILER) + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) + #else + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) __attribute__((alloc_align(p))) + #endif +#else + #define mi_cdecl + #define mi_decl_export + #define mi_decl_restrict + #define mi_attr_malloc + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#endif + +// ------------------------------------------------------ +// Includes +// ------------------------------------------------------ + +#include // size_t +#include // bool + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ +// Standard malloc interface +// ------------------------------------------------------ + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_export void mi_free(void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +// ------------------------------------------------------ +// Extended functionality +// ------------------------------------------------------ +#define MI_SMALL_WSIZE_MAX (128) +#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*)) + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Internals +// ------------------------------------------------------ + +typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg); +mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg); +mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_error_fun)(int err, void* arg); +mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg); + +mi_decl_export void mi_collect(bool force) mi_attr_noexcept; +mi_decl_export int mi_version(void) mi_attr_noexcept; +mi_decl_export void mi_stats_reset(void) mi_attr_noexcept; +mi_decl_export void mi_stats_merge(void) mi_attr_noexcept; +mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL +mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_done(void) mi_attr_noexcept; +mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, + size_t* current_rss, size_t* peak_rss, + size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept; + +// ------------------------------------------------------------------------------------- +// Aligned allocation +// Note that `alignment` always follows `size` for consistency with unaligned +// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`. +// ------------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); + + +// ------------------------------------------------------------------------------------- +// Heaps: first-class, but can only allocate from the same thread that created it. +// ------------------------------------------------------------------------------------- + +struct mi_heap_s; +typedef struct mi_heap_s mi_heap_t; + +mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void); +mi_decl_export void mi_heap_delete(mi_heap_t* heap); +mi_decl_export void mi_heap_destroy(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_get_default(void); +mi_decl_export mi_heap_t* mi_heap_get_backing(void); +mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); + + +// -------------------------------------------------------------------------------- +// Zero initialized re-allocation. +// Only valid on memory that was originally allocated with zero initialization too. +// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc. +// see +// -------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4); + + +// ------------------------------------------------------ +// Analysis +// ------------------------------------------------------ + +mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_check_owned(const void* p); + +// An area of heap space contains blocks of a single size. +typedef struct mi_heap_area_s { + void* blocks; // start of the area containing heap blocks + size_t reserved; // bytes reserved for this area (virtual) + size_t committed; // current available bytes for this area + size_t used; // bytes in use by allocated blocks + size_t block_size; // size in bytes of each block +} mi_heap_area_t; + +typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg); + +mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg); + +// Experimental +mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept; + +mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept; +mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept; + +// deprecated +mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Convenience +// ------------------------------------------------------ + +#define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp))) +#define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp))) +#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp))) +#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp))) +#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp))) +#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp))) + +#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp))) +#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp))) +#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp))) +#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp))) +#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp))) +#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp))) + + +// ------------------------------------------------------ +// Options, all `false` by default +// ------------------------------------------------------ + +typedef enum mi_option_e { + // stable options + mi_option_show_errors, + mi_option_show_stats, + mi_option_verbose, + // the following options are experimental + mi_option_eager_commit, + mi_option_eager_region_commit, + mi_option_reset_decommits, + mi_option_large_os_pages, // implies eager commit + mi_option_reserve_huge_os_pages, + mi_option_segment_cache, + mi_option_page_reset, + mi_option_abandoned_page_reset, + mi_option_segment_reset, + mi_option_eager_commit_delay, + mi_option_reset_delay, + mi_option_use_numa_nodes, + mi_option_os_tag, + mi_option_max_errors, + _mi_option_last +} mi_option_t; + + +mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option); +mi_decl_export void mi_option_enable(mi_option_t option); +mi_decl_export void mi_option_disable(mi_option_t option); +mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable); +mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable); + +mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option); +mi_decl_export void mi_option_set(mi_option_t option, long value); +mi_decl_export void mi_option_set_default(mi_option_t option, long value); + + +// ------------------------------------------------------------------------------------------------------- +// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions. +// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.) +// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing. +// ------------------------------------------------------------------------------------------------------- + +mi_decl_export void mi_cfree(void* p) mi_attr_noexcept; +mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept; + +mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); + +mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept; +mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept; + +mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept; +mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept; + +// The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`. +// (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception). +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(1, 2); +mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3); + +#ifdef __cplusplus +} +#endif + +// --------------------------------------------------------------------------------------------- +// Implement the C++ std::allocator interface for use in STL containers. +// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally) +// --------------------------------------------------------------------------------------------- +#ifdef __cplusplus + +#include // PTRDIFF_MAX +#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 +#include // std::true_type +#include // std::forward +#endif + +template struct mi_stl_allocator { + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef value_type* pointer; + typedef value_type const* const_pointer; + template struct rebind { typedef mi_stl_allocator other; }; + + mi_stl_allocator() mi_attr_noexcept = default; + mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default; + template mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept { } + mi_stl_allocator select_on_container_copy_construction() const { return *this; } + void deallocate(T* p, size_type) { mi_free(p); } + + #if (__cplusplus >= 201703L) // C++17 + mi_decl_nodiscard T* allocate(size_type count) { return static_cast(mi_new_n(count, sizeof(T))); } + mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); } + #else + mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast(mi_new_n(count, sizeof(value_type))); } + #endif + + #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11 + using propagate_on_container_copy_assignment = std::true_type; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; + using is_always_equal = std::true_type; + template void construct(U* p, Args&& ...args) { ::new(p) U(std::forward(args)...); } + template void destroy(U* p) mi_attr_noexcept { p->~U(); } + #else + void construct(pointer p, value_type const& val) { ::new(p) value_type(val); } + void destroy(pointer p) { p->~value_type(); } + #endif + + size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); } + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } +}; + +template bool operator==(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return true; } +template bool operator!=(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return false; } +#endif // __cplusplus + +#endif diff --git a/deps/mimalloc/readme.md b/deps/mimalloc/readme.md new file mode 100644 index 000000000..9419a6583 --- /dev/null +++ b/deps/mimalloc/readme.md @@ -0,0 +1,608 @@ + + + +[](https://dev.azure.com/Daan0324/mimalloc/_build?definitionId=1&_a=summary) + +# mimalloc + +  + +mimalloc (pronounced "me-malloc") +is a general purpose allocator with excellent [performance](#performance) characteristics. +Initially developed by Daan Leijen for the run-time systems of the +[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages. +Latest release:`v1.6.7` (2020-09-24). + +It is a drop-in replacement for `malloc` and can be used in other programs +without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as: +``` +> LD_PRELOAD=/usr/bin/libmimalloc.so myprogram +``` +It also has an easy way to override the default allocator in [Windows](#override_on_windows). Notable aspects of the design include: + +- __small and consistent__: the library is about 8k LOC using simple and + consistent data structures. This makes it very suitable + to integrate and adapt in other projects. For runtime systems it + provides hooks for a monotonic _heartbeat_ and deferred freeing (for + bounded worst-case times with reference counting). +- __free list sharding__: instead of one big free list (per size class) we have + many smaller lists per "mimalloc page" which reduces fragmentation and + increases locality -- + things that are allocated close in time get allocated close in memory. + (A mimalloc page contains blocks of one size class and is usually 64KiB on a 64-bit system). +- __free list multi-sharding__: the big idea! Not only do we shard the free list + per mimalloc page, but for each page we have multiple free lists. In particular, there + is one list for thread-local `free` operations, and another one for concurrent `free` + operations. Free-ing from another thread can now be a single CAS without needing + sophisticated coordination between threads. Since there will be + thousands of separate free lists, contention is naturally distributed over the heap, + and the chance of contending on a single location will be low -- this is quite + similar to randomized algorithms like skip lists where adding + a random oracle removes the need for a more complex algorithm. +- __eager page reset__: when a "page" becomes empty (with increased chance + due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged") + reducing (real) memory pressure and fragmentation, especially in long running + programs. +- __secure__: _mimalloc_ can be built in secure mode, adding guard pages, + randomized allocation, encrypted free lists, etc. to protect against various + heap vulnerabilities. The performance penalty is usually around 10% on average + over our benchmarks. +- __first-class heaps__: efficiently create and use multiple heaps to allocate across different regions. + A heap can be destroyed at once instead of deallocating each object separately. +- __bounded__: it does not suffer from _blowup_ \[1\], has bounded worst-case allocation + times (_wcat_), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes), + and has no internal points of contention using only atomic operations. +- __fast__: In our benchmarks (see [below](#performance)), + _mimalloc_ outperforms other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), + and usually uses less memory (up to 25% more in the worst case). A nice property + is that it does consistently well over a wide range of benchmarks. There is also good huge OS page + support for larger server programs. + +The [documentation](https://microsoft.github.io/mimalloc) gives a full overview of the API. +You can read more on the design of _mimalloc_ in the [technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action) which also has detailed benchmark results. + +Enjoy! + +### Branches + +* `master`: latest stable release. +* `dev`: latest development branch. +* `dev-slice`: experimental branch with a different way of managing mimalloc pages that tends + to use less memory than regular mimalloc with similar performance. Give it a try and please + report any significant performance improvement or degradation. + +### Releases + +* 2020-09-24, `v1.6.7`: stable release 1.6: using standard C atomics, passing tsan testing, improved + handling of failing to commit on Windows, add [`mi_process_info`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc.h#L156) api call. +* 2020-08-06, `v1.6.4`: stable release 1.6: improved error recovery in low-memory situations, + support for IllumOS and Haiku, NUMA support for Vista/XP, improved NUMA detection for AMD Ryzen, ubsan support. +* 2020-05-05, `v1.6.3`: stable release 1.6: improved behavior in out-of-memory situations, improved malloc zones on macOS, + build PIC static libraries by default, add option to abort on out-of-memory, line buffered statistics. +* 2020-04-20, `v1.6.2`: stable release 1.6: fix compilation on Android, MingW, Raspberry, and Conda, + stability fix for Windows 7, fix multiple mimalloc instances in one executable, fix `strnlen` overload, + fix aligned debug padding. +* 2020-02-17, `v1.6.1`: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects). +* 2020-02-09, `v1.6.0`: stable release 1.6: fixed potential memory leak, improved overriding + and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise + heap block overflow detection in debug mode (besides the double-free detection and free-list + corruption detection). Add `nodiscard` attribute to most allocation functions. + Enable `MIMALLOC_PAGE_RESET` by default. New reclamation strategy for abandoned heap pages + for better memory footprint. +* 2020-02-09, `v1.5.0`: stable release 1.5: improved free performance, small bug fixes. +* 2020-01-22, `v1.4.0`: stable release 1.4: improved performance for delayed OS page reset, +more eager concurrent free, addition of STL allocator, fixed potential memory leak. +* 2020-01-15, `v1.3.0`: stable release 1.3: bug fixes, improved randomness and [stronger +free list encoding](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396) in secure mode. +* 2019-12-22, `v1.2.2`: stable release 1.2: minor updates. +* 2019-11-22, `v1.2.0`: stable release 1.2: bug fixes, improved secure mode (free list corruption checks, double free mitigation). Improved dynamic overriding on Windows. +* 2019-10-07, `v1.1.0`: stable release 1.1. +* 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support. +* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements. + +Special thanks to: + +* Mary Feofanova (@mary3000), Evgeniy Moiseenko, and Manuel Pöter (@mpoeter) for making mimalloc TSAN checkable, and finding + memory model bugs using the [genMC] model checker. +* Weipeng Liu (@pongba), Zhuowei Li, Junhua Wang, and Jakub Szymanski, for their early support of mimalloc and deployment + at large scale services, leading to many improvements in the mimalloc algorithms for large workloads. +* Jason Gibson (@jasongibson) for exhaustive testing on large scale workloads and server environments, and finding complex bugs + in (early versions of) `mimalloc`. +* Manuel Pöter (@mpoeter) and Sam Gross (@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation. + +[genMC]: https://plv.mpi-sws.org/genmc/ + +# Building + +## Windows + +Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`). +The `mimalloc` project builds a static library (in `out/msvc-x64`), while the +`mimalloc-override` project builds a DLL for overriding malloc +in the entire program. + +## macOS, Linux, BSD, etc. + +We use [`cmake`](https://cmake.org)1 as the build system: + +``` +> mkdir -p out/release +> cd out/release +> cmake ../.. +> make +``` +This builds the library as a shared (dynamic) +library (`.so` or `.dylib`), a static library (`.a`), and +as a single object file (`.o`). + +`> sudo make install` (install the library and header files in `/usr/local/lib` and `/usr/local/include`) + +You can build the debug version which does many internal checks and +maintains detailed statistics as: + +``` +> mkdir -p out/debug +> cd out/debug +> cmake -DCMAKE_BUILD_TYPE=Debug ../.. +> make +``` +This will name the shared library as `libmimalloc-debug.so`. + +Finally, you can build a _secure_ version that uses guard pages, encrypted +free lists, etc., as: +``` +> mkdir -p out/secure +> cd out/secure +> cmake -DMI_SECURE=ON ../.. +> make +``` +This will name the shared library as `libmimalloc-secure.so`. +Use `ccmake`2 instead of `cmake` +to see and customize all the available build options. + +Notes: +1. Install CMake: `sudo apt-get install cmake` +2. Install CCMake: `sudo apt-get install cmake-curses-gui` + + + +# Using the library + +The preferred usage is including ``, linking with +the shared- or static library, and using the `mi_malloc` API exclusively for allocation. For example, +``` +> gcc -o myprogram -lmimalloc myfile.c +``` + +mimalloc uses only safe OS calls (`mmap` and `VirtualAlloc`) and can co-exist +with other allocators linked to the same program. +If you use `cmake`, you can simply use: +``` +find_package(mimalloc 1.4 REQUIRED) +``` +in your `CMakeLists.txt` to find a locally installed mimalloc. Then use either: +``` +target_link_libraries(myapp PUBLIC mimalloc) +``` +to link with the shared (dynamic) library, or: +``` +target_link_libraries(myapp PUBLIC mimalloc-static) +``` +to link with the static library. See `test\CMakeLists.txt` for an example. + +For best performance in C++ programs, it is also recommended to override the +global `new` and `delete` operators. For convience, mimalloc provides +[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project. +In C++, mimalloc also provides the `mi_stl_allocator` struct which implements the `std::allocator` +interface. + +You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`) +and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version): +``` +> env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363 + +175451865205073170563711388363 = 374456281610909315237213 * 468551 + +heap stats: peak total freed unit +normal 2: 16.4 kb 17.5 mb 17.5 mb 16 b ok +normal 3: 16.3 kb 15.2 mb 15.2 mb 24 b ok +normal 4: 64 b 4.6 kb 4.6 kb 32 b ok +normal 5: 80 b 118.4 kb 118.4 kb 40 b ok +normal 6: 48 b 48 b 48 b 48 b ok +normal 17: 960 b 960 b 960 b 320 b ok + +heap stats: peak total freed unit + normal: 33.9 kb 32.8 mb 32.8 mb 1 b ok + huge: 0 b 0 b 0 b 1 b ok + total: 33.9 kb 32.8 mb 32.8 mb 1 b ok +malloc requested: 32.8 mb + + committed: 58.2 kb 58.2 kb 58.2 kb 1 b ok + reserved: 2.0 mb 2.0 mb 2.0 mb 1 b ok + reset: 0 b 0 b 0 b 1 b ok + segments: 1 1 1 +-abandoned: 0 + pages: 6 6 6 +-abandoned: 0 + mmaps: 3 + mmap fast: 0 + mmap slow: 1 + threads: 0 + elapsed: 2.022s + process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb +``` + +The above model of using the `mi_` prefixed API is not always possible +though in existing programs that already use the standard malloc interface, +and another option is to override the standard malloc interface +completely and redirect all calls to the _mimalloc_ library instead . + +## Environment Options + +You can set further options either programmatically (using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)), +or via environment variables: + +- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates. +- `MIMALLOC_VERBOSE=1`: show verbose messages. +- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages. +- `MIMALLOC_PAGE_RESET=0`: by default, mimalloc will reset (or purge) OS pages that are not in use, to signal to the OS + that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server) + programs. By setting it to `0` this will no longer be done which can improve performance for batch-like programs. + As an alternative, the `MIMALLOC_RESET_DELAY=` can be set higher (100ms by default) to make the page + reset occur less frequently instead of turning it off completely. +- `MIMALLOC_USE_NUMA_NODES=N`: pretend there are at most `N` NUMA nodes. If not set, the actual NUMA nodes are detected + at runtime. Setting `N` to 1 may avoid problems in some virtual environments. Also, setting it to a lower number than + the actual NUMA nodes is fine and will only cause threads to potentially allocate more memory across actual NUMA + nodes (but this can happen in any case as NUMA local allocation is always a best effort but not guaranteed). +- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages (2MiB) when available; for some workloads this can significantly + improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs + to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes + the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that + can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead whenever possible). + +- `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB _huge_ OS pages. This reserves the huge pages at + startup and sometimes this can give a large (latency) performance improvement on big workloads. + Usually it is better to not use + `MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving + contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at + startup only once). + Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])). + With huge OS pages, it may be beneficial to set the setting + `MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB) + of a thread to not allocate in the huge OS pages; this prevents threads that are short lived + and allocate just a little to take up space in the huge OS page area (which cannot be reset). + +Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write +for all pages in the original process including the huge OS pages. When any memory is now written in that area, the +OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments. + +[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5 +[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017 + +## Secure Mode + +_mimalloc_ can be build in secure mode by using the `-DMI_SECURE=ON` flags in `cmake`. This build enables various mitigations +to make mimalloc more robust against exploits. In particular: + +- All internal mimalloc pages are surrounded by guard pages and the heap metadata is behind a guard page as well (so a buffer overflow + exploit cannot reach into the metadata). +- All free list pointers are + [encoded](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396) + with per-page keys which is used both to prevent overwrites with a known pointer, as well as to detect heap corruption. +- Double free's are detected (and ignored). +- The free lists are initialized in a random order and allocation randomly chooses between extension and reuse within a page to + mitigate against attacks that rely on a predicable allocation order. Similarly, the larger heap blocks allocated by mimalloc + from the OS are also address randomized. + +As always, evaluate with care as part of an overall security strategy as all of the above are mitigations but not guarantees. + +## Debug Mode + +When _mimalloc_ is built using debug mode, various checks are done at runtime to catch development errors. + +- Statistics are maintained in detail for each object size. They can be shown using `MIMALLOC_SHOW_STATS=1` at runtime. +- All objects have padding at the end to detect (byte precise) heap block overflows. +- Double free's, and freeing invalid heap pointers are detected. +- Corrupted free-lists and some forms of use-after-free are detected. + + +# Overriding Malloc + +Overriding the standard `malloc` can be done either _dynamically_ or _statically_. + +## Dynamic override + +This is the recommended way to override the standard malloc interface. + +### Override on Linux, BSD + +On these ELF-based systems we preload the mimalloc shared +library so all calls to the standard `malloc` interface are +resolved to the _mimalloc_ library. +``` +> env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram +``` + +You can set extra environment variables to check that mimalloc is running, +like: +``` +> env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram +``` +or run with the debug version to get detailed statistics: +``` +> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram +``` + +### Override on MacOS + +On macOS we can also preload the mimalloc shared +library so all calls to the standard `malloc` interface are +resolved to the _mimalloc_ library. +``` +> env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram +``` + +Note that certain security restrictions may apply when doing this from +the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash). + +(Note: macOS support for dynamic overriding is recent, please report any issues.) + +### Override on Windows + +Overriding on Windows is robust and has the +particular advantage to be able to redirect all malloc/free calls that go through +the (dynamic) C runtime allocator, including those from other DLL's or libraries. + +The overriding on Windows requires that you link your program explicitly with +the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). +Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be available +in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency). +The redirection DLL ensures that all calls to the C runtime malloc API get redirected to +mimalloc (in `mimalloc-override.dll`). + +To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some +call to the mimalloc API in the `main` function, like `mi_version()` +(or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project +for an example on how to use this. For best performance on Windows with C++, it +is also recommended to also override the `new`/`delete` operations (by including +[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) a single(!) source file in your project). + +The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic +overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. + +(Note: in principle, it is possible to even patch existing executables without any recompilation +if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll` +into the import table (and put `mimalloc-redirect.dll` in the same folder) +Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)). + + +## Static override + +On Unix-like systems, you can also statically link with _mimalloc_ to override the standard +malloc interface. The recommended way is to link the final program with the +_mimalloc_ single object file (`mimalloc-override.o`). We use +an object file instead of a library file as linkers give preference to +that over archives to resolve symbols. To ensure that the standard +malloc interface resolves to the _mimalloc_ library, link it as the first +object file. For example: +``` +> gcc -o myprogram mimalloc-override.o myfile1.c ... +``` + +Another way to override statically that works on all platforms, is to +link statically to mimalloc (as shown in the introduction) and include a +header file in each source file that re-defines `malloc` etc. to `mi_malloc`. +This is provided by [`mimalloc-override.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-override.h). This only works reliably though if all sources are +under your control or otherwise mixing of pointers from different heaps may occur! + + +# Performance + +Last update: 2020-01-20 + +We tested _mimalloc_ against many other top allocators over a wide +range of benchmarks, ranging from various real world programs to +synthetic benchmarks that see how the allocator behaves under more +extreme circumstances. In our benchmark suite, _mimalloc_ outperforms other leading +allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), and has a similar memory footprint. A nice property is that it +does consistently well over the wide range of benchmarks. + +General memory allocators are interesting as there exists no algorithm that is +optimal -- for a given allocator one can usually construct a workload +where it does not do so well. The goal is thus to find an allocation +strategy that performs well over a wide range of benchmarks without +suffering from (too much) underperformance in less common situations. + +As always, interpret these results with care since some benchmarks test synthetic +or uncommon situations that may never apply to your workloads. For example, most +allocators do not do well on `xmalloc-testN` but that includes the best +industrial allocators like _jemalloc_ and _tcmalloc_ that are used in some of +the world's largest systems (like Chrome or FreeBSD). + +We show here only an overview -- for +more specific details and further benchmarks we refer to the +[technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action). +The benchmark suite is automated and available separately +as [mimalloc-bench](https://github.com/daanx/mimalloc-bench). + + +## Benchmark Results on 36-core Intel + +Testing on a big Amazon EC2 compute instance +([c5.18xlarge](https://aws.amazon.com/ec2/instance-types/#Compute_Optimized)) +consisting of a 72 processor Intel Xeon at 3GHz +with 144GiB ECC memory, running Ubuntu 18.04.1 with glibc 2.27 and GCC 7.4.0. +The measured allocators are _mimalloc_ (xmi, tag:v1.4.0, page reset enabled) +and its secure build as _smi_, +Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (tc, tag:gperftools-2.7) used in Chrome, +Facebook's [_jemalloc_](https://github.com/jemalloc/jemalloc) (je, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD, +the Intel thread building blocks [allocator](https://github.com/intel/tbb) (tbb, tag:2020), +[rpmalloc](https://github.com/mjansson/rpmalloc) (rp,tag:1.4.0) by Mattias Jansson, +the original scalable [_Hoard_](https://github.com/emeryberger/Hoard) (tag:3.13) allocator by Emery Berger \[1], +the memory compacting [_Mesh_](https://github.com/plasma-umass/Mesh) (git:51222e7) allocator by +Bobby Powers _et al_ \[8], +and finally the default system allocator (glibc, 2.27) (based on _PtMalloc2_). + + + + +Any benchmarks ending in `N` run on all processors in parallel. +Results are averaged over 10 runs and reported relative +to mimalloc (where 1.2 means it took 1.2× longer to run). +The legend also contains the _overall relative score_ between the +allocators where 100 points is the maximum if an allocator is fastest on +all benchmarks. + +The single threaded _cfrac_ benchmark by Dave Barrett is an implementation of +continued fraction factorization which uses many small short-lived allocations. +All allocators do well on such common usage, where _mimalloc_ is just a tad +faster than _tcmalloc_ and +_jemalloc_. + +The _leanN_ program is interesting as a large realistic and +concurrent workload of the [Lean](https://github.com/leanprover/lean) +theorem prover compiling its own standard library, and there is a 7% +speedup over _tcmalloc_. This is +quite significant: if Lean spends 20% of its time in the +allocator that means that _mimalloc_ is 1.3× faster than _tcmalloc_ +here. (This is surprising as that is not measured in a pure +allocation benchmark like _alloc-test_. We conjecture that we see this +outsized improvement here because _mimalloc_ has better locality in +the allocation which improves performance for the *other* computations +in a program as well). + +The single threaded _redis_ benchmark again show that most allocators do well on such workloads where _tcmalloc_ +did best this time. + +The _larsonN_ server benchmark by Larson and Krishnan \[2] allocates and frees between threads. They observed this +behavior (which they call _bleeding_) in actual server applications, and the benchmark simulates this. +Here, _mimalloc_ is quite a bit faster than _tcmalloc_ and _jemalloc_ probably due to the object migration between different threads. + +The _mstressN_ workload performs many allocations and re-allocations, +and migrates objects between threads (as in _larsonN_). However, it also +creates and destroys the _N_ worker threads a few times keeping some objects +alive beyond the life time of the allocating thread. We observed this +behavior in many larger server applications. + +The [_rptestN_](https://github.com/mjansson/rpmalloc-benchmark) benchmark +by Mattias Jansson is a allocator test originally designed +for _rpmalloc_, and tries to simulate realistic allocation patterns over +multiple threads. Here the differences between allocators become more apparent. + +The second benchmark set tests specific aspects of the allocators and +shows even more extreme differences between them. + +The _alloc-test_, by +[OLogN Technologies AG](http://ithare.com/testing-memory-allocators-ptmalloc2-tcmalloc-hoard-jemalloc-while-trying-to-simulate-real-world-loads/), is a very allocation intensive benchmark doing millions of +allocations in various size classes. The test is scaled such that when an +allocator performs almost identically on _alloc-test1_ as _alloc-testN_ it +means that it scales linearly. Here, _tcmalloc_, and +_Hoard_ seem to scale less well and do more than 10% worse on the multi-core version. Even the best industrial +allocators (_tcmalloc_, _jemalloc_, and _tbb_) are more than 10% slower as _mimalloc_ here. + +The _sh6bench_ and _sh8bench_ benchmarks are +developed by [MicroQuill](http://www.microquill.com/) as part of SmartHeap. +In _sh6bench_ _mimalloc_ does much +better than the others (more than 1.5× faster than _jemalloc_). +We cannot explain this well but believe it is +caused in part by the "reverse" free-ing pattern in _sh6bench_. +The _sh8bench_ is a variation with object migration +between threads; whereas _tcmalloc_ did well on _sh6bench_, the addition of object migration causes it to be 10× slower than before. + +The _xmalloc-testN_ benchmark by Lever and Boreham \[5] and Christian Eder, simulates an asymmetric workload where +some threads only allocate, and others only free -- they observed this pattern in +larger server applications. Here we see that +the _mimalloc_ technique of having non-contended sharded thread free +lists pays off as it outperforms others by a very large margin. Only _rpmalloc_ and _tbb_ also scale well on this benchmark. + +The _cache-scratch_ benchmark by Emery Berger \[1], and introduced with +the Hoard allocator to test for _passive-false_ sharing of cache lines. +With a single thread they all +perform the same, but when running with multiple threads the potential allocator +induced false sharing of the cache lines can cause large run-time differences. +Crundal \[6] describes in detail why the false cache line sharing occurs in the _tcmalloc_ design, and also discusses how this +can be avoided with some small implementation changes. +Only the _tbb_, _rpmalloc_ and _mesh_ allocators also avoid the +cache line sharing completely, while _Hoard_ and _glibc_ seem to mitigate +the effects. Kukanov and Voss \[7] describe in detail +how the design of _tbb_ avoids the false cache line sharing. + +## On 24-core AMD Epyc + +For completeness, here are the results on a +[r5a.12xlarge](https://aws.amazon.com/ec2/instance-types/#Memory_Optimized) instance +having a 48 processor AMD Epyc 7000 at 2.5GHz with 384GiB of memory. +The results are similar to the Intel results but it is interesting to +see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks. + + + + + +## Peak Working Set + +The following figure shows the peak working set (rss) of the allocators +on the benchmarks (on the c5.18xlarge instance). + + + + +Note that the _xmalloc-testN_ memory usage should be disregarded as it +allocates more the faster the program runs. Similarly, memory usage of +_mstressN_, _rptestN_ and _sh8bench_ can vary depending on scheduling and +speed. Nevertheless, even though _mimalloc_ is fast on these benchmarks we +believe the memory usage is too high and hope to improve. + + +# References + +- \[1] Emery D. Berger, Kathryn S. McKinley, Robert D. Blumofe, and Paul R. Wilson. + _Hoard: A Scalable Memory Allocator for Multithreaded Applications_ + the Ninth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS-IX). Cambridge, MA, November 2000. + [pdf](http://www.cs.utexas.edu/users/mckinley/papers/asplos-2000.pdf) + +- \[2] P. Larson and M. Krishnan. _Memory allocation for long-running server applications_. + In ISMM, Vancouver, B.C., Canada, 1998. [pdf](http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.45.1947&rep=rep1&type=pdf) + +- \[3] D. Grunwald, B. Zorn, and R. Henderson. + _Improving the cache locality of memory allocation_. In R. Cartwright, editor, + Proceedings of the Conference on Programming Language Design and Implementation, pages 177–186, New York, NY, USA, June 1993. [pdf](http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.43.6621&rep=rep1&type=pdf) + +- \[4] J. Barnes and P. Hut. _A hierarchical O(n*log(n)) force-calculation algorithm_. Nature, 324:446-449, 1986. + +- \[5] C. Lever, and D. Boreham. _Malloc() Performance in a Multithreaded Linux Environment._ + In USENIX Annual Technical Conference, Freenix Session. San Diego, CA. Jun. 2000. + Available at + +- \[6] Timothy Crundal. _Reducing Active-False Sharing in TCMalloc_. 2016. CS16S1 project at the Australian National University. [pdf](http://courses.cecs.anu.edu.au/courses/CSPROJECTS/16S1/Reports/Timothy_Crundal_Report.pdf) + +- \[7] Alexey Kukanov, and Michael J Voss. + _The Foundations for Scalable Multi-Core Software in Intel Threading Building Blocks._ + Intel Technology Journal 11 (4). 2007 + +- \[8] Bobby Powers, David Tench, Emery D. Berger, and Andrew McGregor. + _Mesh: Compacting Memory Management for C/C++_ + In Proceedings of the 40th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI'19), June 2019, pages 333-–346. + + + + +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. diff --git a/deps/mimalloc/src/alloc-aligned.c b/deps/mimalloc/src/alloc-aligned.c new file mode 100644 index 000000000..ca16d3676 --- /dev/null +++ b/deps/mimalloc/src/alloc-aligned.c @@ -0,0 +1,205 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memset, memcpy + +// ------------------------------------------------------ +// Aligned Allocation +// ------------------------------------------------------ + +static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept { + // note: we don't require `size > offset`, we just guarantee that + // the address at offset is aligned regardless of the allocated size. + mi_assert(alignment > 0); + if (mi_unlikely(size > PTRDIFF_MAX)) return NULL; // we don't allocate more than PTRDIFF_MAX (see ) + if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see ) + const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` + + // try if there is a small block available with just the right alignment + const size_t padsize = size + MI_PADDING_SIZE; + if (mi_likely(padsize <= MI_SMALL_SIZE_MAX)) { + mi_page_t* page = _mi_heap_get_free_small_page(heap,padsize); + const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0; + if (mi_likely(page->free != NULL && is_aligned)) + { + #if MI_STAT>1 + mi_heap_stat_increase( heap, malloc, size); + #endif + void* p = _mi_page_malloc(heap,page,padsize); // TODO: inline _mi_page_malloc + mi_assert_internal(p != NULL); + mi_assert_internal(((uintptr_t)p + offset) % alignment == 0); + if (zero) _mi_block_zero_init(page,p,size); + return p; + } + } + + // use regular allocation if it is guaranteed to fit the alignment constraints + if (offset==0 && alignment<=padsize && padsize<=MI_MEDIUM_OBJ_SIZE_MAX && (padsize&align_mask)==0) { + void* p = _mi_heap_malloc_zero(heap, size, zero); + mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); + return p; + } + + // otherwise over-allocate + void* p = _mi_heap_malloc_zero(heap, size + alignment - 1, zero); + if (p == NULL) return NULL; + + // .. and align within the allocation + uintptr_t adjust = alignment - (((uintptr_t)p + offset) & align_mask); + mi_assert_internal(adjust <= alignment); + void* aligned_p = (adjust == alignment ? p : (void*)((uintptr_t)p + adjust)); + if (aligned_p != p) mi_page_set_has_aligned(_mi_ptr_page(p), true); + mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); + mi_assert_internal( p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p),_mi_ptr_page(aligned_p),aligned_p) ); + return aligned_p; +} + + +mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false); +} + +mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_malloc_aligned_at(heap, size, alignment, 0); +} + +mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true); +} + +mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(heap, size, alignment, 0); +} + +mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_zalloc_aligned_at(heap, total, alignment, offset); +} + +mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(heap,count,size,alignment,0); +} + +mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset); +} + +mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_malloc_aligned(mi_get_default_heap(), size, alignment); +} + +mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset); +} + +mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned(mi_get_default_heap(), size, alignment); +} + +mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset); +} + +mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned(mi_get_default_heap(), count, size, alignment); +} + + +static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + if (p == NULL) return mi_heap_malloc_zero_aligned_at(heap,newsize,alignment,offset,zero); + size_t size = mi_usable_size(p); + if (newsize <= size && newsize >= (size - (size / 2)) + && (((uintptr_t)p + offset) % alignment) == 0) { + return p; // reallocation still fits, is aligned and not more than 50% waste + } + else { + void* newp = mi_heap_malloc_aligned_at(heap,newsize,alignment,offset); + if (newp != NULL) { + if (zero && newsize > size) { + const mi_page_t* page = _mi_ptr_page(newp); + if (page->is_zero) { + // already zero initialized + mi_assert_expensive(mi_mem_is_zero(newp,newsize)); + } + else { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + memset((uint8_t*)newp + start, 0, newsize - start); + } + } + memcpy(newp, p, (newsize > size ? size : newsize)); + mi_free(p); // only free if successful + } + return newp; + } +} + +static void* mi_heap_realloc_zero_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + size_t offset = ((uintptr_t)p % alignment); // use offset of previous allocation (p can be NULL) + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,zero); +} + +void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,false); +} + +void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false); +} + +void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap, p, newsize, alignment, offset, true); +} + +void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap, p, newsize, alignment, true); +} + +void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset); +} + +void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned(heap, p, total, alignment); +} + +void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset); +} + +void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_aligned(mi_get_default_heap(), p, newsize, alignment); +} + +void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_rezalloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset); +} + +void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_rezalloc_aligned(mi_get_default_heap(), p, newsize, alignment); +} + +void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_recalloc_aligned_at(mi_get_default_heap(), p, newcount, size, alignment, offset); +} + +void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_recalloc_aligned(mi_get_default_heap(), p, newcount, size, alignment); +} + diff --git a/deps/mimalloc/src/alloc-override-osx.c b/deps/mimalloc/src/alloc-override-osx.c new file mode 100644 index 000000000..c1c880ca2 --- /dev/null +++ b/deps/mimalloc/src/alloc-override-osx.c @@ -0,0 +1,260 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#if defined(MI_MALLOC_OVERRIDE) + +#if !defined(__APPLE__) +#error "this file should only be included on macOS" +#endif + +/* ------------------------------------------------------ + Override system malloc on macOS + This is done through the malloc zone interface. + It seems we also need to interpose (see `alloc-override.c`) + or otherwise we get zone errors as there are usually + already allocations done by the time we take over the + zone. Unfortunately, that means we need to replace + the `free` with a checked free (`cfree`) impacting + performance. +------------------------------------------------------ */ + +#include +#include +#include // memset + +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +// only available from OSX 10.6 +extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_import)); +#endif + + +/* ------------------------------------------------------ + malloc zone members +------------------------------------------------------ */ + +static size_t zone_size(malloc_zone_t* zone, const void* p) { + UNUSED(zone); + if (!mi_is_in_heap_region(p)) + return 0; // not our pointer, bail out + + return mi_usable_size(p); +} + +static void* zone_malloc(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_malloc(size); +} + +static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) { + UNUSED(zone); + return mi_calloc(count, size); +} + +static void* zone_valloc(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_malloc_aligned(size, _mi_os_page_size()); +} + +static void zone_free(malloc_zone_t* zone, void* p) { + UNUSED(zone); + return mi_free(p); +} + +static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) { + UNUSED(zone); + return mi_realloc(p, newsize); +} + +static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) { + UNUSED(zone); + return mi_malloc_aligned(size,alignment); +} + +static void zone_destroy(malloc_zone_t* zone) { + UNUSED(zone); + // todo: ignore for now? +} + +static unsigned zone_batch_malloc(malloc_zone_t* zone, size_t size, void** ps, unsigned count) { + size_t i; + for (i = 0; i < count; i++) { + ps[i] = zone_malloc(zone, size); + if (ps[i] == NULL) break; + } + return i; +} + +static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) { + for(size_t i = 0; i < count; i++) { + zone_free(zone, ps[i]); + ps[i] = NULL; + } +} + +static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) { + UNUSED(zone); UNUSED(size); + mi_collect(false); + return 0; +} + +static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) { + UNUSED(size); + zone_free(zone,p); +} + + +/* ------------------------------------------------------ + Introspection members +------------------------------------------------------ */ + +static kern_return_t intro_enumerator(task_t task, void* p, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) +{ + // todo: enumerate all memory + UNUSED(task); UNUSED(p); UNUSED(type_mask); UNUSED(zone_address); + UNUSED(reader); UNUSED(recorder); + return KERN_SUCCESS; +} + +static size_t intro_good_size(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_good_size(size); +} + +static boolean_t intro_check(malloc_zone_t* zone) { + UNUSED(zone); + return true; +} + +static void intro_print(malloc_zone_t* zone, boolean_t verbose) { + UNUSED(zone); UNUSED(verbose); + mi_stats_print(NULL); +} + +static void intro_log(malloc_zone_t* zone, void* p) { + UNUSED(zone); UNUSED(p); + // todo? +} + +static void intro_force_lock(malloc_zone_t* zone) { + UNUSED(zone); + // todo? +} + +static void intro_force_unlock(malloc_zone_t* zone) { + UNUSED(zone); + // todo? +} + +static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) { + UNUSED(zone); + // todo... + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t intro_zone_locked(malloc_zone_t* zone) { + UNUSED(zone); + return false; +} + + +/* ------------------------------------------------------ + At process start, override the default allocator +------------------------------------------------------ */ + +static malloc_zone_t* mi_get_default_zone() +{ + // The first returned zone is the real default + malloc_zone_t** zones = NULL; + unsigned count = 0; + kern_return_t ret = malloc_get_all_zones(0, NULL, (vm_address_t**)&zones, &count); + if (ret == KERN_SUCCESS && count > 0) { + return zones[0]; + } + else { + // fallback + return malloc_default_zone(); + } +} + +static void __attribute__((constructor)) _mi_macos_override_malloc() +{ + static malloc_introspection_t intro; + memset(&intro, 0, sizeof(intro)); + + intro.enumerator = &intro_enumerator; + intro.good_size = &intro_good_size; + intro.check = &intro_check; + intro.print = &intro_print; + intro.log = &intro_log; + intro.force_lock = &intro_force_lock; + intro.force_unlock = &intro_force_unlock; + + static malloc_zone_t zone; + memset(&zone, 0, sizeof(zone)); + + zone.version = 4; + zone.zone_name = "mimalloc"; + zone.size = &zone_size; + zone.introspect = &intro; + zone.malloc = &zone_malloc; + zone.calloc = &zone_calloc; + zone.valloc = &zone_valloc; + zone.free = &zone_free; + zone.realloc = &zone_realloc; + zone.destroy = &zone_destroy; + zone.batch_malloc = &zone_batch_malloc; + zone.batch_free = &zone_batch_free; + + malloc_zone_t* purgeable_zone = NULL; + +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + // switch to version 9 on OSX 10.6 to support memalign. + zone.version = 9; + zone.memalign = &zone_memalign; + zone.free_definite_size = &zone_free_definite_size; + zone.pressure_relief = &zone_pressure_relief; + intro.zone_locked = &intro_zone_locked; + intro.statistics = &intro_statistics; + + // force the purgeable zone to exist to avoid strange bugs + if (malloc_default_purgeable_zone) { + purgeable_zone = malloc_default_purgeable_zone(); + } +#endif + + // Register our zone + malloc_zone_register(&zone); + + // Unregister the default zone, this makes our zone the new default + // as that was the last registered. + malloc_zone_t *default_zone = mi_get_default_zone(); + malloc_zone_unregister(default_zone); + + // Reregister the default zone so free and realloc in that zone keep working. + malloc_zone_register(default_zone); + + // Unregister, and re-register the purgeable_zone to avoid bugs if it occurs + // earlier than the default zone. + if (purgeable_zone != NULL) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } + +} + +#endif // MI_MALLOC_OVERRIDE diff --git a/deps/mimalloc/src/alloc-override.c b/deps/mimalloc/src/alloc-override.c new file mode 100644 index 000000000..ae7ad7ddb --- /dev/null +++ b/deps/mimalloc/src/alloc-override.c @@ -0,0 +1,214 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#if !defined(MI_IN_ALLOC_C) +#error "this file should be included from 'alloc.c' (so aliases can work)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && defined(_WIN32) && !(defined(MI_SHARED_LIB) && defined(_DLL)) +#error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) // || (defined(__MACH__) && !defined(MI_INTERPOSE))) + +// ------------------------------------------------------ +// Override system malloc +// ------------------------------------------------------ + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) + // use aliasing to alias the exported function to one of our `mi_` functions + #if (defined(__GNUC__) && __GNUC__ >= 9) + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun))) + #else + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"))) + #endif + #define MI_FORWARD1(fun,x) MI_FORWARD(fun) + #define MI_FORWARD2(fun,x,y) MI_FORWARD(fun) + #define MI_FORWARD3(fun,x,y,z) MI_FORWARD(fun) + #define MI_FORWARD0(fun,x) MI_FORWARD(fun) + #define MI_FORWARD02(fun,x,y) MI_FORWARD(fun) +#else + // use forwarding by calling our `mi_` function + #define MI_FORWARD1(fun,x) { return fun(x); } + #define MI_FORWARD2(fun,x,y) { return fun(x,y); } + #define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); } + #define MI_FORWARD0(fun,x) { fun(x); } + #define MI_FORWARD02(fun,x,y) { fun(x,y); } +#endif + +#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE) + // use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1` + // See: + struct mi_interpose_s { + const void* replacement; + const void* target; + }; + #define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun } + #define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun) + __attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) = + { + MI_INTERPOSE_MI(malloc), + MI_INTERPOSE_MI(calloc), + MI_INTERPOSE_MI(realloc), + MI_INTERPOSE_MI(strdup), + MI_INTERPOSE_MI(strndup), + MI_INTERPOSE_MI(realpath), + MI_INTERPOSE_MI(posix_memalign), + MI_INTERPOSE_MI(reallocf), + MI_INTERPOSE_MI(valloc), + // some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity ) + MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us + }; +#elif defined(_MSC_VER) + // cannot override malloc unless using a dll. + // we just override new/delete which does work in a static library. +#else + // On all other systems forward to our API + void* malloc(size_t size) MI_FORWARD1(mi_malloc, size); + void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n); + void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize); + void free(void* p) MI_FORWARD0(mi_free, p); +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) +#pragma GCC visibility push(default) +#endif + +// ------------------------------------------------------ +// Override new/delete +// This is not really necessary as they usually call +// malloc/free anyway, but it improves performance. +// ------------------------------------------------------ +#ifdef __cplusplus + // ------------------------------------------------------ + // With a C++ compiler we override the new/delete operators. + // see + // ------------------------------------------------------ + #include + void operator delete(void* p) noexcept MI_FORWARD0(mi_free,p); + void operator delete[](void* p) noexcept MI_FORWARD0(mi_free,p); + + void* operator new(std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n); + void* operator new[](std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n); + + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n); + void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n); + #endif + + #if (__cplusplus > 201402L && defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + #endif + +#elif (defined(__GNUC__) || defined(__clang__)) + // ------------------------------------------------------ + // Override by defining the mangled C++ names of the operators (as + // used by GCC and CLang). + // See + // ------------------------------------------------------ + void _ZdlPv(void* p) MI_FORWARD0(mi_free,p); // delete + void _ZdaPv(void* p) MI_FORWARD0(mi_free,p); // delete[] + void _ZdlPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n); + void _ZdaPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n); + void _ZdlPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdaPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + + typedef struct mi_nothrow_s { } mi_nothrow_t; + #if (MI_INTPTR_SIZE==8) + void* _Znwm(size_t n) MI_FORWARD1(mi_new,n); // new 64-bit + void* _Znam(size_t n) MI_FORWARD1(mi_new,n); // new[] 64-bit + void* _ZnwmSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnamSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #elif (MI_INTPTR_SIZE==4) + void* _Znwj(size_t n) MI_FORWARD1(mi_new,n); // new 64-bit + void* _Znaj(size_t n) MI_FORWARD1(mi_new,n); // new[] 64-bit + void* _ZnwjSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnajSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #else + #error "define overloads for new/delete for this platform (just for performance, can be skipped)" + #endif +#endif // __cplusplus + + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +void cfree(void* p) MI_FORWARD0(mi_free, p); +void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize); +size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p); +#if !defined(__ANDROID__) +size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p); +#else +size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p); +#endif + +// no forwarding here due to aliasing/name mangling issues +void* valloc(size_t size) { return mi_valloc(size); } +void* pvalloc(size_t size) { return mi_pvalloc(size); } +void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); } +void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } +int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); } +void* _aligned_malloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } + +// on some glibc `aligned_alloc` is declared `static inline` so we cannot override it (e.g. Conda). This happens +// when _GLIBCXX_HAVE_ALIGNED_ALLOC is not defined. However, in those cases it will use `memalign`, `posix_memalign`, +// or `_aligned_malloc` and we can avoid overriding it ourselves. +// We should always override if using C compilation. (issue #276) +#if _GLIBCXX_HAVE_ALIGNED_ALLOC || !defined(__cplusplus) +void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } +#endif + + +#if defined(__GLIBC__) && defined(__linux__) + // forward __libc interface (needed for glibc-based Linux distributions) + void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc,size); + void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc,count,size); + void* __libc_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc,p,size); + void __libc_free(void* p) MI_FORWARD0(mi_free,p); + void __libc_cfree(void* p) MI_FORWARD0(mi_free,p); + + void* __libc_valloc(size_t size) { return mi_valloc(size); } + void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); } + void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); } + int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); } +#endif + +#ifdef __cplusplus +} +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) +#pragma GCC visibility pop +#endif + +#endif // MI_MALLOC_OVERRIDE && !_WIN32 diff --git a/deps/mimalloc/src/alloc-posix.c b/deps/mimalloc/src/alloc-posix.c new file mode 100644 index 000000000..1ba1509b6 --- /dev/null +++ b/deps/mimalloc/src/alloc-posix.c @@ -0,0 +1,157 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// ------------------------------------------------------------------------ +// mi prefixed publi definitions of various Posix, Unix, and C++ functions +// for convenience and used when overriding these functions. +// ------------------------------------------------------------------------ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +#include +#include // memcpy +#include // getenv + +#ifdef _MSC_VER +#pragma warning(disable:4996) // getenv _wgetenv +#endif + +#ifndef EINVAL +#define EINVAL 22 +#endif +#ifndef ENOMEM +#define ENOMEM 12 +#endif + + +size_t mi_malloc_size(const void* p) mi_attr_noexcept { + return mi_usable_size(p); +} + +size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept { + return mi_usable_size(p); +} + +void mi_cfree(void* p) mi_attr_noexcept { + if (mi_is_in_heap_region(p)) { + mi_free(p); + } +} + +int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { + // Note: The spec dictates we should not modify `*p` on an error. (issue#27) + // + if (p == NULL) return EINVAL; + if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment + if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 + void* q = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + if (q==NULL && size != 0) return ENOMEM; + mi_assert_internal(((uintptr_t)q % alignment) == 0); + *p = q; + return 0; +} + +mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { + void* p = (mi_malloc_satisfies_alignment(alignment,size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept { + return mi_memalign( _mi_os_page_size(), size ); +} + +mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept { + size_t psize = _mi_os_page_size(); + if (size >= SIZE_MAX - psize) return NULL; // overflow + size_t asize = _mi_align_up(size, psize); + return mi_malloc_aligned(asize, psize); +} + +mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { + if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; + if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see + void* p = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD + void* newp = mi_reallocn(p,count,size); + if (newp==NULL) errno = ENOMEM; + return newp; +} + +void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft + void* res = mi_expand(p, newsize); + if (res == NULL) errno = ENOMEM; + return res; +} + +mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { + if (s==NULL) return NULL; + size_t len; + for(len = 0; s[len] != 0; len++) { } + size_t size = (len+1)*sizeof(unsigned short); + unsigned short* p = (unsigned short*)mi_malloc(size); + if (p != NULL) { + memcpy(p,s,size); + } + return p; +} + +mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { + return (unsigned char*)mi_strdup((const char*)s); +} + +int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; + char* p = getenv(name); // mscver warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_strdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = strlen(p); + } + return 0; +} + +int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; +#if !defined(_WIN32) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)) + // not supported + *buf = NULL; + return EINVAL; +#else + unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name); // msvc warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_wcsdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = wcslen((const wchar_t*)p); + } + return 0; +#endif +} + +void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned_at(p, newcount, size, alignment, offset); +} + +void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned(p, newcount, size, alignment); +} diff --git a/deps/mimalloc/src/alloc.c b/deps/mimalloc/src/alloc.c new file mode 100644 index 000000000..8e863a67d --- /dev/null +++ b/deps/mimalloc/src/alloc.c @@ -0,0 +1,855 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset, memcpy, strlen +#include // malloc, exit + +#define MI_IN_ALLOC_C +#include "alloc-override.c" +#undef MI_IN_ALLOC_C + +// ------------------------------------------------------ +// Allocation +// ------------------------------------------------------ + +// Fast allocation in a page: just pop from the free list. +// Fall back to generic allocation only if the list is empty. +extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept { + mi_assert_internal(page->xblock_size==0||mi_page_block_size(page) >= size); + mi_block_t* block = page->free; + if (mi_unlikely(block == NULL)) { + return _mi_malloc_generic(heap, size); + } + mi_assert_internal(block != NULL && _mi_ptr_page(block) == page); + // pop from the free list + page->free = mi_block_next(page, block); + page->used++; + mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); +#if (MI_DEBUG>0) + if (!page->is_zero) { memset(block, MI_DEBUG_UNINIT, size); } +#elif (MI_SECURE!=0) + block->next = 0; // don't leak internal data +#endif +#if (MI_STAT>1) + const size_t bsize = mi_page_usable_block_size(page); + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + const size_t bin = _mi_bin(bsize); + mi_heap_stat_increase(heap, normal[bin], 1); + } +#endif +#if (MI_PADDING > 0) && defined(MI_ENCODE_FREELIST) + mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page)); + ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE)); + mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta)); + padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys)); + padding->delta = (uint32_t)(delta); + uint8_t* fill = (uint8_t*)padding - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes + for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; } +#endif + return block; +} + +// allocate a small block +extern inline mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept { + mi_assert(heap!=NULL); + mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local + mi_assert(size <= MI_SMALL_SIZE_MAX); + #if (MI_PADDING) + if (size == 0) { + size = sizeof(void*); + } + #endif + mi_page_t* page = _mi_heap_get_free_small_page(heap,size + MI_PADDING_SIZE); + void* p = _mi_page_malloc(heap, page, size + MI_PADDING_SIZE); + mi_assert_internal(p==NULL || mi_usable_size(p) >= size); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + return p; +} + +extern inline mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept { + return mi_heap_malloc_small(mi_get_default_heap(), size); +} + +// The main allocation function +extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + if (mi_likely(size <= MI_SMALL_SIZE_MAX)) { + return mi_heap_malloc_small(heap, size); + } + else { + mi_assert(heap!=NULL); + mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local + void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE); // note: size can overflow but it is detected in malloc_generic + mi_assert_internal(p == NULL || mi_usable_size(p) >= size); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + return p; + } +} + +extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept { + return mi_heap_malloc(mi_get_default_heap(), size); +} + + +void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size) { + // note: we need to initialize the whole usable block size to zero, not just the requested size, + // or the recalloc/rezalloc functions cannot safely expand in place (see issue #63) + UNUSED(size); + mi_assert_internal(p != NULL); + mi_assert_internal(mi_usable_size(p) >= size); // size can be zero + mi_assert_internal(_mi_ptr_page(p)==page); + if (page->is_zero && size > sizeof(mi_block_t)) { + // already zero initialized memory + ((mi_block_t*)p)->next = 0; // clear the free list pointer + mi_assert_expensive(mi_mem_is_zero(p, mi_usable_size(p))); + } + else { + // otherwise memset + memset(p, 0, mi_usable_size(p)); + } +} + +// zero initialized small block +mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept { + void* p = mi_malloc_small(size); + if (p != NULL) { + _mi_block_zero_init(_mi_ptr_page(p), p, size); // todo: can we avoid getting the page again? + } + return p; +} + +void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) { + void* p = mi_heap_malloc(heap,size); + if (zero && p != NULL) { + _mi_block_zero_init(_mi_ptr_page(p),p,size); // todo: can we avoid getting the page again? + } + return p; +} + +extern inline mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + return _mi_heap_malloc_zero(heap, size, true); +} + +mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept { + return mi_heap_zalloc(mi_get_default_heap(),size); +} + + +// ------------------------------------------------------ +// Check for double free in secure and debug mode +// This is somewhat expensive so only enabled for secure mode 4 +// ------------------------------------------------------ + +#if (MI_ENCODE_FREELIST && (MI_SECURE>=4 || MI_DEBUG!=0)) +// linear check if the free list contains a specific element +static bool mi_list_contains(const mi_page_t* page, const mi_block_t* list, const mi_block_t* elem) { + while (list != NULL) { + if (elem==list) return true; + list = mi_block_next(page, list); + } + return false; +} + +static mi_decl_noinline bool mi_check_is_double_freex(const mi_page_t* page, const mi_block_t* block) { + // The decoded value is in the same page (or NULL). + // Walk the free lists to verify positively if it is already freed + if (mi_list_contains(page, page->free, block) || + mi_list_contains(page, page->local_free, block) || + mi_list_contains(page, mi_page_thread_free(page), block)) + { + _mi_error_message(EAGAIN, "double free detected of block %p with size %zu\n", block, mi_page_block_size(page)); + return true; + } + return false; +} + +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + mi_block_t* n = mi_block_nextx(page, block, page->keys); // pretend it is freed, and get the decoded first field + if (((uintptr_t)n & (MI_INTPTR_SIZE-1))==0 && // quick check: aligned pointer? + (n==NULL || mi_is_in_same_page(block, n))) // quick check: in same page or NULL? + { + // Suspicous: decoded value a in block is in the same page (or NULL) -- maybe a double free? + // (continue in separate function to improve code generation) + return mi_check_is_double_freex(page, block); + } + return false; +} +#else +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + UNUSED(page); + UNUSED(block); + return false; +} +#endif + +// --------------------------------------------------------------------------- +// Check for heap block overflow by setting up padding at the end of the block +// --------------------------------------------------------------------------- + +#if (MI_PADDING>0) && defined(MI_ENCODE_FREELIST) +static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) { + *bsize = mi_page_usable_block_size(page); + const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize); + *delta = padding->delta; + return ((uint32_t)mi_ptr_encode(page,block,page->keys) == padding->canary && *delta <= *bsize); +} + +// Return the exact usable size of a block. +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); mi_assert_internal(delta <= bsize); + return (ok ? bsize - delta : 0); +} + +static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, size_t* size, size_t* wrong) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + *size = *wrong = bsize; + if (!ok) return false; + mi_assert_internal(bsize >= delta); + *size = bsize - delta; + uint8_t* fill = (uint8_t*)block + bsize - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // check at most the first N padding bytes + for (size_t i = 0; i < maxpad; i++) { + if (fill[i] != MI_DEBUG_PADDING) { + *wrong = bsize - delta + i; + return false; + } + } + return true; +} + +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + size_t size; + size_t wrong; + if (!mi_verify_padding(page,block,&size,&wrong)) { + _mi_error_message(EFAULT, "buffer overflow in heap block %p of size %zu: write after %zu bytes\n", block, size, wrong ); + } +} + +// When a non-thread-local block is freed, it becomes part of the thread delayed free +// list that is freed later by the owning heap. If the exact usable size is too small to +// contain the pointer for the delayed list, then shrink the padding (by decreasing delta) +// so it will later not trigger an overflow error in `mi_free_block`. +static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); + if (!ok || (bsize - delta) >= min_size) return; // usually already enough space + mi_assert_internal(bsize >= min_size); + if (bsize < min_size) return; // should never happen + size_t new_delta = (bsize - min_size); + mi_assert_internal(new_delta < bsize); + mi_padding_t* padding = (mi_padding_t*)((uint8_t*)block + bsize); + padding->delta = (uint32_t)new_delta; +} +#else +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + UNUSED(page); + UNUSED(block); +} + +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + UNUSED(block); + return mi_page_usable_block_size(page); +} + +static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + UNUSED(page); + UNUSED(block); + UNUSED(min_size); +} +#endif + +// ------------------------------------------------------ +// Free +// ------------------------------------------------------ + +// multi-threaded free +static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* block) +{ + // The padding check may access the non-thread-owned page for the key values. + // that is safe as these are constant and the page won't be freed (as the block is not freed yet). + mi_check_padding(page, block); + mi_padding_shrink(page, block, sizeof(mi_block_t)); // for small size, ensure we can fit the delayed thread pointers without triggering overflow detection + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_usable_size(block)); + #endif + + // huge page segments are always abandoned and can be freed immediately + mi_segment_t* const segment = _mi_page_segment(page); + if (segment->page_kind==MI_PAGE_HUGE) { + _mi_segment_huge_page_free(segment, page, block); + return; + } + + // Try to put the block on either the page-local thread free list, or the heap delayed free list. + mi_thread_free_t tfreex; + bool use_delayed; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + use_delayed = (mi_tf_delayed(tfree) == MI_USE_DELAYED_FREE); + if (mi_unlikely(use_delayed)) { + // unlikely: this only happens on the first concurrent free in a page that is in the full list + tfreex = mi_tf_set_delayed(tfree,MI_DELAYED_FREEING); + } + else { + // usual: directly add to page thread_free list + mi_block_set_next(page, block, mi_tf_block(tfree)); + tfreex = mi_tf_set_block(tfree,block); + } + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + + if (mi_unlikely(use_delayed)) { + // racy read on `heap`, but ok because MI_DELAYED_FREEING is set (see `mi_heap_delete` and `mi_heap_collect_abandon`) + mi_heap_t* const heap = (mi_heap_t*)(mi_atomic_load_acquire(&page->xheap)); //mi_page_heap(page); + mi_assert_internal(heap != NULL); + if (heap != NULL) { + // add to the delayed free list of this heap. (do this atomically as the lock only protects heap memory validity) + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap,block,dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + + // and reset the MI_DELAYED_FREEING flag + tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + tfreex = tfree; + mi_assert_internal(mi_tf_delayed(tfree) == MI_DELAYED_FREEING); + tfreex = mi_tf_set_delayed(tfree,MI_NO_DELAYED_FREE); + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + } +} + + +// regular free +static inline void _mi_free_block(mi_page_t* page, bool local, mi_block_t* block) +{ + // and push it on the free list + if (mi_likely(local)) { + // owning thread can free a block directly + if (mi_unlikely(mi_check_is_double_free(page, block))) return; + mi_check_padding(page, block); + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + #endif + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + page->used--; + if (mi_unlikely(mi_page_all_free(page))) { + _mi_page_retire(page); + } + else if (mi_unlikely(mi_page_is_in_full(page))) { + _mi_page_unfull(page); + } + } + else { + _mi_free_block_mt(page,block); + } +} + + +// Adjust a block that was allocated aligned, to the actual start of the block in the page. +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p) { + mi_assert_internal(page!=NULL && p!=NULL); + const size_t diff = (uint8_t*)p - _mi_page_start(segment, page, NULL); + const size_t adjust = (diff % mi_page_block_size(page)); + return (mi_block_t*)((uintptr_t)p - adjust); +} + + +static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) { + mi_page_t* const page = _mi_segment_page_of(segment, p); + mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p); + _mi_free_block(page, local, block); +} + +// Get the segment data belonging to a pointer +// This is just a single `and` in assembly but does further checks in debug mode +// (and secure mode) if this was a valid pointer. +static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* msg) +{ + UNUSED(msg); +#if (MI_DEBUG>0) + if (mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0)) { + _mi_error_message(EINVAL, "%s: invalid (unaligned) pointer: %p\n", msg, p); + return NULL; + } +#endif + + mi_segment_t* const segment = _mi_ptr_segment(p); + if (mi_unlikely(segment == NULL)) return NULL; // checks also for (p==NULL) + +#if (MI_DEBUG>0) + if (mi_unlikely(!mi_is_in_heap_region(p))) { + _mi_warning_message("%s: pointer might not point to a valid heap region: %p\n" + "(this may still be a valid very large allocation (over 64MiB))\n", msg, p); + if (mi_likely(_mi_ptr_cookie(segment) == segment->cookie)) { + _mi_warning_message("(yes, the previous pointer %p was valid after all)\n", p); + } + } +#endif +#if (MI_DEBUG>0 || MI_SECURE>=4) + if (mi_unlikely(_mi_ptr_cookie(segment) != segment->cookie)) { + _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", p); + } +#endif + return segment; +} + + +// Free a block +void mi_free(void* p) mi_attr_noexcept +{ + const mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free"); + if (mi_unlikely(segment == NULL)) return; + + const uintptr_t tid = _mi_thread_id(); + mi_page_t* const page = _mi_segment_page_of(segment, p); + mi_block_t* const block = (mi_block_t*)p; + +#if (MI_STAT>1) + mi_heap_t* const heap = mi_heap_get_default(); + const size_t bsize = mi_page_usable_block_size(page); + mi_heap_stat_decrease(heap, malloc, bsize); + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { // huge page stats are accounted for in `_mi_page_retire` + mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], 1); + } +#endif + + if (mi_likely(tid == segment->thread_id && page->flags.full_aligned == 0)) { // the thread id matches and it is not a full page, nor has aligned blocks + // local, and not full or aligned + if (mi_unlikely(mi_check_is_double_free(page,block))) return; + mi_check_padding(page, block); + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + #endif + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + if (mi_unlikely(--page->used == 0)) { // using this expression generates better code than: page->used--; if (mi_page_all_free(page)) + _mi_page_retire(page); + } + } + else { + // non-local, aligned blocks, or a full page; use the more generic path + // note: recalc page in generic to improve code generation + mi_free_generic(segment, tid == segment->thread_id, p); + } +} + +bool _mi_free_delayed_block(mi_block_t* block) { + // get segment and page + const mi_segment_t* const segment = _mi_ptr_segment(block); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(_mi_thread_id() == segment->thread_id); + mi_page_t* const page = _mi_segment_page_of(segment, block); + + // Clear the no-delayed flag so delayed freeing is used again for this page. + // This must be done before collecting the free lists on this page -- otherwise + // some blocks may end up in the page `thread_free` list with no blocks in the + // heap `thread_delayed_free` list which may cause the page to be never freed! + // (it would only be freed if we happen to scan it in `mi_page_queue_find_free_ex`) + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, false /* dont overwrite never delayed */); + + // collect all other non-local frees to ensure up-to-date `used` count + _mi_page_free_collect(page, false); + + // and free the block (possibly freeing the page as well since used is updated) + _mi_free_block(page, true, block); + return true; +} + +// Bytes available in a block +static size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept { + const mi_segment_t* const segment = mi_checked_ptr_segment(p,msg); + if (segment==NULL) return 0; + const mi_page_t* const page = _mi_segment_page_of(segment, p); + const mi_block_t* block = (const mi_block_t*)p; + if (mi_unlikely(mi_page_has_aligned(page))) { + block = _mi_page_ptr_unalign(segment, page, p); + size_t size = mi_page_usable_size_of(page, block); + ptrdiff_t const adjust = (uint8_t*)p - (uint8_t*)block; + mi_assert_internal(adjust >= 0 && (size_t)adjust <= size); + return (size - adjust); + } + else { + return mi_page_usable_size_of(page, block); + } +} + +size_t mi_usable_size(const void* p) mi_attr_noexcept { + return _mi_usable_size(p, "mi_usable_size"); +} + + +// ------------------------------------------------------ +// ensure explicit external inline definitions are emitted! +// ------------------------------------------------------ + +#ifdef __cplusplus +void* _mi_externs[] = { + (void*)&_mi_page_malloc, + (void*)&mi_malloc, + (void*)&mi_malloc_small, + (void*)&mi_heap_malloc, + (void*)&mi_heap_zalloc, + (void*)&mi_heap_malloc_small +}; +#endif + + +// ------------------------------------------------------ +// Allocation extensions +// ------------------------------------------------------ + +void mi_free_size(void* p, size_t size) mi_attr_noexcept { + UNUSED_RELEASE(size); + mi_assert(p == NULL || size <= _mi_usable_size(p,"mi_free_size")); + mi_free(p); +} + +void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept { + UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free_size(p,size); +} + +void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept { + UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free(p); +} + +extern inline mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count,size,&total)) return NULL; + return mi_heap_zalloc(heap,total); +} + +mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_calloc(mi_get_default_heap(),count,size); +} + +// Uninitialized `calloc` +extern mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_malloc(heap, total); +} + +mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_mallocn(mi_get_default_heap(),count,size); +} + +// Expand in place or fail +void* mi_expand(void* p, size_t newsize) mi_attr_noexcept { + if (p == NULL) return NULL; + size_t size = _mi_usable_size(p,"mi_expand"); + if (newsize > size) return NULL; + return p; // it fits +} + +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) { + if (p == NULL) return _mi_heap_malloc_zero(heap,newsize,zero); + size_t size = _mi_usable_size(p,"mi_realloc"); + if (newsize <= size && newsize >= (size / 2)) { + return p; // reallocation still fits and not more than 50% waste + } + void* newp = mi_heap_malloc(heap,newsize); + if (mi_likely(newp != NULL)) { + if (zero && newsize > size) { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + memset((uint8_t*)newp + start, 0, newsize - start); + } + memcpy(newp, p, (newsize > size ? size : newsize)); + mi_free(p); // only free if successful + } + return newp; +} + +void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, false); +} + +void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_realloc(heap, p, total); +} + + +// Reallocate but free `p` on errors +void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + void* newp = mi_heap_realloc(heap, p, newsize); + if (newp==NULL && p!=NULL) mi_free(p); + return newp; +} + +void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, true); +} + +void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_rezalloc(heap, p, total); +} + + +void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_realloc(mi_get_default_heap(),p,newsize); +} + +void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_reallocn(mi_get_default_heap(),p,count,size); +} + +// Reallocate but free `p` on errors +void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_reallocf(mi_get_default_heap(),p,newsize); +} + +void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_rezalloc(mi_get_default_heap(), p, newsize); +} + +void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_recalloc(mi_get_default_heap(), p, count, size); +} + + + +// ------------------------------------------------------ +// strdup, strndup, and realpath +// ------------------------------------------------------ + +// `strdup` using mi_malloc +mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept { + if (s == NULL) return NULL; + size_t n = strlen(s); + char* t = (char*)mi_heap_malloc(heap,n+1); + if (t != NULL) memcpy(t, s, n + 1); + return t; +} + +mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept { + return mi_heap_strdup(mi_get_default_heap(), s); +} + +// `strndup` using mi_malloc +mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { + if (s == NULL) return NULL; + const char* end = (const char*)memchr(s, 0, n); // find end of string in the first `n` characters (returns NULL if not found) + const size_t m = (end != NULL ? (size_t)(end - s) : n); // `m` is the minimum of `n` or the end-of-string + mi_assert_internal(m <= n); + char* t = (char*)mi_heap_malloc(heap, m+1); + if (t == NULL) return NULL; + memcpy(t, s, m); + t[m] = 0; + return t; +} + +mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept { + return mi_heap_strndup(mi_get_default_heap(),s,n); +} + +#ifndef __wasi__ +// `realpath` using mi_malloc +#ifdef _WIN32 +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#include +mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + // todo: use GetFullPathNameW to allow longer file names + char buf[PATH_MAX]; + DWORD res = GetFullPathNameA(fname, PATH_MAX, (resolved_name == NULL ? buf : resolved_name), NULL); + if (res == 0) { + errno = GetLastError(); return NULL; + } + else if (res > PATH_MAX) { + errno = EINVAL; return NULL; + } + else if (resolved_name != NULL) { + return resolved_name; + } + else { + return mi_heap_strndup(heap, buf, PATH_MAX); + } +} +#else +#include // pathconf +static size_t mi_path_max() { + static size_t path_max = 0; + if (path_max <= 0) { + long m = pathconf("/",_PC_PATH_MAX); + if (m <= 0) path_max = 4096; // guess + else if (m < 256) path_max = 256; // at least 256 + else path_max = m; + } + return path_max; +} + +char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + if (resolved_name != NULL) { + return realpath(fname,resolved_name); + } + else { + size_t n = mi_path_max(); + char* buf = (char*)mi_malloc(n+1); + if (buf==NULL) return NULL; + char* rname = realpath(fname,buf); + char* result = mi_heap_strndup(heap,rname,n); // ok if `rname==NULL` + mi_free(buf); + return result; + } +} +#endif + +mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept { + return mi_heap_realpath(mi_get_default_heap(),fname,resolved_name); +} +#endif + +/*------------------------------------------------------- +C++ new and new_aligned +The standard requires calling into `get_new_handler` and +throwing the bad_alloc exception on failure. If we compile +with a C++ compiler we can implement this precisely. If we +use a C compiler we cannot throw a `bad_alloc` exception +but we call `exit` instead (i.e. not returning). +-------------------------------------------------------*/ + +#ifdef __cplusplus +#include +static bool mi_try_new_handler(bool nothrow) { + std::new_handler h = std::get_new_handler(); + if (h==NULL) { + if (!nothrow) throw std::bad_alloc(); + return false; + } + else { + h(); + return true; + } +} +#else +typedef void (*std_new_handler_t)(); + +#if (defined(__GNUC__) || defined(__clang__)) +std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv() { + return NULL; +} +static std_new_handler_t mi_get_new_handler() { + return _ZSt15get_new_handlerv(); +} +#else +// note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`. +static std_new_handler_t mi_get_new_handler() { + return NULL; +} +#endif + +static bool mi_try_new_handler(bool nothrow) { + std_new_handler_t h = mi_get_new_handler(); + if (h==NULL) { + if (!nothrow) exit(ENOMEM); // cannot throw in plain C, use exit as we are out of memory anyway. + return false; + } + else { + h(); + return true; + } +} +#endif + +static mi_decl_noinline void* mi_try_new(size_t size, bool nothrow ) { + void* p = NULL; + while(p == NULL && mi_try_new_handler(nothrow)) { + p = mi_malloc(size); + } + return p; +} + +mi_decl_restrict void* mi_new(size_t size) { + void* p = mi_malloc(size); + if (mi_unlikely(p == NULL)) return mi_try_new(size,false); + return p; +} + +mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept { + void* p = mi_malloc(size); + if (mi_unlikely(p == NULL)) return mi_try_new(size, true); + return p; +} + +mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(false)); + return p; +} + +mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(true)); + return p; +} + +mi_decl_restrict void* mi_new_n(size_t count, size_t size) { + size_t total; + if (mi_unlikely(mi_count_size_overflow(count, size, &total))) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_new(total); + } +} + +void* mi_new_realloc(void* p, size_t newsize) { + void* q; + do { + q = mi_realloc(p, newsize); + } while (q == NULL && mi_try_new_handler(false)); + return q; +} + +void* mi_new_reallocn(void* p, size_t newcount, size_t size) { + size_t total; + if (mi_unlikely(mi_count_size_overflow(newcount, size, &total))) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_new_realloc(p, total); + } +} diff --git a/deps/mimalloc/src/arena.c b/deps/mimalloc/src/arena.c new file mode 100644 index 000000000..73a7e7043 --- /dev/null +++ b/deps/mimalloc/src/arena.c @@ -0,0 +1,357 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +"Arenas" are fixed area's of OS memory from which we can allocate +large blocks (>= MI_ARENA_BLOCK_SIZE, 32MiB). +In contrast to the rest of mimalloc, the arenas are shared between +threads and need to be accessed using atomic operations. + +Currently arenas are only used to for huge OS page (1GiB) reservations, +otherwise it delegates to direct allocation from the OS. +In the future, we can expose an API to manually add more kinds of arenas +which is sometimes needed for embedded devices or shared memory for example. +(We can also employ this with WASI or `sbrk` systems to reserve large arenas + on demand and be able to reuse them efficiently). + +The arena allocation needs to be thread safe and we use an atomic +bitmap to allocate. The current implementation of the bitmap can +only do this within a field (`uintptr_t`) so we can allocate at most +blocks of 2GiB (64*32MiB) and no object can cross the boundary. This +can lead to fragmentation but fortunately most objects will be regions +of 256MiB in practice. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset + +#include "bitmap.inc.c" // atomic bitmap + + +// os.c +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld); +void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats); +void _mi_os_free(void* p, size_t size, mi_stats_t* stats); + +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize); +void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats); + +bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); + +/* ----------------------------------------------------------- + Arena allocation +----------------------------------------------------------- */ + +#define MI_SEGMENT_ALIGN MI_SEGMENT_SIZE +#define MI_ARENA_BLOCK_SIZE (8*MI_SEGMENT_ALIGN) // 32MiB +#define MI_ARENA_MAX_OBJ_SIZE (MI_BITMAP_FIELD_BITS * MI_ARENA_BLOCK_SIZE) // 2GiB +#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2) // 16MiB +#define MI_MAX_ARENAS (64) // not more than 256 (since we use 8 bits in the memid) + +// A memory arena descriptor +typedef struct mi_arena_s { + _Atomic(uint8_t*) start; // the start of the memory area + size_t block_count; // size of the area in arena blocks (of `MI_ARENA_BLOCK_SIZE`) + size_t field_count; // number of bitmap fields (where `field_count * MI_BITMAP_FIELD_BITS >= block_count`) + int numa_node; // associated NUMA node + bool is_zero_init; // is the arena zero initialized? + bool is_committed; // is the memory committed + bool is_large; // large OS page allocated + _Atomic(uintptr_t) search_idx; // optimization to start the search for free blocks + mi_bitmap_field_t* blocks_dirty; // are the blocks potentially non-zero? + mi_bitmap_field_t* blocks_committed; // if `!is_committed`, are the blocks committed? + mi_bitmap_field_t blocks_inuse[1]; // in-place bitmap of in-use blocks (of size `field_count`) +} mi_arena_t; + + +// The available arenas +static mi_decl_cache_align _Atomic(mi_arena_t*) mi_arenas[MI_MAX_ARENAS]; +static mi_decl_cache_align _Atomic(uintptr_t) mi_arena_count; // = 0 + + +/* ----------------------------------------------------------- + Arena allocations get a memory id where the lower 8 bits are + the arena index +1, and the upper bits the block index. +----------------------------------------------------------- */ + +// Use `0` as a special id for direct OS allocated memory. +#define MI_MEMID_OS 0 + +static size_t mi_arena_id_create(size_t arena_index, mi_bitmap_index_t bitmap_index) { + mi_assert_internal(arena_index < 0xFE); + mi_assert_internal(((bitmap_index << 8) >> 8) == bitmap_index); // no overflow? + return ((bitmap_index << 8) | ((arena_index+1) & 0xFF)); +} + +static void mi_arena_id_indices(size_t memid, size_t* arena_index, mi_bitmap_index_t* bitmap_index) { + mi_assert_internal(memid != MI_MEMID_OS); + *arena_index = (memid & 0xFF) - 1; + *bitmap_index = (memid >> 8); +} + +static size_t mi_block_count_of_size(size_t size) { + return _mi_divide_up(size, MI_ARENA_BLOCK_SIZE); +} + +/* ----------------------------------------------------------- + Thread safe allocation in an arena +----------------------------------------------------------- */ +static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx) +{ + const size_t fcount = arena->field_count; + size_t idx = mi_atomic_load_acquire(&arena->search_idx); // start from last search + for (size_t visited = 0; visited < fcount; visited++, idx++) { + if (idx >= fcount) idx = 0; // wrap around + // try to atomically claim a range of bits + if (mi_bitmap_try_find_claim_field(arena->blocks_inuse, idx, blocks, bitmap_idx)) { + mi_atomic_store_release(&arena->search_idx, idx); // start search from here next time + return true; + } + } + return false; +} + + +/* ----------------------------------------------------------- + Arena Allocation +----------------------------------------------------------- */ + +static void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t needed_bcount, + bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_bitmap_index_t bitmap_index; + if (!mi_arena_alloc(arena, needed_bcount, &bitmap_index)) return NULL; + + // claimed it! set the dirty bits (todo: no need for an atomic op here?) + void* p = arena->start + (mi_bitmap_index_bit(bitmap_index)*MI_ARENA_BLOCK_SIZE); + *memid = mi_arena_id_create(arena_index, bitmap_index); + *is_zero = mi_bitmap_claim(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL); + *large = arena->is_large; + if (arena->is_committed) { + // always committed + *commit = true; + } + else if (*commit) { + // arena not committed as a whole, but commit requested: ensure commit now + bool any_uncommitted; + mi_bitmap_claim(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted); + if (any_uncommitted) { + bool commit_zero; + _mi_os_commit(p, needed_bcount * MI_ARENA_BLOCK_SIZE, &commit_zero, tld->stats); + if (commit_zero) *is_zero = true; + } + } + else { + // no need to commit, but check if already fully committed + *commit = mi_bitmap_is_claimed(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index); + } + return p; +} + +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, + bool* commit, bool* large, bool* is_zero, + size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(commit != NULL && large != NULL && is_zero != NULL && memid != NULL && tld != NULL); + mi_assert_internal(size > 0); + *memid = MI_MEMID_OS; + *is_zero = false; + + // try to allocate in an arena if the alignment is small enough + // and the object is not too large or too small. + if (alignment <= MI_SEGMENT_ALIGN && + size <= MI_ARENA_MAX_OBJ_SIZE && + size >= MI_ARENA_MIN_OBJ_SIZE) + { + const size_t bcount = mi_block_count_of_size(size); + const int numa_node = _mi_os_numa_node(tld); // current numa node + + mi_assert_internal(size <= bcount*MI_ARENA_BLOCK_SIZE); + // try numa affine allocation + for (size_t i = 0; i < MI_MAX_ARENAS; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); + if (arena==NULL) break; // end reached + if ((arena->numa_node<0 || arena->numa_node==numa_node) && // numa local? + (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages + { + void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld); + mi_assert_internal((uintptr_t)p % alignment == 0); + if (p != NULL) return p; + } + } + // try from another numa node instead.. + for (size_t i = 0; i < MI_MAX_ARENAS; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); + if (arena==NULL) break; // end reached + if ((arena->numa_node>=0 && arena->numa_node!=numa_node) && // not numa local! + (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages + { + void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld); + mi_assert_internal((uintptr_t)p % alignment == 0); + if (p != NULL) return p; + } + } + } + + // finally, fall back to the OS + *is_zero = true; + *memid = MI_MEMID_OS; + return _mi_os_alloc_aligned(size, alignment, *commit, large, tld); +} + +void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, commit, large, is_zero, memid, tld); +} + +/* ----------------------------------------------------------- + Arena free +----------------------------------------------------------- */ + +void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats) { + mi_assert_internal(size > 0 && stats != NULL); + if (p==NULL) return; + if (size==0) return; + if (memid == MI_MEMID_OS) { + // was a direct OS allocation, pass through + _mi_os_free_ex(p, size, all_committed, stats); + } + else { + // allocated in an arena + size_t arena_idx; + size_t bitmap_idx; + mi_arena_id_indices(memid, &arena_idx, &bitmap_idx); + mi_assert_internal(arena_idx < MI_MAX_ARENAS); + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t,&mi_arenas[arena_idx]); + mi_assert_internal(arena != NULL); + if (arena == NULL) { + _mi_error_message(EINVAL, "trying to free from non-existent arena: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + mi_assert_internal(arena->field_count > mi_bitmap_index_field(bitmap_idx)); + if (arena->field_count <= mi_bitmap_index_field(bitmap_idx)) { + _mi_error_message(EINVAL, "trying to free from non-existent arena block: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + const size_t blocks = mi_block_count_of_size(size); + bool ones = mi_bitmap_unclaim(arena->blocks_inuse, arena->field_count, blocks, bitmap_idx); + if (!ones) { + _mi_error_message(EAGAIN, "trying to free an already freed block: %p, size %zu\n", p, size); + return; + }; + } +} + +/* ----------------------------------------------------------- + Add an arena. +----------------------------------------------------------- */ + +static bool mi_arena_add(mi_arena_t* arena) { + mi_assert_internal(arena != NULL); + mi_assert_internal((uintptr_t)mi_atomic_load_ptr_relaxed(uint8_t,&arena->start) % MI_SEGMENT_ALIGN == 0); + mi_assert_internal(arena->block_count > 0); + + uintptr_t i = mi_atomic_increment_acq_rel(&mi_arena_count); + if (i >= MI_MAX_ARENAS) { + mi_atomic_decrement_acq_rel(&mi_arena_count); + return false; + } + mi_atomic_store_ptr_release(mi_arena_t,&mi_arenas[i], arena); + return true; +} + + +/* ----------------------------------------------------------- + Reserve a huge page arena. +----------------------------------------------------------- */ +#include // ENOMEM + +// reserve at a specific numa node +int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept { + if (pages==0) return 0; + if (numa_node < -1) numa_node = -1; + if (numa_node >= 0) numa_node = numa_node % _mi_os_numa_node_count(); + size_t hsize = 0; + size_t pages_reserved = 0; + void* p = _mi_os_alloc_huge_os_pages(pages, numa_node, timeout_msecs, &pages_reserved, &hsize); + if (p==NULL || pages_reserved==0) { + _mi_warning_message("failed to reserve %zu gb huge pages\n", pages); + return ENOMEM; + } + _mi_verbose_message("numa node %i: reserved %zu gb huge pages (of the %zu gb requested)\n", numa_node, pages_reserved, pages); + + size_t bcount = mi_block_count_of_size(hsize); + size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS); + size_t asize = sizeof(mi_arena_t) + (2*fields*sizeof(mi_bitmap_field_t)); + mi_arena_t* arena = (mi_arena_t*)_mi_os_alloc(asize, &_mi_stats_main); // TODO: can we avoid allocating from the OS? + if (arena == NULL) { + _mi_os_free_huge_pages(p, hsize, &_mi_stats_main); + return ENOMEM; + } + arena->block_count = bcount; + arena->field_count = fields; + arena->start = (uint8_t*)p; + arena->numa_node = numa_node; // TODO: or get the current numa node if -1? (now it allows anyone to allocate on -1) + arena->is_large = true; + arena->is_zero_init = true; + arena->is_committed = true; + arena->search_idx = 0; + arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap + arena->blocks_committed = NULL; + // the bitmaps are already zero initialized due to os_alloc + // just claim leftover blocks if needed + ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount; + mi_assert_internal(post >= 0); + if (post > 0) { + // don't use leftover bits at the end + mi_bitmap_index_t postidx = mi_bitmap_index_create(fields - 1, MI_BITMAP_FIELD_BITS - post); + mi_bitmap_claim(arena->blocks_inuse, fields, post, postidx, NULL); + } + + mi_arena_add(arena); + return 0; +} + + +// reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected) +int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept { + if (pages == 0) return 0; + + // pages per numa node + size_t numa_count = (numa_nodes > 0 ? numa_nodes : _mi_os_numa_node_count()); + if (numa_count <= 0) numa_count = 1; + const size_t pages_per = pages / numa_count; + const size_t pages_mod = pages % numa_count; + const size_t timeout_per = (timeout_msecs==0 ? 0 : (timeout_msecs / numa_count) + 50); + + // reserve evenly among numa nodes + for (size_t numa_node = 0; numa_node < numa_count && pages > 0; numa_node++) { + size_t node_pages = pages_per; // can be 0 + if (numa_node < pages_mod) node_pages++; + int err = mi_reserve_huge_os_pages_at(node_pages, (int)numa_node, timeout_per); + if (err) return err; + if (pages < node_pages) { + pages = 0; + } + else { + pages -= node_pages; + } + } + + return 0; +} + +int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept { + UNUSED(max_secs); + _mi_warning_message("mi_reserve_huge_os_pages is deprecated: use mi_reserve_huge_os_pages_interleave/at instead\n"); + if (pages_reserved != NULL) *pages_reserved = 0; + int err = mi_reserve_huge_os_pages_interleave(pages, 0, (size_t)(max_secs * 1000.0)); + if (err==0 && pages_reserved!=NULL) *pages_reserved = pages; + return err; +} diff --git a/deps/mimalloc/src/bitmap.inc.c b/deps/mimalloc/src/bitmap.inc.c new file mode 100644 index 000000000..2d6df46e8 --- /dev/null +++ b/deps/mimalloc/src/bitmap.inc.c @@ -0,0 +1,247 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +This file is meant to be included in other files for efficiency. +It implements a bitmap that can set/reset sequences of bits atomically +and is used to concurrently claim memory ranges. + +A bitmap is an array of fields where each field is a machine word (`uintptr_t`) + +A current limitation is that the bit sequences cannot cross fields +and that the sequence must be smaller or equal to the bits in a field. +---------------------------------------------------------------------------- */ +#pragma once +#ifndef MI_BITMAP_C +#define MI_BITMAP_C + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +/* ----------------------------------------------------------- + Bitmap definition +----------------------------------------------------------- */ + +#define MI_BITMAP_FIELD_BITS (8*MI_INTPTR_SIZE) +#define MI_BITMAP_FIELD_FULL (~((uintptr_t)0)) // all bits set + +// An atomic bitmap of `uintptr_t` fields +typedef _Atomic(uintptr_t) mi_bitmap_field_t; +typedef mi_bitmap_field_t* mi_bitmap_t; + +// A bitmap index is the index of the bit in a bitmap. +typedef size_t mi_bitmap_index_t; + +// Create a bit index. +static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) { + mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS); + return (idx*MI_BITMAP_FIELD_BITS) + bitidx; +} + +// Get the field index from a bit index. +static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx / MI_BITMAP_FIELD_BITS); +} + +// Get the bit index in a bitmap field +static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx % MI_BITMAP_FIELD_BITS); +} + +// Get the full bit index +static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) { + return bitmap_idx; +} + + +// The bit mask for a given number of blocks at a specified bit index. +static inline uintptr_t mi_bitmap_mask_(size_t count, size_t bitidx) { + mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS); + if (count == MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL; + return ((((uintptr_t)1 << count) - 1) << bitidx); +} + + +/* ----------------------------------------------------------- + Use bit scan forward/reverse to quickly find the first zero bit if it is available +----------------------------------------------------------- */ +#if defined(_MSC_VER) +#define MI_HAVE_BITSCAN +#include +#ifndef MI_64 +#if MI_INTPTR_SIZE==8 +#define MI_64(f) f##64 +#else +#define MI_64(f) f +#endif +#endif + +static inline size_t mi_bsf(uintptr_t x) { + if (x==0) return 8*MI_INTPTR_SIZE; + DWORD idx; + MI_64(_BitScanForward)(&idx, x); + return idx; +} +static inline size_t mi_bsr(uintptr_t x) { + if (x==0) return 8*MI_INTPTR_SIZE; + DWORD idx; + MI_64(_BitScanReverse)(&idx, x); + return idx; +} +#elif defined(__GNUC__) || defined(__clang__) +#include // LONG_MAX +#define MI_HAVE_BITSCAN +#if (INTPTR_MAX == LONG_MAX) +# define MI_L(x) x##l +#else +# define MI_L(x) x##ll +#endif +static inline size_t mi_bsf(uintptr_t x) { + return (x==0 ? 8*MI_INTPTR_SIZE : MI_L(__builtin_ctz)(x)); +} +static inline size_t mi_bsr(uintptr_t x) { + return (x==0 ? 8*MI_INTPTR_SIZE : (8*MI_INTPTR_SIZE - 1) - MI_L(__builtin_clz)(x)); +} +#endif + +/* ----------------------------------------------------------- + Claim a bit sequence atomically +----------------------------------------------------------- */ + +// Try to atomically claim a sequence of `count` bits at in `idx` +// in the bitmap field. Returns `true` on success. +static inline bool mi_bitmap_try_claim_field(mi_bitmap_t bitmap, size_t bitmap_fields, const size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + mi_assert_internal(bitidx + count <= MI_BITMAP_FIELD_BITS); + + uintptr_t field = mi_atomic_load_relaxed(&bitmap[idx]); + if ((field & mask) == 0) { // free? + if (mi_atomic_cas_strong_acq_rel(&bitmap[idx], &field, (field|mask))) { + // claimed! + return true; + } + } + return false; +} + + +// Try to atomically claim a sequence of `count` bits in a single +// field at `idx` in `bitmap`. Returns `true` on success. +static 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) +{ + mi_assert_internal(bitmap_idx != NULL); + _Atomic(uintptr_t)* field = &bitmap[idx]; + uintptr_t map = mi_atomic_load_relaxed(field); + if (map==MI_BITMAP_FIELD_FULL) return false; // short cut + + // search for 0-bit sequence of length count + const uintptr_t mask = mi_bitmap_mask_(count, 0); + const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count; + +#ifdef MI_HAVE_BITSCAN + size_t bitidx = mi_bsf(~map); // quickly find the first zero bit if possible +#else + size_t bitidx = 0; // otherwise start at 0 +#endif + uintptr_t m = (mask << bitidx); // invariant: m == mask shifted by bitidx + + // scan linearly for a free range of zero bits + while (bitidx <= bitidx_max) { + if ((map & m) == 0) { // are the mask bits free at bitidx? + mi_assert_internal((m >> bitidx) == mask); // no overflow? + const uintptr_t newmap = map | m; + mi_assert_internal((newmap^map) >> bitidx == mask); + if (!mi_atomic_cas_weak_acq_rel(field, &map, newmap)) { // TODO: use strong cas here? + // no success, another thread claimed concurrently.. keep going (with updated `map`) + continue; + } + else { + // success, we claimed the bits! + *bitmap_idx = mi_bitmap_index_create(idx, bitidx); + return true; + } + } + else { + // on to the next bit range +#ifdef MI_HAVE_BITSCAN + const size_t shift = (count == 1 ? 1 : mi_bsr(map & m) - bitidx + 1); + mi_assert_internal(shift > 0 && shift <= count); +#else + const size_t shift = 1; +#endif + bitidx += shift; + m <<= shift; + } + } + // no bits found + return false; +} + + +// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success. +// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never span fields. +static inline bool mi_bitmap_try_find_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t* bitmap_idx) { + for (size_t idx = 0; idx < bitmap_fields; idx++) { + if (mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) { + return true; + } + } + return false; +} + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +static inline bool mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + // mi_assert_internal((bitmap[idx] & mask) == mask); + uintptr_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask); + return ((prev & mask) == mask); +} + + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +static inline bool mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + //mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0); + uintptr_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask); + if (any_zero != NULL) *any_zero = ((prev & mask) != mask); + return ((prev & mask) == 0); +} + +// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one. +static inline 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) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + uintptr_t field = mi_atomic_load_relaxed(&bitmap[idx]); + if (any_ones != NULL) *any_ones = ((field & mask) != 0); + return ((field & mask) == mask); +} + +static inline bool mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL); +} + +static inline bool mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + bool any_ones; + mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones); + return any_ones; +} + + +#endif diff --git a/deps/mimalloc/src/heap.c b/deps/mimalloc/src/heap.c new file mode 100644 index 000000000..b1079e14a --- /dev/null +++ b/deps/mimalloc/src/heap.c @@ -0,0 +1,558 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset, memcpy + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Helpers +----------------------------------------------------------- */ + +// return `true` if ok, `false` to break +typedef bool (heap_page_visitor_fun)(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2); + +// Visit all pages in a heap; returns `false` if break was called. +static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void* arg1, void* arg2) +{ + if (heap==NULL || heap->page_count==0) return 0; + + // visit all pages + #if MI_DEBUG>1 + size_t total = heap->page_count; + #endif + size_t count = 0; + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_t* page = pq->first; + while(page != NULL) { + mi_page_t* next = page->next; // save next in case the page gets removed from the queue + mi_assert_internal(mi_page_heap(page) == heap); + count++; + if (!fn(heap, pq, page, arg1, arg2)) return false; + page = next; // and continue + } + } + mi_assert_internal(count == total); + return true; +} + + +#if MI_DEBUG>=2 +static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(pq); + mi_assert_internal(mi_page_heap(page) == heap); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_internal(segment->thread_id == heap->thread_id); + mi_assert_expensive(_mi_page_is_valid(page)); + return true; +} +#endif +#if MI_DEBUG>=3 +static bool mi_heap_is_valid(mi_heap_t* heap) { + mi_assert_internal(heap!=NULL); + mi_heap_visit_pages(heap, &mi_heap_page_is_valid, NULL, NULL); + return true; +} +#endif + + + + +/* ----------------------------------------------------------- + "Collect" pages by migrating `local_free` and `thread_free` + lists and freeing empty pages. This is done when a thread + stops (and in that case abandons pages if there are still + blocks alive) +----------------------------------------------------------- */ + +typedef enum mi_collect_e { + MI_NORMAL, + MI_FORCE, + MI_ABANDON +} mi_collect_t; + + +static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg_collect, void* arg2 ) { + UNUSED(arg2); + UNUSED(heap); + mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL)); + mi_collect_t collect = *((mi_collect_t*)arg_collect); + _mi_page_free_collect(page, collect >= MI_FORCE); + if (mi_page_all_free(page)) { + // no more used blocks, free the page. + // note: this will free retired pages as well. + _mi_page_free(page, pq, collect >= MI_FORCE); + } + else if (collect == MI_ABANDON) { + // still used blocks but the thread is done; abandon the page + _mi_page_abandon(page, pq); + } + return true; // don't break +} + +static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(heap); + UNUSED(pq); + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + return true; // don't break +} + +static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) +{ + if (!mi_heap_is_initialized(heap)) return; + _mi_deferred_free(heap, collect >= MI_FORCE); + + // note: never reclaim on collect but leave it to threads that need storage to reclaim + if ( + #ifdef NDEBUG + collect == MI_FORCE + #else + collect >= MI_FORCE + #endif + && _mi_is_main_thread() && mi_heap_is_backing(heap) && !heap->no_reclaim) + { + // the main thread is abandoned (end-of-program), try to reclaim all abandoned segments. + // if all memory is freed by now, all segments should be freed. + _mi_abandoned_reclaim_all(heap, &heap->tld->segments); + } + + // if abandoning, mark all pages to no longer add to delayed_free + if (collect == MI_ABANDON) { + mi_heap_visit_pages(heap, &mi_heap_page_never_delayed_free, NULL, NULL); + } + + // free thread delayed blocks. + // (if abandoning, after this there are no more thread-delayed references into the pages.) + _mi_heap_delayed_free(heap); + + // collect retired pages + _mi_heap_collect_retired(heap, collect >= MI_FORCE); + + // collect all pages owned by this thread + mi_heap_visit_pages(heap, &mi_heap_page_collect, &collect, NULL); + mi_assert_internal( collect != MI_ABANDON || mi_atomic_load_ptr_acquire(mi_block_t,&heap->thread_delayed_free) == NULL ); + + // collect segment caches + if (collect >= MI_FORCE) { + _mi_segment_thread_collect(&heap->tld->segments); + } + + // collect regions on program-exit (or shared library unload) + if (collect >= MI_FORCE && _mi_is_main_thread() && mi_heap_is_backing(heap)) { + _mi_mem_collect(&heap->tld->os); + } +} + +void _mi_heap_collect_abandon(mi_heap_t* heap) { + mi_heap_collect_ex(heap, MI_ABANDON); +} + +void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept { + mi_heap_collect_ex(heap, (force ? MI_FORCE : MI_NORMAL)); +} + +void mi_collect(bool force) mi_attr_noexcept { + mi_heap_collect(mi_get_default_heap(), force); +} + + +/* ----------------------------------------------------------- + Heap new +----------------------------------------------------------- */ + +mi_heap_t* mi_heap_get_default(void) { + mi_thread_init(); + return mi_get_default_heap(); +} + +mi_heap_t* mi_heap_get_backing(void) { + mi_heap_t* heap = mi_heap_get_default(); + mi_assert_internal(heap!=NULL); + mi_heap_t* bheap = heap->tld->heap_backing; + mi_assert_internal(bheap!=NULL); + mi_assert_internal(bheap->thread_id == _mi_thread_id()); + return bheap; +} + +mi_heap_t* mi_heap_new(void) { + mi_heap_t* bheap = mi_heap_get_backing(); + mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t); // todo: OS allocate in secure mode? + if (heap==NULL) return NULL; + memcpy(heap, &_mi_heap_empty, sizeof(mi_heap_t)); + heap->tld = bheap->tld; + heap->thread_id = _mi_thread_id(); + _mi_random_split(&bheap->random, &heap->random); + heap->cookie = _mi_heap_random_next(heap) | 1; + heap->keys[0] = _mi_heap_random_next(heap); + heap->keys[1] = _mi_heap_random_next(heap); + heap->no_reclaim = true; // don't reclaim abandoned pages or otherwise destroy is unsafe + // push on the thread local heaps list + heap->next = heap->tld->heaps; + heap->tld->heaps = heap; + return heap; +} + +uintptr_t _mi_heap_random_next(mi_heap_t* heap) { + return _mi_random_next(&heap->random); +} + +// zero out the page queues +static void mi_heap_reset_pages(mi_heap_t* heap) { + mi_assert_internal(mi_heap_is_initialized(heap)); + // TODO: copy full empty heap instead? + memset(&heap->pages_free_direct, 0, sizeof(heap->pages_free_direct)); +#ifdef MI_MEDIUM_DIRECT + memset(&heap->pages_free_medium, 0, sizeof(heap->pages_free_medium)); +#endif + memcpy(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages)); + heap->thread_delayed_free = NULL; + heap->page_count = 0; +} + +// called from `mi_heap_destroy` and `mi_heap_delete` to free the internal heap resources. +static void mi_heap_free(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert_internal(mi_heap_is_initialized(heap)); + if (mi_heap_is_backing(heap)) return; // dont free the backing heap + + // reset default + if (mi_heap_is_default(heap)) { + _mi_heap_set_default_direct(heap->tld->heap_backing); + } + + // remove ourselves from the thread local heaps list + // linear search but we expect the number of heaps to be relatively small + mi_heap_t* prev = NULL; + mi_heap_t* curr = heap->tld->heaps; + while (curr != heap && curr != NULL) { + prev = curr; + curr = curr->next; + } + mi_assert_internal(curr == heap); + if (curr == heap) { + if (prev != NULL) { prev->next = heap->next; } + else { heap->tld->heaps = heap->next; } + } + mi_assert_internal(heap->tld->heaps != NULL); + + // and free the used memory + mi_free(heap); +} + + +/* ----------------------------------------------------------- + Heap destroy +----------------------------------------------------------- */ + +static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(heap); + UNUSED(pq); + + // ensure no more thread_delayed_free will be added + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + + // stats + const size_t bsize = mi_page_block_size(page); + if (bsize > MI_LARGE_OBJ_SIZE_MAX) { + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_decrease(&heap->tld->stats.giant, bsize); + } + else { + _mi_stat_decrease(&heap->tld->stats.huge, bsize); + } + } +#if (MI_STAT>1) + _mi_page_free_collect(page, false); // update used count + const size_t inuse = page->used; + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], inuse); + } + mi_heap_stat_decrease(heap, malloc, bsize * inuse); // todo: off for aligned blocks... +#endif + + /// pretend it is all free now + mi_assert_internal(mi_page_thread_free(page) == NULL); + page->used = 0; + + // and free the page + // mi_page_free(page,false); + page->next = NULL; + page->prev = NULL; + _mi_segment_page_free(page,false /* no force? */, &heap->tld->segments); + + return true; // keep going +} + +void _mi_heap_destroy_pages(mi_heap_t* heap) { + mi_heap_visit_pages(heap, &_mi_heap_page_destroy, NULL, NULL); + mi_heap_reset_pages(heap); +} + +void mi_heap_destroy(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert(heap->no_reclaim); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (!mi_heap_is_initialized(heap)) return; + if (!heap->no_reclaim) { + // don't free in case it may contain reclaimed pages + mi_heap_delete(heap); + } + else { + // free all pages + _mi_heap_destroy_pages(heap); + mi_heap_free(heap); + } +} + + + +/* ----------------------------------------------------------- + Safe Heap delete +----------------------------------------------------------- */ + +// Tranfer the pages from one heap to the other +static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) { + mi_assert_internal(heap!=NULL); + if (from==NULL || from->page_count == 0) return; + + // reduce the size of the delayed frees + _mi_heap_delayed_free(from); + + // transfer all pages by appending the queues; this will set a new heap field + // so threads may do delayed frees in either heap for a while. + // note: appending waits for each page to not be in the `MI_DELAYED_FREEING` state + // so after this only the new heap will get delayed frees + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_queue_t* append = &from->pages[i]; + size_t pcount = _mi_page_queue_append(heap, pq, append); + heap->page_count += pcount; + from->page_count -= pcount; + } + mi_assert_internal(from->page_count == 0); + + // and do outstanding delayed frees in the `from` heap + // note: be careful here as the `heap` field in all those pages no longer point to `from`, + // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a + // the regular `_mi_free_delayed_block` which is safe. + _mi_heap_delayed_free(from); + mi_assert_internal(from->thread_delayed_free == NULL); + + // and reset the `from` heap + mi_heap_reset_pages(from); +} + +// Safe delete a heap without freeing any still allocated blocks in that heap. +void mi_heap_delete(mi_heap_t* heap) +{ + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (!mi_heap_is_initialized(heap)) return; + + if (!mi_heap_is_backing(heap)) { + // tranfer still used pages to the backing heap + mi_heap_absorb(heap->tld->heap_backing, heap); + } + else { + // the backing heap abandons its pages + _mi_heap_collect_abandon(heap); + } + mi_assert_internal(heap->page_count==0); + mi_heap_free(heap); +} + +mi_heap_t* mi_heap_set_default(mi_heap_t* heap) { + mi_assert(mi_heap_is_initialized(heap)); + if (!mi_heap_is_initialized(heap)) return NULL; + mi_assert_expensive(mi_heap_is_valid(heap)); + mi_heap_t* old = mi_get_default_heap(); + _mi_heap_set_default_direct(heap); + return old; +} + + + + +/* ----------------------------------------------------------- + Analysis +----------------------------------------------------------- */ + +// static since it is not thread safe to access heaps from other threads. +static mi_heap_t* mi_heap_of_block(const void* p) { + if (p == NULL) return NULL; + mi_segment_t* segment = _mi_ptr_segment(p); + bool valid = (_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(valid); + if (mi_unlikely(!valid)) return NULL; + return mi_page_heap(_mi_segment_page_of(segment,p)); +} + +bool mi_heap_contains_block(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (!mi_heap_is_initialized(heap)) return false; + return (heap == mi_heap_of_block(p)); +} + + +static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* p, void* vfound) { + UNUSED(heap); + UNUSED(pq); + bool* found = (bool*)vfound; + mi_segment_t* segment = _mi_page_segment(page); + void* start = _mi_page_start(segment, page, NULL); + void* end = (uint8_t*)start + (page->capacity * mi_page_block_size(page)); + *found = (p >= start && p < end); + return (!*found); // continue if not found +} + +bool mi_heap_check_owned(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (!mi_heap_is_initialized(heap)) return false; + if (((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) return false; // only aligned pointers + bool found = false; + mi_heap_visit_pages(heap, &mi_heap_page_check_owned, (void*)p, &found); + return found; +} + +bool mi_check_owned(const void* p) { + return mi_heap_check_owned(mi_get_default_heap(), p); +} + +/* ----------------------------------------------------------- + Visit all heap blocks and areas + Todo: enable visiting abandoned pages, and + enable visiting all blocks of all heaps across threads +----------------------------------------------------------- */ + +// Separate struct to keep `mi_page_t` out of the public interface +typedef struct mi_heap_area_ex_s { + mi_heap_area_t area; + mi_page_t* page; +} mi_heap_area_ex_t; + +static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_visit_fun* visitor, void* arg) { + mi_assert(xarea != NULL); + if (xarea==NULL) return true; + const mi_heap_area_t* area = &xarea->area; + mi_page_t* page = xarea->page; + mi_assert(page != NULL); + if (page == NULL) return true; + + _mi_page_free_collect(page,true); + mi_assert_internal(page->local_free == NULL); + if (page->used == 0) return true; + + const size_t bsize = mi_page_block_size(page); + size_t psize; + uint8_t* pstart = _mi_page_start(_mi_page_segment(page), page, &psize); + + if (page->capacity == 1) { + // optimize page with one block + mi_assert_internal(page->used == 1 && page->free == NULL); + return visitor(mi_page_heap(page), area, pstart, bsize, arg); + } + + // create a bitmap of free blocks. + #define MI_MAX_BLOCKS (MI_SMALL_PAGE_SIZE / sizeof(void*)) + uintptr_t free_map[MI_MAX_BLOCKS / sizeof(uintptr_t)]; + memset(free_map, 0, sizeof(free_map)); + + size_t free_count = 0; + for (mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) { + free_count++; + mi_assert_internal((uint8_t*)block >= pstart && (uint8_t*)block < (pstart + psize)); + size_t offset = (uint8_t*)block - pstart; + mi_assert_internal(offset % bsize == 0); + size_t blockidx = offset / bsize; // Todo: avoid division? + mi_assert_internal( blockidx < MI_MAX_BLOCKS); + size_t bitidx = (blockidx / sizeof(uintptr_t)); + size_t bit = blockidx - (bitidx * sizeof(uintptr_t)); + free_map[bitidx] |= ((uintptr_t)1 << bit); + } + mi_assert_internal(page->capacity == (free_count + page->used)); + + // walk through all blocks skipping the free ones + size_t used_count = 0; + for (size_t i = 0; i < page->capacity; i++) { + size_t bitidx = (i / sizeof(uintptr_t)); + size_t bit = i - (bitidx * sizeof(uintptr_t)); + uintptr_t m = free_map[bitidx]; + if (bit == 0 && m == UINTPTR_MAX) { + i += (sizeof(uintptr_t) - 1); // skip a run of free blocks + } + else if ((m & ((uintptr_t)1 << bit)) == 0) { + used_count++; + uint8_t* block = pstart + (i * bsize); + if (!visitor(mi_page_heap(page), area, block, bsize, arg)) return false; + } + } + mi_assert_internal(page->used == used_count); + return true; +} + +typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_ex_t* area, void* arg); + + +static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* vfun, void* arg) { + UNUSED(heap); + UNUSED(pq); + mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun; + mi_heap_area_ex_t xarea; + const size_t bsize = mi_page_block_size(page); + xarea.page = page; + xarea.area.reserved = page->reserved * bsize; + xarea.area.committed = page->capacity * bsize; + xarea.area.blocks = _mi_page_start(_mi_page_segment(page), page, NULL); + xarea.area.used = page->used; + xarea.area.block_size = bsize; + return fun(heap, &xarea, arg); +} + +// Visit all heap pages as areas +static bool mi_heap_visit_areas(const mi_heap_t* heap, mi_heap_area_visit_fun* visitor, void* arg) { + if (visitor == NULL) return false; + return mi_heap_visit_pages((mi_heap_t*)heap, &mi_heap_visit_areas_page, (void*)(visitor), arg); // note: function pointer to void* :-{ +} + +// Just to pass arguments +typedef struct mi_visit_blocks_args_s { + bool visit_blocks; + mi_block_visit_fun* visitor; + void* arg; +} mi_visit_blocks_args_t; + +static bool mi_heap_area_visitor(const mi_heap_t* heap, const mi_heap_area_ex_t* xarea, void* arg) { + mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg; + if (!args->visitor(heap, &xarea->area, NULL, xarea->area.block_size, args->arg)) return false; + if (args->visit_blocks) { + return mi_heap_area_visit_blocks(xarea, args->visitor, args->arg); + } + else { + return true; + } +} + +// Visit all blocks in a heap +bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_blocks, mi_block_visit_fun* visitor, void* arg) { + mi_visit_blocks_args_t args = { visit_blocks, visitor, arg }; + return mi_heap_visit_areas(heap, &mi_heap_area_visitor, &args); +} diff --git a/deps/mimalloc/src/init.c b/deps/mimalloc/src/init.c new file mode 100644 index 000000000..07a34f577 --- /dev/null +++ b/deps/mimalloc/src/init.c @@ -0,0 +1,563 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memcpy, memset +#include // atexit + +// Empty page used to initialize the small free pages array +const mi_page_t _mi_page_empty = { + 0, false, false, false, false, + 0, // capacity + 0, // reserved capacity + { 0 }, // flags + false, // is_zero + 0, // retire_expire + NULL, // free + #if MI_ENCODE_FREELIST + { 0, 0 }, + #endif + 0, // used + 0, // xblock_size + NULL, // local_free + ATOMIC_VAR_INIT(0), // xthread_free + ATOMIC_VAR_INIT(0), // xheap + NULL, NULL +}; + +#define MI_PAGE_EMPTY() ((mi_page_t*)&_mi_page_empty) + +#if (MI_PADDING>0) && (MI_INTPTR_SIZE >= 8) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#elif (MI_PADDING>0) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#else +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY() } +#endif + + +// Empty page queues for every bin +#define QNULL(sz) { NULL, NULL, (sz)*sizeof(uintptr_t) } +#define MI_PAGE_QUEUES_EMPTY \ + { QNULL(1), \ + QNULL( 1), QNULL( 2), QNULL( 3), QNULL( 4), QNULL( 5), QNULL( 6), QNULL( 7), QNULL( 8), /* 8 */ \ + QNULL( 10), QNULL( 12), QNULL( 14), QNULL( 16), QNULL( 20), QNULL( 24), QNULL( 28), QNULL( 32), /* 16 */ \ + QNULL( 40), QNULL( 48), QNULL( 56), QNULL( 64), QNULL( 80), QNULL( 96), QNULL( 112), QNULL( 128), /* 24 */ \ + QNULL( 160), QNULL( 192), QNULL( 224), QNULL( 256), QNULL( 320), QNULL( 384), QNULL( 448), QNULL( 512), /* 32 */ \ + QNULL( 640), QNULL( 768), QNULL( 896), QNULL( 1024), QNULL( 1280), QNULL( 1536), QNULL( 1792), QNULL( 2048), /* 40 */ \ + QNULL( 2560), QNULL( 3072), QNULL( 3584), QNULL( 4096), QNULL( 5120), QNULL( 6144), QNULL( 7168), QNULL( 8192), /* 48 */ \ + QNULL( 10240), QNULL( 12288), QNULL( 14336), QNULL( 16384), QNULL( 20480), QNULL( 24576), QNULL( 28672), QNULL( 32768), /* 56 */ \ + QNULL( 40960), QNULL( 49152), QNULL( 57344), QNULL( 65536), QNULL( 81920), QNULL( 98304), QNULL(114688), QNULL(131072), /* 64 */ \ + QNULL(163840), QNULL(196608), QNULL(229376), QNULL(262144), QNULL(327680), QNULL(393216), QNULL(458752), QNULL(524288), /* 72 */ \ + QNULL(MI_LARGE_OBJ_WSIZE_MAX + 1 /* 655360, Huge queue */), \ + QNULL(MI_LARGE_OBJ_WSIZE_MAX + 2) /* Full queue */ } + +#define MI_STAT_COUNT_NULL() {0,0,0,0} + +// Empty statistics +#if MI_STAT>1 +#define MI_STAT_COUNT_END_NULL() , { MI_STAT_COUNT_NULL(), MI_INIT32(MI_STAT_COUNT_NULL) } +#else +#define MI_STAT_COUNT_END_NULL() +#endif + +#define MI_STATS_NULL \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \ + MI_STAT_COUNT_END_NULL() + +// -------------------------------------------------------- +// Statically allocate an empty heap as the initial +// thread local value for the default heap, +// and statically allocate the backing heap for the main +// thread so it can function without doing any allocation +// itself (as accessing a thread local for the first time +// may lead to allocation itself on some platforms) +// -------------------------------------------------------- + +const mi_heap_t _mi_heap_empty = { + NULL, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + ATOMIC_VAR_INIT(NULL), + 0, // tid + 0, // cookie + { 0, 0 }, // keys + { {0}, {0}, 0 }, + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next + false +}; + +// the thread-local default heap for allocation +mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty; + +extern mi_heap_t _mi_heap_main; + +static mi_tld_t tld_main = { + 0, false, + &_mi_heap_main, &_mi_heap_main, + { { NULL, NULL }, {NULL ,NULL}, {NULL ,NULL, 0}, + 0, 0, 0, 0, 0, 0, NULL, + &tld_main.stats, &tld_main.os + }, // segments + { 0, &tld_main.stats }, // os + { MI_STATS_NULL } // stats +}; + +mi_heap_t _mi_heap_main = { + &tld_main, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + ATOMIC_VAR_INIT(NULL), + 0, // thread id + 0, // initial cookie + { 0, 0 }, // the key of the main heap can be fixed (unlike page keys that need to be secure!) + { {0x846ca68b}, {0}, 0 }, // random + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next heap + false // can reclaim +}; + +bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`. + +mi_stats_t _mi_stats_main = { MI_STATS_NULL }; + + +static void mi_heap_main_init(void) { + if (_mi_heap_main.cookie == 0) { + _mi_heap_main.thread_id = _mi_thread_id(); + _mi_heap_main.cookie = _os_random_weak((uintptr_t)&mi_heap_main_init); + _mi_random_init(&_mi_heap_main.random); + _mi_heap_main.keys[0] = _mi_heap_random_next(&_mi_heap_main); + _mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main); + } +} + +mi_heap_t* _mi_heap_main_get(void) { + mi_heap_main_init(); + return &_mi_heap_main; +} + + +/* ----------------------------------------------------------- + Initialization and freeing of the thread local heaps +----------------------------------------------------------- */ + +// note: in x64 in release build `sizeof(mi_thread_data_t)` is under 4KiB (= OS page size). +typedef struct mi_thread_data_s { + mi_heap_t heap; // must come first due to cast in `_mi_heap_done` + mi_tld_t tld; +} mi_thread_data_t; + +// Initialize the thread local default heap, called from `mi_thread_init` +static bool _mi_heap_init(void) { + if (mi_heap_is_initialized(mi_get_default_heap())) return true; + if (_mi_is_main_thread()) { + // mi_assert_internal(_mi_heap_main.thread_id != 0); // can happen on freeBSD where alloc is called before any initialization + // the main heap is statically allocated + mi_heap_main_init(); + _mi_heap_set_default_direct(&_mi_heap_main); + //mi_assert_internal(_mi_heap_default->tld->heap_backing == mi_get_default_heap()); + } + else { + // use `_mi_os_alloc` to allocate directly from the OS + mi_thread_data_t* td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main); // Todo: more efficient allocation? + if (td == NULL) { + // if this fails, try once more. (issue #257) + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main); + if (td == NULL) { + // really out of memory + _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t)); + return false; + } + } + // OS allocated so already zero initialized + mi_tld_t* tld = &td->tld; + mi_heap_t* heap = &td->heap; + memcpy(heap, &_mi_heap_empty, sizeof(*heap)); + heap->thread_id = _mi_thread_id(); + _mi_random_init(&heap->random); + heap->cookie = _mi_heap_random_next(heap) | 1; + heap->keys[0] = _mi_heap_random_next(heap); + heap->keys[1] = _mi_heap_random_next(heap); + heap->tld = tld; + tld->heap_backing = heap; + tld->heaps = heap; + tld->segments.stats = &tld->stats; + tld->segments.os = &tld->os; + tld->os.stats = &tld->stats; + _mi_heap_set_default_direct(heap); + } + return false; +} + +// Free the thread local default heap (called from `mi_thread_done`) +static bool _mi_heap_done(mi_heap_t* heap) { + if (!mi_heap_is_initialized(heap)) return true; + + // reset default heap + _mi_heap_set_default_direct(_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty); + + // switch to backing heap + heap = heap->tld->heap_backing; + if (!mi_heap_is_initialized(heap)) return false; + + // delete all non-backing heaps in this thread + mi_heap_t* curr = heap->tld->heaps; + while (curr != NULL) { + mi_heap_t* next = curr->next; // save `next` as `curr` will be freed + if (curr != heap) { + mi_assert_internal(!mi_heap_is_backing(curr)); + mi_heap_delete(curr); + } + curr = next; + } + mi_assert_internal(heap->tld->heaps == heap && heap->next == NULL); + mi_assert_internal(mi_heap_is_backing(heap)); + + // collect if not the main thread + if (heap != &_mi_heap_main) { + _mi_heap_collect_abandon(heap); + } + + // merge stats + _mi_stats_done(&heap->tld->stats); + + // free if not the main thread + if (heap != &_mi_heap_main) { + mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id()); + _mi_os_free(heap, sizeof(mi_thread_data_t), &_mi_stats_main); + } +#if 0 + // never free the main thread even in debug mode; if a dll is linked statically with mimalloc, + // there may still be delete/free calls after the mi_fls_done is called. Issue #207 + else { + _mi_heap_destroy_pages(heap); + mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main); + } +#endif + return false; +} + + + +// -------------------------------------------------------- +// Try to run `mi_thread_done()` automatically so any memory +// owned by the thread but not yet released can be abandoned +// and re-owned by another thread. +// +// 1. windows dynamic library: +// call from DllMain on DLL_THREAD_DETACH +// 2. windows static library: +// use `FlsAlloc` to call a destructor when the thread is done +// 3. unix, pthreads: +// use a pthread key to call a destructor when a pthread is done +// +// In the last two cases we also need to call `mi_process_init` +// to set up the thread local keys. +// -------------------------------------------------------- + +static void _mi_thread_done(mi_heap_t* default_heap); + +#ifdef __wasi__ +// no pthreads in the WebAssembly Standard Interface +#elif !defined(_WIN32) +#define MI_USE_PTHREADS +#endif + +#if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain +#elif defined(_WIN32) && !defined(MI_SHARED_LIB) + // use thread local storage keys to detect thread ending + #include + #include + #if (_WIN32_WINNT < 0x600) // before Windows Vista + WINBASEAPI DWORD WINAPI FlsAlloc( _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback ); + WINBASEAPI PVOID WINAPI FlsGetValue( _In_ DWORD dwFlsIndex ); + WINBASEAPI BOOL WINAPI FlsSetValue( _In_ DWORD dwFlsIndex, _In_opt_ PVOID lpFlsData ); + WINBASEAPI BOOL WINAPI FlsFree(_In_ DWORD dwFlsIndex); + #endif + static DWORD mi_fls_key = (DWORD)(-1); + static void NTAPI mi_fls_done(PVOID value) { + if (value!=NULL) _mi_thread_done((mi_heap_t*)value); + } +#elif defined(MI_USE_PTHREADS) + // use pthread local storage keys to detect thread ending + // (and used with MI_TLS_PTHREADS for the default heap) + #include + pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1); + static void mi_pthread_done(void* value) { + if (value!=NULL) _mi_thread_done((mi_heap_t*)value); + } +#elif defined(__wasi__) +// no pthreads in the WebAssembly Standard Interface +#else + #pragma message("define a way to call mi_thread_done when a thread is done") +#endif + +// Set up handlers so `mi_thread_done` is called automatically +static void mi_process_setup_auto_thread_done(void) { + static bool tls_initialized = false; // fine if it races + if (tls_initialized) return; + tls_initialized = true; + #if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain + #elif defined(_WIN32) && !defined(MI_SHARED_LIB) + mi_fls_key = FlsAlloc(&mi_fls_done); + #elif defined(MI_USE_PTHREADS) + mi_assert_internal(_mi_heap_default_key == (pthread_key_t)(-1)); + pthread_key_create(&_mi_heap_default_key, &mi_pthread_done); + #endif + _mi_heap_set_default_direct(&_mi_heap_main); +} + + +bool _mi_is_main_thread(void) { + return (_mi_heap_main.thread_id==0 || _mi_heap_main.thread_id == _mi_thread_id()); +} + +// This is called from the `mi_malloc_generic` +void mi_thread_init(void) mi_attr_noexcept +{ + // ensure our process has started already + mi_process_init(); + + // initialize the thread local default heap + // (this will call `_mi_heap_set_default_direct` and thus set the + // fiber/pthread key to a non-zero value, ensuring `_mi_thread_done` is called) + if (_mi_heap_init()) return; // returns true if already initialized + + _mi_stat_increase(&_mi_stats_main.threads, 1); + //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id()); +} + +void mi_thread_done(void) mi_attr_noexcept { + _mi_thread_done(mi_get_default_heap()); +} + +static void _mi_thread_done(mi_heap_t* heap) { + _mi_stat_decrease(&_mi_stats_main.threads, 1); + + // check thread-id as on Windows shutdown with FLS the main (exit) thread may call this on thread-local heaps... + if (heap->thread_id != _mi_thread_id()) return; + + // abandon the thread local heap + if (_mi_heap_done(heap)) return; // returns true if already ran +} + +void _mi_heap_set_default_direct(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + #if defined(MI_TLS_SLOT) + mi_tls_slot_set(MI_TLS_SLOT,heap); + #elif defined(MI_TLS_PTHREAD_SLOT_OFS) + *mi_tls_pthread_heap_slot() = heap; + #elif defined(MI_TLS_PTHREAD) + // we use _mi_heap_default_key + #else + _mi_heap_default = heap; + #endif + + // ensure the default heap is passed to `_mi_thread_done` + // setting to a non-NULL value also ensures `mi_thread_done` is called. + #if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain + #elif defined(_WIN32) && !defined(MI_SHARED_LIB) + mi_assert_internal(mi_fls_key != 0); + FlsSetValue(mi_fls_key, heap); + #elif defined(MI_USE_PTHREADS) + if (_mi_heap_default_key != (pthread_key_t)(-1)) { // can happen during recursive invocation on freeBSD + pthread_setspecific(_mi_heap_default_key, heap); + } + #endif +} + + +// -------------------------------------------------------- +// Run functions on process init/done, and thread init/done +// -------------------------------------------------------- +static void mi_process_done(void); + +static bool os_preloading = true; // true until this module is initialized +static bool mi_redirected = false; // true if malloc redirects to mi_malloc + +// Returns true if this module has not been initialized; Don't use C runtime routines until it returns false. +bool _mi_preloading(void) { + return os_preloading; +} + +bool mi_is_redirected(void) mi_attr_noexcept { + return mi_redirected; +} + +// Communicate with the redirection module on Windows +#if defined(_WIN32) && defined(MI_SHARED_LIB) +#ifdef __cplusplus +extern "C" { +#endif +mi_decl_export void _mi_redirect_entry(DWORD reason) { + // called on redirection; careful as this may be called before DllMain + if (reason == DLL_PROCESS_ATTACH) { + mi_redirected = true; + } + else if (reason == DLL_PROCESS_DETACH) { + mi_redirected = false; + } + else if (reason == DLL_THREAD_DETACH) { + mi_thread_done(); + } +} +__declspec(dllimport) bool mi_allocator_init(const char** message); +__declspec(dllimport) void mi_allocator_done(void); +#ifdef __cplusplus +} +#endif +#else +static bool mi_allocator_init(const char** message) { + if (message != NULL) *message = NULL; + return true; +} +static void mi_allocator_done(void) { + // nothing to do +} +#endif + +// Called once by the process loader +static void mi_process_load(void) { + mi_heap_main_init(); + #if defined(MI_TLS_RECURSE_GUARD) + volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to allocate it before setting tls_initialized to true; + UNUSED(dummy); + #endif + os_preloading = false; + atexit(&mi_process_done); + _mi_options_init(); + mi_process_init(); + //mi_stats_reset();- + if (mi_redirected) _mi_verbose_message("malloc is redirected.\n"); + + // show message from the redirector (if present) + const char* msg = NULL; + mi_allocator_init(&msg); + if (msg != NULL && (mi_option_is_enabled(mi_option_verbose) || mi_option_is_enabled(mi_option_show_errors))) { + _mi_fputs(NULL,NULL,NULL,msg); + } +} + +// Initialize the process; called by thread_init or the process loader +void mi_process_init(void) mi_attr_noexcept { + // ensure we are called once + if (_mi_process_is_initialized) return; + _mi_process_is_initialized = true; + mi_process_setup_auto_thread_done(); + + _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id()); + _mi_os_init(); + mi_heap_main_init(); + #if (MI_DEBUG) + _mi_verbose_message("debug level : %d\n", MI_DEBUG); + #endif + _mi_verbose_message("secure level: %d\n", MI_SECURE); + mi_thread_init(); + mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL) + + if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + size_t pages = mi_option_get(mi_option_reserve_huge_os_pages); + mi_reserve_huge_os_pages_interleave(pages, 0, pages*500); + } +} + +// Called when the process is done (through `at_exit`) +static void mi_process_done(void) { + // only shutdown if we were initialized + if (!_mi_process_is_initialized) return; + // ensure we are called once + static bool process_done = false; + if (process_done) return; + process_done = true; + + #if defined(_WIN32) && !defined(MI_SHARED_LIB) + FlsSetValue(mi_fls_key, NULL); // don't call main-thread callback + FlsFree(mi_fls_key); // call thread-done on all threads to prevent dangling callback pointer if statically linked with a DLL; Issue #208 + #endif + + #if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB) + // free all memory if possible on process exit. This is not needed for a stand-alone process + // but should be done if mimalloc is statically linked into another shared library which + // is repeatedly loaded/unloaded, see issue #281. + mi_collect(true /* force */ ); + #endif + + if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { + mi_stats_print(NULL); + } + mi_allocator_done(); + _mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id); + os_preloading = true; // don't call the C runtime anymore +} + + + +#if defined(_WIN32) && defined(MI_SHARED_LIB) + // Windows DLL: easy to hook into process_init and thread_done + __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { + UNUSED(reserved); + UNUSED(inst); + if (reason==DLL_PROCESS_ATTACH) { + mi_process_load(); + } + else if (reason==DLL_THREAD_DETACH) { + if (!mi_is_redirected()) mi_thread_done(); + } + return TRUE; + } + +#elif defined(__cplusplus) + // C++: use static initialization to detect process start + static bool _mi_process_init(void) { + mi_process_load(); + return (_mi_heap_main.thread_id != 0); + } + static bool mi_initialized = _mi_process_init(); + +#elif defined(__GNUC__) || defined(__clang__) + // GCC,Clang: use the constructor attribute + static void __attribute__((constructor)) _mi_process_init(void) { + mi_process_load(); + } + +#elif defined(_MSC_VER) + // MSVC: use data section magic for static libraries + // See + static int _mi_process_init(void) { + mi_process_load(); + return 0; + } + typedef int(*_crt_cb)(void); + #ifdef _M_X64 + __pragma(comment(linker, "/include:" "_mi_msvc_initu")) + #pragma section(".CRT$XIU", long, read) + #else + __pragma(comment(linker, "/include:" "__mi_msvc_initu")) + #endif + #pragma data_seg(".CRT$XIU") + _crt_cb _mi_msvc_initu[] = { &_mi_process_init }; + #pragma data_seg() + +#else +#pragma message("define a way to call mi_process_load on your platform") +#endif diff --git a/deps/mimalloc/src/options.c b/deps/mimalloc/src/options.c new file mode 100644 index 000000000..9da3a9bdd --- /dev/null +++ b/deps/mimalloc/src/options.c @@ -0,0 +1,520 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include +#include // strtol +#include // strncpy, strncat, strlen, strstr +#include // toupper +#include + +#ifdef _MSC_VER +#pragma warning(disable:4996) // strncpy, strncat +#endif + + +static uintptr_t mi_max_error_count = 16; // stop outputting errors after this + +static void mi_add_stderr_output(); + +int mi_version(void) mi_attr_noexcept { + return MI_MALLOC_VERSION; +} + +#ifdef _WIN32 +#include +#endif + +// -------------------------------------------------------- +// Options +// These can be accessed by multiple threads and may be +// concurrently initialized, but an initializing data race +// is ok since they resolve to the same value. +// -------------------------------------------------------- +typedef enum mi_init_e { + UNINIT, // not yet initialized + DEFAULTED, // not found in the environment, use default value + INITIALIZED // found in environment or set explicitly +} mi_init_t; + +typedef struct mi_option_desc_s { + long value; // the value + mi_init_t init; // is it initialized yet? (from the environment) + mi_option_t option; // for debugging: the option index should match the option + const char* name; // option name without `mimalloc_` prefix +} mi_option_desc_t; + +#define MI_OPTION(opt) mi_option_##opt, #opt +#define MI_OPTION_DESC(opt) {0, UNINIT, MI_OPTION(opt) } + +static mi_option_desc_t options[_mi_option_last] = +{ + // stable options +#if MI_DEBUG || defined(MI_SHOW_ERRORS) + { 1, UNINIT, MI_OPTION(show_errors) }, +#else + { 0, UNINIT, MI_OPTION(show_errors) }, +#endif + { 0, UNINIT, MI_OPTION(show_stats) }, + { 0, UNINIT, MI_OPTION(verbose) }, + + // the following options are experimental and not all combinations make sense. + { 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) + #if defined(_WIN32) || (MI_INTPTR_SIZE <= 4) // and other OS's without overcommit? + { 0, UNINIT, MI_OPTION(eager_region_commit) }, + { 1, UNINIT, MI_OPTION(reset_decommits) }, // reset decommits memory + #else + { 1, UNINIT, MI_OPTION(eager_region_commit) }, + { 0, UNINIT, MI_OPTION(reset_decommits) }, // reset uses MADV_FREE/MADV_DONTNEED + #endif + { 0, UNINIT, MI_OPTION(large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, + { 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread + { 1, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free + { 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates + { 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit) +#if defined(__NetBSD__) + { 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed +#else + { 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand) +#endif + { 100, UNINIT, MI_OPTION(reset_delay) }, // reset delay in milli-seconds + { 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes. + { 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose + { 16, UNINIT, MI_OPTION(max_errors) } // maximum errors that are output +}; + +static void mi_option_init(mi_option_desc_t* desc); + +void _mi_options_init(void) { + // called on process load; should not be called before the CRT is initialized! + // (e.g. do not call this from process_init as that may run before CRT initialization) + mi_add_stderr_output(); // now it safe to use stderr for output + for(int i = 0; i < _mi_option_last; i++ ) { + mi_option_t option = (mi_option_t)i; + long l = mi_option_get(option); UNUSED(l); // initialize + if (option != mi_option_verbose) { + mi_option_desc_t* desc = &options[option]; + _mi_verbose_message("option '%s': %ld\n", desc->name, desc->value); + } + } + mi_max_error_count = mi_option_get(mi_option_max_errors); +} + +long mi_option_get(mi_option_t option) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + if (mi_unlikely(desc->init == UNINIT)) { + mi_option_init(desc); + } + return desc->value; +} + +void mi_option_set(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + desc->value = value; + desc->init = INITIALIZED; +} + +void mi_option_set_default(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + if (desc->init != INITIALIZED) { + desc->value = value; + } +} + +bool mi_option_is_enabled(mi_option_t option) { + return (mi_option_get(option) != 0); +} + +void mi_option_set_enabled(mi_option_t option, bool enable) { + mi_option_set(option, (enable ? 1 : 0)); +} + +void mi_option_set_enabled_default(mi_option_t option, bool enable) { + mi_option_set_default(option, (enable ? 1 : 0)); +} + +void mi_option_enable(mi_option_t option) { + mi_option_set_enabled(option,true); +} + +void mi_option_disable(mi_option_t option) { + mi_option_set_enabled(option,false); +} + + +static void mi_out_stderr(const char* msg, void* arg) { + UNUSED(arg); + #ifdef _WIN32 + // on windows with redirection, the C runtime cannot handle locale dependent output + // after the main thread closes so we use direct console output. + if (!_mi_preloading()) { _cputs(msg); } + #else + fputs(msg, stderr); + #endif +} + +// Since an output function can be registered earliest in the `main` +// function we also buffer output that happens earlier. When +// an output function is registered it is called immediately with +// the output up to that point. +#ifndef MI_MAX_DELAY_OUTPUT +#define MI_MAX_DELAY_OUTPUT ((uintptr_t)(32*1024)) +#endif +static char out_buf[MI_MAX_DELAY_OUTPUT+1]; +static _Atomic(uintptr_t) out_len; + +static void mi_out_buf(const char* msg, void* arg) { + UNUSED(arg); + if (msg==NULL) return; + if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return; + size_t n = strlen(msg); + if (n==0) return; + // claim space + uintptr_t start = mi_atomic_add_acq_rel(&out_len, n); + if (start >= MI_MAX_DELAY_OUTPUT) return; + // check bound + if (start+n >= MI_MAX_DELAY_OUTPUT) { + n = MI_MAX_DELAY_OUTPUT-start-1; + } + memcpy(&out_buf[start], msg, n); +} + +static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) { + if (out==NULL) return; + // claim (if `no_more_buf == true`, no more output will be added after this point) + size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1)); + // and output the current contents + if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT; + out_buf[count] = 0; + out(out_buf,arg); + if (!no_more_buf) { + out_buf[count] = '\n'; // if continue with the buffer, insert a newline + } +} + + +// Once this module is loaded, switch to this routine +// which outputs to stderr and the delayed output buffer. +static void mi_out_buf_stderr(const char* msg, void* arg) { + mi_out_stderr(msg,arg); + mi_out_buf(msg,arg); +} + + + +// -------------------------------------------------------- +// Default output handler +// -------------------------------------------------------- + +// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t. +// For now, don't register output from multiple threads. +static mi_output_fun* volatile mi_out_default; // = NULL +static _Atomic(void*) mi_out_arg; // = NULL + +static mi_output_fun* mi_out_get_default(void** parg) { + if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); } + mi_output_fun* out = mi_out_default; + return (out == NULL ? &mi_out_buf : out); +} + +void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_out_default = (out == NULL ? &mi_out_stderr : out); // stop using the delayed output buffer + mi_atomic_store_ptr_release(void,&mi_out_arg, arg); + if (out!=NULL) mi_out_buf_flush(out,true,arg); // output all the delayed output now +} + +// add stderr to the delayed output after the module is loaded +static void mi_add_stderr_output() { + mi_assert_internal(mi_out_default == NULL); + mi_out_buf_flush(&mi_out_stderr, false, NULL); // flush current contents to stderr + mi_out_default = &mi_out_buf_stderr; // and add stderr to the delayed output +} + +// -------------------------------------------------------- +// Messages, all end up calling `_mi_fputs`. +// -------------------------------------------------------- +static _Atomic(uintptr_t) error_count; // = 0; // when MAX_ERROR_COUNT stop emitting errors and warnings + +// When overriding malloc, we may recurse into mi_vfprintf if an allocation +// inside the C runtime causes another message. +static mi_decl_thread bool recurse = false; + +static bool mi_recurse_enter(void) { + #ifdef MI_TLS_RECURSE_GUARD + if (_mi_preloading()) return true; + #endif + if (recurse) return false; + recurse = true; + return true; +} + +static void mi_recurse_exit(void) { + #ifdef MI_TLS_RECURSE_GUARD + if (_mi_preloading()) return; + #endif + recurse = false; +} + +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) { + if (out==NULL || (FILE*)out==stdout || (FILE*)out==stderr) { // TODO: use mi_out_stderr for stderr? + if (!mi_recurse_enter()) return; + out = mi_out_get_default(&arg); + if (prefix != NULL) out(prefix, arg); + out(message, arg); + mi_recurse_exit(); + } + else { + if (prefix != NULL) out(prefix, arg); + out(message, arg); + } +} + +// Define our own limited `fprintf` that avoids memory allocation. +// We do this using `snprintf` with a limited buffer. +static void mi_vfprintf( mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args ) { + char buf[512]; + if (fmt==NULL) return; + if (!mi_recurse_enter()) return; + vsnprintf(buf,sizeof(buf)-1,fmt,args); + mi_recurse_exit(); + _mi_fputs(out,arg,prefix,buf); +} + +void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) { + va_list args; + va_start(args,fmt); + mi_vfprintf(out,arg,NULL,fmt,args); + va_end(args); +} + +void _mi_trace_message(const char* fmt, ...) { + if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher + va_list args; + va_start(args, fmt); + mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +void _mi_verbose_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_verbose)) return; + va_list args; + va_start(args,fmt); + mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +static void mi_show_error_message(const char* fmt, va_list args) { + if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return; + if (mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return; + mi_vfprintf(NULL, NULL, "mimalloc: error: ", fmt, args); +} + +void _mi_warning_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return; + if (mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return; + va_list args; + va_start(args,fmt); + mi_vfprintf(NULL, NULL, "mimalloc: warning: ", fmt, args); + va_end(args); +} + + +#if MI_DEBUG +void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) { + _mi_fprintf(NULL, NULL, "mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion); + abort(); +} +#endif + +// -------------------------------------------------------- +// Errors +// -------------------------------------------------------- + +static mi_error_fun* volatile mi_error_handler; // = NULL +static _Atomic(void*) mi_error_arg; // = NULL + +static void mi_error_default(int err) { + UNUSED(err); +#if (MI_DEBUG>0) + if (err==EFAULT) { + #ifdef _MSC_VER + __debugbreak(); + #endif + abort(); + } +#endif +#if (MI_SECURE>0) + if (err==EFAULT) { // abort on serious errors in secure mode (corrupted meta-data) + abort(); + } +#endif +#if defined(MI_XMALLOC) + if (err==ENOMEM || err==EOVERFLOW) { // abort on memory allocation fails in xmalloc mode + abort(); + } +#endif +} + +void mi_register_error(mi_error_fun* fun, void* arg) { + mi_error_handler = fun; // can be NULL + mi_atomic_store_ptr_release(void,&mi_error_arg, arg); +} + +void _mi_error_message(int err, const char* fmt, ...) { + // show detailed error message + va_list args; + va_start(args, fmt); + mi_show_error_message(fmt, args); + va_end(args); + // and call the error handler which may abort (or return normally) + if (mi_error_handler != NULL) { + mi_error_handler(err, mi_atomic_load_ptr_acquire(void,&mi_error_arg)); + } + else { + mi_error_default(err); + } +} + +// -------------------------------------------------------- +// Initialize options by checking the environment +// -------------------------------------------------------- + +static void mi_strlcpy(char* dest, const char* src, size_t dest_size) { + dest[0] = 0; + strncpy(dest, src, dest_size - 1); + dest[dest_size - 1] = 0; +} + +static void mi_strlcat(char* dest, const char* src, size_t dest_size) { + strncat(dest, src, dest_size - 1); + dest[dest_size - 1] = 0; +} + +static inline int mi_strnicmp(const char* s, const char* t, size_t n) { + if (n==0) return 0; + for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) { + if (toupper(*s) != toupper(*t)) break; + } + return (n==0 ? 0 : *s - *t); +} + +#if defined _WIN32 +// On Windows use GetEnvironmentVariable instead of getenv to work +// reliably even when this is invoked before the C runtime is initialized. +// i.e. when `_mi_preloading() == true`. +// Note: on windows, environment names are not case sensitive. +#include +static bool mi_getenv(const char* name, char* result, size_t result_size) { + result[0] = 0; + size_t len = GetEnvironmentVariableA(name, result, (DWORD)result_size); + return (len > 0 && len < result_size); +} +#elif !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0) +// On Posix systemsr use `environ` to acces environment variables +// even before the C runtime is initialized. +#if defined(__APPLE__) && defined(__has_include) && __has_include() +#include +static char** mi_get_environ(void) { + return (*_NSGetEnviron()); +} +#else +extern char** environ; +static char** mi_get_environ(void) { + return environ; +} +#endif +static bool mi_getenv(const char* name, char* result, size_t result_size) { + if (name==NULL) return false; + const size_t len = strlen(name); + if (len == 0) return false; + char** env = mi_get_environ(); + if (env == NULL) return false; + // compare up to 256 entries + for (int i = 0; i < 256 && env[i] != NULL; i++) { + const char* s = env[i]; + if (mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive + // found it + mi_strlcpy(result, s + len + 1, result_size); + return true; + } + } + return false; +} +#else +// fallback: use standard C `getenv` but this cannot be used while initializing the C runtime +static bool mi_getenv(const char* name, char* result, size_t result_size) { + // cannot call getenv() when still initializing the C runtime. + if (_mi_preloading()) return false; + const char* s = getenv(name); + if (s == NULL) { + // we check the upper case name too. + char buf[64+1]; + size_t len = strlen(name); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = toupper(name[i]); + } + buf[len] = 0; + s = getenv(buf); + } + if (s != NULL && strlen(s) < result_size) { + mi_strlcpy(result, s, result_size); + return true; + } + else { + return false; + } +} +#endif + +static void mi_option_init(mi_option_desc_t* desc) { + // Read option value from the environment + char buf[64+1]; + mi_strlcpy(buf, "mimalloc_", sizeof(buf)); + mi_strlcat(buf, desc->name, sizeof(buf)); + char s[64+1]; + if (mi_getenv(buf, s, sizeof(s))) { + size_t len = strlen(s); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = (char)toupper(s[i]); + } + buf[len] = 0; + if (buf[0]==0 || strstr("1;TRUE;YES;ON", buf) != NULL) { + desc->value = 1; + desc->init = INITIALIZED; + } + else if (strstr("0;FALSE;NO;OFF", buf) != NULL) { + desc->value = 0; + desc->init = INITIALIZED; + } + else { + char* end = buf; + long value = strtol(buf, &end, 10); + if (*end == 0) { + desc->value = value; + desc->init = INITIALIZED; + } + else { + _mi_warning_message("environment option mimalloc_%s has an invalid value: %s\n", desc->name, buf); + desc->init = DEFAULTED; + } + } + mi_assert_internal(desc->init != UNINIT); + } + else if (!_mi_preloading()) { + desc->init = DEFAULTED; + } +} diff --git a/deps/mimalloc/src/os.c b/deps/mimalloc/src/os.c new file mode 100644 index 000000000..6985587c3 --- /dev/null +++ b/deps/mimalloc/src/os.c @@ -0,0 +1,1193 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE // ensure mmap flags are defined +#endif + +#if defined(__sun) +// illumos provides new mman.h api when any of these are defined +// otherwise the old api based on caddr_t which predates the void pointers one. +// stock solaris provides only the former, chose to atomically to discard those +// flags only here rather than project wide tough. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // strerror + +#ifdef _MSC_VER +#pragma warning(disable:4996) // strerror +#endif + + +#if defined(_WIN32) +#include +#elif defined(__wasi__) +// stdlib.h is all we need, and has already been included in mimalloc.h +#else +#include // mmap +#include // sysconf +#if defined(__linux__) +#include +#if defined(__GLIBC__) +#include // linux mmap flags +#else +#include +#endif +#endif +#if defined(__APPLE__) +#include +#if !TARGET_IOS_IPHONE && !TARGET_IOS_SIMULATOR +#include +#endif +#endif +#if defined(__HAIKU__) +#define madvise posix_madvise +#define MADV_DONTNEED POSIX_MADV_DONTNEED +#endif +#endif + +/* ----------------------------------------------------------- + Initialization. + On windows initializes support for aligned allocation and + large OS pages (if MIMALLOC_LARGE_OS_PAGES is true). +----------------------------------------------------------- */ +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); + +static void* mi_align_up_ptr(void* p, size_t alignment) { + return (void*)_mi_align_up((uintptr_t)p, alignment); +} + +static uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) { + return (sz / alignment) * alignment; +} + +static void* mi_align_down_ptr(void* p, size_t alignment) { + return (void*)_mi_align_down((uintptr_t)p, alignment); +} + +// page size (initialized properly in `os_init`) +static size_t os_page_size = 4096; + +// minimal allocation granularity +static size_t os_alloc_granularity = 4096; + +// if non-zero, use large page allocation +static size_t large_os_page_size = 0; + +// OS (small) page size +size_t _mi_os_page_size() { + return os_page_size; +} + +// if large OS pages are supported (2 or 4MiB), then return the size, otherwise return the small page size (4KiB) +size_t _mi_os_large_page_size() { + return (large_os_page_size != 0 ? large_os_page_size : _mi_os_page_size()); +} + +static bool use_large_os_page(size_t size, size_t alignment) { + // if we have access, check the size and alignment requirements + if (large_os_page_size == 0 || !mi_option_is_enabled(mi_option_large_os_pages)) return false; + return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0); +} + +// round to a good OS allocation size (bounded by max 12.5% waste) +size_t _mi_os_good_alloc_size(size_t size) { + size_t align_size; + if (size < 512*KiB) align_size = _mi_os_page_size(); + else if (size < 2*MiB) align_size = 64*KiB; + else if (size < 8*MiB) align_size = 256*KiB; + else if (size < 32*MiB) align_size = 1*MiB; + else align_size = 4*MiB; + if (size >= (SIZE_MAX - align_size)) return size; // possible overflow? + return _mi_align_up(size, align_size); +} + +#if defined(_WIN32) +// We use VirtualAlloc2 for aligned allocation, but it is only supported on Windows 10 and Windows Server 2016. +// So, we need to look it up dynamically to run on older systems. (use __stdcall for 32-bit compatibility) +// NtAllocateVirtualAllocEx is used for huge OS page allocation (1GiB) +// +// We hide MEM_EXTENDED_PARAMETER to compile with older SDK's. +#include +typedef PVOID (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ void*, ULONG); +typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ PVOID, ULONG); +static PVirtualAlloc2 pVirtualAlloc2 = NULL; +static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL; + +// Similarly, GetNumaProcesorNodeEx is only supported since Windows 7 +#if (_WIN32_WINNT < 0x601) // before Win7 +typedef struct _PROCESSOR_NUMBER { WORD Group; BYTE Number; BYTE Reserved; } PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; +#endif +typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(PPROCESSOR_NUMBER ProcNumber); +typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(PPROCESSOR_NUMBER Processor, PUSHORT NodeNumber); +typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask); +static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL; +static PGetNumaProcessorNodeEx pGetNumaProcessorNodeEx = NULL; +static PGetNumaNodeProcessorMaskEx pGetNumaNodeProcessorMaskEx = NULL; + +static bool mi_win_enable_large_os_pages() +{ + if (large_os_page_size > 0) return true; + + // Try to see if large OS pages are supported + // To use large pages on Windows, we first need access permission + // Set "Lock pages in memory" permission in the group policy editor + // + unsigned long err = 0; + HANDLE token = NULL; + BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (ok) { + TOKEN_PRIVILEGES tp; + ok = LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid); + if (ok) { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ok = AdjustTokenPrivileges(token, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + if (ok) { + err = GetLastError(); + ok = (err == ERROR_SUCCESS); + if (ok) { + large_os_page_size = GetLargePageMinimum(); + } + } + } + CloseHandle(token); + } + if (!ok) { + if (err == 0) err = GetLastError(); + _mi_warning_message("cannot enable large OS page support, error %lu\n", err); + } + return (ok!=0); +} + +void _mi_os_init(void) { + // get the page size + SYSTEM_INFO si; + GetSystemInfo(&si); + if (si.dwPageSize > 0) os_page_size = si.dwPageSize; + if (si.dwAllocationGranularity > 0) os_alloc_granularity = si.dwAllocationGranularity; + // get the VirtualAlloc2 function + HINSTANCE hDll; + hDll = LoadLibrary(TEXT("kernelbase.dll")); + if (hDll != NULL) { + // use VirtualAlloc2FromApp if possible as it is available to Windows store apps + pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2FromApp"); + if (pVirtualAlloc2==NULL) pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2"); + FreeLibrary(hDll); + } + // NtAllocateVirtualMemoryEx is used for huge page allocation + hDll = LoadLibrary(TEXT("ntdll.dll")); + if (hDll != NULL) { + pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)(void (*)(void))GetProcAddress(hDll, "NtAllocateVirtualMemoryEx"); + FreeLibrary(hDll); + } + // Try to use Win7+ numa API + hDll = LoadLibrary(TEXT("kernel32.dll")); + if (hDll != NULL) { + pGetCurrentProcessorNumberEx = (PGetCurrentProcessorNumberEx)(void (*)(void))GetProcAddress(hDll, "GetCurrentProcessorNumberEx"); + pGetNumaProcessorNodeEx = (PGetNumaProcessorNodeEx)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNodeEx"); + pGetNumaNodeProcessorMaskEx = (PGetNumaNodeProcessorMaskEx)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMaskEx"); + FreeLibrary(hDll); + } + if (mi_option_is_enabled(mi_option_large_os_pages) || mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + mi_win_enable_large_os_pages(); + } +} +#elif defined(__wasi__) +void _mi_os_init() { + os_page_size = 0x10000; // WebAssembly has a fixed page size: 64KB + os_alloc_granularity = 16; +} +#else +void _mi_os_init() { + // get the page size + long result = sysconf(_SC_PAGESIZE); + if (result > 0) { + os_page_size = (size_t)result; + os_alloc_granularity = os_page_size; + } + large_os_page_size = 2*MiB; // TODO: can we query the OS for this? +} +#endif + + +/* ----------------------------------------------------------- + Raw allocation on Windows (VirtualAlloc) and Unix's (mmap). +----------------------------------------------------------- */ + +static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats) +{ + if (addr == NULL || size == 0) return true; // || _mi_os_is_huge_reserved(addr) + bool err = false; +#if defined(_WIN32) + err = (VirtualFree(addr, 0, MEM_RELEASE) == 0); +#elif defined(__wasi__) + err = 0; // WebAssembly's heap cannot be shrunk +#else + err = (munmap(addr, size) == -1); +#endif + if (was_committed) _mi_stat_decrease(&stats->committed, size); + _mi_stat_decrease(&stats->reserved, size); + if (err) { + _mi_warning_message("munmap failed: %s, addr 0x%8li, size %lu\n", strerror(errno), (size_t)addr, size); + return false; + } + else { + return true; + } +} + +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size); + +#ifdef _WIN32 +static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) { +#if (MI_INTPTR_SIZE >= 8) + // on 64-bit systems, try to use the virtual address area after 4TiB for 4MiB aligned allocations + void* hint; + if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment,size)) != NULL) { + void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE); + if (p != NULL) return p; + DWORD err = GetLastError(); + if (err != ERROR_INVALID_ADDRESS && // If linked with multiple instances, we may have tried to allocate at an already allocated area (#210) + err != ERROR_INVALID_PARAMETER) { // Windows7 instability (#230) + return NULL; + } + // fall through + } +#endif +#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) + // on modern Windows try use VirtualAlloc2 for aligned allocation + if (try_alignment > 0 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) { + MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 }; + reqs.Alignment = try_alignment; + MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} }; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &reqs; + return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, ¶m, 1); + } +#endif + // last resort + return VirtualAlloc(addr, size, flags, PAGE_READWRITE); +} + +static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DWORD flags, bool large_only, bool allow_large, bool* is_large) { + mi_assert_internal(!(large_only && !allow_large)); + static _Atomic(uintptr_t) large_page_try_ok; // = 0; + void* p = NULL; + if ((large_only || use_large_os_page(size, try_alignment)) + && allow_large && (flags&MEM_COMMIT)!=0 && (flags&MEM_RESERVE)!=0) { + uintptr_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive. + // therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + // large OS pages must always reserve and commit. + *is_large = true; + p = mi_win_virtual_allocx(addr, size, try_alignment, flags | MEM_LARGE_PAGES); + if (large_only) return p; + // fall back to non-large page allocation on error (`p == NULL`). + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok,10UL); // on error, don't try again for the next N allocations + } + } + } + if (p == NULL) { + *is_large = ((flags&MEM_LARGE_PAGES) != 0); + p = mi_win_virtual_allocx(addr, size, try_alignment, flags); + } + if (p == NULL) { + _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, GetLastError(), addr, large_only, allow_large); + } + return p; +} + +#elif defined(__wasi__) +static void* mi_wasm_heap_grow(size_t size, size_t try_alignment) { + uintptr_t base = __builtin_wasm_memory_size(0) * _mi_os_page_size(); + uintptr_t aligned_base = _mi_align_up(base, (uintptr_t) try_alignment); + size_t alloc_size = _mi_align_up( aligned_base - base + size, _mi_os_page_size()); + mi_assert(alloc_size >= size && (alloc_size % _mi_os_page_size()) == 0); + if (alloc_size < size) return NULL; + if (__builtin_wasm_memory_grow(0, alloc_size / _mi_os_page_size()) == SIZE_MAX) { + errno = ENOMEM; + return NULL; + } + return (void*)aligned_base; +} +#else +#define MI_OS_USE_MMAP +static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) { + void* p = NULL; + #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED) + // on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations + void* hint; + if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment, size)) != NULL) { + p = mmap(hint,size,protect_flags,flags,fd,0); + if (p==MAP_FAILED) p = NULL; // fall back to regular mmap + } + #else + UNUSED(try_alignment); + UNUSED(mi_os_get_aligned_hint); + #endif + if (p==NULL) { + p = mmap(addr,size,protect_flags,flags,fd,0); + if (p==MAP_FAILED) p = NULL; + } + return p; +} + +static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) { + void* p = NULL; + #if !defined(MAP_ANONYMOUS) + #define MAP_ANONYMOUS MAP_ANON + #endif + #if !defined(MAP_NORESERVE) + #define MAP_NORESERVE 0 + #endif + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; + int fd = -1; + #if defined(MAP_ALIGNED) // BSD + if (try_alignment > 0) { + size_t n = _mi_bsr(try_alignment); + if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) { // alignment is a power of 2 and 4096 <= alignment <= 1GiB + flags |= MAP_ALIGNED(n); + } + } + #endif + #if defined(PROT_MAX) + protect_flags |= PROT_MAX(PROT_READ | PROT_WRITE); // BSD + #endif + #if defined(VM_MAKE_TAG) + // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99) + int os_tag = (int)mi_option_get(mi_option_os_tag); + if (os_tag < 100 || os_tag > 255) os_tag = 100; + fd = VM_MAKE_TAG(os_tag); + #endif + if ((large_only || use_large_os_page(size, try_alignment)) && allow_large) { + static _Atomic(uintptr_t) large_page_try_ok; // = 0; + uintptr_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // If the OS is not configured for large OS pages, or the user does not have + // enough permission, the `mmap` will always fail (but it might also fail for other reasons). + // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times + // to avoid too many failing calls to mmap. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + int lflags = flags & ~MAP_NORESERVE; // using NORESERVE on huge pages seems to fail on Linux + int lfd = fd; + #ifdef MAP_ALIGNED_SUPER + lflags |= MAP_ALIGNED_SUPER; + #endif + #ifdef MAP_HUGETLB + lflags |= MAP_HUGETLB; + #endif + #ifdef MAP_HUGE_1GB + static bool mi_huge_pages_available = true; + if ((size % GiB) == 0 && mi_huge_pages_available) { + lflags |= MAP_HUGE_1GB; + } + else + #endif + { + #ifdef MAP_HUGE_2MB + lflags |= MAP_HUGE_2MB; + #endif + } + #ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB + lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + #endif + if (large_only || lflags != flags) { + // try large OS page allocation + *is_large = true; + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd); + #ifdef MAP_HUGE_1GB + if (p == NULL && (lflags & MAP_HUGE_1GB) != 0) { + mi_huge_pages_available = false; // don't try huge 1GiB pages again + _mi_warning_message("unable to allocate huge (1GiB) page, trying large (2MiB) pages instead (error %i)\n", errno); + lflags = ((lflags & ~MAP_HUGE_1GB) | MAP_HUGE_2MB); + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd); + } + #endif + if (large_only) return p; + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok, 10UL); // on error, don't try again for the next N allocations + } + } + } + } + if (p == NULL) { + *is_large = false; + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, flags, fd); + #if defined(MADV_HUGEPAGE) + // Many Linux systems don't allow MAP_HUGETLB but they support instead + // transparent huge pages (THP). It is not required to call `madvise` with MADV_HUGE + // though since properly aligned allocations will already use large pages if available + // in that case -- in particular for our large regions (in `memory.c`). + // However, some systems only allow THP if called with explicit `madvise`, so + // when large OS pages are enabled for mimalloc, we call `madvice` anyways. + if (allow_large && use_large_os_page(size, try_alignment)) { + if (madvise(p, size, MADV_HUGEPAGE) == 0) { + *is_large = true; // possibly + }; + } + #endif + #if defined(__sun) + if (allow_large && use_large_os_page(size, try_alignment)) { + struct memcntl_mha cmd = {0}; + cmd.mha_pagesize = large_os_page_size; + cmd.mha_cmd = MHA_MAPSIZE_VA; + if (memcntl(p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) { + *is_large = true; + } + } + #endif + } + if (p == NULL) { + _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, errno, addr, large_only, allow_large); + } + return p; +} +#endif + +// On 64-bit systems, we can do efficient aligned allocation by using +// the 4TiB to 30TiB area to allocate them. +#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED))) +static mi_decl_cache_align _Atomic(uintptr_t) aligned_base; + +// Return a 4MiB aligned address that is probably available +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) { + if (try_alignment == 0 || try_alignment > MI_SEGMENT_SIZE) return NULL; + if ((size%MI_SEGMENT_SIZE) != 0) return NULL; + uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size); + if (hint == 0 || hint > ((intptr_t)30<<40)) { // try to wrap around after 30TiB (area after 32TiB is used for huge OS pages) + uintptr_t init = ((uintptr_t)4 << 40); // start at 4TiB area + #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_get_default_heap()); + init = init + (MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)); // (randomly 20 bits)*4MiB == 0 to 4TiB + #endif + uintptr_t expected = hint + size; + mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init); + hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > 30TiB but that is ok, it is a hint after all + } + if (hint%try_alignment != 0) return NULL; + return (void*)hint; +} +#else +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) { + UNUSED(try_alignment); UNUSED(size); + return NULL; +} +#endif + + +// Primitive allocation from the OS. +// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. +static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) { + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + if (size == 0) return NULL; + if (!commit) allow_large = false; + + void* p = NULL; + /* + if (commit && allow_large) { + p = _mi_os_try_alloc_from_huge_reserved(size, try_alignment); + if (p != NULL) { + *is_large = true; + return p; + } + } + */ + + #if defined(_WIN32) + int flags = MEM_RESERVE; + if (commit) flags |= MEM_COMMIT; + p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large); + #elif defined(__wasi__) + *is_large = false; + p = mi_wasm_heap_grow(size, try_alignment); + #else + int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE); + p = mi_unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large); + #endif + mi_stat_counter_increase(stats->mmap_calls, 1); + if (p != NULL) { + _mi_stat_increase(&stats->reserved, size); + if (commit) { _mi_stat_increase(&stats->committed, size); } + } + return p; +} + + +// Primitive aligned allocation from the OS. +// This function guarantees the allocated memory is aligned. +static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) { + mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0)); + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + if (!commit) allow_large = false; + if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL; + size = _mi_align_up(size, _mi_os_page_size()); + + // try first with a hint (this will be aligned directly on Win 10+ or BSD) + void* p = mi_os_mem_alloc(size, alignment, commit, allow_large, is_large, stats); + if (p == NULL) return NULL; + + // if not aligned, free it, overallocate, and unmap around it + if (((uintptr_t)p % alignment != 0)) { + mi_os_mem_free(p, size, commit, stats); + if (size >= (SIZE_MAX - alignment)) return NULL; // overflow + size_t over_size = size + alignment; + +#if _WIN32 + // over-allocate and than re-allocate exactly at an aligned address in there. + // this may fail due to threads allocating at the same time so we + // retry this at most 3 times before giving up. + // (we can not decommit around the overallocation on Windows, because we can only + // free the original pointer, not one pointing inside the area) + int flags = MEM_RESERVE; + if (commit) flags |= MEM_COMMIT; + for (int tries = 0; tries < 3; tries++) { + // over-allocate to determine a virtual memory range + p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats); + if (p == NULL) return NULL; // error + if (((uintptr_t)p % alignment) == 0) { + // if p happens to be aligned, just decommit the left-over area + _mi_os_decommit((uint8_t*)p + size, over_size - size, stats); + break; + } + else { + // otherwise free and allocate at an aligned address in there + mi_os_mem_free(p, over_size, commit, stats); + void* aligned_p = mi_align_up_ptr(p, alignment); + p = mi_win_virtual_alloc(aligned_p, size, alignment, flags, false, allow_large, is_large); + if (p == aligned_p) break; // success! + if (p != NULL) { // should not happen? + mi_os_mem_free(p, size, commit, stats); + p = NULL; + } + } + } +#else + // overallocate... + p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats); + if (p == NULL) return NULL; + // and selectively unmap parts around the over-allocated area. + void* aligned_p = mi_align_up_ptr(p, alignment); + size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p; + size_t mid_size = _mi_align_up(size, _mi_os_page_size()); + size_t post_size = over_size - pre_size - mid_size; + mi_assert_internal(pre_size < over_size && post_size < over_size && mid_size >= size); + if (pre_size > 0) mi_os_mem_free(p, pre_size, commit, stats); + if (post_size > 0) mi_os_mem_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); + // we can return the aligned pointer on `mmap` systems + p = aligned_p; +#endif + } + + mi_assert_internal(p == NULL || (p != NULL && ((uintptr_t)p % alignment) == 0)); + return p; +} + +/* ----------------------------------------------------------- + OS API: alloc, free, alloc_aligned +----------------------------------------------------------- */ + +void* _mi_os_alloc(size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + bool is_large = false; + return mi_os_mem_alloc(size, 0, true, false, &is_large, stats); +} + +void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (size == 0 || p == NULL) return; + size = _mi_os_good_alloc_size(size); + mi_os_mem_free(p, size, was_committed, stats); +} + +void _mi_os_free(void* p, size_t size, mi_stats_t* stats) { + _mi_os_free_ex(p, size, true, stats); +} + +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld) +{ + UNUSED(tld); + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + alignment = _mi_align_up(alignment, _mi_os_page_size()); + bool allow_large = false; + if (large != NULL) { + allow_large = *large; + *large = false; + } + return mi_os_mem_alloc_aligned(size, alignment, commit, allow_large, (large!=NULL?large:&allow_large), &_mi_stats_main /*tld->stats*/ ); +} + + + +/* ----------------------------------------------------------- + OS memory API: reset, commit, decommit, protect, unprotect. +----------------------------------------------------------- */ + + +// OS page align within a given area, either conservative (pages inside the area only), +// or not (straddling pages outside the area is possible) +static void* mi_os_page_align_areax(bool conservative, void* addr, size_t size, size_t* newsize) { + mi_assert(addr != NULL && size > 0); + if (newsize != NULL) *newsize = 0; + if (size == 0 || addr == NULL) return NULL; + + // page align conservatively within the range + void* start = (conservative ? mi_align_up_ptr(addr, _mi_os_page_size()) + : mi_align_down_ptr(addr, _mi_os_page_size())); + void* end = (conservative ? mi_align_down_ptr((uint8_t*)addr + size, _mi_os_page_size()) + : mi_align_up_ptr((uint8_t*)addr + size, _mi_os_page_size())); + ptrdiff_t diff = (uint8_t*)end - (uint8_t*)start; + if (diff <= 0) return NULL; + + mi_assert_internal((conservative && (size_t)diff <= size) || (!conservative && (size_t)diff >= size)); + if (newsize != NULL) *newsize = (size_t)diff; + return start; +} + +static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t* newsize) { + return mi_os_page_align_areax(true, addr, size, newsize); +} + +static void mi_mprotect_hint(int err) { +#if defined(MI_OS_USE_MMAP) && (MI_SECURE>=2) // guard page around every mimalloc page + if (err == ENOMEM) { + _mi_warning_message("the previous warning may have been caused by a low memory map limit.\n" + " On Linux this is controlled by the vm.max_map_count. For example:\n" + " > sudo sysctl -w vm.max_map_count=262144\n"); + } +#else + UNUSED(err); +#endif +} + +// Commit/Decommit memory. +// Usually commit is aligned liberal, while decommit is aligned conservative. +// (but not for the reset version where we want commit to be conservative as well) +static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservative, bool* is_zero, mi_stats_t* stats) { + // page align in the range, commit liberally, decommit conservative + if (is_zero != NULL) { *is_zero = false; } + size_t csize; + void* start = mi_os_page_align_areax(conservative, addr, size, &csize); + if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr)) + int err = 0; + if (commit) { + _mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit + _mi_stat_counter_increase(&stats->commit_calls, 1); + } + else { + _mi_stat_decrease(&stats->committed, size); + } + + #if defined(_WIN32) + if (commit) { + // if the memory was already committed, the call succeeds but it is not zero'd + // *is_zero = true; + void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE); + err = (p == start ? 0 : GetLastError()); + } + else { + BOOL ok = VirtualFree(start, csize, MEM_DECOMMIT); + err = (ok ? 0 : GetLastError()); + } + #elif defined(__wasi__) + // WebAssembly guests can't control memory protection + #elif defined(MAP_FIXED) + if (!commit) { + // use mmap with MAP_FIXED to discard the existing memory (and reduce commit charge) + void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), -1, 0); + if (p != start) { err = errno; } + } + else { + // for commit, just change the protection + err = mprotect(start, csize, (PROT_READ | PROT_WRITE)); + if (err != 0) { err = errno; } + } + #else + err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE)); + if (err != 0) { err = errno; } + #endif + if (err != 0) { + _mi_warning_message("%s error: start: %p, csize: 0x%x, err: %i\n", commit ? "commit" : "decommit", start, csize, err); + mi_mprotect_hint(err); + } + mi_assert_internal(err == 0); + return (err == 0); +} + +bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + return mi_os_commitx(addr, size, true, false /* liberal */, is_zero, stats); +} + +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + bool is_zero; + return mi_os_commitx(addr, size, false, true /* conservative */, &is_zero, stats); +} + +static bool mi_os_commit_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) { + return mi_os_commitx(addr, size, true, true /* conservative */, is_zero, stats); +} + +// Signal to the OS that the address range is no longer in use +// but may be used later again. This will release physical memory +// pages and reduce swapping while keeping the memory committed. +// We page align to a conservative area inside the range to reset. +static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats) { + // page align conservatively within the range + size_t csize; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr) + if (reset) _mi_stat_increase(&stats->reset, csize); + else _mi_stat_decrease(&stats->reset, csize); + if (!reset) return true; // nothing to do on unreset! + + #if (MI_DEBUG>1) + if (MI_SECURE==0) { + memset(start, 0, csize); // pretend it is eagerly reset + } + #endif + +#if defined(_WIN32) + // Testing shows that for us (on `malloc-large`) MEM_RESET is 2x faster than DiscardVirtualMemory + void* p = VirtualAlloc(start, csize, MEM_RESET, PAGE_READWRITE); + mi_assert_internal(p == start); + #if 1 + if (p == start && start != NULL) { + VirtualUnlock(start,csize); // VirtualUnlock after MEM_RESET removes the memory from the working set + } + #endif + if (p != start) return false; +#else +#if defined(MADV_FREE) + static _Atomic(uintptr_t) advice = ATOMIC_VAR_INIT(MADV_FREE); + int err = madvise(start, csize, (int)mi_atomic_load_relaxed(&advice)); + if (err != 0 && errno == EINVAL && advice == MADV_FREE) { + // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on + mi_atomic_store_release(&advice, (uintptr_t)MADV_DONTNEED); + err = madvise(start, csize, MADV_DONTNEED); + } +#elif defined(__wasi__) + int err = 0; +#else + int err = madvise(start, csize, MADV_DONTNEED); +#endif + if (err != 0) { + _mi_warning_message("madvise reset error: start: %p, csize: 0x%x, errno: %i\n", start, csize, errno); + } + //mi_assert(err == 0); + if (err != 0) return false; +#endif + return true; +} + +// Signal to the OS that the address range is no longer in use +// but may be used later again. This will release physical memory +// pages and reduce swapping while keeping the memory committed. +// We page align to a conservative area inside the range to reset. +bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (mi_option_is_enabled(mi_option_reset_decommits)) { + return _mi_os_decommit(addr, size, stats); + } + else { + return mi_os_resetx(addr, size, true, stats); + } +} + +bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (mi_option_is_enabled(mi_option_reset_decommits)) { + return mi_os_commit_unreset(addr, size, is_zero, stats); // re-commit it (conservatively!) + } + else { + *is_zero = false; + return mi_os_resetx(addr, size, false, stats); + } +} + + +// Protect a region in memory to be not accessible. +static bool mi_os_protectx(void* addr, size_t size, bool protect) { + // page align conservatively within the range + size_t csize = 0; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return false; + /* + if (_mi_os_is_huge_reserved(addr)) { + _mi_warning_message("cannot mprotect memory allocated in huge OS pages\n"); + } + */ + int err = 0; +#ifdef _WIN32 + DWORD oldprotect = 0; + BOOL ok = VirtualProtect(start, csize, protect ? PAGE_NOACCESS : PAGE_READWRITE, &oldprotect); + err = (ok ? 0 : GetLastError()); +#elif defined(__wasi__) + err = 0; +#else + err = mprotect(start, csize, protect ? PROT_NONE : (PROT_READ | PROT_WRITE)); + if (err != 0) { err = errno; } +#endif + if (err != 0) { + _mi_warning_message("mprotect error: start: %p, csize: 0x%x, err: %i\n", start, csize, err); + mi_mprotect_hint(err); + } + return (err == 0); +} + +bool _mi_os_protect(void* addr, size_t size) { + return mi_os_protectx(addr, size, true); +} + +bool _mi_os_unprotect(void* addr, size_t size) { + return mi_os_protectx(addr, size, false); +} + + + +bool _mi_os_shrink(void* p, size_t oldsize, size_t newsize, mi_stats_t* stats) { + // page align conservatively within the range + mi_assert_internal(oldsize > newsize && p != NULL); + if (oldsize < newsize || p == NULL) return false; + if (oldsize == newsize) return true; + + // oldsize and newsize should be page aligned or we cannot shrink precisely + void* addr = (uint8_t*)p + newsize; + size_t size = 0; + void* start = mi_os_page_align_area_conservative(addr, oldsize - newsize, &size); + if (size == 0 || start != addr) return false; + +#ifdef _WIN32 + // we cannot shrink on windows, but we can decommit + return _mi_os_decommit(start, size, stats); +#else + return mi_os_mem_free(start, size, true, stats); +#endif +} + + +/* ---------------------------------------------------------------------------- +Support for allocating huge OS pages (1Gib) that are reserved up-front +and possibly associated with a specific NUMA node. (use `numa_node>=0`) +-----------------------------------------------------------------------------*/ +#define MI_HUGE_OS_PAGE_SIZE (GiB) + +#if defined(_WIN32) && (MI_INTPTR_SIZE >= 8) +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) +{ + mi_assert_internal(size%GiB == 0); + mi_assert_internal(addr != NULL); + const DWORD flags = MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE; + + mi_win_enable_large_os_pages(); + + #if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) + MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} }; + // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages + static bool mi_huge_pages_available = true; + if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) { + #ifndef MEM_EXTENDED_PARAMETER_NONPAGED_HUGE + #define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE (0x10) + #endif + params[0].Type = 5; // == MemExtendedParameterAttributeFlags; + params[0].ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE; + ULONG param_count = 1; + if (numa_node >= 0) { + param_count++; + params[1].Type = MemExtendedParameterNumaNode; + params[1].ULong = (unsigned)numa_node; + } + SIZE_T psize = size; + void* base = addr; + NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, params, param_count); + if (err == 0 && base != NULL) { + return base; + } + else { + // fall back to regular large pages + mi_huge_pages_available = false; // don't try further huge pages + _mi_warning_message("unable to allocate using huge (1gb) pages, trying large (2mb) pages instead (status 0x%lx)\n", err); + } + } + // on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation + if (pVirtualAlloc2 != NULL && numa_node >= 0) { + params[0].Type = MemExtendedParameterNumaNode; + params[0].ULong = (unsigned)numa_node; + return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, params, 1); + } + #else + UNUSED(numa_node); + #endif + // otherwise use regular virtual alloc on older windows + return VirtualAlloc(addr, size, flags, PAGE_READWRITE); +} + +#elif defined(MI_OS_USE_MMAP) && (MI_INTPTR_SIZE >= 8) && !defined(__HAIKU__) +#include +#ifndef MPOL_PREFERRED +#define MPOL_PREFERRED 1 +#endif +#if defined(SYS_mbind) +static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + return syscall(SYS_mbind, start, len, mode, nmask, maxnode, flags); +} +#else +static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + UNUSED(start); UNUSED(len); UNUSED(mode); UNUSED(nmask); UNUSED(maxnode); UNUSED(flags); + return 0; +} +#endif +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) { + mi_assert_internal(size%GiB == 0); + bool is_large = true; + void* p = mi_unix_mmap(addr, size, MI_SEGMENT_SIZE, PROT_READ | PROT_WRITE, true, true, &is_large); + if (p == NULL) return NULL; + if (numa_node >= 0 && numa_node < 8*MI_INTPTR_SIZE) { // at most 64 nodes + uintptr_t numa_mask = (1UL << numa_node); + // TODO: does `mbind` work correctly for huge OS pages? should we + // use `set_mempolicy` before calling mmap instead? + // see: + long err = mi_os_mbind(p, size, MPOL_PREFERRED, &numa_mask, 8*MI_INTPTR_SIZE, 0); + if (err != 0) { + _mi_warning_message("failed to bind huge (1gb) pages to numa node %d: %s\n", numa_node, strerror(errno)); + } + } + return p; +} +#else +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) { + UNUSED(addr); UNUSED(size); UNUSED(numa_node); + return NULL; +} +#endif + +#if (MI_INTPTR_SIZE >= 8) +// To ensure proper alignment, use our own area for huge OS pages +static mi_decl_cache_align _Atomic(uintptr_t) mi_huge_start; // = 0 + +// Claim an aligned address range for huge pages +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + if (total_size != NULL) *total_size = 0; + const size_t size = pages * MI_HUGE_OS_PAGE_SIZE; + + uintptr_t start = 0; + uintptr_t end = 0; + uintptr_t huge_start = mi_atomic_load_relaxed(&mi_huge_start); + do { + start = huge_start; + if (start == 0) { + // Initialize the start address after the 32TiB area + start = ((uintptr_t)32 << 40); // 32TiB virtual start address +#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_get_default_heap()); + start = start + ((uintptr_t)MI_HUGE_OS_PAGE_SIZE * ((r>>17) & 0x0FFF)); // (randomly 12bits)*1GiB == between 0 to 4TiB +#endif + } + end = start + size; + mi_assert_internal(end % MI_SEGMENT_SIZE == 0); + } while (!mi_atomic_cas_strong_acq_rel(&mi_huge_start, &huge_start, end)); + + if (total_size != NULL) *total_size = size; + return (uint8_t*)start; +} +#else +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + UNUSED(pages); + if (total_size != NULL) *total_size = 0; + return NULL; +} +#endif + +// Allocate MI_SEGMENT_SIZE aligned huge pages +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_msecs, size_t* pages_reserved, size_t* psize) { + if (psize != NULL) *psize = 0; + if (pages_reserved != NULL) *pages_reserved = 0; + size_t size = 0; + uint8_t* start = mi_os_claim_huge_pages(pages, &size); + if (start == NULL) return NULL; // or 32-bit systems + + // Allocate one page at the time but try to place them contiguously + // We allocate one page at the time to be able to abort if it takes too long + // or to at least allocate as many as available on the system. + mi_msecs_t start_t = _mi_clock_start(); + size_t page; + for (page = 0; page < pages; page++) { + // allocate a page + void* addr = start + (page * MI_HUGE_OS_PAGE_SIZE); + void* p = mi_os_alloc_huge_os_pagesx(addr, MI_HUGE_OS_PAGE_SIZE, numa_node); + + // Did we succeed at a contiguous address? + if (p != addr) { + // no success, issue a warning and break + if (p != NULL) { + _mi_warning_message("could not allocate contiguous huge page %zu at %p\n", page, addr); + _mi_os_free(p, MI_HUGE_OS_PAGE_SIZE, &_mi_stats_main); + } + break; + } + + // success, record it + _mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE); + _mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE); + + // check for timeout + if (max_msecs > 0) { + mi_msecs_t elapsed = _mi_clock_end(start_t); + if (page >= 1) { + mi_msecs_t estimate = ((elapsed / (page+1)) * pages); + if (estimate > 2*max_msecs) { // seems like we are going to timeout, break + elapsed = max_msecs + 1; + } + } + if (elapsed > max_msecs) { + _mi_warning_message("huge page allocation timed out\n"); + break; + } + } + } + mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size); + if (pages_reserved != NULL) *pages_reserved = page; + if (psize != NULL) *psize = page * MI_HUGE_OS_PAGE_SIZE; + return (page == 0 ? NULL : start); +} + +// free every huge page in a range individually (as we allocated per page) +// note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems. +void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats) { + if (p==NULL || size==0) return; + uint8_t* base = (uint8_t*)p; + while (size >= MI_HUGE_OS_PAGE_SIZE) { + _mi_os_free(base, MI_HUGE_OS_PAGE_SIZE, stats); + size -= MI_HUGE_OS_PAGE_SIZE; + } +} + +/* ---------------------------------------------------------------------------- +Support NUMA aware allocation +-----------------------------------------------------------------------------*/ +#ifdef _WIN32 +static size_t mi_os_numa_nodex() { + USHORT numa_node = 0; + if (pGetCurrentProcessorNumberEx != NULL && pGetNumaProcessorNodeEx != NULL) { + // Extended API is supported + PROCESSOR_NUMBER pnum; + (*pGetCurrentProcessorNumberEx)(&pnum); + USHORT nnode = 0; + BOOL ok = (*pGetNumaProcessorNodeEx)(&pnum, &nnode); + if (ok) numa_node = nnode; + } + else { + // Vista or earlier, use older API that is limited to 64 processors. Issue #277 + DWORD pnum = GetCurrentProcessorNumber(); + UCHAR nnode = 0; + BOOL ok = GetNumaProcessorNode((UCHAR)pnum, &nnode); + if (ok) numa_node = nnode; + } + return numa_node; +} + +static size_t mi_os_numa_node_countx(void) { + ULONG numa_max = 0; + GetNumaHighestNodeNumber(&numa_max); + // find the highest node number that has actual processors assigned to it. Issue #282 + while(numa_max > 0) { + if (pGetNumaNodeProcessorMaskEx != NULL) { + // Extended API is supported + GROUP_AFFINITY affinity; + if ((*pGetNumaNodeProcessorMaskEx)((USHORT)numa_max, &affinity)) { + if (affinity.Mask != 0) break; // found the maximum non-empty node + } + } + else { + // Vista or earlier, use older API that is limited to 64 processors. + ULONGLONG mask; + if (GetNumaNodeProcessorMask((UCHAR)numa_max, &mask)) { + if (mask != 0) break; // found the maximum non-empty node + }; + } + // max node was invalid or had no processor assigned, try again + numa_max--; + } + return ((size_t)numa_max + 1); +} +#elif defined(__linux__) +#include // getcpu +#include // access + +static size_t mi_os_numa_nodex(void) { +#ifdef SYS_getcpu + unsigned long node = 0; + unsigned long ncpu = 0; + long err = syscall(SYS_getcpu, &ncpu, &node, NULL); + if (err != 0) return 0; + return node; +#else + return 0; +#endif +} +static size_t mi_os_numa_node_countx(void) { + char buf[128]; + unsigned node = 0; + for(node = 0; node < 256; node++) { + // enumerate node entries -- todo: it there a more efficient way to do this? (but ensure there is no allocation) + snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1); + if (access(buf,R_OK) != 0) break; + } + return (node+1); +} +#else +static size_t mi_os_numa_nodex(void) { + return 0; +} +static size_t mi_os_numa_node_countx(void) { + return 1; +} +#endif + +size_t _mi_numa_node_count = 0; // cache the node count + +size_t _mi_os_numa_node_count_get(void) { + if (mi_unlikely(_mi_numa_node_count <= 0)) { + long ncount = mi_option_get(mi_option_use_numa_nodes); // given explicitly? + if (ncount <= 0) ncount = (long)mi_os_numa_node_countx(); // or detect dynamically + _mi_numa_node_count = (size_t)(ncount <= 0 ? 1 : ncount); + _mi_verbose_message("using %zd numa regions\n", _mi_numa_node_count); + } + mi_assert_internal(_mi_numa_node_count >= 1); + return _mi_numa_node_count; +} + +int _mi_os_numa_node_get(mi_os_tld_t* tld) { + UNUSED(tld); + size_t numa_count = _mi_os_numa_node_count(); + if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0 + // never more than the node count and >= 0 + size_t numa_node = mi_os_numa_nodex(); + if (numa_node >= numa_count) { numa_node = numa_node % numa_count; } + return (int)numa_node; +} diff --git a/deps/mimalloc/src/page-queue.c b/deps/mimalloc/src/page-queue.c new file mode 100644 index 000000000..37719e02a --- /dev/null +++ b/deps/mimalloc/src/page-queue.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#ifndef MI_IN_PAGE_C +#error "this file should be included from 'page.c'" +#endif + +/* ----------------------------------------------------------- + Minimal alignment in machine words (i.e. `sizeof(void*)`) +----------------------------------------------------------- */ + +#if (MI_MAX_ALIGN_SIZE > 4*MI_INTPTR_SIZE) + #error "define alignment for more than 4x word size for this platform" +#elif (MI_MAX_ALIGN_SIZE > 2*MI_INTPTR_SIZE) + #define MI_ALIGN4W // 4 machine words minimal alignment +#elif (MI_MAX_ALIGN_SIZE > MI_INTPTR_SIZE) + #define MI_ALIGN2W // 2 machine words minimal alignment +#else + // ok, default alignment is 1 word +#endif + + +/* ----------------------------------------------------------- + Queue query +----------------------------------------------------------- */ + + +static inline bool mi_page_queue_is_huge(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+sizeof(uintptr_t))); +} + +static inline bool mi_page_queue_is_full(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+(2*sizeof(uintptr_t)))); +} + +static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) { + return (pq->block_size > MI_LARGE_OBJ_SIZE_MAX); +} + +/* ----------------------------------------------------------- + Bins +----------------------------------------------------------- */ + +// Bit scan reverse: return the index of the highest bit. +static inline uint8_t mi_bsr32(uint32_t x); + +#if defined(_MSC_VER) +#include +static inline uint8_t mi_bsr32(uint32_t x) { + uint32_t idx; + _BitScanReverse((DWORD*)&idx, x); + return (uint8_t)idx; +} +#elif defined(__GNUC__) || defined(__clang__) +static inline uint8_t mi_bsr32(uint32_t x) { + return (31 - __builtin_clz(x)); +} +#else +static inline uint8_t mi_bsr32(uint32_t x) { + // de Bruijn multiplication, see + static const uint8_t debruijn[32] = { + 31, 0, 22, 1, 28, 23, 18, 2, 29, 26, 24, 10, 19, 7, 3, 12, + 30, 21, 27, 17, 25, 9, 6, 11, 20, 16, 8, 5, 15, 4, 14, 13, + }; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return debruijn[(x*0x076be629) >> 27]; +} +#endif + +// Bit scan reverse: return the index of the highest bit. +uint8_t _mi_bsr(uintptr_t x) { + if (x == 0) return 0; +#if MI_INTPTR_SIZE==8 + uint32_t hi = (x >> 32); + return (hi == 0 ? mi_bsr32((uint32_t)x) : 32 + mi_bsr32(hi)); +#elif MI_INTPTR_SIZE==4 + return mi_bsr32(x); +#else +# error "define bsr for non-32 or 64-bit platforms" +#endif +} + +// Return the bin for a given field size. +// Returns MI_BIN_HUGE if the size is too large. +// We use `wsize` for the size in "machine word sizes", +// i.e. byte size == `wsize*sizeof(void*)`. +extern inline uint8_t _mi_bin(size_t size) { + size_t wsize = _mi_wsize_from_size(size); + uint8_t bin; + if (wsize <= 1) { + bin = 1; + } + #if defined(MI_ALIGN4W) + else if (wsize <= 4) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #elif defined(MI_ALIGN2W) + else if (wsize <= 8) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #else + else if (wsize <= 8) { + bin = (uint8_t)wsize; + } + #endif + else if (wsize > MI_LARGE_OBJ_WSIZE_MAX) { + bin = MI_BIN_HUGE; + } + else { + #if defined(MI_ALIGN4W) + if (wsize <= 16) { wsize = (wsize+3)&~3; } // round to 4x word sizes + #endif + wsize--; + // find the highest bit + uint8_t b = mi_bsr32((uint32_t)wsize); + // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). + // - adjust with 3 because we use do not round the first 8 sizes + // which each get an exact bin + bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; + mi_assert_internal(bin < MI_BIN_HUGE); + } + mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE); + return bin; +} + + + +/* ----------------------------------------------------------- + Queue of pages with free blocks +----------------------------------------------------------- */ + +size_t _mi_bin_size(uint8_t bin) { + return _mi_heap_empty.pages[bin].block_size; +} + +// Good size for allocation +size_t mi_good_size(size_t size) mi_attr_noexcept { + if (size <= MI_LARGE_OBJ_SIZE_MAX) { + return _mi_bin_size(_mi_bin(size)); + } + else { + return _mi_align_up(size,_mi_os_page_size()); + } +} + +#if (MI_DEBUG>1) +static bool mi_page_queue_contains(mi_page_queue_t* queue, const mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_page_t* list = queue->first; + while (list != NULL) { + mi_assert_internal(list->next == NULL || list->next->prev == list); + mi_assert_internal(list->prev == NULL || list->prev->next == list); + if (list == page) break; + list = list->next; + } + return (list == page); +} + +#endif + +#if (MI_DEBUG>1) +static bool mi_heap_contains_queue(const mi_heap_t* heap, const mi_page_queue_t* pq) { + return (pq >= &heap->pages[0] && pq <= &heap->pages[MI_BIN_FULL]); +} +#endif + +static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(heap != NULL && bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(bin >= MI_BIN_HUGE || page->xblock_size == pq->block_size); + mi_assert_expensive(mi_page_queue_contains(pq, page)); + return pq; +} + +static mi_page_queue_t* mi_heap_page_queue_of(mi_heap_t* heap, const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + mi_assert_internal(bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(mi_page_is_in_full(page) || page->xblock_size == pq->block_size); + return pq; +} + +// The current small page array is for efficiency and for each +// small size (up to 256) it points directly to the page for that +// size without having to compute the bin. This means when the +// current free page queue is updated for a small bin, we need to update a +// range of entries in `_mi_page_small_free`. +static inline void mi_heap_queue_first_update(mi_heap_t* heap, const mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + size_t size = pq->block_size; + if (size > MI_SMALL_SIZE_MAX) return; + + mi_page_t* page = pq->first; + if (pq->first == NULL) page = (mi_page_t*)&_mi_page_empty; + + // find index in the right direct page array + size_t start; + size_t idx = _mi_wsize_from_size(size); + mi_page_t** pages_free = heap->pages_free_direct; + + if (pages_free[idx] == page) return; // already set + + // find start slot + if (idx<=1) { + start = 0; + } + else { + // find previous size; due to minimal alignment upto 3 previous bins may need to be skipped + uint8_t bin = _mi_bin(size); + const mi_page_queue_t* prev = pq - 1; + while( bin == _mi_bin(prev->block_size) && prev > &heap->pages[0]) { + prev--; + } + start = 1 + _mi_wsize_from_size(prev->block_size); + if (start > idx) start = idx; + } + + // set size range to the right page + mi_assert(start <= idx); + for (size_t sz = start; sz <= idx; sz++) { + pages_free[sz] = page; + } +} + +/* +static bool mi_page_queue_is_empty(mi_page_queue_t* queue) { + return (queue->first == NULL); +} +*/ + +static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(queue, page)); + mi_assert_internal(page->xblock_size == queue->block_size || (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) || (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + mi_heap_t* heap = mi_page_heap(page); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == queue->last) queue->last = page->prev; + if (page == queue->first) { + queue->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, queue)); + mi_heap_queue_first_update(heap,queue); + } + heap->page_count--; + page->next = NULL; + page->prev = NULL; + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), NULL); + mi_page_set_in_full(page,false); +} + + +static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(!mi_page_queue_contains(queue, page)); + mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_assert_internal(page->xblock_size == queue->block_size || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) || + (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + + mi_page_set_in_full(page, mi_page_queue_is_full(queue)); + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), heap); + page->next = queue->first; + page->prev = NULL; + if (queue->first != NULL) { + mi_assert_internal(queue->first->prev == NULL); + queue->first->prev = page; + queue->first = page; + } + else { + queue->first = queue->last = page; + } + + // update direct + mi_heap_queue_first_update(heap, queue); + heap->page_count++; +} + + +static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(from, page)); + mi_assert_expensive(!mi_page_queue_contains(to, page)); + mi_assert_internal((page->xblock_size == to->block_size && page->xblock_size == from->block_size) || + (page->xblock_size == to->block_size && mi_page_queue_is_full(from)) || + (page->xblock_size == from->block_size && mi_page_queue_is_full(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_full(to))); + + mi_heap_t* heap = mi_page_heap(page); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == from->last) from->last = page->prev; + if (page == from->first) { + from->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, from)); + mi_heap_queue_first_update(heap, from); + } + + page->prev = to->last; + page->next = NULL; + if (to->last != NULL) { + mi_assert_internal(heap == mi_page_heap(to->last)); + to->last->next = page; + to->last = page; + } + else { + to->first = page; + to->last = page; + mi_heap_queue_first_update(heap, to); + } + + mi_page_set_in_full(page, mi_page_queue_is_full(to)); +} + +// Only called from `mi_heap_absorb`. +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + mi_assert_internal(pq->block_size == append->block_size); + + if (append->first==NULL) return 0; + + // set append pages to new heap and count + size_t count = 0; + for (mi_page_t* page = append->first; page != NULL; page = page->next) { + // inline `mi_page_set_heap` to avoid wrong assertion during absorption; + // in this case it is ok to be delayed freeing since both "to" and "from" heap are still alive. + mi_atomic_store_release(&page->xheap, (uintptr_t)heap); + // set the flag to delayed free (not overriding NEVER_DELAYED_FREE) which has as a + // side effect that it spins until any DELAYED_FREEING is finished. This ensures + // that after appending only the new heap will be used for delayed free operations. + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, false); + count++; + } + + if (pq->last==NULL) { + // take over afresh + mi_assert_internal(pq->first==NULL); + pq->first = append->first; + pq->last = append->last; + mi_heap_queue_first_update(heap, pq); + } + else { + // append to end + mi_assert_internal(pq->last!=NULL); + mi_assert_internal(append->first!=NULL); + pq->last->next = append->first; + append->first->prev = pq->last; + pq->last = append->last; + } + return count; +} diff --git a/deps/mimalloc/src/page.c b/deps/mimalloc/src/page.c new file mode 100644 index 000000000..cd96bb908 --- /dev/null +++ b/deps/mimalloc/src/page.c @@ -0,0 +1,843 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + The core of the allocator. Every segment contains + pages of a {certain block size. The main function + exported is `mi_malloc_generic`. +----------------------------------------------------------- */ + +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#define MI_IN_PAGE_C +#include "page-queue.c" +#undef MI_IN_PAGE_C + + +/* ----------------------------------------------------------- + Page helpers +----------------------------------------------------------- */ + +// Index a block in a page +static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_start, size_t block_size, size_t i) { + UNUSED(page); + mi_assert_internal(page != NULL); + mi_assert_internal(i <= page->reserved); + return (mi_block_t*)((uint8_t*)page_start + (i * block_size)); +} + +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld); +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld); + +#if (MI_DEBUG>=3) +static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) { + size_t count = 0; + while (head != NULL) { + mi_assert_internal(page == _mi_ptr_page(head)); + count++; + head = mi_block_next(page, head); + } + return count; +} + +/* +// Start of the page available memory +static inline uint8_t* mi_page_area(const mi_page_t* page) { + return _mi_page_start(_mi_page_segment(page), page, NULL); +} +*/ + +static bool mi_page_list_is_valid(mi_page_t* page, mi_block_t* p) { + size_t psize; + uint8_t* page_area = _mi_page_start(_mi_page_segment(page), page, &psize); + mi_block_t* start = (mi_block_t*)page_area; + mi_block_t* end = (mi_block_t*)(page_area + psize); + while(p != NULL) { + if (p < start || p >= end) return false; + p = mi_block_next(page, p); + } + return true; +} + +static bool mi_page_is_valid_init(mi_page_t* page) { + mi_assert_internal(page->xblock_size > 0); + mi_assert_internal(page->used <= page->capacity); + mi_assert_internal(page->capacity <= page->reserved); + + const size_t bsize = mi_page_block_size(page); + mi_segment_t* segment = _mi_page_segment(page); + uint8_t* start = _mi_page_start(segment,page,NULL); + mi_assert_internal(start == _mi_segment_page_start(segment,page,bsize,NULL,NULL)); + //mi_assert_internal(start + page->capacity*page->block_size == page->top); + + mi_assert_internal(mi_page_list_is_valid(page,page->free)); + mi_assert_internal(mi_page_list_is_valid(page,page->local_free)); + + #if MI_DEBUG>3 // generally too expensive to check this + if (page->flags.is_zero) { + for(mi_block_t* block = page->free; block != NULL; mi_block_next(page,block)) { + mi_assert_expensive(mi_mem_is_zero(block + 1, page->block_size - sizeof(mi_block_t))); + } + } + #endif + + mi_block_t* tfree = mi_page_thread_free(page); + mi_assert_internal(mi_page_list_is_valid(page, tfree)); + //size_t tfree_count = mi_page_list_count(page, tfree); + //mi_assert_internal(tfree_count <= page->thread_freed + 1); + + size_t free_count = mi_page_list_count(page, page->free) + mi_page_list_count(page, page->local_free); + mi_assert_internal(page->used + free_count == page->capacity); + + return true; +} + +bool _mi_page_is_valid(mi_page_t* page) { + mi_assert_internal(mi_page_is_valid_init(page)); + #if MI_SECURE + mi_assert_internal(page->keys[0] != 0); + #endif + if (mi_page_heap(page)!=NULL) { + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_internal(!_mi_process_is_initialized || segment->thread_id == mi_page_heap(page)->thread_id || segment->thread_id==0); + if (segment->page_kind != MI_PAGE_HUGE) { + mi_page_queue_t* pq = mi_page_queue_of(page); + mi_assert_internal(mi_page_queue_contains(pq, page)); + mi_assert_internal(pq->block_size==mi_page_block_size(page) || mi_page_block_size(page) > MI_LARGE_OBJ_SIZE_MAX || mi_page_is_in_full(page)); + mi_assert_internal(mi_heap_contains_queue(mi_page_heap(page),pq)); + } + } + return true; +} +#endif + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) { + mi_thread_free_t tfreex; + mi_delayed_t old_delay; + mi_thread_free_t tfree; + do { + tfree = mi_atomic_load_acquire(&page->xthread_free); // note: must acquire as we can break/repeat this loop and not do a CAS; + tfreex = mi_tf_set_delayed(tfree, delay); + old_delay = mi_tf_delayed(tfree); + if (mi_unlikely(old_delay == MI_DELAYED_FREEING)) { + mi_atomic_yield(); // delay until outstanding MI_DELAYED_FREEING are done. + // tfree = mi_tf_set_delayed(tfree, MI_NO_DELAYED_FREE); // will cause CAS to busy fail + } + else if (delay == old_delay) { + break; // avoid atomic operation if already equal + } + else if (!override_never && old_delay == MI_NEVER_DELAYED_FREE) { + break; // leave never-delayed flag set + } + } while ((old_delay == MI_DELAYED_FREEING) || + !mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); +} + +/* ----------------------------------------------------------- + Page collect the `local_free` and `thread_free` lists +----------------------------------------------------------- */ + +// Collect the local `thread_free` list using an atomic exchange. +// Note: The exchange must be done atomically as this is used right after +// moving to the full list in `mi_page_collect_ex` and we need to +// ensure that there was no race where the page became unfull just before the move. +static void _mi_page_thread_free_collect(mi_page_t* page) +{ + mi_block_t* head; + mi_thread_free_t tfreex; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + head = mi_tf_block(tfree); + tfreex = mi_tf_set_block(tfree,NULL); + } while (!mi_atomic_cas_weak_acq_rel(&page->xthread_free, &tfree, tfreex)); + + // return if the list is empty + if (head == NULL) return; + + // find the tail -- also to get a proper count (without data races) + uint32_t max_count = page->capacity; // cannot collect more than capacity + uint32_t count = 1; + mi_block_t* tail = head; + mi_block_t* next; + while ((next = mi_block_next(page,tail)) != NULL && count <= max_count) { + count++; + tail = next; + } + // if `count > max_count` there was a memory corruption (possibly infinite list due to double multi-threaded free) + if (count > max_count) { + _mi_error_message(EFAULT, "corrupted thread-free list\n"); + return; // the thread-free items cannot be freed + } + + // and append the current local free list + mi_block_set_next(page,tail, page->local_free); + page->local_free = head; + + // update counts now + page->used -= count; +} + +void _mi_page_free_collect(mi_page_t* page, bool force) { + mi_assert_internal(page!=NULL); + + // collect the thread free list + if (force || mi_page_thread_free(page) != NULL) { // quick test to avoid an atomic operation + _mi_page_thread_free_collect(page); + } + + // and the local free list + if (page->local_free != NULL) { + if (mi_likely(page->free == NULL)) { + // usual case + page->free = page->local_free; + page->local_free = NULL; + page->is_zero = false; + } + else if (force) { + // append -- only on shutdown (force) as this is a linear operation + mi_block_t* tail = page->local_free; + mi_block_t* next; + while ((next = mi_block_next(page, tail)) != NULL) { + tail = next; + } + mi_block_set_next(page, tail, page->free); + page->free = page->local_free; + page->local_free = NULL; + page->is_zero = false; + } + } + + mi_assert_internal(!force || page->local_free == NULL); +} + + + +/* ----------------------------------------------------------- + Page fresh and retire +----------------------------------------------------------- */ + +// called from segments when reclaiming abandoned pages +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page) { + mi_assert_expensive(mi_page_is_valid_init(page)); + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(mi_page_thread_free_flag(page) != MI_NEVER_DELAYED_FREE); + mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_assert_internal(!page->is_reset); + // TODO: push on full queue immediately if it is full? + mi_page_queue_t* pq = mi_page_queue(heap, mi_page_block_size(page)); + mi_page_queue_push(heap, pq, page); + mi_assert_expensive(_mi_page_is_valid(page)); +} + +// allocate a fresh page from a segment +static mi_page_t* mi_page_fresh_alloc(mi_heap_t* heap, mi_page_queue_t* pq, size_t block_size) { + mi_assert_internal(pq==NULL||mi_heap_contains_queue(heap, pq)); + mi_assert_internal(pq==NULL||block_size == pq->block_size); + mi_page_t* page = _mi_segment_page_alloc(heap, block_size, &heap->tld->segments, &heap->tld->os); + if (page == NULL) { + // this may be out-of-memory, or an abandoned page was reclaimed (and in our queue) + return NULL; + } + // a fresh page was found, initialize it + mi_assert_internal(pq==NULL || _mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_page_init(heap, page, block_size, heap->tld); + _mi_stat_increase(&heap->tld->stats.pages, 1); + if (pq!=NULL) mi_page_queue_push(heap, pq, page); // huge pages use pq==NULL + mi_assert_expensive(_mi_page_is_valid(page)); + return page; +} + +// Get a fresh page to use +static mi_page_t* mi_page_fresh(mi_heap_t* heap, mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap, pq)); + mi_page_t* page = mi_page_fresh_alloc(heap, pq, pq->block_size); + if (page==NULL) return NULL; + mi_assert_internal(pq->block_size==mi_page_block_size(page)); + mi_assert_internal(pq==mi_page_queue(heap, mi_page_block_size(page))); + return page; +} + +/* ----------------------------------------------------------- + Do any delayed frees + (put there by other threads if they deallocated in a full page) +----------------------------------------------------------- */ +void _mi_heap_delayed_free(mi_heap_t* heap) { + // take over the list (note: no atomic exchange since it is often NULL) + mi_block_t* block = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + while (block != NULL && !mi_atomic_cas_ptr_weak_acq_rel(mi_block_t, &heap->thread_delayed_free, &block, NULL)) { /* nothing */ }; + + // and free them all + while(block != NULL) { + mi_block_t* next = mi_block_nextx(heap,block, heap->keys); + // use internal free instead of regular one to keep stats etc correct + if (!_mi_free_delayed_block(block)) { + // we might already start delayed freeing while another thread has not yet + // reset the delayed_freeing flag; in that case delay it further by reinserting. + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap, block, dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + block = next; + } +} + +/* ----------------------------------------------------------- + Unfull, abandon, free and retire +----------------------------------------------------------- */ + +// Move a page from the full list back to a regular list +void _mi_page_unfull(mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_is_in_full(page)); + if (!mi_page_is_in_full(page)) return; + + mi_heap_t* heap = mi_page_heap(page); + mi_page_queue_t* pqfull = &heap->pages[MI_BIN_FULL]; + mi_page_set_in_full(page, false); // to get the right queue + mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); + mi_page_set_in_full(page, true); + mi_page_queue_enqueue_from(pq, pqfull, page); +} + +static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(!mi_page_immediate_available(page)); + mi_assert_internal(!mi_page_is_in_full(page)); + + if (mi_page_is_in_full(page)) return; + mi_page_queue_enqueue_from(&mi_page_heap(page)->pages[MI_BIN_FULL], pq, page); + _mi_page_free_collect(page,false); // try to collect right away in case another thread freed just before MI_USE_DELAYED_FREE was set +} + + +// Abandon a page with used blocks at the end of a thread. +// Note: only call if it is ensured that no references exist from +// the `page->heap->thread_delayed_free` into this page. +// Currently only called through `mi_heap_collect_ex` which ensures this. +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_heap(page) != NULL); + + mi_heap_t* pheap = mi_page_heap(page); + + // remove from our page list + mi_segments_tld_t* segments_tld = &pheap->tld->segments; + mi_page_queue_remove(pq, page); + + // page is no longer associated with our heap + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_page_set_heap(page, NULL); + +#if MI_DEBUG>1 + // check there are no references left.. + for (mi_block_t* block = (mi_block_t*)pheap->thread_delayed_free; block != NULL; block = mi_block_nextx(pheap, block, pheap->keys)) { + mi_assert_internal(_mi_ptr_page(block) != page); + } +#endif + + // and abandon it + mi_assert_internal(mi_page_heap(page) == NULL); + _mi_segment_page_abandon(page,segments_tld); +} + + +// Free a page with no more free blocks +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_all_free(page)); + mi_assert_internal(mi_page_thread_free_flag(page)!=MI_DELAYED_FREEING); + + // no more aligned blocks in here + mi_page_set_has_aligned(page, false); + + // remove from the page list + // (no need to do _mi_heap_delayed_free first as all blocks are already free) + mi_segments_tld_t* segments_tld = &mi_page_heap(page)->tld->segments; + mi_page_queue_remove(pq, page); + + // and free it + mi_page_set_heap(page,NULL); + _mi_segment_page_free(page, force, segments_tld); +} + +#define MI_MAX_RETIRE_SIZE MI_LARGE_OBJ_SIZE_MAX +#define MI_RETIRE_CYCLES (8) + +// Retire a page with no more used blocks +// Important to not retire too quickly though as new +// allocations might coming. +// Note: called from `mi_free` and benchmarks often +// trigger this due to freeing everything and then +// allocating again so careful when changing this. +void _mi_page_retire(mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_all_free(page)); + + mi_page_set_has_aligned(page, false); + + // don't retire too often.. + // (or we end up retiring and re-allocating most of the time) + // NOTE: refine this more: we should not retire if this + // is the only page left with free blocks. It is not clear + // how to check this efficiently though... + // for now, we don't retire if it is the only page left of this size class. + mi_page_queue_t* pq = mi_page_queue_of(page); + if (mi_likely(page->xblock_size <= MI_MAX_RETIRE_SIZE && !mi_page_is_in_full(page))) { + if (pq->last==page && pq->first==page) { // the only page in the queue? + mi_stat_counter_increase(_mi_stats_main.page_no_retire,1); + page->retire_expire = (page->xblock_size <= MI_SMALL_OBJ_SIZE_MAX ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(pq >= heap->pages); + const size_t index = pq - heap->pages; + mi_assert_internal(index < MI_BIN_FULL && index < MI_BIN_HUGE); + if (index < heap->page_retired_min) heap->page_retired_min = index; + if (index > heap->page_retired_max) heap->page_retired_max = index; + mi_assert_internal(mi_page_all_free(page)); + return; // dont't free after all + } + } + + _mi_page_free(page, pq, false); +} + +// free retired pages: we don't need to look at the entire queues +// since we only retire pages that are at the head position in a queue. +void _mi_heap_collect_retired(mi_heap_t* heap, bool force) { + size_t min = MI_BIN_FULL; + size_t max = 0; + for(size_t bin = heap->page_retired_min; bin <= heap->page_retired_max; bin++) { + mi_page_queue_t* pq = &heap->pages[bin]; + mi_page_t* page = pq->first; + if (page != NULL && page->retire_expire != 0) { + if (mi_page_all_free(page)) { + page->retire_expire--; + if (force || page->retire_expire == 0) { + _mi_page_free(pq->first, pq, force); + } + else { + // keep retired, update min/max + if (bin < min) min = bin; + if (bin > max) max = bin; + } + } + else { + page->retire_expire = 0; + } + } + } + heap->page_retired_min = min; + heap->page_retired_max = max; +} + + +/* ----------------------------------------------------------- + Initialize the initial free list in a page. + In secure mode we initialize a randomized list by + alternating between slices. +----------------------------------------------------------- */ + +#define MI_MAX_SLICE_SHIFT (6) // at most 64 slices +#define MI_MAX_SLICES (1UL << MI_MAX_SLICE_SHIFT) +#define MI_MIN_SLICES (2) + +static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) { + UNUSED(stats); + #if (MI_SECURE<=2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL); + + // initialize a randomized free list + // set up `slice_count` slices to alternate between + size_t shift = MI_MAX_SLICE_SHIFT; + while ((extend >> shift) == 0) { + shift--; + } + const size_t slice_count = (size_t)1U << shift; + const size_t slice_extend = extend / slice_count; + mi_assert_internal(slice_extend >= 1); + mi_block_t* blocks[MI_MAX_SLICES]; // current start of the slice + size_t counts[MI_MAX_SLICES]; // available objects in the slice + for (size_t i = 0; i < slice_count; i++) { + blocks[i] = mi_page_block_at(page, page_area, bsize, page->capacity + i*slice_extend); + counts[i] = slice_extend; + } + counts[slice_count-1] += (extend % slice_count); // final slice holds the modulus too (todo: distribute evenly?) + + // and initialize the free list by randomly threading through them + // set up first element + const uintptr_t r = _mi_heap_random_next(heap); + size_t current = r % slice_count; + counts[current]--; + mi_block_t* const free_start = blocks[current]; + // and iterate through the rest; use `random_shuffle` for performance + uintptr_t rnd = _mi_random_shuffle(r|1); // ensure not 0 + for (size_t i = 1; i < extend; i++) { + // call random_shuffle only every INTPTR_SIZE rounds + const size_t round = i%MI_INTPTR_SIZE; + if (round == 0) rnd = _mi_random_shuffle(rnd); + // select a random next slice index + size_t next = ((rnd >> 8*round) & (slice_count-1)); + while (counts[next]==0) { // ensure it still has space + next++; + if (next==slice_count) next = 0; + } + // and link the current block to it + counts[next]--; + mi_block_t* const block = blocks[current]; + blocks[current] = (mi_block_t*)((uint8_t*)block + bsize); // bump to the following block + mi_block_set_next(page, block, blocks[next]); // and set next; note: we may have `current == next` + current = next; + } + // prepend to the free list (usually NULL) + mi_block_set_next(page, blocks[current], page->free); // end of the list + page->free = free_start; +} + +static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) +{ + UNUSED(stats); + #if (MI_SECURE <= 2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL ); + + mi_block_t* const start = mi_page_block_at(page, page_area, bsize, page->capacity); + + // initialize a sequential free list + mi_block_t* const last = mi_page_block_at(page, page_area, bsize, page->capacity + extend - 1); + mi_block_t* block = start; + while(block <= last) { + mi_block_t* next = (mi_block_t*)((uint8_t*)block + bsize); + mi_block_set_next(page,block,next); + block = next; + } + // prepend to free list (usually `NULL`) + mi_block_set_next(page, last, page->free); + page->free = start; +} + +/* ----------------------------------------------------------- + Page initialize and extend the capacity +----------------------------------------------------------- */ + +#define MI_MAX_EXTEND_SIZE (4*1024) // heuristic, one OS page seems to work well. +#if (MI_SECURE>0) +#define MI_MIN_EXTEND (8*MI_SECURE) // extend at least by this many +#else +#define MI_MIN_EXTEND (1) +#endif + +// Extend the capacity (up to reserved) by initializing a free list +// We do at most `MI_MAX_EXTEND` to avoid touching too much memory +// Note: we also experimented with "bump" allocation on the first +// allocations but this did not speed up any benchmark (due to an +// extra test in malloc? or cache effects?) +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) { + mi_assert_expensive(mi_page_is_valid_init(page)); + #if (MI_SECURE<=2) + mi_assert(page->free == NULL); + mi_assert(page->local_free == NULL); + if (page->free != NULL) return; + #endif + if (page->capacity >= page->reserved) return; + + size_t page_size; + //uint8_t* page_start = + _mi_page_start(_mi_page_segment(page), page, &page_size); + mi_stat_counter_increase(tld->stats.pages_extended, 1); + + // calculate the extend count + const size_t bsize = (page->xblock_size < MI_HUGE_BLOCK_SIZE ? page->xblock_size : page_size); + size_t extend = page->reserved - page->capacity; + size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize); + if (max_extend < MI_MIN_EXTEND) max_extend = MI_MIN_EXTEND; + + if (extend > max_extend) { + // ensure we don't touch memory beyond the page to reduce page commit. + // the `lean` benchmark tests this. Going from 1 to 8 increases rss by 50%. + extend = (max_extend==0 ? 1 : max_extend); + } + + mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved); + mi_assert_internal(extend < (1UL<<16)); + + // and append the extend the free list + if (extend < MI_MIN_SLICES || MI_SECURE==0) { //!mi_option_is_enabled(mi_option_secure)) { + mi_page_free_list_extend(page, bsize, extend, &tld->stats ); + } + else { + mi_page_free_list_extend_secure(heap, page, bsize, extend, &tld->stats); + } + // enable the new free list + page->capacity += (uint16_t)extend; + mi_stat_increase(tld->stats.page_committed, extend * bsize); + + // extension into zero initialized memory preserves the zero'd free list + if (!page->is_zero_init) { + page->is_zero = false; + } + mi_assert_expensive(mi_page_is_valid_init(page)); +} + +// Initialize a fresh page +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi_tld_t* tld) { + mi_assert(page != NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert(segment != NULL); + mi_assert_internal(block_size > 0); + // set fields + mi_page_set_heap(page, heap); + size_t page_size; + _mi_segment_page_start(segment, page, block_size, &page_size, NULL); + page->xblock_size = (block_size < MI_HUGE_BLOCK_SIZE ? (uint32_t)block_size : MI_HUGE_BLOCK_SIZE); + mi_assert_internal(page_size / block_size < (1L<<16)); + page->reserved = (uint16_t)(page_size / block_size); + #ifdef MI_ENCODE_FREELIST + page->keys[0] = _mi_heap_random_next(heap); + page->keys[1] = _mi_heap_random_next(heap); + #endif + page->is_zero = page->is_zero_init; + + mi_assert_internal(page->capacity == 0); + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->used == 0); + mi_assert_internal(page->xthread_free == 0); + mi_assert_internal(page->next == NULL); + mi_assert_internal(page->prev == NULL); + mi_assert_internal(page->retire_expire == 0); + mi_assert_internal(!mi_page_has_aligned(page)); + #if (MI_ENCODE_FREELIST) + mi_assert_internal(page->keys[0] != 0); + mi_assert_internal(page->keys[1] != 0); + #endif + mi_assert_expensive(mi_page_is_valid_init(page)); + + // initialize an initial free list + mi_page_extend_free(heap,page,tld); + mi_assert(mi_page_immediate_available(page)); +} + + +/* ----------------------------------------------------------- + Find pages with free blocks +-------------------------------------------------------------*/ + +// Find a page with free blocks of `page->block_size`. +static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* pq, bool first_try) +{ + // search through the pages in "next fit" order + size_t count = 0; + mi_page_t* page = pq->first; + while (page != NULL) + { + mi_page_t* next = page->next; // remember next + count++; + + // 0. collect freed blocks by us and other threads + _mi_page_free_collect(page, false); + + // 1. if the page contains free blocks, we are done + if (mi_page_immediate_available(page)) { + break; // pick this one + } + + // 2. Try to extend + if (page->capacity < page->reserved) { + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + break; + } + + // 3. If the page is completely full, move it to the `mi_pages_full` + // queue so we don't visit long-lived pages too often. + mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); + mi_page_to_full(page, pq); + + page = next; + } // for each page + + mi_stat_counter_increase(heap->tld->stats.searches, count); + + if (page == NULL) { + _mi_heap_collect_retired(heap, false); // perhaps make a page available + page = mi_page_fresh(heap, pq); + if (page == NULL && first_try) { + // out-of-memory _or_ an abandoned page with free blocks was reclaimed, try once again + page = mi_page_queue_find_free_ex(heap, pq, false); + } + } + else { + mi_assert(pq->first == page); + page->retire_expire = 0; + } + mi_assert_internal(page == NULL || mi_page_immediate_available(page)); + return page; +} + + + +// Find a page with free blocks of `size`. +static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { + mi_page_queue_t* pq = mi_page_queue(heap,size); + mi_page_t* page = pq->first; + if (page != NULL) { + if ((MI_SECURE >= 3) && page->capacity < page->reserved && ((_mi_heap_random_next(heap) & 1) == 1)) { + // in secure mode, we extend half the time to increase randomness + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + } + else { + _mi_page_free_collect(page,false); + } + if (mi_page_immediate_available(page)) { + page->retire_expire = 0; + return page; // fast path + } + } + return mi_page_queue_find_free_ex(heap, pq, true); +} + + +/* ----------------------------------------------------------- + Users can register a deferred free function called + when the `free` list is empty. Since the `local_free` + is separate this is deterministically called after + a certain number of allocations. +----------------------------------------------------------- */ + +static mi_deferred_free_fun* volatile deferred_free = NULL; +static _Atomic(void*) deferred_arg; // = NULL + +void _mi_deferred_free(mi_heap_t* heap, bool force) { + heap->tld->heartbeat++; + if (deferred_free != NULL && !heap->tld->recurse) { + heap->tld->recurse = true; + deferred_free(force, heap->tld->heartbeat, mi_atomic_load_ptr_relaxed(void,&deferred_arg)); + heap->tld->recurse = false; + } +} + +void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noexcept { + deferred_free = fn; + mi_atomic_store_ptr_release(void,&deferred_arg, arg); +} + + +/* ----------------------------------------------------------- + General allocation +----------------------------------------------------------- */ + +// A huge page is allocated directly without being in a queue. +// Because huge pages contain just one block, and the segment contains +// just that page, we always treat them as abandoned and any thread +// that frees the block can free the whole page and segment directly. +static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) { + size_t block_size = _mi_os_good_alloc_size(size); + mi_assert_internal(_mi_bin(block_size) == MI_BIN_HUGE); + mi_page_t* page = mi_page_fresh_alloc(heap,NULL,block_size); + if (page != NULL) { + const size_t bsize = mi_page_block_size(page); // note: not `mi_page_usable_block_size` as `size` includes padding already + mi_assert_internal(bsize >= size); + mi_assert_internal(mi_page_immediate_available(page)); + mi_assert_internal(_mi_page_segment(page)->page_kind==MI_PAGE_HUGE); + mi_assert_internal(_mi_page_segment(page)->used==1); + mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue + mi_page_set_heap(page, NULL); + + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_increase(&heap->tld->stats.giant, bsize); + _mi_stat_counter_increase(&heap->tld->stats.giant_count, 1); + } + else { + _mi_stat_increase(&heap->tld->stats.huge, bsize); + _mi_stat_counter_increase(&heap->tld->stats.huge_count, 1); + } + } + return page; +} + + +// Allocate a page +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +static mi_page_t* mi_find_page(mi_heap_t* heap, size_t size) mi_attr_noexcept { + // huge allocation? + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + if (mi_unlikely(req_size > (MI_LARGE_OBJ_SIZE_MAX - MI_PADDING_SIZE) )) { + if (mi_unlikely(req_size > PTRDIFF_MAX)) { // we don't allocate more than PTRDIFF_MAX (see ) + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size); + return NULL; + } + else { + return mi_huge_page_alloc(heap,size); + } + } + else { + // otherwise find a page with free blocks in our size segregated queues + mi_assert_internal(size >= MI_PADDING_SIZE); + return mi_find_free_page(heap, size); + } +} + +// Generic allocation routine if the fast path (`alloc.c:mi_page_malloc`) does not succeed. +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept +{ + mi_assert_internal(heap != NULL); + + // initialize if necessary + if (mi_unlikely(!mi_heap_is_initialized(heap))) { + mi_thread_init(); // calls `_mi_heap_init` in turn + heap = mi_get_default_heap(); + if (mi_unlikely(!mi_heap_is_initialized(heap))) { return NULL; } + } + mi_assert_internal(mi_heap_is_initialized(heap)); + + // call potential deferred free routines + _mi_deferred_free(heap, false); + + // free delayed frees from other threads + _mi_heap_delayed_free(heap); + + // find (or allocate) a page of the right size + mi_page_t* page = mi_find_page(heap, size); + if (mi_unlikely(page == NULL)) { // first time out of memory, try to collect and retry the allocation once more + mi_heap_collect(heap, true /* force */); + page = mi_find_page(heap, size); + } + + if (mi_unlikely(page == NULL)) { // out of memory + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + _mi_error_message(ENOMEM, "unable to allocate memory (%zu bytes)\n", req_size); + return NULL; + } + + mi_assert_internal(mi_page_immediate_available(page)); + mi_assert_internal(mi_page_block_size(page) >= size); + + // and try again, this time succeeding! (i.e. this should never recurse) + return _mi_page_malloc(heap, page, size); +} diff --git a/deps/mimalloc/src/random.c b/deps/mimalloc/src/random.c new file mode 100644 index 000000000..b9485ea09 --- /dev/null +++ b/deps/mimalloc/src/random.c @@ -0,0 +1,339 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memset + +/* ---------------------------------------------------------------------------- +We use our own PRNG to keep predictable performance of random number generation +and to avoid implementations that use a lock. We only use the OS provided +random source to initialize the initial seeds. Since we do not need ultimate +performance but we do rely on the security (for secret cookies in secure mode) +we use a cryptographically secure generator (chacha20). +-----------------------------------------------------------------------------*/ + +#define MI_CHACHA_ROUNDS (20) // perhaps use 12 for better performance? + + +/* ---------------------------------------------------------------------------- +Chacha20 implementation as the original algorithm with a 64-bit nonce +and counter: https://en.wikipedia.org/wiki/Salsa20 +The input matrix has sixteen 32-bit values: +Position 0 to 3: constant key +Position 4 to 11: the key +Position 12 to 13: the counter. +Position 14 to 15: the nonce. + +The implementation uses regular C code which compiles very well on modern compilers. +(gcc x64 has no register spills, and clang 6+ uses SSE instructions) +-----------------------------------------------------------------------------*/ + +static inline uint32_t rotl(uint32_t x, uint32_t shift) { + return (x << shift) | (x >> (32 - shift)); +} + +static inline void qround(uint32_t x[16], size_t a, size_t b, size_t c, size_t d) { + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 7); +} + +static void chacha_block(mi_random_ctx_t* ctx) +{ + // scramble into `x` + uint32_t x[16]; + for (size_t i = 0; i < 16; i++) { + x[i] = ctx->input[i]; + } + for (size_t i = 0; i < MI_CHACHA_ROUNDS; i += 2) { + qround(x, 0, 4, 8, 12); + qround(x, 1, 5, 9, 13); + qround(x, 2, 6, 10, 14); + qround(x, 3, 7, 11, 15); + qround(x, 0, 5, 10, 15); + qround(x, 1, 6, 11, 12); + qround(x, 2, 7, 8, 13); + qround(x, 3, 4, 9, 14); + } + + // add scrambled data to the initial state + for (size_t i = 0; i < 16; i++) { + ctx->output[i] = x[i] + ctx->input[i]; + } + ctx->output_available = 16; + + // increment the counter for the next round + ctx->input[12] += 1; + if (ctx->input[12] == 0) { + ctx->input[13] += 1; + if (ctx->input[13] == 0) { // and keep increasing into the nonce + ctx->input[14] += 1; + } + } +} + +static uint32_t chacha_next32(mi_random_ctx_t* ctx) { + if (ctx->output_available <= 0) { + chacha_block(ctx); + ctx->output_available = 16; // (assign again to suppress static analysis warning) + } + const uint32_t x = ctx->output[16 - ctx->output_available]; + ctx->output[16 - ctx->output_available] = 0; // reset once the data is handed out + ctx->output_available--; + return x; +} + +static inline uint32_t read32(const uint8_t* p, size_t idx32) { + const size_t i = 4*idx32; + return ((uint32_t)p[i+0] | (uint32_t)p[i+1] << 8 | (uint32_t)p[i+2] << 16 | (uint32_t)p[i+3] << 24); +} + +static void chacha_init(mi_random_ctx_t* ctx, const uint8_t key[32], uint64_t nonce) +{ + // since we only use chacha for randomness (and not encryption) we + // do not _need_ to read 32-bit values as little endian but we do anyways + // just for being compatible :-) + memset(ctx, 0, sizeof(*ctx)); + for (size_t i = 0; i < 4; i++) { + const uint8_t* sigma = (uint8_t*)"expand 32-byte k"; + ctx->input[i] = read32(sigma,i); + } + for (size_t i = 0; i < 8; i++) { + ctx->input[i + 4] = read32(key,i); + } + ctx->input[12] = 0; + ctx->input[13] = 0; + ctx->input[14] = (uint32_t)nonce; + ctx->input[15] = (uint32_t)(nonce >> 32); +} + +static void chacha_split(mi_random_ctx_t* ctx, uint64_t nonce, mi_random_ctx_t* ctx_new) { + memset(ctx_new, 0, sizeof(*ctx_new)); + memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input)); + ctx_new->input[12] = 0; + ctx_new->input[13] = 0; + ctx_new->input[14] = (uint32_t)nonce; + ctx_new->input[15] = (uint32_t)(nonce >> 32); + mi_assert_internal(ctx->input[14] != ctx_new->input[14] || ctx->input[15] != ctx_new->input[15]); // do not reuse nonces! + chacha_block(ctx_new); +} + + +/* ---------------------------------------------------------------------------- +Random interface +-----------------------------------------------------------------------------*/ + +#if MI_DEBUG>1 +static bool mi_random_is_initialized(mi_random_ctx_t* ctx) { + return (ctx != NULL && ctx->input[0] != 0); +} +#endif + +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* ctx_new) { + mi_assert_internal(mi_random_is_initialized(ctx)); + mi_assert_internal(ctx != ctx_new); + chacha_split(ctx, (uintptr_t)ctx_new /*nonce*/, ctx_new); +} + +uintptr_t _mi_random_next(mi_random_ctx_t* ctx) { + mi_assert_internal(mi_random_is_initialized(ctx)); + #if MI_INTPTR_SIZE <= 4 + return chacha_next32(ctx); + #elif MI_INTPTR_SIZE == 8 + return (((uintptr_t)chacha_next32(ctx) << 32) | chacha_next32(ctx)); + #else + # error "define mi_random_next for this platform" + #endif +} + + +/* ---------------------------------------------------------------------------- +To initialize a fresh random context we rely on the OS: +- Windows : BCryptGenRandom (or RtlGenRandom) +- osX,bsd,wasi: arc4random_buf +- Linux : getrandom,/dev/urandom +If we cannot get good randomness, we fall back to weak randomness based on a timer and ASLR. +-----------------------------------------------------------------------------*/ + +#if defined(_WIN32) + +#if !defined(MI_USE_RTLGENRANDOM) +// We prefer BCryptGenRandom over RtlGenRandom +#pragma comment (lib,"bcrypt.lib") +#include +static bool os_random_buf(void* buf, size_t buf_len) { + return (BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0); +} +#else +// Use (unofficial) RtlGenRandom +#pragma comment (lib,"advapi32.lib") +#define RtlGenRandom SystemFunction036 +#ifdef __cplusplus +extern "C" { +#endif +BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); +#ifdef __cplusplus +} +#endif +static bool os_random_buf(void* buf, size_t buf_len) { + return (RtlGenRandom(buf, (ULONG)buf_len) != 0); +} +#endif + +#elif defined(ANDROID) || defined(XP_DARWIN) || defined(__APPLE__) || defined(__DragonFly__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__sun) || defined(__wasi__) +#include +static bool os_random_buf(void* buf, size_t buf_len) { + arc4random_buf(buf, buf_len); + return true; +} +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +static bool os_random_buf(void* buf, size_t buf_len) { + // Modern Linux provides `getrandom` but different distributions either use `sys/random.h` or `linux/random.h` + // and for the latter the actual `getrandom` call is not always defined. + // (see ) + // We therefore use a syscall directly and fall back dynamically to /dev/urandom when needed. +#ifdef SYS_getrandom + #ifndef GRND_NONBLOCK + #define GRND_NONBLOCK (1) + #endif + static _Atomic(uintptr_t) no_getrandom; // = 0 + if (mi_atomic_load_acquire(&no_getrandom)==0) { + ssize_t ret = syscall(SYS_getrandom, buf, buf_len, GRND_NONBLOCK); + if (ret >= 0) return (buf_len == (size_t)ret); + if (ret != ENOSYS) return false; + mi_atomic_store_release(&no_getrandom, 1UL); // don't call again, and fall back to /dev/urandom + } +#endif + int flags = O_RDONLY; + #if defined(O_CLOEXEC) + flags |= O_CLOEXEC; + #endif + int fd = open("/dev/urandom", flags, 0); + if (fd < 0) return false; + size_t count = 0; + while(count < buf_len) { + ssize_t ret = read(fd, (char*)buf + count, buf_len - count); + if (ret<=0) { + if (errno!=EAGAIN && errno!=EINTR) break; + } + else { + count += ret; + } + } + close(fd); + return (count==buf_len); +} +#else +static bool os_random_buf(void* buf, size_t buf_len) { + return false; +} +#endif + +#if defined(_WIN32) +#include +#elif defined(__APPLE__) +#include +#else +#include +#endif + +uintptr_t _os_random_weak(uintptr_t extra_seed) { + uintptr_t x = (uintptr_t)&_os_random_weak ^ extra_seed; // ASLR makes the address random + + #if defined(_WIN32) + LARGE_INTEGER pcount; + QueryPerformanceCounter(&pcount); + x ^= (uintptr_t)(pcount.QuadPart); + #elif defined(__APPLE__) + x ^= (uintptr_t)mach_absolute_time(); + #else + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + x ^= (uintptr_t)time.tv_sec; + x ^= (uintptr_t)time.tv_nsec; + #endif + // and do a few randomization steps + uintptr_t max = ((x ^ (x >> 17)) & 0x0F) + 1; + for (uintptr_t i = 0; i < max; i++) { + x = _mi_random_shuffle(x); + } + mi_assert_internal(x != 0); + return x; +} + +void _mi_random_init(mi_random_ctx_t* ctx) { + uint8_t key[32]; + if (!os_random_buf(key, sizeof(key))) { + // if we fail to get random data from the OS, we fall back to a + // weak random source based on the current time + _mi_warning_message("unable to use secure randomness\n"); + uintptr_t x = _os_random_weak(0); + for (size_t i = 0; i < 8; i++) { // key is eight 32-bit words. + x = _mi_random_shuffle(x); + ((uint32_t*)key)[i] = (uint32_t)x; + } + } + chacha_init(ctx, key, (uintptr_t)ctx /*nonce*/ ); +} + +/* -------------------------------------------------------- +test vectors from +----------------------------------------------------------- */ +/* +static bool array_equals(uint32_t* x, uint32_t* y, size_t n) { + for (size_t i = 0; i < n; i++) { + if (x[i] != y[i]) return false; + } + return true; +} +static void chacha_test(void) +{ + uint32_t x[4] = { 0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567 }; + uint32_t x_out[4] = { 0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb }; + qround(x, 0, 1, 2, 3); + mi_assert_internal(array_equals(x, x_out, 4)); + + uint32_t y[16] = { + 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c, + 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320 }; + uint32_t y_out[16] = { + 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2, + 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320 }; + qround(y, 2, 7, 8, 13); + mi_assert_internal(array_equals(y, y_out, 16)); + + mi_random_ctx_t r = { + { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x00000001, 0x09000000, 0x4a000000, 0x00000000 }, + {0}, + 0 + }; + uint32_t r_out[16] = { + 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, + 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, + 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, + 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 }; + chacha_block(&r); + mi_assert_internal(array_equals(r.output, r_out, 16)); +} +*/ diff --git a/deps/mimalloc/src/region.c b/deps/mimalloc/src/region.c new file mode 100644 index 000000000..b6d0da315 --- /dev/null +++ b/deps/mimalloc/src/region.c @@ -0,0 +1,500 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +This implements a layer between the raw OS memory (VirtualAlloc/mmap/sbrk/..) +and the segment and huge object allocation by mimalloc. There may be multiple +implementations of this (one could be the identity going directly to the OS, +another could be a simple cache etc), but the current one uses large "regions". +In contrast to the rest of mimalloc, the "regions" are shared between threads and +need to be accessed using atomic operations. +We need this memory layer between the raw OS calls because of: +1. on `sbrk` like systems (like WebAssembly) we need our own memory maps in order + to reuse memory effectively. +2. It turns out that for large objects, between 1MiB and 32MiB (?), the cost of + an OS allocation/free is still (much) too expensive relative to the accesses + in that object :-( (`malloc-large` tests this). This means we need a cheaper + way to reuse memory. +3. This layer allows for NUMA aware allocation. + +Possible issues: +- (2) can potentially be addressed too with a small cache per thread which is much + simpler. Generally though that requires shrinking of huge pages, and may overuse + memory per thread. (and is not compatible with `sbrk`). +- Since the current regions are per-process, we need atomic operations to + claim blocks which may be contended +- In the worst case, we need to search the whole region map (16KiB for 256GiB) + linearly. At what point will direct OS calls be faster? Is there a way to + do this better without adding too much complexity? +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset + +#include "bitmap.inc.c" + +// Internal raw OS interface +size_t _mi_os_large_page_size(); +bool _mi_os_protect(void* addr, size_t size); +bool _mi_os_unprotect(void* addr, size_t size); +bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); +bool _mi_os_decommit(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_reset(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats); + +// arena.c +void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats); +void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); + + + +// Constants +#if (MI_INTPTR_SIZE==8) +#define MI_HEAP_REGION_MAX_SIZE (256 * GiB) // 64KiB for the region map +#elif (MI_INTPTR_SIZE==4) +#define MI_HEAP_REGION_MAX_SIZE (3 * GiB) // ~ KiB for the region map +#else +#error "define the maximum heap space allowed for regions on this platform" +#endif + +#define MI_SEGMENT_ALIGN MI_SEGMENT_SIZE + +#define MI_REGION_MAX_BLOCKS MI_BITMAP_FIELD_BITS +#define MI_REGION_SIZE (MI_SEGMENT_SIZE * MI_BITMAP_FIELD_BITS) // 256MiB (64MiB on 32 bits) +#define MI_REGION_MAX (MI_HEAP_REGION_MAX_SIZE / MI_REGION_SIZE) // 1024 (48 on 32 bits) +#define MI_REGION_MAX_OBJ_BLOCKS (MI_REGION_MAX_BLOCKS/4) // 64MiB +#define MI_REGION_MAX_OBJ_SIZE (MI_REGION_MAX_OBJ_BLOCKS*MI_SEGMENT_SIZE) + +// Region info +typedef union mi_region_info_u { + uintptr_t value; + struct { + bool valid; // initialized? + bool is_large; // allocated in fixed large/huge OS pages + short numa_node; // the associated NUMA node (where -1 means no associated node) + } x; +} mi_region_info_t; + + +// A region owns a chunk of REGION_SIZE (256MiB) (virtual) memory with +// a bit map with one bit per MI_SEGMENT_SIZE (4MiB) block. +typedef struct mem_region_s { + _Atomic(uintptr_t) info; // mi_region_info_t.value + _Atomic(void*) start; // start of the memory area + mi_bitmap_field_t in_use; // bit per in-use block + mi_bitmap_field_t dirty; // track if non-zero per block + mi_bitmap_field_t commit; // track if committed per block + mi_bitmap_field_t reset; // track if reset per block + _Atomic(uintptr_t) arena_memid; // if allocated from a (huge page) arena + uintptr_t padding; // round to 8 fields +} mem_region_t; + +// The region map +static mem_region_t regions[MI_REGION_MAX]; + +// Allocated regions +static _Atomic(uintptr_t) regions_count; // = 0; + + +/* ---------------------------------------------------------------------------- +Utility functions +-----------------------------------------------------------------------------*/ + +// Blocks (of 4MiB) needed for the given size. +static size_t mi_region_block_count(size_t size) { + return _mi_divide_up(size, MI_SEGMENT_SIZE); +} + +/* +// Return a rounded commit/reset size such that we don't fragment large OS pages into small ones. +static size_t mi_good_commit_size(size_t size) { + if (size > (SIZE_MAX - _mi_os_large_page_size())) return size; + return _mi_align_up(size, _mi_os_large_page_size()); +} +*/ + +// Return if a pointer points into a region reserved by us. +bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { + if (p==NULL) return false; + size_t count = mi_atomic_load_relaxed(®ions_count); + for (size_t i = 0; i < count; i++) { + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_relaxed(uint8_t, ®ions[i].start); + if (start != NULL && (uint8_t*)p >= start && (uint8_t*)p < start + MI_REGION_SIZE) return true; + } + return false; +} + + +static void* mi_region_blocks_start(const mem_region_t* region, mi_bitmap_index_t bit_idx) { + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t, &((mem_region_t*)region)->start); + mi_assert_internal(start != NULL); + return (start + (bit_idx * MI_SEGMENT_SIZE)); +} + +static size_t mi_memid_create(mem_region_t* region, mi_bitmap_index_t bit_idx) { + mi_assert_internal(bit_idx < MI_BITMAP_FIELD_BITS); + size_t idx = region - regions; + mi_assert_internal(®ions[idx] == region); + return (idx*MI_BITMAP_FIELD_BITS + bit_idx)<<1; +} + +static size_t mi_memid_create_from_arena(size_t arena_memid) { + return (arena_memid << 1) | 1; +} + + +static bool mi_memid_is_arena(size_t id, mem_region_t** region, mi_bitmap_index_t* bit_idx, size_t* arena_memid) { + if ((id&1)==1) { + if (arena_memid != NULL) *arena_memid = (id>>1); + return true; + } + else { + size_t idx = (id >> 1) / MI_BITMAP_FIELD_BITS; + *bit_idx = (mi_bitmap_index_t)(id>>1) % MI_BITMAP_FIELD_BITS; + *region = ®ions[idx]; + return false; + } +} + + +/* ---------------------------------------------------------------------------- + Allocate a region is allocated from the OS (or an arena) +-----------------------------------------------------------------------------*/ + +static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld) +{ + // not out of regions yet? + if (mi_atomic_load_relaxed(®ions_count) >= MI_REGION_MAX - 1) return false; + + // try to allocate a fresh region from the OS + bool region_commit = (commit && mi_option_is_enabled(mi_option_eager_region_commit)); + bool region_large = (commit && allow_large); + bool is_zero = false; + size_t arena_memid = 0; + void* const start = _mi_arena_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, ®ion_commit, ®ion_large, &is_zero, &arena_memid, tld); + if (start == NULL) return false; + mi_assert_internal(!(region_large && !allow_large)); + mi_assert_internal(!region_large || region_commit); + + // claim a fresh slot + const uintptr_t idx = mi_atomic_increment_acq_rel(®ions_count); + if (idx >= MI_REGION_MAX) { + mi_atomic_decrement_acq_rel(®ions_count); + _mi_arena_free(start, MI_REGION_SIZE, arena_memid, region_commit, tld->stats); + _mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, GiB)); + return false; + } + + // allocated, initialize and claim the initial blocks + mem_region_t* r = ®ions[idx]; + r->arena_memid = arena_memid; + mi_atomic_store_release(&r->in_use, (uintptr_t)0); + mi_atomic_store_release(&r->dirty, (is_zero ? 0 : MI_BITMAP_FIELD_FULL)); + mi_atomic_store_release(&r->commit, (region_commit ? MI_BITMAP_FIELD_FULL : 0)); + mi_atomic_store_release(&r->reset, (uintptr_t)0); + *bit_idx = 0; + mi_bitmap_claim(&r->in_use, 1, blocks, *bit_idx, NULL); + mi_atomic_store_ptr_release(void,&r->start, start); + + // and share it + mi_region_info_t info; + info.value = 0; // initialize the full union to zero + info.x.valid = true; + info.x.is_large = region_large; + info.x.numa_node = (short)_mi_os_numa_node(tld); + mi_atomic_store_release(&r->info, info.value); // now make it available to others + *region = r; + return true; +} + +/* ---------------------------------------------------------------------------- + Try to claim blocks in suitable regions +-----------------------------------------------------------------------------*/ + +static bool mi_region_is_suitable(const mem_region_t* region, int numa_node, bool allow_large ) { + // initialized at all? + mi_region_info_t info; + info.value = mi_atomic_load_relaxed(&((mem_region_t*)region)->info); + if (info.value==0) return false; + + // numa correct + if (numa_node >= 0) { // use negative numa node to always succeed + int rnode = info.x.numa_node; + if (rnode >= 0 && rnode != numa_node) return false; + } + + // check allow-large + if (!allow_large && info.x.is_large) return false; + + return true; +} + + +static bool mi_region_try_claim(int numa_node, size_t blocks, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld) +{ + // try all regions for a free slot + const size_t count = mi_atomic_load_relaxed(®ions_count); // monotonic, so ok to be relaxed + size_t idx = tld->region_idx; // Or start at 0 to reuse low addresses? Starting at 0 seems to increase latency though + for (size_t visited = 0; visited < count; visited++, idx++) { + if (idx >= count) idx = 0; // wrap around + mem_region_t* r = ®ions[idx]; + // if this region suits our demand (numa node matches, large OS page matches) + if (mi_region_is_suitable(r, numa_node, allow_large)) { + // then try to atomically claim a segment(s) in this region + if (mi_bitmap_try_find_claim_field(&r->in_use, 0, blocks, bit_idx)) { + tld->region_idx = idx; // remember the last found position + *region = r; + return true; + } + } + } + return false; +} + + +static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(blocks <= MI_BITMAP_FIELD_BITS); + mem_region_t* region; + mi_bitmap_index_t bit_idx; + const int numa_node = (_mi_os_numa_node_count() <= 1 ? -1 : _mi_os_numa_node(tld)); + // try to claim in existing regions + if (!mi_region_try_claim(numa_node, blocks, *is_large, ®ion, &bit_idx, tld)) { + // otherwise try to allocate a fresh region and claim in there + if (!mi_region_try_alloc_os(blocks, *commit, *is_large, ®ion, &bit_idx, tld)) { + // out of regions or memory + return NULL; + } + } + + // ------------------------------------------------ + // found a region and claimed `blocks` at `bit_idx`, initialize them now + mi_assert_internal(region != NULL); + mi_assert_internal(mi_bitmap_is_claimed(®ion->in_use, 1, blocks, bit_idx)); + + mi_region_info_t info; + info.value = mi_atomic_load_acquire(®ion->info); + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,®ion->start); + mi_assert_internal(!(info.x.is_large && !*is_large)); + mi_assert_internal(start != NULL); + + *is_zero = mi_bitmap_claim(®ion->dirty, 1, blocks, bit_idx, NULL); + *is_large = info.x.is_large; + *memid = mi_memid_create(region, bit_idx); + void* p = start + (mi_bitmap_index_bit_in_field(bit_idx) * MI_SEGMENT_SIZE); + + // commit + if (*commit) { + // ensure commit + bool any_uncommitted; + mi_bitmap_claim(®ion->commit, 1, blocks, bit_idx, &any_uncommitted); + if (any_uncommitted) { + mi_assert_internal(!info.x.is_large); + bool commit_zero = false; + if (!_mi_mem_commit(p, blocks * MI_SEGMENT_SIZE, &commit_zero, tld)) { + // failed to commit! unclaim and return + mi_bitmap_unclaim(®ion->in_use, 1, blocks, bit_idx); + return NULL; + } + if (commit_zero) *is_zero = true; + } + } + else { + // no need to commit, but check if already fully committed + *commit = mi_bitmap_is_claimed(®ion->commit, 1, blocks, bit_idx); + } + mi_assert_internal(!*commit || mi_bitmap_is_claimed(®ion->commit, 1, blocks, bit_idx)); + + // unreset reset blocks + if (mi_bitmap_is_any_claimed(®ion->reset, 1, blocks, bit_idx)) { + // some blocks are still reset + mi_assert_internal(!info.x.is_large); + mi_assert_internal(!mi_option_is_enabled(mi_option_eager_commit) || *commit || mi_option_get(mi_option_eager_commit_delay) > 0); + mi_bitmap_unclaim(®ion->reset, 1, blocks, bit_idx); + if (*commit || !mi_option_is_enabled(mi_option_reset_decommits)) { // only if needed + bool reset_zero = false; + _mi_mem_unreset(p, blocks * MI_SEGMENT_SIZE, &reset_zero, tld); + if (reset_zero) *is_zero = true; + } + } + mi_assert_internal(!mi_bitmap_is_any_claimed(®ion->reset, 1, blocks, bit_idx)); + + #if (MI_DEBUG>=2) + if (*commit) { ((uint8_t*)p)[0] = 0; } + #endif + + // and return the allocation + mi_assert_internal(p != NULL); + return p; +} + + +/* ---------------------------------------------------------------------------- + Allocation +-----------------------------------------------------------------------------*/ + +// Allocate `size` memory aligned at `alignment`. Return non NULL on success, with a given memory `id`. +// (`id` is abstract, but `id = idx*MI_REGION_MAP_BITS + bitidx`) +void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(memid != NULL && tld != NULL); + mi_assert_internal(size > 0); + *memid = 0; + *is_zero = false; + bool default_large = false; + if (large==NULL) large = &default_large; // ensure `large != NULL` + if (size == 0) return NULL; + size = _mi_align_up(size, _mi_os_page_size()); + + // allocate from regions if possible + void* p = NULL; + size_t arena_memid; + const size_t blocks = mi_region_block_count(size); + if (blocks <= MI_REGION_MAX_OBJ_BLOCKS && alignment <= MI_SEGMENT_ALIGN) { + p = mi_region_try_alloc(blocks, commit, large, is_zero, memid, tld); + if (p == NULL) { + _mi_warning_message("unable to allocate from region: size %zu\n", size); + } + } + if (p == NULL) { + // and otherwise fall back to the OS + p = _mi_arena_alloc_aligned(size, alignment, commit, large, is_zero, &arena_memid, tld); + *memid = mi_memid_create_from_arena(arena_memid); + } + + if (p != NULL) { + mi_assert_internal((uintptr_t)p % alignment == 0); +#if (MI_DEBUG>=2) + if (*commit) { ((uint8_t*)p)[0] = 0; } // ensure the memory is committed +#endif + } + return p; +} + + + +/* ---------------------------------------------------------------------------- +Free +-----------------------------------------------------------------------------*/ + +// Free previously allocated memory with a given id. +void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_reset, mi_os_tld_t* tld) { + mi_assert_internal(size > 0 && tld != NULL); + if (p==NULL) return; + if (size==0) return; + size = _mi_align_up(size, _mi_os_page_size()); + + size_t arena_memid = 0; + mi_bitmap_index_t bit_idx; + mem_region_t* region; + if (mi_memid_is_arena(id,®ion,&bit_idx,&arena_memid)) { + // was a direct arena allocation, pass through + _mi_arena_free(p, size, arena_memid, full_commit, tld->stats); + } + else { + // allocated in a region + mi_assert_internal(size <= MI_REGION_MAX_OBJ_SIZE); if (size > MI_REGION_MAX_OBJ_SIZE) return; + const size_t blocks = mi_region_block_count(size); + mi_assert_internal(blocks + bit_idx <= MI_BITMAP_FIELD_BITS); + mi_region_info_t info; + info.value = mi_atomic_load_acquire(®ion->info); + mi_assert_internal(info.value != 0); + void* blocks_start = mi_region_blocks_start(region, bit_idx); + mi_assert_internal(blocks_start == p); // not a pointer in our area? + mi_assert_internal(bit_idx + blocks <= MI_BITMAP_FIELD_BITS); + if (blocks_start != p || bit_idx + blocks > MI_BITMAP_FIELD_BITS) return; // or `abort`? + + // committed? + if (full_commit && (size % MI_SEGMENT_SIZE) == 0) { + mi_bitmap_claim(®ion->commit, 1, blocks, bit_idx, NULL); + } + + if (any_reset) { + // set the is_reset bits if any pages were reset + mi_bitmap_claim(®ion->reset, 1, blocks, bit_idx, NULL); + } + + // reset the blocks to reduce the working set. + if (!info.x.is_large && mi_option_is_enabled(mi_option_segment_reset) + && (mi_option_is_enabled(mi_option_eager_commit) || + mi_option_is_enabled(mi_option_reset_decommits))) // cannot reset halfway committed segments, use only `option_page_reset` instead + { + bool any_unreset; + mi_bitmap_claim(®ion->reset, 1, blocks, bit_idx, &any_unreset); + if (any_unreset) { + _mi_abandoned_await_readers(); // ensure no more pending write (in case reset = decommit) + _mi_mem_reset(p, blocks * MI_SEGMENT_SIZE, tld); + } + } + + // and unclaim + bool all_unclaimed = mi_bitmap_unclaim(®ion->in_use, 1, blocks, bit_idx); + mi_assert_internal(all_unclaimed); UNUSED(all_unclaimed); + } +} + + +/* ---------------------------------------------------------------------------- + collection +-----------------------------------------------------------------------------*/ +void _mi_mem_collect(mi_os_tld_t* tld) { + // free every region that has no segments in use. + uintptr_t rcount = mi_atomic_load_relaxed(®ions_count); + for (size_t i = 0; i < rcount; i++) { + mem_region_t* region = ®ions[i]; + if (mi_atomic_load_relaxed(®ion->info) != 0) { + // if no segments used, try to claim the whole region + uintptr_t m = mi_atomic_load_relaxed(®ion->in_use); + while (m == 0 && !mi_atomic_cas_weak_release(®ion->in_use, &m, MI_BITMAP_FIELD_FULL)) { /* nothing */ }; + if (m == 0) { + // on success, free the whole region + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,®ions[i].start); + size_t arena_memid = mi_atomic_load_relaxed(®ions[i].arena_memid); + uintptr_t commit = mi_atomic_load_relaxed(®ions[i].commit); + memset(®ions[i], 0, sizeof(mem_region_t)); + // and release the whole region + mi_atomic_store_release(®ion->info, (uintptr_t)0); + if (start != NULL) { // && !_mi_os_is_huge_reserved(start)) { + _mi_abandoned_await_readers(); // ensure no pending reads + _mi_arena_free(start, MI_REGION_SIZE, arena_memid, (~commit == 0), tld->stats); + } + } + } + } +} + + +/* ---------------------------------------------------------------------------- + Other +-----------------------------------------------------------------------------*/ + +bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld) { + return _mi_os_reset(p, size, tld->stats); +} + +bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld) { + return _mi_os_unreset(p, size, is_zero, tld->stats); +} + +bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld) { + return _mi_os_commit(p, size, is_zero, tld->stats); +} + +bool _mi_mem_decommit(void* p, size_t size, mi_os_tld_t* tld) { + return _mi_os_decommit(p, size, tld->stats); +} + +bool _mi_mem_protect(void* p, size_t size) { + return _mi_os_protect(p, size); +} + +bool _mi_mem_unprotect(void* p, size_t size) { + return _mi_os_unprotect(p, size); +} diff --git a/deps/mimalloc/src/segment.c b/deps/mimalloc/src/segment.c new file mode 100644 index 000000000..0daf8ddb4 --- /dev/null +++ b/deps/mimalloc/src/segment.c @@ -0,0 +1,1373 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset +#include + +#define MI_PAGE_HUGE_ALIGN (256*1024) + +static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); + +/* -------------------------------------------------------------------------------- + Segment allocation + We allocate pages inside bigger "segments" (4mb on 64-bit). This is to avoid + splitting VMA's on Linux and reduce fragmentation on other OS's. + Each thread owns its own segments. + + Currently we have: + - small pages (64kb), 64 in one segment + - medium pages (512kb), 8 in one segment + - large pages (4mb), 1 in one segment + - huge blocks > MI_LARGE_OBJ_SIZE_MAX become large segment with 1 page + + In any case the memory for a segment is virtual and usually committed on demand. + (i.e. we are careful to not touch the memory until we actually allocate a block there) + + If a thread ends, it "abandons" pages with used blocks + and there is an abandoned segment list whose segments can + be reclaimed by still running threads, much like work-stealing. +-------------------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------- + Queue of segments containing free pages +----------------------------------------------------------- */ + +#if (MI_DEBUG>=3) +static bool mi_segment_queue_contains(const mi_segment_queue_t* queue, const mi_segment_t* segment) { + mi_assert_internal(segment != NULL); + mi_segment_t* list = queue->first; + while (list != NULL) { + if (list == segment) break; + mi_assert_internal(list->next==NULL || list->next->prev == list); + mi_assert_internal(list->prev==NULL || list->prev->next == list); + list = list->next; + } + return (list == segment); +} +#endif + +static bool mi_segment_queue_is_empty(const mi_segment_queue_t* queue) { + return (queue->first == NULL); +} + +static void mi_segment_queue_remove(mi_segment_queue_t* queue, mi_segment_t* segment) { + mi_assert_expensive(mi_segment_queue_contains(queue, segment)); + if (segment->prev != NULL) segment->prev->next = segment->next; + if (segment->next != NULL) segment->next->prev = segment->prev; + if (segment == queue->first) queue->first = segment->next; + if (segment == queue->last) queue->last = segment->prev; + segment->next = NULL; + segment->prev = NULL; +} + +static void mi_segment_enqueue(mi_segment_queue_t* queue, mi_segment_t* segment) { + mi_assert_expensive(!mi_segment_queue_contains(queue, segment)); + segment->next = NULL; + segment->prev = queue->last; + if (queue->last != NULL) { + mi_assert_internal(queue->last->next == NULL); + queue->last->next = segment; + queue->last = segment; + } + else { + queue->last = queue->first = segment; + } +} + +static mi_segment_queue_t* mi_segment_free_queue_of_kind(mi_page_kind_t kind, mi_segments_tld_t* tld) { + if (kind == MI_PAGE_SMALL) return &tld->small_free; + else if (kind == MI_PAGE_MEDIUM) return &tld->medium_free; + else return NULL; +} + +static mi_segment_queue_t* mi_segment_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) { + return mi_segment_free_queue_of_kind(segment->page_kind, tld); +} + +// remove from free queue if it is in one +static void mi_segment_remove_from_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld); // may be NULL + bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment)); + if (in_queue) { + mi_segment_queue_remove(queue, segment); + } +} + +static void mi_segment_insert_in_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_enqueue(mi_segment_free_queue(segment, tld), segment); +} + + +/* ----------------------------------------------------------- + Invariant checking +----------------------------------------------------------- */ + +#if (MI_DEBUG>=2) +static bool mi_segment_is_in_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld); + bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment)); + if (in_queue) { + mi_assert_expensive(mi_segment_queue_contains(queue, segment)); + } + return in_queue; +} +#endif + +static size_t mi_segment_page_size(const mi_segment_t* segment) { + if (segment->capacity > 1) { + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM); + return ((size_t)1 << segment->page_shift); + } + else { + mi_assert_internal(segment->page_kind >= MI_PAGE_LARGE); + return segment->segment_size; + } +} + + +#if (MI_DEBUG>=2) +static bool mi_pages_reset_contains(const mi_page_t* page, mi_segments_tld_t* tld) { + mi_page_t* p = tld->pages_reset.first; + while (p != NULL) { + if (p == page) return true; + p = p->next; + } + return false; +} +#endif + +#if (MI_DEBUG>=3) +static bool mi_segment_is_valid(const mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment != NULL); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(segment->used <= segment->capacity); + mi_assert_internal(segment->abandoned <= segment->used); + size_t nfree = 0; + for (size_t i = 0; i < segment->capacity; i++) { + const mi_page_t* const page = &segment->pages[i]; + if (!page->segment_in_use) { + nfree++; + } + if (page->segment_in_use || page->is_reset) { + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + } + } + mi_assert_internal(nfree + segment->used == segment->capacity); + // mi_assert_internal(segment->thread_id == _mi_thread_id() || (segment->thread_id==0)); // or 0 + mi_assert_internal(segment->page_kind == MI_PAGE_HUGE || + (mi_segment_page_size(segment) * segment->capacity == segment->segment_size)); + return true; +} +#endif + +static bool mi_page_not_in_queue(const mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(page != NULL); + if (page->next != NULL || page->prev != NULL) { + mi_assert_internal(mi_pages_reset_contains(page, tld)); + return false; + } + else { + // both next and prev are NULL, check for singleton list + return (tld->pages_reset.first != page && tld->pages_reset.last != page); + } +} + + +/* ----------------------------------------------------------- + Guard pages +----------------------------------------------------------- */ + +static void mi_segment_protect_range(void* p, size_t size, bool protect) { + if (protect) { + _mi_mem_protect(p, size); + } + else { + _mi_mem_unprotect(p, size); + } +} + +static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t* tld) { + // add/remove guard pages + if (MI_SECURE != 0) { + // in secure mode, we set up a protected page in between the segment info and the page data + const size_t os_psize = _mi_os_page_size(); + mi_assert_internal((segment->segment_info_size - os_psize) >= (sizeof(mi_segment_t) + ((segment->capacity - 1) * sizeof(mi_page_t)))); + mi_assert_internal(((uintptr_t)segment + segment->segment_info_size) % os_psize == 0); + mi_segment_protect_range((uint8_t*)segment + segment->segment_info_size - os_psize, os_psize, protect); + if (MI_SECURE <= 1 || segment->capacity == 1) { + // and protect the last (or only) page too + mi_assert_internal(MI_SECURE <= 1 || segment->page_kind >= MI_PAGE_LARGE); + uint8_t* start = (uint8_t*)segment + segment->segment_size - os_psize; + if (protect && !segment->mem_is_committed) { + if (protect) { + // ensure secure page is committed + if (_mi_mem_commit(start, os_psize, NULL, tld)) { // if this fails that is ok (as it is an unaccessible page) + mi_segment_protect_range(start, os_psize, protect); + } + } + } + else { + mi_segment_protect_range(start, os_psize, protect); + } + } + else { + // or protect every page + const size_t page_size = mi_segment_page_size(segment); + for (size_t i = 0; i < segment->capacity; i++) { + if (segment->pages[i].is_committed) { + mi_segment_protect_range((uint8_t*)segment + (i+1)*page_size - os_psize, os_psize, protect); + } + } + } + } +} + +/* ----------------------------------------------------------- + Page reset +----------------------------------------------------------- */ + +static void mi_page_reset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) { + mi_assert_internal(page->is_committed); + if (!mi_option_is_enabled(mi_option_page_reset)) return; + if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return; + size_t psize; + void* start = mi_segment_raw_page_start(segment, page, &psize); + page->is_reset = true; + mi_assert_internal(size <= psize); + size_t reset_size = ((size == 0 || size > psize) ? psize : size); + if (reset_size > 0) _mi_mem_reset(start, reset_size, tld->os); +} + +static bool mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) +{ + mi_assert_internal(page->is_reset); + mi_assert_internal(page->is_committed); + mi_assert_internal(!segment->mem_is_fixed); + if (segment->mem_is_fixed || !page->is_committed || !page->is_reset) return true; + page->is_reset = false; + size_t psize; + uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); + size_t unreset_size = (size == 0 || size > psize ? psize : size); + bool is_zero = false; + bool ok = true; + if (unreset_size > 0) { + ok = _mi_mem_unreset(start, unreset_size, &is_zero, tld->os); + } + if (is_zero) page->is_zero_init = true; + return ok; +} + + +/* ----------------------------------------------------------- + The free page queue +----------------------------------------------------------- */ + +// we re-use the `used` field for the expiration counter. Since this is a +// a 32-bit field while the clock is always 64-bit we need to guard +// against overflow, we use substraction to check for expiry which work +// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days) +static void mi_page_reset_set_expire(mi_page_t* page) { + uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_reset_delay); + page->used = expire; +} + +static bool mi_page_reset_is_expired(mi_page_t* page, mi_msecs_t now) { + int32_t expire = (int32_t)(page->used); + return (((int32_t)now - expire) >= 0); +} + +static void mi_pages_reset_add(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(!page->segment_in_use || !page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page,tld)); + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + mi_assert_internal(_mi_page_segment(page)==segment); + if (!mi_option_is_enabled(mi_option_page_reset)) return; + if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return; + + if (mi_option_get(mi_option_reset_delay) == 0) { + // reset immediately? + mi_page_reset(segment, page, 0, tld); + } + else { + // otherwise push on the delayed page reset queue + mi_page_queue_t* pq = &tld->pages_reset; + // push on top + mi_page_reset_set_expire(page); + page->next = pq->first; + page->prev = NULL; + if (pq->first == NULL) { + mi_assert_internal(pq->last == NULL); + pq->first = pq->last = page; + } + else { + pq->first->prev = page; + pq->first = page; + } + } +} + +static void mi_pages_reset_remove(mi_page_t* page, mi_segments_tld_t* tld) { + if (mi_page_not_in_queue(page,tld)) return; + + mi_page_queue_t* pq = &tld->pages_reset; + mi_assert_internal(pq!=NULL); + mi_assert_internal(!page->segment_in_use); + mi_assert_internal(mi_pages_reset_contains(page, tld)); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == pq->last) pq->last = page->prev; + if (page == pq->first) pq->first = page->next; + page->next = page->prev = NULL; + page->used = 0; +} + +static void mi_pages_reset_remove_all_in_segment(mi_segment_t* segment, bool force_reset, mi_segments_tld_t* tld) { + if (segment->mem_is_fixed) return; // never reset in huge OS pages + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (!page->segment_in_use && page->is_committed && !page->is_reset) { + mi_pages_reset_remove(page, tld); + if (force_reset) { + mi_page_reset(segment, page, 0, tld); + } + } + else { + mi_assert_internal(mi_page_not_in_queue(page,tld)); + } + } +} + +static void mi_reset_delayed(mi_segments_tld_t* tld) { + if (!mi_option_is_enabled(mi_option_page_reset)) return; + mi_msecs_t now = _mi_clock_now(); + mi_page_queue_t* pq = &tld->pages_reset; + // from oldest up to the first that has not expired yet + mi_page_t* page = pq->last; + while (page != NULL && mi_page_reset_is_expired(page,now)) { + mi_page_t* const prev = page->prev; // save previous field + mi_page_reset(_mi_page_segment(page), page, 0, tld); + page->used = 0; + page->prev = page->next = NULL; + page = prev; + } + // discard the reset pages from the queue + pq->last = page; + if (page != NULL){ + page->next = NULL; + } + else { + pq->first = NULL; + } +} + + +/* ----------------------------------------------------------- + Segment size calculations +----------------------------------------------------------- */ + +// Raw start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set) +// The raw start is not taking aligned block allocation into consideration. +static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { + size_t psize = (segment->page_kind == MI_PAGE_HUGE ? segment->segment_size : (size_t)1 << segment->page_shift); + uint8_t* p = (uint8_t*)segment + page->segment_idx * psize; + + if (page->segment_idx == 0) { + // the first page starts after the segment info (and possible guard page) + p += segment->segment_info_size; + psize -= segment->segment_info_size; + } + + if (MI_SECURE > 1 || (MI_SECURE == 1 && page->segment_idx == segment->capacity - 1)) { + // secure == 1: the last page has an os guard page at the end + // secure > 1: every page has an os guard page + psize -= _mi_os_page_size(); + } + + if (page_size != NULL) *page_size = psize; + mi_assert_internal(page->xblock_size == 0 || _mi_ptr_page(p) == page); + mi_assert_internal(_mi_ptr_segment(p) == segment); + return p; +} + +// Start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set) +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size) +{ + size_t psize; + uint8_t* p = mi_segment_raw_page_start(segment, page, &psize); + if (pre_size != NULL) *pre_size = 0; + if (page->segment_idx == 0 && block_size > 0 && segment->page_kind <= MI_PAGE_MEDIUM) { + // for small and medium objects, ensure the page start is aligned with the block size (PR#66 by kickunderscore) + size_t adjust = block_size - ((uintptr_t)p % block_size); + if (adjust < block_size) { + p += adjust; + psize -= adjust; + if (pre_size != NULL) *pre_size = adjust; + } + mi_assert_internal((uintptr_t)p % block_size == 0); + } + + if (page_size != NULL) *page_size = psize; + mi_assert_internal(page->xblock_size==0 || _mi_ptr_page(p) == page); + mi_assert_internal(_mi_ptr_segment(p) == segment); + return p; +} + +static size_t mi_segment_size(size_t capacity, size_t required, size_t* pre_size, size_t* info_size) +{ + const size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */; + size_t guardsize = 0; + size_t isize = 0; + + if (MI_SECURE == 0) { + // normally no guard pages + isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE); + } + else { + // in secure mode, we set up a protected page in between the segment info + // and the page data (and one at the end of the segment) + const size_t page_size = _mi_os_page_size(); + isize = _mi_align_up(minsize, page_size); + guardsize = page_size; + required = _mi_align_up(required, page_size); + } + + if (info_size != NULL) *info_size = isize; + if (pre_size != NULL) *pre_size = isize + guardsize; + return (required==0 ? MI_SEGMENT_SIZE : _mi_align_up( required + isize + 2*guardsize, MI_PAGE_HUGE_ALIGN) ); +} + + +/* ---------------------------------------------------------------------------- +Segment caches +We keep a small segment cache per thread to increase local +reuse and avoid setting/clearing guard pages in secure mode. +------------------------------------------------------------------------------- */ + +static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) { + if (segment_size>=0) _mi_stat_increase(&tld->stats->segments,1); + else _mi_stat_decrease(&tld->stats->segments,1); + tld->count += (segment_size >= 0 ? 1 : -1); + if (tld->count > tld->peak_count) tld->peak_count = tld->count; + tld->current_size += segment_size; + if (tld->current_size > tld->peak_size) tld->peak_size = tld->current_size; +} + +static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_segments_tld_t* tld) { + segment->thread_id = 0; + mi_segments_track_size(-((long)segment_size),tld); + if (MI_SECURE != 0) { + mi_assert_internal(!segment->mem_is_fixed); + mi_segment_protect(segment, false, tld->os); // ensure no more guard pages are set + } + + bool any_reset = false; + bool fully_committed = true; + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (!page->is_committed) { fully_committed = false; } + if (page->is_reset) { any_reset = true; } + } + if (any_reset && mi_option_is_enabled(mi_option_reset_decommits)) { + fully_committed = false; + } + _mi_mem_free(segment, segment_size, segment->memid, fully_committed, any_reset, tld->os); +} + + +// The thread local segment cache is limited to be at most 1/8 of the peak size of segments in use, +#define MI_SEGMENT_CACHE_FRACTION (8) + +// note: returned segment may be partially reset +static mi_segment_t* mi_segment_cache_pop(size_t segment_size, mi_segments_tld_t* tld) { + if (segment_size != 0 && segment_size != MI_SEGMENT_SIZE) return NULL; + mi_segment_t* segment = tld->cache; + if (segment == NULL) return NULL; + tld->cache_count--; + tld->cache = segment->next; + segment->next = NULL; + mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE); + _mi_stat_decrease(&tld->stats->segments_cache, 1); + return segment; +} + +static bool mi_segment_cache_full(mi_segments_tld_t* tld) +{ + // if (tld->count == 1 && tld->cache_count==0) return false; // always cache at least the final segment of a thread + size_t max_cache = mi_option_get(mi_option_segment_cache); + if (tld->cache_count < max_cache + && tld->cache_count < (1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION)) // at least allow a 1 element cache + ) { + return false; + } + // take the opportunity to reduce the segment cache if it is too large (now) + // TODO: this never happens as we check against peak usage, should we use current usage instead? + while (tld->cache_count > max_cache) { //(1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION))) { + mi_segment_t* segment = mi_segment_cache_pop(0,tld); + mi_assert_internal(segment != NULL); + if (segment != NULL) mi_segment_os_free(segment, segment->segment_size, tld); + } + return true; +} + +static bool mi_segment_cache_push(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(!mi_segment_is_in_free_queue(segment, tld)); + mi_assert_internal(segment->next == NULL); + if (segment->segment_size != MI_SEGMENT_SIZE || mi_segment_cache_full(tld)) { + return false; + } + mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE); + segment->next = tld->cache; + tld->cache = segment; + tld->cache_count++; + _mi_stat_increase(&tld->stats->segments_cache,1); + return true; +} + +// called by threads that are terminating to free cached segments +void _mi_segment_thread_collect(mi_segments_tld_t* tld) { + mi_segment_t* segment; + while ((segment = mi_segment_cache_pop(0,tld)) != NULL) { + mi_segment_os_free(segment, segment->segment_size, tld); + } + mi_assert_internal(tld->cache_count == 0); + mi_assert_internal(tld->cache == NULL); +#if MI_DEBUG>=2 + if (!_mi_is_main_thread()) { + mi_assert_internal(tld->pages_reset.first == NULL); + mi_assert_internal(tld->pages_reset.last == NULL); + } +#endif +} + + +/* ----------------------------------------------------------- + Segment allocation +----------------------------------------------------------- */ + +// Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` . +static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + // the segment parameter is non-null if it came from our cache + mi_assert_internal(segment==NULL || (required==0 && page_kind <= MI_PAGE_LARGE)); + + // calculate needed sizes first + size_t capacity; + if (page_kind == MI_PAGE_HUGE) { + mi_assert_internal(page_shift == MI_SEGMENT_SHIFT && required > 0); + capacity = 1; + } + else { + mi_assert_internal(required == 0); + size_t page_size = (size_t)1 << page_shift; + capacity = MI_SEGMENT_SIZE / page_size; + mi_assert_internal(MI_SEGMENT_SIZE % page_size == 0); + mi_assert_internal(capacity >= 1 && capacity <= MI_SMALL_PAGES_PER_SEGMENT); + } + size_t info_size; + size_t pre_size; + size_t segment_size = mi_segment_size(capacity, required, &pre_size, &info_size); + mi_assert_internal(segment_size >= required); + + // Initialize parameters + const bool eager_delayed = (page_kind <= MI_PAGE_MEDIUM && tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay)); + const bool eager = !eager_delayed && mi_option_is_enabled(mi_option_eager_commit); + bool commit = eager; // || (page_kind >= MI_PAGE_LARGE); + bool pages_still_good = false; + bool is_zero = false; + + // Try to get it from our thread local cache first + if (segment != NULL) { + // came from cache + mi_assert_internal(segment->segment_size == segment_size); + if (page_kind <= MI_PAGE_MEDIUM && segment->page_kind == page_kind && segment->segment_size == segment_size) { + pages_still_good = true; + } + else + { + if (MI_SECURE!=0) { + mi_assert_internal(!segment->mem_is_fixed); + mi_segment_protect(segment, false, tld->os); // reset protection if the page kind differs + } + // different page kinds; unreset any reset pages, and unprotect + // TODO: optimize cache pop to return fitting pages if possible? + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->is_reset) { + if (!commit && mi_option_is_enabled(mi_option_reset_decommits)) { + page->is_reset = false; + } + else { + mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset? (instead of the full page) + } + } + } + // ensure the initial info is committed + if (segment->capacity < capacity) { + bool commit_zero = false; + bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os); + if (commit_zero) is_zero = true; + if (!ok) { + return NULL; + } + } + } + } + else { + // Allocate the segment from the OS + size_t memid; + bool mem_large = (!eager_delayed && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy + segment = (mi_segment_t*)_mi_mem_alloc_aligned(segment_size, MI_SEGMENT_SIZE, &commit, &mem_large, &is_zero, &memid, os_tld); + if (segment == NULL) return NULL; // failed to allocate + if (!commit) { + // ensure the initial info is committed + bool commit_zero = false; + bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os); + if (commit_zero) is_zero = true; + if (!ok) { + // commit failed; we cannot touch the memory: free the segment directly and return `NULL` + _mi_mem_free(segment, MI_SEGMENT_SIZE, memid, false, false, os_tld); + return NULL; + } + } + segment->memid = memid; + segment->mem_is_fixed = mem_large; + segment->mem_is_committed = commit; + mi_segments_track_size((long)segment_size, tld); + } + mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0); + mi_assert_internal(segment->mem_is_fixed ? segment->mem_is_committed : true); + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); // tsan + if (!pages_still_good) { + // zero the segment info (but not the `mem` fields) + ptrdiff_t ofs = offsetof(mi_segment_t, next); + memset((uint8_t*)segment + ofs, 0, info_size - ofs); + + // initialize pages info + for (uint8_t i = 0; i < capacity; i++) { + segment->pages[i].segment_idx = i; + segment->pages[i].is_reset = false; + segment->pages[i].is_committed = commit; + segment->pages[i].is_zero_init = is_zero; + } + } + else { + // zero the segment info but not the pages info (and mem fields) + ptrdiff_t ofs = offsetof(mi_segment_t, next); + memset((uint8_t*)segment + ofs, 0, offsetof(mi_segment_t,pages) - ofs); + } + + // initialize + segment->page_kind = page_kind; + segment->capacity = capacity; + segment->page_shift = page_shift; + segment->segment_size = segment_size; + segment->segment_info_size = pre_size; + segment->thread_id = _mi_thread_id(); + segment->cookie = _mi_ptr_cookie(segment); + // _mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size); + + // set protection + mi_segment_protect(segment, true, tld->os); + + // insert in free lists for small and medium pages + if (page_kind <= MI_PAGE_MEDIUM) { + mi_segment_insert_in_free_queue(segment, tld); + } + + //fprintf(stderr,"mimalloc: alloc segment at %p\n", (void*)segment); + return segment; +} + +static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_init(NULL, required, page_kind, page_shift, tld, os_tld); +} + +static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) { + UNUSED(force); + mi_assert(segment != NULL); + // note: don't reset pages even on abandon as the whole segment is freed? (and ready for reuse) + bool force_reset = (force && mi_option_is_enabled(mi_option_abandoned_page_reset)); + mi_pages_reset_remove_all_in_segment(segment, force_reset, tld); + mi_segment_remove_from_free_queue(segment,tld); + + mi_assert_expensive(!mi_segment_queue_contains(&tld->small_free, segment)); + mi_assert_expensive(!mi_segment_queue_contains(&tld->medium_free, segment)); + mi_assert(segment->next == NULL); + mi_assert(segment->prev == NULL); + _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size); + + if (!force && mi_segment_cache_push(segment, tld)) { + // it is put in our cache + } + else { + // otherwise return it to the OS + mi_segment_os_free(segment, segment->segment_size, tld); + } +} + +/* ----------------------------------------------------------- + Free page management inside a segment +----------------------------------------------------------- */ + + +static bool mi_segment_has_free(const mi_segment_t* segment) { + return (segment->used < segment->capacity); +} + +static bool mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(_mi_page_segment(page) == segment); + mi_assert_internal(!page->segment_in_use); + mi_pages_reset_remove(page, tld); + // check commit + if (!page->is_committed) { + mi_assert_internal(!segment->mem_is_fixed); + mi_assert_internal(!page->is_reset); + size_t psize; + uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); + bool is_zero = false; + const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0); + bool ok = _mi_mem_commit(start, psize + gsize, &is_zero, tld->os); + if (!ok) return false; // failed to commit! + if (gsize > 0) { mi_segment_protect_range(start + psize, gsize, true); } + if (is_zero) { page->is_zero_init = true; } + page->is_committed = true; + } + // set in-use before doing unreset to prevent delayed reset + page->segment_in_use = true; + segment->used++; + // check reset + if (page->is_reset) { + mi_assert_internal(!segment->mem_is_fixed); + bool ok = mi_page_unreset(segment, page, 0, tld); + if (!ok) { + page->segment_in_use = false; + segment->used--; + return false; + } + } + mi_assert_internal(page->segment_in_use); + mi_assert_internal(segment->used <= segment->capacity); + if (segment->used == segment->capacity && segment->page_kind <= MI_PAGE_MEDIUM) { + // if no more free pages, remove from the queue + mi_assert_internal(!mi_segment_has_free(segment)); + mi_segment_remove_from_free_queue(segment, tld); + } + return true; +} + + +/* ----------------------------------------------------------- + Free +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld); + +// clear page data; can be called on abandoned segments +static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, bool allow_reset, mi_segments_tld_t* tld) +{ + mi_assert_internal(page->segment_in_use); + mi_assert_internal(mi_page_all_free(page)); + mi_assert_internal(page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page, tld)); + + size_t inuse = page->capacity * mi_page_block_size(page); + _mi_stat_decrease(&tld->stats->page_committed, inuse); + _mi_stat_decrease(&tld->stats->pages, 1); + + // calculate the used size from the raw (non-aligned) start of the page + //size_t pre_size; + //_mi_segment_page_start(segment, page, page->block_size, NULL, &pre_size); + //size_t used_size = pre_size + (page->capacity * page->block_size); + + page->is_zero_init = false; + page->segment_in_use = false; + + // reset the page memory to reduce memory pressure? + // note: must come after setting `segment_in_use` to false but before block_size becomes 0 + //mi_page_reset(segment, page, 0 /*used_size*/, tld); + + // zero the page data, but not the segment fields and capacity, and block_size (for page size calculations) + uint32_t block_size = page->xblock_size; + uint16_t capacity = page->capacity; + uint16_t reserved = page->reserved; + ptrdiff_t ofs = offsetof(mi_page_t,capacity); + memset((uint8_t*)page + ofs, 0, sizeof(*page) - ofs); + page->capacity = capacity; + page->reserved = reserved; + page->xblock_size = block_size; + segment->used--; + + // add to the free page list for reuse/reset + if (allow_reset) { + mi_pages_reset_add(segment, page, tld); + } + + page->capacity = 0; // after reset these can be zero'd now + page->reserved = 0; +} + +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) +{ + mi_assert(page != NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + mi_reset_delayed(tld); + + // mark it as free now + mi_segment_page_clear(segment, page, true, tld); + + if (segment->used == 0) { + // no more used pages; remove from the free list and free the segment + mi_segment_free(segment, force, tld); + } + else { + if (segment->used == segment->abandoned) { + // only abandoned pages; remove from free list and abandon + mi_segment_abandon(segment,tld); + } + else if (segment->used + 1 == segment->capacity) { + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM); // for now we only support small and medium pages + // move back to segments free list + mi_segment_insert_in_free_queue(segment,tld); + } + } +} + + +/* ----------------------------------------------------------- +Abandonment + +When threads terminate, they can leave segments with +live blocks (reached through other threads). Such segments +are "abandoned" and will be reclaimed by other threads to +reuse their pages and/or free them eventually + +We maintain a global list of abandoned segments that are +reclaimed on demand. Since this is shared among threads +the implementation needs to avoid the A-B-A problem on +popping abandoned segments: +We use tagged pointers to avoid accidentially identifying +reused segments, much like stamped references in Java. +Secondly, we maintain a reader counter to avoid resetting +or decommitting segments that have a pending read operation. + +Note: the current implementation is one possible design; +another way might be to keep track of abandoned segments +in the regions. This would have the advantage of keeping +all concurrent code in one place and not needing to deal +with ABA issues. The drawback is that it is unclear how to +scan abandoned segments efficiently in that case as they +would be spread among all other segments in the regions. +----------------------------------------------------------- */ + +// Use the bottom 20-bits (on 64-bit) of the aligned segment pointers +// to put in a tag that increments on update to avoid the A-B-A problem. +#define MI_TAGGED_MASK MI_SEGMENT_MASK +typedef uintptr_t mi_tagged_segment_t; + +static mi_segment_t* mi_tagged_segment_ptr(mi_tagged_segment_t ts) { + return (mi_segment_t*)(ts & ~MI_TAGGED_MASK); +} + +static mi_tagged_segment_t mi_tagged_segment(mi_segment_t* segment, mi_tagged_segment_t ts) { + mi_assert_internal(((uintptr_t)segment & MI_TAGGED_MASK) == 0); + uintptr_t tag = ((ts & MI_TAGGED_MASK) + 1) & MI_TAGGED_MASK; + return ((uintptr_t)segment | tag); +} + +// This is a list of visited abandoned pages that were full at the time. +// this list migrates to `abandoned` when that becomes NULL. The use of +// this list reduces contention and the rate at which segments are visited. +static mi_decl_cache_align _Atomic(mi_segment_t*) abandoned_visited; // = NULL + +// The abandoned page list (tagged as it supports pop) +static mi_decl_cache_align _Atomic(mi_tagged_segment_t) abandoned; // = NULL + +// Maintain these for debug purposes (these counts may be a bit off) +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_count; +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_visited_count; + +// We also maintain a count of current readers of the abandoned list +// in order to prevent resetting/decommitting segment memory if it might +// still be read. +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_readers; // = 0 + +// Push on the visited list +static void mi_abandoned_visited_push(mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t,&segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_internal(segment->used > 0); + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, anext); + } while (!mi_atomic_cas_ptr_weak_release(mi_segment_t, &abandoned_visited, &anext, segment)); + mi_atomic_increment_relaxed(&abandoned_visited_count); +} + +// Move the visited list to the abandoned list. +static bool mi_abandoned_visited_revisit(void) +{ + // quick check if the visited list is empty + if (mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited) == NULL) return false; + + // grab the whole visited list + mi_segment_t* first = mi_atomic_exchange_ptr_acq_rel(mi_segment_t, &abandoned_visited, NULL); + if (first == NULL) return false; + + // first try to swap directly if the abandoned list happens to be NULL + mi_tagged_segment_t afirst; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + if (mi_tagged_segment_ptr(ts)==NULL) { + uintptr_t count = mi_atomic_load_relaxed(&abandoned_visited_count); + afirst = mi_tagged_segment(first, ts); + if (mi_atomic_cas_strong_acq_rel(&abandoned, &ts, afirst)) { + mi_atomic_add_relaxed(&abandoned_count, count); + mi_atomic_sub_relaxed(&abandoned_visited_count, count); + return true; + } + } + + // find the last element of the visited list: O(n) + mi_segment_t* last = first; + mi_segment_t* next; + while ((next = mi_atomic_load_ptr_relaxed(mi_segment_t, &last->abandoned_next)) != NULL) { + last = next; + } + + // and atomically prepend to the abandoned list + // (no need to increase the readers as we don't access the abandoned segments) + mi_tagged_segment_t anext = mi_atomic_load_relaxed(&abandoned); + uintptr_t count; + do { + count = mi_atomic_load_relaxed(&abandoned_visited_count); + mi_atomic_store_ptr_release(mi_segment_t, &last->abandoned_next, mi_tagged_segment_ptr(anext)); + afirst = mi_tagged_segment(first, anext); + } while (!mi_atomic_cas_weak_release(&abandoned, &anext, afirst)); + mi_atomic_add_relaxed(&abandoned_count, count); + mi_atomic_sub_relaxed(&abandoned_visited_count, count); + return true; +} + +// Push on the abandoned list. +static void mi_abandoned_push(mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_internal(segment->used > 0); + mi_tagged_segment_t next; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, mi_tagged_segment_ptr(ts)); + next = mi_tagged_segment(segment, ts); + } while (!mi_atomic_cas_weak_release(&abandoned, &ts, next)); + mi_atomic_increment_relaxed(&abandoned_count); +} + +// Wait until there are no more pending reads on segments that used to be in the abandoned list +void _mi_abandoned_await_readers(void) { + uintptr_t n; + do { + n = mi_atomic_load_acquire(&abandoned_readers); + if (n != 0) mi_atomic_yield(); + } while (n != 0); +} + +// Pop from the abandoned list +static mi_segment_t* mi_abandoned_pop(void) { + mi_segment_t* segment; + // Check efficiently if it is empty (or if the visited list needs to be moved) + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + segment = mi_tagged_segment_ptr(ts); + if (mi_likely(segment == NULL)) { + if (mi_likely(!mi_abandoned_visited_revisit())) { // try to swap in the visited list on NULL + return NULL; + } + } + + // Do a pop. We use a reader count to prevent + // a segment to be decommitted while a read is still pending, + // and a tagged pointer to prevent A-B-A link corruption. + // (this is called from `region.c:_mi_mem_free` for example) + mi_atomic_increment_relaxed(&abandoned_readers); // ensure no segment gets decommitted + mi_tagged_segment_t next = 0; + ts = mi_atomic_load_acquire(&abandoned); + do { + segment = mi_tagged_segment_ptr(ts); + if (segment != NULL) { + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next); + next = mi_tagged_segment(anext, ts); // note: reads the segment's `abandoned_next` field so should not be decommitted + } + } while (segment != NULL && !mi_atomic_cas_weak_acq_rel(&abandoned, &ts, next)); + mi_atomic_decrement_relaxed(&abandoned_readers); // release reader lock + if (segment != NULL) { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + mi_atomic_decrement_relaxed(&abandoned_count); + } + return segment; +} + +/* ----------------------------------------------------------- + Abandon segment/page +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment->used == segment->abandoned); + mi_assert_internal(segment->used > 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + + // remove the segment from the free page queue if needed + mi_reset_delayed(tld); + mi_pages_reset_remove_all_in_segment(segment, mi_option_is_enabled(mi_option_abandoned_page_reset), tld); + mi_segment_remove_from_free_queue(segment, tld); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + + // all pages in the segment are abandoned; add it to the abandoned list + _mi_stat_increase(&tld->stats->segments_abandoned, 1); + mi_segments_track_size(-((long)segment->segment_size), tld); + segment->thread_id = 0; + segment->abandoned_visits = 0; + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + mi_abandoned_push(segment); +} + +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert(page != NULL); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + segment->abandoned++; + _mi_stat_increase(&tld->stats->pages_abandoned, 1); + mi_assert_internal(segment->abandoned <= segment->used); + if (segment->used == segment->abandoned) { + // all pages are abandoned, abandon the entire segment + mi_segment_abandon(segment, tld); + } +} + +/* ----------------------------------------------------------- + Reclaim abandoned pages +----------------------------------------------------------- */ + +// Possibly clear pages and check if free space is available +static bool mi_segment_check_free(mi_segment_t* segment, size_t block_size, bool* all_pages_free) +{ + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + bool has_page = false; + size_t pages_used = 0; + size_t pages_used_empty = 0; + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->segment_in_use) { + pages_used++; + // ensure used count is up to date and collect potential concurrent frees + _mi_page_free_collect(page, false); + if (mi_page_all_free(page)) { + // if everything free already, page can be reused for some block size + // note: don't clear the page yet as we can only OS reset it once it is reclaimed + pages_used_empty++; + has_page = true; + } + else if (page->xblock_size == block_size && mi_page_has_any_available(page)) { + // a page has available free blocks of the right size + has_page = true; + } + } + else { + // whole empty page + has_page = true; + } + } + mi_assert_internal(pages_used == segment->used && pages_used >= pages_used_empty); + if (all_pages_free != NULL) { + *all_pages_free = ((pages_used - pages_used_empty) == 0); + } + return has_page; +} + + +// Reclaim a segment; returns NULL if the segment was freed +// set `right_page_reclaimed` to `true` if it reclaimed a page of the right `block_size` that was not full. +static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, size_t requested_block_size, bool* right_page_reclaimed, mi_segments_tld_t* tld) { + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + if (right_page_reclaimed != NULL) { *right_page_reclaimed = false; } + + segment->thread_id = _mi_thread_id(); + segment->abandoned_visits = 0; + mi_segments_track_size((long)segment->segment_size, tld); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + _mi_stat_decrease(&tld->stats->segments_abandoned, 1); + + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->segment_in_use) { + mi_assert_internal(!page->is_reset); + mi_assert_internal(page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page, tld)); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + segment->abandoned--; + mi_assert(page->next == NULL); + _mi_stat_decrease(&tld->stats->pages_abandoned, 1); + // set the heap again and allow heap thread delayed free again. + mi_page_set_heap(page, heap); + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, true); // override never (after heap is set) + // TODO: should we not collect again given that we just collected in `check_free`? + _mi_page_free_collect(page, false); // ensure used count is up to date + if (mi_page_all_free(page)) { + // if everything free already, clear the page directly + mi_segment_page_clear(segment, page, true, tld); // reset is ok now + } + else { + // otherwise reclaim it into the heap + _mi_page_reclaim(heap, page); + if (requested_block_size == page->xblock_size && mi_page_has_any_available(page)) { + if (right_page_reclaimed != NULL) { *right_page_reclaimed = true; } + } + } + } + else if (page->is_committed && !page->is_reset) { // not in-use, and not reset yet + // note: do not reset as this includes pages that were not touched before + // mi_pages_reset_add(segment, page, tld); + } + } + mi_assert_internal(segment->abandoned == 0); + if (segment->used == 0) { + mi_assert_internal(right_page_reclaimed == NULL || !(*right_page_reclaimed)); + mi_segment_free(segment, false, tld); + return NULL; + } + else { + if (segment->page_kind <= MI_PAGE_MEDIUM && mi_segment_has_free(segment)) { + mi_segment_insert_in_free_queue(segment, tld); + } + return segment; + } +} + + +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld) { + mi_segment_t* segment; + while ((segment = mi_abandoned_pop()) != NULL) { + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } +} + +static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, bool* reclaimed, mi_segments_tld_t* tld) +{ + *reclaimed = false; + mi_segment_t* segment; + int max_tries = 8; // limit the work to bound allocation times + while ((max_tries-- > 0) && ((segment = mi_abandoned_pop()) != NULL)) { + segment->abandoned_visits++; + bool all_pages_free; + bool has_page = mi_segment_check_free(segment,block_size,&all_pages_free); // try to free up pages (due to concurrent frees) + if (all_pages_free) { + // free the segment (by forced reclaim) to make it available to other threads. + // note1: we prefer to free a segment as that might lead to reclaiming another + // segment that is still partially used. + // note2: we could in principle optimize this by skipping reclaim and directly + // freeing but that would violate some invariants temporarily) + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else if (has_page && segment->page_kind == page_kind) { + // found a free page of the right kind, or page of the right block_size with free space + // we return the result of reclaim (which is usually `segment`) as it might free + // the segment due to concurrent frees (in which case `NULL` is returned). + return mi_segment_reclaim(segment, heap, block_size, reclaimed, tld); + } + else if (segment->abandoned_visits >= 3) { + // always reclaim on 3rd visit to limit the list length. + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else { + // otherwise, push on the visited list so it gets not looked at too quickly again + mi_abandoned_visited_push(segment); + } + } + return NULL; +} + + +/* ----------------------------------------------------------- + Reclaim or allocate +----------------------------------------------------------- */ + +static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_assert_internal(page_kind <= MI_PAGE_LARGE); + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + // 1. try to get a segment from our cache + mi_segment_t* segment = mi_segment_cache_pop(MI_SEGMENT_SIZE, tld); + if (segment != NULL) { + mi_segment_init(segment, 0, page_kind, page_shift, tld, os_tld); + return segment; + } + // 2. try to reclaim an abandoned segment + bool reclaimed; + segment = mi_segment_try_reclaim(heap, block_size, page_kind, &reclaimed, tld); + if (reclaimed) { + // reclaimed the right page right into the heap + mi_assert_internal(segment != NULL && segment->page_kind == page_kind && page_kind <= MI_PAGE_LARGE); + return NULL; // pretend out-of-memory as the page will be in the page queue of the heap with available blocks + } + else if (segment != NULL) { + // reclaimed a segment with empty pages (of `page_kind`) in it + return segment; + } + // 3. otherwise allocate a fresh segment + return mi_segment_alloc(0, page_kind, page_shift, tld, os_tld); +} + + +/* ----------------------------------------------------------- + Small page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segment_find_free(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(mi_segment_has_free(segment)); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + for (size_t i = 0; i < segment->capacity; i++) { // TODO: use a bitmap instead of search? + mi_page_t* page = &segment->pages[i]; + if (!page->segment_in_use) { + bool ok = mi_segment_page_claim(segment, page, tld); + if (ok) return page; + } + } + mi_assert(false); + return NULL; +} + +// Allocate a page inside a segment. Requires that the page has free pages +static mi_page_t* mi_segment_page_alloc_in(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(mi_segment_has_free(segment)); + return mi_segment_find_free(segment, tld); +} + +static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + // find an available segment the segment free queue + mi_segment_queue_t* const free_queue = mi_segment_free_queue_of_kind(kind, tld); + if (mi_segment_queue_is_empty(free_queue)) { + // possibly allocate or reclaim a fresh segment + mi_segment_t* const segment = mi_segment_reclaim_or_alloc(heap, block_size, kind, page_shift, tld, os_tld); + if (segment == NULL) return NULL; // return NULL if out-of-memory (or reclaimed) + mi_assert_internal(free_queue->first == segment); + mi_assert_internal(segment->page_kind==kind); + mi_assert_internal(segment->used < segment->capacity); + } + mi_assert_internal(free_queue->first != NULL); + mi_page_t* const page = mi_segment_page_alloc_in(free_queue->first, tld); + mi_assert_internal(page != NULL); +#if MI_DEBUG>=2 + // verify it is committed + _mi_segment_page_start(_mi_page_segment(page), page, sizeof(void*), NULL, NULL)[0] = 0; +#endif + return page; +} + +static mi_page_t* mi_segment_small_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_SMALL,MI_SMALL_PAGE_SHIFT,tld,os_tld); +} + +static mi_page_t* mi_segment_medium_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_MEDIUM, MI_MEDIUM_PAGE_SHIFT, tld, os_tld); +} + +/* ----------------------------------------------------------- + large page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + mi_segment_t* segment = mi_segment_reclaim_or_alloc(heap,block_size,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld); + if (segment == NULL) return NULL; + mi_page_t* page = mi_segment_find_free(segment, tld); + mi_assert_internal(page != NULL); +#if MI_DEBUG>=2 + _mi_segment_page_start(segment, page, sizeof(void*), NULL, NULL)[0] = 0; +#endif + return page; +} + +static mi_page_t* mi_segment_huge_page_alloc(size_t size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT,tld,os_tld); + if (segment == NULL) return NULL; + mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size); + segment->thread_id = 0; // huge pages are immediately abandoned + mi_segments_track_size(-(long)segment->segment_size, tld); + mi_page_t* page = mi_segment_find_free(segment, tld); + mi_assert_internal(page != NULL); + return page; +} + +// free huge block from another thread +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block) { + // huge page segments are always abandoned and can be freed immediately by any thread + mi_assert_internal(segment->page_kind==MI_PAGE_HUGE); + mi_assert_internal(segment == _mi_page_segment(page)); + mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id)==0); + + // claim it and free + mi_heap_t* heap = mi_heap_get_default(); // issue #221; don't use the internal get_default_heap as we need to ensure the thread is initialized. + // paranoia: if this it the last reference, the cas should always succeed + uintptr_t expected_tid = 0; + if (mi_atomic_cas_strong_acq_rel(&segment->thread_id, &expected_tid, heap->thread_id)) { + mi_block_set_next(page, block, page->free); + page->free = block; + page->used--; + page->is_zero = false; + mi_assert(page->used == 0); + mi_tld_t* tld = heap->tld; + const size_t bsize = mi_page_usable_block_size(page); + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_decrease(&tld->stats.giant, bsize); + } + else { + _mi_stat_decrease(&tld->stats.huge, bsize); + } + mi_segments_track_size((long)segment->segment_size, &tld->segments); + _mi_segment_page_free(page, true, &tld->segments); + } +#if (MI_DEBUG!=0) + else { + mi_assert_internal(false); + } +#endif +} + +/* ----------------------------------------------------------- + Page allocation +----------------------------------------------------------- */ + +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + mi_page_t* page; + if (block_size <= MI_SMALL_OBJ_SIZE_MAX) { + page = mi_segment_small_page_alloc(heap, block_size, tld, os_tld); + } + else if (block_size <= MI_MEDIUM_OBJ_SIZE_MAX) { + page = mi_segment_medium_page_alloc(heap, block_size, tld, os_tld); + } + else if (block_size <= MI_LARGE_OBJ_SIZE_MAX) { + page = mi_segment_large_page_alloc(heap, block_size, tld, os_tld); + } + else { + page = mi_segment_huge_page_alloc(block_size,tld,os_tld); + } + mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld)); + mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size); + mi_reset_delayed(tld); + mi_assert_internal(page == NULL || mi_page_not_in_queue(page, tld)); + return page; +} diff --git a/deps/mimalloc/src/static.c b/deps/mimalloc/src/static.c new file mode 100644 index 000000000..d024b01a9 --- /dev/null +++ b/deps/mimalloc/src/static.c @@ -0,0 +1,38 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#if defined(__sun) +// same remarks as os.c for the static's context. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +// For a static override we create a single object file +// containing the whole library. If it is linked first +// it will override all the standard library allocation +// functions (on Unix's). +#include "stats.c" +#include "random.c" +#include "os.c" +#include "arena.c" +#include "region.c" +#include "segment.c" +#include "page.c" +#include "heap.c" +#include "alloc.c" +#include "alloc-aligned.c" +#include "alloc-posix.c" +#if MI_OSX_ZONE +#include "alloc-override-osx.c" +#endif +#include "init.c" +#include "options.c" diff --git a/deps/mimalloc/src/stats.c b/deps/mimalloc/src/stats.c new file mode 100644 index 000000000..b04822cca --- /dev/null +++ b/deps/mimalloc/src/stats.c @@ -0,0 +1,570 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // fputs, stderr +#include // memset + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Statistics operations +----------------------------------------------------------- */ + +static bool mi_is_in_main(void* stat) { + return ((uint8_t*)stat >= (uint8_t*)&_mi_stats_main + && (uint8_t*)stat < ((uint8_t*)&_mi_stats_main + sizeof(mi_stats_t))); +} + +static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + if (mi_is_in_main(stat)) + { + // add atomically (for abandoned pages) + int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount); + mi_atomic_maxi64_relaxed(&stat->peak, current + amount); + if (amount > 0) { + mi_atomic_addi64_relaxed(&stat->allocated,amount); + } + else { + mi_atomic_addi64_relaxed(&stat->freed, -amount); + } + } + else { + // add thread local + stat->current += amount; + if (stat->current > stat->peak) stat->peak = stat->current; + if (amount > 0) { + stat->allocated += amount; + } + else { + stat->freed += -amount; + } + } +} + +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) { + if (mi_is_in_main(stat)) { + mi_atomic_addi64_relaxed( &stat->count, 1 ); + mi_atomic_addi64_relaxed( &stat->total, (int64_t)amount ); + } + else { + stat->count++; + stat->total += amount; + } +} + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, (int64_t)amount); +} + +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, -((int64_t)amount)); +} + +// must be thread safe as it is called from stats_merge +static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) { + if (stat==src) return; + if (src->allocated==0 && src->freed==0) return; + mi_atomic_addi64_relaxed( &stat->allocated, src->allocated * unit); + mi_atomic_addi64_relaxed( &stat->current, src->current * unit); + mi_atomic_addi64_relaxed( &stat->freed, src->freed * unit); + // peak scores do not work across threads.. + mi_atomic_addi64_relaxed( &stat->peak, src->peak * unit); +} + +static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src, int64_t unit) { + if (stat==src) return; + mi_atomic_addi64_relaxed( &stat->total, src->total * unit); + mi_atomic_addi64_relaxed( &stat->count, src->count * unit); +} + +// must be thread safe as it is called from stats_merge +static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { + if (stats==src) return; + mi_stat_add(&stats->segments, &src->segments,1); + mi_stat_add(&stats->pages, &src->pages,1); + mi_stat_add(&stats->reserved, &src->reserved, 1); + mi_stat_add(&stats->committed, &src->committed, 1); + mi_stat_add(&stats->reset, &src->reset, 1); + mi_stat_add(&stats->page_committed, &src->page_committed, 1); + + mi_stat_add(&stats->pages_abandoned, &src->pages_abandoned, 1); + mi_stat_add(&stats->segments_abandoned, &src->segments_abandoned, 1); + mi_stat_add(&stats->threads, &src->threads, 1); + + mi_stat_add(&stats->malloc, &src->malloc, 1); + mi_stat_add(&stats->segments_cache, &src->segments_cache, 1); + mi_stat_add(&stats->huge, &src->huge, 1); + mi_stat_add(&stats->giant, &src->giant, 1); + + mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1); + mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls, 1); + mi_stat_counter_add(&stats->commit_calls, &src->commit_calls, 1); + + mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire, 1); + mi_stat_counter_add(&stats->searches, &src->searches, 1); + mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1); + mi_stat_counter_add(&stats->giant_count, &src->giant_count, 1); +#if MI_STAT>1 + for (size_t i = 0; i <= MI_BIN_HUGE; i++) { + if (src->normal[i].allocated > 0 || src->normal[i].freed > 0) { + mi_stat_add(&stats->normal[i], &src->normal[i], 1); + } + } +#endif +} + +/* ----------------------------------------------------------- + Display statistics +----------------------------------------------------------- */ + +// unit > 0 : size in binary bytes +// unit == 0: count as decimal +// unit < 0 : count in binary +static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg, const char* fmt) { + char buf[32]; + int len = 32; + const char* suffix = (unit <= 0 ? " " : "b"); + const int64_t base = (unit == 0 ? 1000 : 1024); + if (unit>0) n *= unit; + + const int64_t pos = (n < 0 ? -n : n); + if (pos < base) { + snprintf(buf, len, "%d %s ", (int)n, suffix); + } + else { + int64_t divider = base; + const char* magnitude = "k"; + if (pos >= divider*base) { divider *= base; magnitude = "m"; } + if (pos >= divider*base) { divider *= base; magnitude = "g"; } + const int64_t tens = (n / (divider/10)); + const long whole = (long)(tens/10); + const long frac1 = (long)(tens%10); + snprintf(buf, len, "%ld.%ld %s%s", whole, frac1, magnitude, suffix); + } + _mi_fprintf(out, arg, (fmt==NULL ? "%11s" : fmt), buf); +} + + +static void mi_print_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + mi_printf_amount(n,unit,out,arg,NULL); +} + +static void mi_print_count(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + if (unit==1) _mi_fprintf(out, arg, "%11s"," "); + else mi_print_amount(n,0,out,arg); +} + +static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg,"%10s:", msg); + if (unit>0) { + mi_print_amount(stat->peak, unit, out, arg); + mi_print_amount(stat->allocated, unit, out, arg); + mi_print_amount(stat->freed, unit, out, arg); + mi_print_amount(unit, 1, out, arg); + mi_print_count(stat->allocated, unit, out, arg); + if (stat->allocated > stat->freed) + _mi_fprintf(out, arg, " not all freed!\n"); + else + _mi_fprintf(out, arg, " ok\n"); + } + else if (unit<0) { + mi_print_amount(stat->peak, -1, out, arg); + mi_print_amount(stat->allocated, -1, out, arg); + mi_print_amount(stat->freed, -1, out, arg); + if (unit==-1) { + _mi_fprintf(out, arg, "%22s", ""); + } + else { + mi_print_amount(-unit, 1, out, arg); + mi_print_count((stat->allocated / -unit), 0, out, arg); + } + if (stat->allocated > stat->freed) + _mi_fprintf(out, arg, " not all freed!\n"); + else + _mi_fprintf(out, arg, " ok\n"); + } + else { + mi_print_amount(stat->peak, 1, out, arg); + mi_print_amount(stat->allocated, 1, out, arg); + _mi_fprintf(out, arg, "\n"); + } +} + +static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s:", msg); + mi_print_amount(stat->total, -1, out, arg); + _mi_fprintf(out, arg, "\n"); +} + +static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg) { + const int64_t avg_tens = (stat->count == 0 ? 0 : (stat->total*10 / stat->count)); + const long avg_whole = (long)(avg_tens/10); + const long avg_frac1 = (long)(avg_tens%10); + _mi_fprintf(out, arg, "%10s: %5ld.%ld avg\n", msg, avg_whole, avg_frac1); +} + + +static void mi_print_header(mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "unit ", "count "); +} + +#if MI_STAT>1 +static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out, void* arg) { + bool found = false; + char buf[64]; + for (size_t i = 0; i <= max; i++) { + if (bins[i].allocated > 0) { + found = true; + int64_t unit = _mi_bin_size((uint8_t)i); + snprintf(buf, 64, "%s %3lu", fmt, (long)i); + mi_stat_add(all, &bins[i], unit); + mi_stat_print(&bins[i], buf, unit, out, arg); + } + } + //snprintf(buf, 64, "%s all", fmt); + //mi_stat_print(all, buf, 1); + if (found) { + _mi_fprintf(out, arg, "\n"); + mi_print_header(out, arg); + } +} +#endif + + + +//------------------------------------------------------------ +// Use an output wrapper for line-buffered output +// (which is nice when using loggers etc.) +//------------------------------------------------------------ +typedef struct buffered_s { + mi_output_fun* out; // original output function + void* arg; // and state + char* buf; // local buffer of at least size `count+1` + size_t used; // currently used chars `used <= count` + size_t count; // total chars available for output +} buffered_t; + +static void mi_buffered_flush(buffered_t* buf) { + buf->buf[buf->used] = 0; + _mi_fputs(buf->out, buf->arg, NULL, buf->buf); + buf->used = 0; +} + +static void mi_buffered_out(const char* msg, void* arg) { + buffered_t* buf = (buffered_t*)arg; + if (msg==NULL || buf==NULL) return; + for (const char* src = msg; *src != 0; src++) { + char c = *src; + if (buf->used >= buf->count) mi_buffered_flush(buf); + mi_assert_internal(buf->used < buf->count); + buf->buf[buf->used++] = c; + if (c == '\n') mi_buffered_flush(buf); + } +} + +//------------------------------------------------------------ +// Print statistics +//------------------------------------------------------------ + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults); + +static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept { + // wrap the output function to be line buffered + char buf[256]; + buffered_t buffer = { out0, arg0, NULL, 0, 255 }; + buffer.buf = buf; + mi_output_fun* out = &mi_buffered_out; + void* arg = &buffer; + + // and print using that + mi_print_header(out,arg); + #if MI_STAT>1 + mi_stat_count_t normal = { 0,0,0,0 }; + mi_stats_print_bins(&normal, stats->normal, MI_BIN_HUGE, "normal",out,arg); + mi_stat_print(&normal, "normal", 1, out, arg); + mi_stat_print(&stats->huge, "huge", (stats->huge_count.count == 0 ? 1 : -(stats->huge.allocated / stats->huge_count.count)), out, arg); + mi_stat_print(&stats->giant, "giant", (stats->giant_count.count == 0 ? 1 : -(stats->giant.allocated / stats->giant_count.count)), out, arg); + mi_stat_count_t total = { 0,0,0,0 }; + mi_stat_add(&total, &normal, 1); + mi_stat_add(&total, &stats->huge, 1); + mi_stat_add(&total, &stats->giant, 1); + mi_stat_print(&total, "total", 1, out, arg); + _mi_fprintf(out, arg, "malloc requested: "); + mi_print_amount(stats->malloc.allocated, 1, out, arg); + _mi_fprintf(out, arg, "\n\n"); + #endif + mi_stat_print(&stats->reserved, "reserved", 1, out, arg); + mi_stat_print(&stats->committed, "committed", 1, out, arg); + mi_stat_print(&stats->reset, "reset", 1, out, arg); + mi_stat_print(&stats->page_committed, "touched", 1, out, arg); + mi_stat_print(&stats->segments, "segments", -1, out, arg); + mi_stat_print(&stats->segments_abandoned, "-abandoned", -1, out, arg); + mi_stat_print(&stats->segments_cache, "-cached", -1, out, arg); + mi_stat_print(&stats->pages, "pages", -1, out, arg); + mi_stat_print(&stats->pages_abandoned, "-abandoned", -1, out, arg); + mi_stat_counter_print(&stats->pages_extended, "-extended", out, arg); + mi_stat_counter_print(&stats->page_no_retire, "-noretire", out, arg); + mi_stat_counter_print(&stats->mmap_calls, "mmaps", out, arg); + mi_stat_counter_print(&stats->commit_calls, "commits", out, arg); + mi_stat_print(&stats->threads, "threads", -1, out, arg); + mi_stat_counter_print_avg(&stats->searches, "searches", out, arg); + _mi_fprintf(out, arg, "%10s: %7i\n", "numa nodes", _mi_os_numa_node_count()); + + mi_msecs_t elapsed; + mi_msecs_t user_time; + mi_msecs_t sys_time; + size_t current_rss; + size_t peak_rss; + size_t current_commit; + size_t peak_commit; + size_t page_faults; + mi_stat_process_info(&elapsed, &user_time, &sys_time, ¤t_rss, &peak_rss, ¤t_commit, &peak_commit, &page_faults); + _mi_fprintf(out, arg, "%10s: %7ld.%03ld s\n", "elapsed", elapsed/1000, elapsed%1000); + _mi_fprintf(out, arg, "%10s: user: %ld.%03ld s, system: %ld.%03ld s, faults: %lu, rss: ", "process", + user_time/1000, user_time%1000, sys_time/1000, sys_time%1000, (unsigned long)page_faults ); + mi_printf_amount((int64_t)peak_rss, 1, out, arg, "%s"); + if (peak_commit > 0) { + _mi_fprintf(out, arg, ", commit: "); + mi_printf_amount((int64_t)peak_commit, 1, out, arg, "%s"); + } + _mi_fprintf(out, arg, "\n"); +} + +static mi_msecs_t mi_process_start; // = 0 + +static mi_stats_t* mi_stats_get_default(void) { + mi_heap_t* heap = mi_heap_get_default(); + return &heap->tld->stats; +} + +static void mi_stats_merge_from(mi_stats_t* stats) { + if (stats != &_mi_stats_main) { + mi_stats_add(&_mi_stats_main, stats); + memset(stats, 0, sizeof(mi_stats_t)); + } +} + +void mi_stats_reset(void) mi_attr_noexcept { + mi_stats_t* stats = mi_stats_get_default(); + if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); } + memset(&_mi_stats_main, 0, sizeof(mi_stats_t)); + if (mi_process_start == 0) { mi_process_start = _mi_clock_start(); }; +} + +void mi_stats_merge(void) mi_attr_noexcept { + mi_stats_merge_from( mi_stats_get_default() ); +} + +void _mi_stats_done(mi_stats_t* stats) { // called from `mi_thread_done` + mi_stats_merge_from(stats); +} + +void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_stats_merge_from(mi_stats_get_default()); + _mi_stats_print(&_mi_stats_main, out, arg); +} + +void mi_stats_print(void* out) mi_attr_noexcept { + // for compatibility there is an `out` parameter (which can be `stdout` or `stderr`) + mi_stats_print_out((mi_output_fun*)out, NULL); +} + +void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + _mi_stats_print(mi_stats_get_default(), out, arg); +} + + +// ---------------------------------------------------------------- +// Basic timer for convenience; use milli-seconds to avoid doubles +// ---------------------------------------------------------------- +#ifdef _WIN32 +#include +static mi_msecs_t mi_to_msecs(LARGE_INTEGER t) { + static LARGE_INTEGER mfreq; // = 0 + if (mfreq.QuadPart == 0LL) { + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + mfreq.QuadPart = f.QuadPart/1000LL; + if (mfreq.QuadPart == 0) mfreq.QuadPart = 1; + } + return (mi_msecs_t)(t.QuadPart / mfreq.QuadPart); +} + +mi_msecs_t _mi_clock_now(void) { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return mi_to_msecs(t); +} +#else +#include +#ifdef CLOCK_REALTIME +mi_msecs_t _mi_clock_now(void) { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000); +} +#else +// low resolution timer +mi_msecs_t _mi_clock_now(void) { + return ((mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000)); +} +#endif +#endif + + +static mi_msecs_t mi_clock_diff; + +mi_msecs_t _mi_clock_start(void) { + if (mi_clock_diff == 0.0) { + mi_msecs_t t0 = _mi_clock_now(); + mi_clock_diff = _mi_clock_now() - t0; + } + return _mi_clock_now(); +} + +mi_msecs_t _mi_clock_end(mi_msecs_t start) { + mi_msecs_t end = _mi_clock_now(); + return (end - start - mi_clock_diff); +} + + +// -------------------------------------------------------- +// Basic process statistics +// -------------------------------------------------------- + +#if defined(_WIN32) +#include +#include +#pragma comment(lib,"psapi.lib") + +static mi_msecs_t filetime_msecs(const FILETIME* ftime) { + ULARGE_INTEGER i; + i.LowPart = ftime->dwLowDateTime; + i.HighPart = ftime->dwHighDateTime; + mi_msecs_t msecs = (i.QuadPart / 10000); // FILETIME is in 100 nano seconds + return msecs; +} + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + FILETIME ct; + FILETIME ut; + FILETIME st; + FILETIME et; + GetProcessTimes(GetCurrentProcess(), &ct, &et, &st, &ut); + *utime = filetime_msecs(&ut); + *stime = filetime_msecs(&st); + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); + *current_rss = (size_t)info.WorkingSetSize; + *peak_rss = (size_t)info.PeakWorkingSetSize; + *current_commit = (size_t)info.PagefileUsage; + *peak_commit = (size_t)info.PeakPagefileUsage; + *page_faults = (size_t)info.PageFaultCount; +} + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) +#include +#include +#include + +#if defined(__APPLE__) && defined(__MACH__) +#include +#endif + +#if defined(__HAIKU__) +#include +#endif + +static mi_msecs_t timeval_secs(const struct timeval* tv) { + return ((mi_msecs_t)tv->tv_sec * 1000L) + ((mi_msecs_t)tv->tv_usec / 1000L); +} + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + *utime = timeval_secs(&rusage.ru_utime); + *stime = timeval_secs(&rusage.ru_stime); +#if !defined(__HAIKU__) + *page_faults = rusage.ru_majflt; +#endif + // estimate commit using our stats + *peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak)); + *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current)); + *current_rss = *current_commit; // estimate +#if defined(__HAIKU__) + // Haiku does not have (yet?) a way to + // get these stats per process + thread_info tid; + area_info mem; + ssize_t c; + get_thread_info(find_thread(0), &tid); + while (get_next_area_info(tid.team, &c, &mem) == B_OK) { + *peak_rss += mem.ram_size; + } +#elif defined(__APPLE__) && defined(__MACH__) + *peak_rss = rusage.ru_maxrss; // BSD reports in bytes + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) { + *current_rss = (size_t)info.resident_size; + } +#else + *peak_rss = rusage.ru_maxrss * 1024; // Linux reports in KiB +#endif +} + +#else +#ifndef __wasi__ +// WebAssembly instances are not processes +#pragma message("define a way to get process info") +#endif + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + *peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak)); + *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current)); + *peak_rss = *peak_commit; + *current_rss = *current_commit; + *page_faults = 0; + *utime = 0; + *stime = 0; +} +#endif + + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept +{ + mi_msecs_t elapsed = 0; + mi_msecs_t utime = 0; + mi_msecs_t stime = 0; + size_t current_rss0 = 0; + size_t peak_rss0 = 0; + size_t current_commit0 = 0; + size_t peak_commit0 = 0; + size_t page_faults0 = 0; + mi_stat_process_info(&elapsed,&utime, &stime, ¤t_rss0, &peak_rss0, ¤t_commit0, &peak_commit0, &page_faults0); + if (elapsed_msecs!=NULL) *elapsed_msecs = (elapsed < 0 ? 0 : (elapsed < (mi_msecs_t)PTRDIFF_MAX ? (size_t)elapsed : PTRDIFF_MAX)); + if (user_msecs!=NULL) *user_msecs = (utime < 0 ? 0 : (utime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)utime : PTRDIFF_MAX)); + if (system_msecs!=NULL) *system_msecs = (stime < 0 ? 0 : (stime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)stime : PTRDIFF_MAX)); + if (current_rss!=NULL) *current_rss = current_rss0; + if (peak_rss!=NULL) *peak_rss = peak_rss0; + if (current_commit!=NULL) *current_commit = current_commit0; + if (peak_commit!=NULL) *peak_commit = peak_commit0; + if (page_faults!=NULL) *page_faults = page_faults0; +} + diff --git a/deps/mimalloc/test/CMakeLists.txt b/deps/mimalloc/test/CMakeLists.txt new file mode 100644 index 000000000..4152f99d0 --- /dev/null +++ b/deps/mimalloc/test/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.0) +project(mimalloc-test C CXX) + +# Set default build type +if (NOT CMAKE_BUILD_TYPE) + if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$") + message(STATUS "No build type selected, default to *** Debug ***") + set(CMAKE_BUILD_TYPE "Debug") + else() + message(STATUS "No build type selected, default to *** Release ***") + set(CMAKE_BUILD_TYPE "Release") + endif() +endif() + +# Import mimalloc (if installed) +find_package(mimalloc 1.6 REQUIRED NO_SYSTEM_ENVIRONMENT_PATH) +message(STATUS "Found mimalloc installed at: ${MIMALLOC_TARGET_DIR}") + +# overriding with a dynamic library +add_executable(dynamic-override main-override.c) +target_link_libraries(dynamic-override PUBLIC mimalloc) + +add_executable(dynamic-override-cxx main-override.cpp) +target_link_libraries(dynamic-override-cxx PUBLIC mimalloc) + + +# overriding with a static object file works reliable as the symbols in the +# object file have priority over those in library files +add_executable(static-override-obj main-override.c ${MIMALLOC_TARGET_DIR}/mimalloc.o) +target_include_directories(static-override-obj PUBLIC ${MIMALLOC_TARGET_DIR}/include) +target_link_libraries(static-override-obj PUBLIC pthread) + + +# overriding with a static library works too if using the `mimalloc-override.h` +# header to redefine malloc/free. (the library already overrides new/delete) +add_executable(static-override-static main-override-static.c) +target_link_libraries(static-override-static PUBLIC mimalloc-static) + + +# overriding with a static library: this may not work if the library is linked too late +# on the command line after the C runtime library; but we cannot control that well in CMake +add_executable(static-override main-override.c) +target_link_libraries(static-override PUBLIC mimalloc-static) + +add_executable(static-override-cxx main-override.cpp) +target_link_libraries(static-override-cxx PUBLIC mimalloc-static) diff --git a/deps/mimalloc/test/main-override-static.c b/deps/mimalloc/test/main-override-static.c new file mode 100644 index 000000000..1efc01d37 --- /dev/null +++ b/deps/mimalloc/test/main-override-static.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include + +#include +#include // redefines malloc etc. + +static void double_free1(); +static void double_free2(); +static void corrupt_free(); +static void block_overflow1(); +static void invalid_free(); +static void test_aslr(void); +static void test_process_info(void); + +int main() { + mi_version(); + + // detect double frees and heap corruption + // double_free1(); + // double_free2(); + // corrupt_free(); + // block_overflow1(); + // test_aslr(); + invalid_free(); + + void* p1 = malloc(78); + void* p2 = malloc(24); + free(p1); + p1 = mi_malloc(8); + //char* s = strdup("hello\n"); + free(p2); + p2 = malloc(16); + p1 = realloc(p1, 32); + free(p1); + free(p2); + //free(s); + //mi_collect(true); + + /* now test if override worked by allocating/freeing across the api's*/ + //p1 = mi_malloc(32); + //free(p1); + //p2 = malloc(32); + //mi_free(p2); + mi_stats_print(NULL); + test_process_info(); + return 0; +} + +static void invalid_free() { + free((void*)0xBADBEEF); + realloc((void*)0xBADBEEF,10); +} + +static void block_overflow1() { + uint8_t* p = (uint8_t*)mi_malloc(17); + p[18] = 0; + free(p); +} + +// The double free samples come ArcHeap [1] by Insu Yun (issue #161) +// [1]: https://arxiv.org/pdf/1903.00503.pdf + +static void double_free1() { + void* p[256]; + //uintptr_t buf[256]; + + p[0] = mi_malloc(622616); + p[1] = mi_malloc(655362); + p[2] = mi_malloc(786432); + mi_free(p[2]); + // [VULN] Double free + mi_free(p[2]); + p[3] = mi_malloc(786456); + // [BUG] Found overlap + // p[3]=0x429b2ea2000 (size=917504), p[1]=0x429b2e42000 (size=786432) + fprintf(stderr, "p3: %p-%p, p1: %p-%p, p2: %p\n", p[3], (uint8_t*)(p[3]) + 786456, p[1], (uint8_t*)(p[1]) + 655362, p[2]); +} + +static void double_free2() { + void* p[256]; + //uintptr_t buf[256]; + // [INFO] Command buffer: 0x327b2000 + // [INFO] Input size: 182 + p[0] = malloc(712352); + p[1] = malloc(786432); + free(p[0]); + // [VULN] Double free + free(p[0]); + p[2] = malloc(786440); + p[3] = malloc(917504); + p[4] = malloc(786440); + // [BUG] Found overlap + // p[4]=0x433f1402000 (size=917504), p[1]=0x433f14c2000 (size=786432) + fprintf(stderr, "p1: %p-%p, p2: %p-%p\n", p[4], (uint8_t*)(p[4]) + 917504, p[1], (uint8_t*)(p[1]) + 786432); +} + + +// Try to corrupt the heap through buffer overflow +#define N 256 +#define SZ 64 + +static void corrupt_free() { + void* p[N]; + // allocate + for (int i = 0; i < N; i++) { + p[i] = malloc(SZ); + } + // free some + for (int i = 0; i < N; i += (N/10)) { + free(p[i]); + p[i] = NULL; + } + // try to corrupt the free list + for (int i = 0; i < N; i++) { + if (p[i] != NULL) { + memset(p[i], 0, SZ+8); + } + } + // allocate more.. trying to trigger an allocation from a corrupted entry + // this may need many allocations to get there (if at all) + for (int i = 0; i < 4096; i++) { + malloc(SZ); + } +} + +static void test_aslr(void) { + void* p[256]; + p[0] = malloc(378200); + p[1] = malloc(1134626); + printf("p1: %p, p2: %p\n", p[0], p[1]); +} + +static void test_process_info(void) { + size_t elapsed = 0; + size_t user_msecs = 0; + size_t system_msecs = 0; + size_t current_rss = 0; + size_t peak_rss = 0; + size_t current_commit = 0; + size_t peak_commit = 0; + size_t page_faults = 0; + for (int i = 0; i < 100000; i++) { + void* p = calloc(100,10); + free(p); + } + mi_process_info(&elapsed, &user_msecs, &system_msecs, ¤t_rss, &peak_rss, ¤t_commit, &peak_commit, &page_faults); + printf("\n\n*** process info: elapsed %3zd.%03zd s, user: %3zd.%03zd s, rss: %zd b, commit: %zd b\n\n", elapsed/1000, elapsed%1000, user_msecs/1000, user_msecs%1000, peak_rss, peak_commit); +} + +static void test_reserved(void) { +#define KiB 1024ULL +#define MiB (KiB*KiB) +#define GiB (MiB*KiB) + mi_reserve_os_memory(4*GiB, false, true); + void* p1 = malloc(100); + void* p2 = malloc(100000); + void* p3 = malloc(2*GiB); + void* p4 = malloc(1*GiB + 100000); + free(p1); + free(p2); + free(p3); + p3 = malloc(1*GiB); + free(p4); +} + diff --git a/deps/mimalloc/test/main-override.c b/deps/mimalloc/test/main-override.c new file mode 100644 index 000000000..1bec11797 --- /dev/null +++ b/deps/mimalloc/test/main-override.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include + +int main() { + mi_version(); // ensure mimalloc library is linked + void* p1 = malloc(78); + void* p2 = malloc(24); + free(p1); + p1 = malloc(8); + //char* s = strdup("hello\n"); + free(p2); + p2 = malloc(16); + p1 = realloc(p1, 32); + free(p1); + free(p2); + //free(s); + //mi_collect(true); + + /* now test if override worked by allocating/freeing across the api's*/ + //p1 = mi_malloc(32); + //free(p1); + //p2 = malloc(32); + //mi_free(p2); + mi_stats_print(NULL); + return 0; +} diff --git a/deps/mimalloc/test/main-override.cpp b/deps/mimalloc/test/main-override.cpp new file mode 100644 index 000000000..fe5403d10 --- /dev/null +++ b/deps/mimalloc/test/main-override.cpp @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +#include +static void msleep(unsigned long msecs) { Sleep(msecs); } +#else +#include +static void msleep(unsigned long msecs) { usleep(msecs * 1000UL); } +#endif + +void heap_thread_free_large(); // issue #221 +void heap_no_delete(); // issue #202 +void heap_late_free(); // issue #204 +void padding_shrink(); // issue #209 +void various_tests(); +void test_mt_shutdown(); + +int main() { + mi_stats_reset(); // ignore earlier allocations + heap_thread_free_large(); + heap_no_delete(); + heap_late_free(); + padding_shrink(); + various_tests(); + //test_mt_shutdown(); + mi_stats_print(NULL); + return 0; +} + +static void* p = malloc(8); + +void free_p() { + free(p); + return; +} + +class Test { +private: + int i; +public: + Test(int x) { i = x; } + ~Test() { } +}; + + +void various_tests() { + atexit(free_p); + void* p1 = malloc(78); + void* p2 = mi_malloc_aligned(16, 24); + free(p1); + p1 = malloc(8); + char* s = mi_strdup("hello\n"); + + //char* s = _strdup("hello\n"); + //char* buf = NULL; + //size_t len; + //_dupenv_s(&buf,&len,"MIMALLOC_VERBOSE"); + //mi_free(buf); + + mi_free(p2); + p2 = malloc(16); + p1 = realloc(p1, 32); + free(p1); + free(p2); + mi_free(s); + Test* t = new Test(42); + delete t; + t = new (std::nothrow) Test(42); + delete t; +} + +class Static { +private: + void* p; +public: + Static() { + p = malloc(64); + return; + } + ~Static() { + free(p); + return; + } +}; + +static Static s = Static(); + + +bool test_stl_allocator1() { + std::vector > vec; + vec.push_back(1); + vec.pop_back(); + return vec.size() == 0; +} + +struct some_struct { int i; int j; double z; }; + +bool test_stl_allocator2() { + std::vector > vec; + vec.push_back(some_struct()); + vec.pop_back(); + return vec.size() == 0; +} + + + +// Issue #202 +void heap_no_delete_worker() { + mi_heap_t* heap = mi_heap_new(); + void* q = mi_heap_malloc(heap, 1024); + // mi_heap_delete(heap); // uncomment to prevent assertion +} + +void heap_no_delete() { + auto t1 = std::thread(heap_no_delete_worker); + t1.join(); +} + + +// Issue #204 +volatile void* global_p; + +void t1main() { + mi_heap_t* heap = mi_heap_new(); + global_p = mi_heap_malloc(heap, 1024); + mi_heap_delete(heap); +} + +void heap_late_free() { + auto t1 = std::thread(t1main); + + msleep(2000); + assert(global_p); + mi_free((void*)global_p); + + t1.join(); +} + +// issue #209 +static void* shared_p; +static void alloc0(/* void* arg */) +{ + shared_p = mi_malloc(8); +} + +void padding_shrink(void) +{ + auto t1 = std::thread(alloc0); + t1.join(); + mi_free(shared_p); +} + + +// Issue #221 +void heap_thread_free_large_worker() { + mi_free(shared_p); +} + +void heap_thread_free_large() { + for (int i = 0; i < 100; i++) { + shared_p = mi_malloc_aligned(2*1024*1024 + 1, 8); + auto t1 = std::thread(heap_thread_free_large_worker); + t1.join(); + } +} + + + +void test_mt_shutdown() +{ + const int threads = 5; + std::vector< std::future< std::vector< char* > > > ts; + + auto fn = [&]() + { + std::vector< char* > ps; + ps.reserve(1000); + for (int i = 0; i < 1000; i++) + ps.emplace_back(new char[1]); + return ps; + }; + + for (int i = 0; i < threads; i++) + ts.emplace_back(std::async(std::launch::async, fn)); + + for (auto& f : ts) + for (auto& p : f.get()) + delete[] p; + + std::cout << "done" << std::endl; +} diff --git a/deps/mimalloc/test/main.c b/deps/mimalloc/test/main.c new file mode 100644 index 000000000..b148f7124 --- /dev/null +++ b/deps/mimalloc/test/main.c @@ -0,0 +1,46 @@ +#include +#include +#include + +void test_heap(void* p_out) { + mi_heap_t* heap = mi_heap_new(); + void* p1 = mi_heap_malloc(heap,32); + void* p2 = mi_heap_malloc(heap,48); + mi_free(p_out); + mi_heap_destroy(heap); + //mi_heap_delete(heap); mi_free(p1); mi_free(p2); +} + +void test_large() { + const size_t N = 1000; + + for (size_t i = 0; i < N; ++i) { + size_t sz = 1ull << 21; + char* a = mi_mallocn_tp(char,sz); + for (size_t k = 0; k < sz; k++) { a[k] = 'x'; } + mi_free(a); + } +} + +int main() { + void* p1 = mi_malloc(16); + void* p2 = mi_malloc(1000000); + mi_free(p1); + mi_free(p2); + p1 = mi_malloc(16); + p2 = mi_malloc(16); + mi_free(p1); + mi_free(p2); + + test_heap(mi_malloc(32)); + + p1 = mi_malloc_aligned(64, 16); + p2 = mi_malloc_aligned(160,24); + mi_free(p2); + mi_free(p1); + //test_large(); + + mi_collect(true); + mi_stats_print(NULL); + return 0; +} diff --git a/deps/mimalloc/test/readme.md b/deps/mimalloc/test/readme.md new file mode 100644 index 000000000..db3524cd4 --- /dev/null +++ b/deps/mimalloc/test/readme.md @@ -0,0 +1,16 @@ +Testing allocators is difficult as bugs may only surface after particular +allocation patterns. The main approach to testing _mimalloc_ is therefore +to have extensive internal invariant checking (see `page_is_valid` in `page.c` +for example), which is enabled in debug mode with `-DMI_DEBUG_FULL=ON`. +The main testing strategy is then to run [`mimalloc-bench`][bench] using full +invariant checking to catch any potential problems over a wide range of intensive +allocation benchmarks and programs. + +However, this does not test well for the entire API surface and this is tested +with `test-api.c` when using `make test` (from `out/debug` etc). (This is +not complete yet, please add to it.) + +The `main.c` and `main-override.c` are there to test if building and overriding +from a local install works and therefore these build a separate `test/CMakeLists.txt`. + +[bench]: https://github.com/daanx/mimalloc-bench diff --git a/deps/mimalloc/test/test-api.c b/deps/mimalloc/test/test-api.c new file mode 100644 index 000000000..e5827a93e --- /dev/null +++ b/deps/mimalloc/test/test-api.c @@ -0,0 +1,249 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* +Testing allocators is difficult as bugs may only surface after particular +allocation patterns. The main approach to testing _mimalloc_ is therefore +to have extensive internal invariant checking (see `page_is_valid` in `page.c` +for example), which is enabled in debug mode with `-DMI_DEBUG_FULL=ON`. +The main testing is then to run `mimalloc-bench` [1] using full invariant checking +to catch any potential problems over a wide range of intensive allocation bench +marks. + +However, this does not test well for the entire API surface. In this test file +we therefore test the API over various inputs. Please add more tests :-) + +[1] https://github.com/daanx/mimalloc-bench +*/ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +#include +#endif + +#include "mimalloc.h" +// #include "mimalloc-internal.h" + +// --------------------------------------------------------------------------- +// Test macros: CHECK(name,predicate) and CHECK_BODY(name,body) +// --------------------------------------------------------------------------- +static int ok = 0; +static int failed = 0; + +#define CHECK_BODY(name,body) \ + do { \ + fprintf(stderr,"test: %s... ", name ); \ + bool result = true; \ + do { body } while(false); \ + if (!(result)) { \ + failed++; \ + fprintf(stderr, \ + "\n FAILED: %s:%d:\n %s\n", \ + __FILE__, \ + __LINE__, \ + #body); \ + /* exit(1); */ \ + } \ + else { \ + ok++; \ + fprintf(stderr,"ok.\n"); \ + } \ + } while (false) + +#define CHECK(name,expr) CHECK_BODY(name,{ result = (expr); }) + +// --------------------------------------------------------------------------- +// Test functions +// --------------------------------------------------------------------------- +bool test_heap1(); +bool test_heap2(); +bool test_stl_allocator1(); +bool test_stl_allocator2(); + +// --------------------------------------------------------------------------- +// Main testing +// --------------------------------------------------------------------------- +int main() { + mi_option_disable(mi_option_verbose); + + // --------------------------------------------------- + // Malloc + // --------------------------------------------------- + + CHECK_BODY("malloc-zero",{ + void* p = mi_malloc(0); mi_free(p); + }); + CHECK_BODY("malloc-nomem1",{ + result = (mi_malloc(SIZE_MAX/2) == NULL); + }); + CHECK_BODY("malloc-null",{ + mi_free(NULL); + }); + CHECK_BODY("calloc-overflow",{ + // use (size_t)&mi_calloc to get some number without triggering compiler warnings + result = (mi_calloc((size_t)&mi_calloc,SIZE_MAX/1000) == NULL); + }); + CHECK_BODY("calloc0",{ + result = (mi_usable_size(mi_calloc(0,1000)) <= 16); + }); + + // --------------------------------------------------- + // Extended + // --------------------------------------------------- + CHECK_BODY("posix_memalign1", { + void* p = &p; + int err = mi_posix_memalign(&p, sizeof(void*), 32); + result = ((err==0 && (uintptr_t)p % sizeof(void*) == 0) || p==&p); + mi_free(p); + }); + CHECK_BODY("posix_memalign_no_align", { + void* p = &p; + int err = mi_posix_memalign(&p, 3, 32); + result = (err==EINVAL && p==&p); + }); + CHECK_BODY("posix_memalign_zero", { + void* p = &p; + int err = mi_posix_memalign(&p, sizeof(void*), 0); + mi_free(p); + result = (err==0); + }); + CHECK_BODY("posix_memalign_nopow2", { + void* p = &p; + int err = mi_posix_memalign(&p, 3*sizeof(void*), 32); + result = (err==EINVAL && p==&p); + }); + CHECK_BODY("posix_memalign_nomem", { + void* p = &p; + int err = mi_posix_memalign(&p, sizeof(void*), SIZE_MAX); + result = (err==ENOMEM && p==&p); + }); + + // --------------------------------------------------- + // Aligned API + // --------------------------------------------------- + CHECK_BODY("malloc-aligned1", { + void* p = mi_malloc_aligned(32,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p); + }); + CHECK_BODY("malloc-aligned2", { + void* p = mi_malloc_aligned(48,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p); + }); + CHECK_BODY("malloc-aligned3", { + void* p1 = mi_malloc_aligned(48,32); bool result1 = (p1 != NULL && (uintptr_t)(p1) % 32 == 0); + void* p2 = mi_malloc_aligned(48,32); bool result2 = (p2 != NULL && (uintptr_t)(p2) % 32 == 0); + mi_free(p2); + mi_free(p1); + result = (result1&&result2); + }); + CHECK_BODY("malloc-aligned4", { + void* p; + bool ok = true; + for (int i = 0; i < 8 && ok; i++) { + p = mi_malloc_aligned(8, 16); + ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p); + } + result = ok; + }); + CHECK_BODY("malloc-aligned5", { + void* p = mi_malloc_aligned(4097,4096); size_t usable = mi_usable_size(p); result = usable >= 4097 && usable < 10000; mi_free(p); + }); + CHECK_BODY("malloc-aligned-at1", { + void* p = mi_malloc_aligned_at(48,32,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 32 == 0); mi_free(p); + }); + CHECK_BODY("malloc-aligned-at2", { + void* p = mi_malloc_aligned_at(50,32,8); result = (p != NULL && ((uintptr_t)(p) + 8) % 32 == 0); mi_free(p); + }); + CHECK_BODY("memalign1", { + void* p; + bool ok = true; + for (int i = 0; i < 8 && ok; i++) { + p = mi_memalign(16,8); + ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p); + } + result = ok; + }); + + // --------------------------------------------------- + // Heaps + // --------------------------------------------------- + CHECK("heap_destroy", test_heap1()); + CHECK("heap_delete", test_heap2()); + + //mi_stats_print(NULL); + + // --------------------------------------------------- + // various + // --------------------------------------------------- + CHECK_BODY("realpath", { + char* s = mi_realpath( ".", NULL ); + // printf("realpath: %s\n",s); + mi_free(s); + }); + + CHECK("stl_allocator1", test_stl_allocator1()); + CHECK("stl_allocator2", test_stl_allocator2()); + + // --------------------------------------------------- + // Done + // ---------------------------------------------------[] + fprintf(stderr,"\n\n---------------------------------------------\n" + "succeeded: %i\n" + "failed : %i\n\n", ok, failed); + return failed; +} + +// --------------------------------------------------- +// Larger test functions +// --------------------------------------------------- + +bool test_heap1() { + mi_heap_t* heap = mi_heap_new(); + int* p1 = mi_heap_malloc_tp(heap,int); + int* p2 = mi_heap_malloc_tp(heap,int); + *p1 = *p2 = 43; + mi_heap_destroy(heap); + return true; +} + +bool test_heap2() { + mi_heap_t* heap = mi_heap_new(); + int* p1 = mi_heap_malloc_tp(heap,int); + int* p2 = mi_heap_malloc_tp(heap,int); + mi_heap_delete(heap); + *p1 = 42; + mi_free(p1); + mi_free(p2); + return true; +} + +bool test_stl_allocator1() { +#ifdef __cplusplus + std::vector > vec; + vec.push_back(1); + vec.pop_back(); + return vec.size() == 0; +#else + return true; +#endif +} + +struct some_struct { int i; int j; double z; }; + +bool test_stl_allocator2() { +#ifdef __cplusplus + std::vector > vec; + vec.push_back(some_struct()); + vec.pop_back(); + return vec.size() == 0; +#else + return true; +#endif +} diff --git a/deps/mimalloc/test/test-stress.c b/deps/mimalloc/test/test-stress.c new file mode 100644 index 000000000..05dbd4b44 --- /dev/null +++ b/deps/mimalloc/test/test-stress.c @@ -0,0 +1,329 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. +-----------------------------------------------------------------------------*/ + +/* This is a stress test for the allocator, using multiple threads and + transferring objects between threads. It tries to reflect real-world workloads: + - allocation size is distributed linearly in powers of two + - with some fraction extra large (and some extra extra large) + - the allocations are initialized and read again at free + - pointers transfer between threads + - threads are terminated and recreated with some objects surviving in between + - uses deterministic "randomness", but execution can still depend on + (random) thread scheduling. Do not use this test as a benchmark! +*/ + +#include +#include +#include +#include +#include +#include + +// > mimalloc-test-stress [THREADS] [SCALE] [ITER] +// +// argument defaults +static int THREADS = 32; // more repeatable if THREADS <= #processors +static int SCALE = 10; // scaling factor +static int ITER = 50; // N full iterations destructing and re-creating all threads + +// static int THREADS = 8; // more repeatable if THREADS <= #processors +// static int SCALE = 100; // scaling factor + +#define STRESS // undefine for leak test + +static bool allow_large_objects = true; // allow very large objects? +static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`? + + +#ifdef USE_STD_MALLOC +#define custom_calloc(n,s) calloc(n,s) +#define custom_realloc(p,s) realloc(p,s) +#define custom_free(p) free(p) +#else +#define custom_calloc(n,s) mi_calloc(n,s) +#define custom_realloc(p,s) mi_realloc(p,s) +#define custom_free(p) mi_free(p) +#endif + +// transfer pointer between threads +#define TRANSFERS (1000) +static volatile void* transfer[TRANSFERS]; + + +#if (UINTPTR_MAX != UINT32_MAX) +const uintptr_t cookie = 0xbf58476d1ce4e5b9UL; +#else +const uintptr_t cookie = 0x1ce4e5b9UL; +#endif + +static void* atomic_exchange_ptr(volatile void** p, void* newval); + +typedef uintptr_t* random_t; + +static uintptr_t pick(random_t r) { + uintptr_t x = *r; +#if (UINTPTR_MAX > UINT32_MAX) + // by Sebastiano Vigna, see: + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9UL; + x ^= x >> 27; + x *= 0x94d049bb133111ebUL; + x ^= x >> 31; +#else + // by Chris Wellons, see: + x ^= x >> 16; + x *= 0x7feb352dUL; + x ^= x >> 15; + x *= 0x846ca68bUL; + x ^= x >> 16; +#endif + *r = x; + return x; +} + +static bool chance(size_t perc, random_t r) { + return (pick(r) % 100 <= perc); +} + +static void* alloc_items(size_t items, random_t r) { + if (chance(1, r)) { + if (chance(1, r) && allow_large_objects) items *= 10000; // 0.01% giant + else if (chance(10, r) && allow_large_objects) items *= 1000; // 0.1% huge + else items *= 100; // 1% large objects; + } + if (items == 40) items++; // pthreads uses that size for stack increases + if (use_one_size > 0) items = (use_one_size / sizeof(uintptr_t)); + if (items==0) items = 1; + uintptr_t* p = (uintptr_t*)custom_calloc(items,sizeof(uintptr_t)); + if (p != NULL) { + for (uintptr_t i = 0; i < items; i++) { + p[i] = (items - i) ^ cookie; + } + } + return p; +} + +static void free_items(void* p) { + if (p != NULL) { + uintptr_t* q = (uintptr_t*)p; + uintptr_t items = (q[0] ^ cookie); + for (uintptr_t i = 0; i < items; i++) { + if ((q[i] ^ cookie) != items - i) { + fprintf(stderr, "memory corruption at block %p at %zu\n", p, i); + abort(); + } + } + } + custom_free(p); +} + + +static void stress(intptr_t tid) { + //bench_start_thread(); + uintptr_t r = (tid * 43); // rand(); + const size_t max_item_shift = 5; // 128 + const size_t max_item_retained_shift = max_item_shift + 2; + size_t allocs = 100 * ((size_t)SCALE) * (tid % 8 + 1); // some threads do more + size_t retain = allocs / 2; + void** data = NULL; + size_t data_size = 0; + size_t data_top = 0; + void** retained = (void**)custom_calloc(retain,sizeof(void*)); + size_t retain_top = 0; + + while (allocs > 0 || retain > 0) { + if (retain == 0 || (chance(50, &r) && allocs > 0)) { + // 50%+ alloc + allocs--; + if (data_top >= data_size) { + data_size += 100000; + data = (void**)custom_realloc(data, data_size * sizeof(void*)); + } + data[data_top++] = alloc_items(1ULL << (pick(&r) % max_item_shift), &r); + } + else { + // 25% retain + retained[retain_top++] = alloc_items( 1ULL << (pick(&r) % max_item_retained_shift), &r); + retain--; + } + if (chance(66, &r) && data_top > 0) { + // 66% free previous alloc + size_t idx = pick(&r) % data_top; + free_items(data[idx]); + data[idx] = NULL; + } + if (chance(25, &r) && data_top > 0) { + // 25% exchange a local pointer with the (shared) transfer buffer. + size_t data_idx = pick(&r) % data_top; + size_t transfer_idx = pick(&r) % TRANSFERS; + void* p = data[data_idx]; + void* q = atomic_exchange_ptr(&transfer[transfer_idx], p); + data[data_idx] = q; + } + } + // free everything that is left + for (size_t i = 0; i < retain_top; i++) { + free_items(retained[i]); + } + for (size_t i = 0; i < data_top; i++) { + free_items(data[i]); + } + custom_free(retained); + custom_free(data); + //bench_end_thread(); +} + +static void run_os_threads(size_t nthreads, void (*entry)(intptr_t tid)); + +static void test_stress(void) { + uintptr_t r = rand(); + for (int n = 0; n < ITER; n++) { + run_os_threads(THREADS, &stress); + for (int i = 0; i < TRANSFERS; i++) { + if (chance(50, &r) || n + 1 == ITER) { // free all on last run, otherwise free half of the transfers + void* p = atomic_exchange_ptr(&transfer[i], NULL); + free_items(p); + } + } + // mi_collect(false); +#if !defined(NDEBUG) || defined(MI_TSAN) + if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); } +#endif + } +} + +#ifndef STRESS +static void leak(intptr_t tid) { + uintptr_t r = rand(); + void* p = alloc_items(1 /*pick(&r)%128*/, &r); + if (chance(50, &r)) { + intptr_t i = (pick(&r) % TRANSFERS); + void* q = atomic_exchange_ptr(&transfer[i], p); + free_items(q); + } +} + +static void test_leak(void) { + for (int n = 0; n < ITER; n++) { + run_os_threads(THREADS, &leak); + mi_collect(false); +#ifndef NDEBUG + if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); } +#endif + } +} +#endif + +int main(int argc, char** argv) { + // > mimalloc-test-stress [THREADS] [SCALE] [ITER] + if (argc >= 2) { + char* end; + long n = strtol(argv[1], &end, 10); + if (n > 0) THREADS = n; + } + if (argc >= 3) { + char* end; + long n = (strtol(argv[2], &end, 10)); + if (n > 0) SCALE = n; + } + if (argc >= 4) { + char* end; + long n = (strtol(argv[3], &end, 10)); + if (n > 0) ITER = n; + } + printf("Using %d threads with a %d%% load-per-thread and %d iterations\n", THREADS, SCALE, ITER); + //int res = mi_reserve_huge_os_pages(4,1); + //printf("(reserve huge: %i\n)", res); + + //bench_start_program(); + + // Run ITER full iterations where half the objects in the transfer buffer survive to the next round. + srand(0x7feb352d); + // mi_stats_reset(); +#ifdef STRESS + test_stress(); +#else + test_leak(); +#endif + + // mi_collect(true); + mi_stats_print(NULL); + //bench_end_program(); + return 0; +} + + +static void (*thread_entry_fun)(intptr_t) = &stress; + +#ifdef _WIN32 + +#include + +static DWORD WINAPI thread_entry(LPVOID param) { + thread_entry_fun((intptr_t)param); + return 0; +} + +static void run_os_threads(size_t nthreads, void (*fun)(intptr_t)) { + thread_entry_fun = fun; + DWORD* tids = (DWORD*)custom_calloc(nthreads,sizeof(DWORD)); + HANDLE* thandles = (HANDLE*)custom_calloc(nthreads,sizeof(HANDLE)); + for (uintptr_t i = 0; i < nthreads; i++) { + thandles[i] = CreateThread(0, 8*1024, &thread_entry, (void*)(i), 0, &tids[i]); + } + for (size_t i = 0; i < nthreads; i++) { + WaitForSingleObject(thandles[i], INFINITE); + } + for (size_t i = 0; i < nthreads; i++) { + CloseHandle(thandles[i]); + } + custom_free(tids); + custom_free(thandles); +} + +static void* atomic_exchange_ptr(volatile void** p, void* newval) { +#if (INTPTR_MAX == INT32_MAX) + return (void*)InterlockedExchange((volatile LONG*)p, (LONG)newval); +#else + return (void*)InterlockedExchange64((volatile LONG64*)p, (LONG64)newval); +#endif +} +#else + +#include + +static void* thread_entry(void* param) { + thread_entry_fun((uintptr_t)param); + return NULL; +} + +static void run_os_threads(size_t nthreads, void (*fun)(intptr_t)) { + thread_entry_fun = fun; + pthread_t* threads = (pthread_t*)custom_calloc(nthreads,sizeof(pthread_t)); + memset(threads, 0, sizeof(pthread_t) * nthreads); + //pthread_setconcurrency(nthreads); + for (uintptr_t i = 0; i < nthreads; i++) { + pthread_create(&threads[i], NULL, &thread_entry, (void*)i); + } + for (size_t i = 0; i < nthreads; i++) { + pthread_join(threads[i], NULL); + } + custom_free(threads); +} + +#ifdef __cplusplus +#include +static void* atomic_exchange_ptr(volatile void** p, void* newval) { + return std::atomic_exchange((volatile std::atomic*)p, newval); +} +#else +#include +static void* atomic_exchange_ptr(volatile void** p, void* newval) { + return atomic_exchange((volatile _Atomic(void*)*)p, newval); +} +#endif + +#endif diff --git a/src/Makefile b/src/Makefile index 9db3e6934..5783dc2b8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -101,6 +101,10 @@ ifeq ($(USE_JEMALLOC),no) MALLOC=libc endif +ifeq ($(USE_MIMALLOC),no) + MALLOC=mimalloc +endif + # Override default settings if possible -include .make-settings @@ -235,6 +239,13 @@ ifeq ($(MALLOC),memkind) FINAL_LIBS := ../deps/memkind/src/.libs/libmemkind.a -lnuma $(FINAL_LIBS) endif +ifeq ($(MIMALLOC),memkind) + DEPENDENCY_TARGETS+= memkind + FINAL_CFLAGS+= -DUSE_MEMKIND -I../deps/memkind/src/include + FINAL_CXXFLAGS+= -DUSE_MEMKIND -I../deps/memkind/src/include + FINAL_LIBS := ../deps/memkind/src/.libs/libmemkind.a -lnuma $(FINAL_LIBS) +endif + ifeq ($(BUILD_TLS),yes) FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CXXFLAGS) FINAL_CXXFLAGS+=-DUSE_OPENSSL $(OPENSSL_CXXFLAGS) From 6a29405a1ffd60bf41bd9cbb5c1596b60bd71434 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Wed, 7 Oct 2020 10:51:41 +0800 Subject: [PATCH 2/2] Added ability to use mimalloc Signed-off-by: Hanif Bin Ariffin --- deps/mimalloc/bin/CMakeCache.txt | 435 ++++++++++ .../CMakeCCompiler.cmake | 77 ++ .../CMakeCXXCompiler.cmake | 89 ++ .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 16544 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 16552 bytes .../3.18.20200806-g4daf76e/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 691 +++++++++++++++ .../3.18.20200806-g4daf76e/CompilerIdC/a.out | Bin 0 -> 16704 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 680 +++++++++++++++ .../CompilerIdCXX/a.out | Bin 0 -> 16712 bytes .../CMakeDirectoryInformation.cmake | 16 + .../mimalloc-1.6/cmake/mimalloc-release.cmake | 29 + .../lib/mimalloc-1.6/cmake/mimalloc.cmake | 101 +++ deps/mimalloc/bin/CMakeFiles/Makefile.cmake | 54 ++ deps/mimalloc/bin/CMakeFiles/Makefile2 | 241 ++++++ .../bin/CMakeFiles/TargetDirectories.txt | 12 + .../mimalloc/bin/CMakeFiles/cmake.check_cache | 1 + .../mimalloc-obj.dir/C.includecache | 356 ++++++++ .../mimalloc-obj.dir/DependInfo.cmake | 26 + .../CMakeFiles/mimalloc-obj.dir/build.make | 109 +++ .../mimalloc-obj.dir/cmake_clean.cmake | 8 + .../mimalloc-obj.dir/depend.internal | 26 + .../CMakeFiles/mimalloc-obj.dir/depend.make | 26 + .../CMakeFiles/mimalloc-obj.dir/flags.make | 10 + .../CMakeFiles/mimalloc-obj.dir/progress.make | 2 + .../mimalloc-static.dir/C.includecache | 310 +++++++ .../mimalloc-static.dir/DependInfo.cmake | 39 + .../CMakeFiles/mimalloc-static.dir/build.make | 298 +++++++ .../mimalloc-static.dir/cmake_clean.cmake | 22 + .../cmake_clean_target.cmake | 3 + .../mimalloc-static.dir/depend.internal | 85 ++ .../mimalloc-static.dir/depend.make | 85 ++ .../CMakeFiles/mimalloc-static.dir/flags.make | 10 + .../CMakeFiles/mimalloc-static.dir/link.txt | 2 + .../mimalloc-static.dir/progress.make | 15 + .../mimalloc-test-api.dir/C.includecache | 36 + .../mimalloc-test-api.dir/DependInfo.cmake | 22 + .../mimalloc-test-api.dir/build.make | 119 +++ .../mimalloc-test-api.dir/cmake_clean.cmake | 10 + .../mimalloc-test-api.dir/depend.internal | 6 + .../mimalloc-test-api.dir/depend.make | 6 + .../mimalloc-test-api.dir/flags.make | 10 + .../CMakeFiles/mimalloc-test-api.dir/link.txt | 1 + .../mimalloc-test-api.dir/progress.make | 3 + .../mimalloc-test-stress.dir/C.includecache | 42 + .../mimalloc-test-stress.dir/DependInfo.cmake | 22 + .../mimalloc-test-stress.dir/build.make | 119 +++ .../cmake_clean.cmake | 10 + .../mimalloc-test-stress.dir/depend.internal | 6 + .../mimalloc-test-stress.dir/depend.make | 6 + .../mimalloc-test-stress.dir/flags.make | 10 + .../mimalloc-test-stress.dir/link.txt | 1 + .../mimalloc-test-stress.dir/progress.make | 3 + .../CMakeFiles/mimalloc.dir/C.includecache | 310 +++++++ .../CMakeFiles/mimalloc.dir/DependInfo.cmake | 47 + .../bin/CMakeFiles/mimalloc.dir/build.make | 302 +++++++ .../CMakeFiles/mimalloc.dir/cmake_clean.cmake | 23 + .../CMakeFiles/mimalloc.dir/depend.internal | 85 ++ .../bin/CMakeFiles/mimalloc.dir/depend.make | 85 ++ .../bin/CMakeFiles/mimalloc.dir/flags.make | 10 + .../bin/CMakeFiles/mimalloc.dir/link.txt | 1 + .../bin/CMakeFiles/mimalloc.dir/progress.make | 15 + deps/mimalloc/bin/CMakeFiles/progress.marks | 1 + deps/mimalloc/bin/CTestTestfile.cmake | 10 + deps/mimalloc/bin/Makefile | 804 ++++++++++++++++++ deps/mimalloc/bin/cmake_install.cmake | 229 +++++ deps/mimalloc/bin/libmimalloc.a | Bin 0 -> 187350 bytes deps/mimalloc/bin/libmimalloc.so.1.6 | Bin 0 -> 143702 bytes deps/mimalloc/bin/mimalloc-test-api | Bin 0 -> 143799 bytes deps/mimalloc/bin/mimalloc-test-stress | Bin 0 -> 17616 bytes src/Makefile | 7 + src/zmalloc.cpp | 5 + src/zmalloc.h | 4 + 73 files changed, 6243 insertions(+) create mode 100644 deps/mimalloc/bin/CMakeCache.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCCompiler.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCXXCompiler.cmake create mode 100755 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_C.bin create mode 100755 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_CXX.bin create mode 100644 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeSystem.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdC/CMakeCCompilerId.c create mode 100755 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdC/a.out create mode 100644 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100755 deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdCXX/a.out create mode 100644 deps/mimalloc/bin/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/Makefile.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/Makefile2 create mode 100644 deps/mimalloc/bin/CMakeFiles/TargetDirectories.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/cmake.check_cache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/C.includecache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/DependInfo.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/build.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/cmake_clean.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.internal create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/flags.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/progress.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/C.includecache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/build.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean_target.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.internal create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/flags.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/link.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/progress.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/C.includecache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/build.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/cmake_clean.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.internal create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/flags.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/link.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/progress.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/C.includecache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/build.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/cmake_clean.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.internal create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/flags.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/link.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/progress.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/C.includecache create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/build.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/cmake_clean.cmake create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.internal create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/flags.make create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/link.txt create mode 100644 deps/mimalloc/bin/CMakeFiles/mimalloc.dir/progress.make create mode 100644 deps/mimalloc/bin/CMakeFiles/progress.marks create mode 100644 deps/mimalloc/bin/CTestTestfile.cmake create mode 100644 deps/mimalloc/bin/Makefile create mode 100644 deps/mimalloc/bin/cmake_install.cmake create mode 100644 deps/mimalloc/bin/libmimalloc.a create mode 100755 deps/mimalloc/bin/libmimalloc.so.1.6 create mode 100755 deps/mimalloc/bin/mimalloc-test-api create mode 100755 deps/mimalloc/bin/mimalloc-test-stress diff --git a/deps/mimalloc/bin/CMakeCache.txt b/deps/mimalloc/bin/CMakeCache.txt new file mode 100644 index 000000000..d8e6fedf5 --- /dev/null +++ b/deps/mimalloc/bin/CMakeCache.txt @@ -0,0 +1,435 @@ +# This is the CMakeCache file. +# For build in directory: /home/hbina/git/KeyDB/deps/mimalloc/bin +# It was generated by CMake: /usr/local/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=libmimalloc + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Path to a library. +LIBRT:FILEPATH=/usr/lib/x86_64-linux-gnu/librt.so + +//Build object library +MI_BUILD_OBJECT:BOOL=ON + +//Build shared library +MI_BUILD_SHARED:BOOL=ON + +//Build static library +MI_BUILD_STATIC:BOOL=ON + +//Build test executables +MI_BUILD_TESTS:BOOL=ON + +//Use full internal invariant checking in DEBUG mode (deprecated, +// use MI_DEBUG_FULL instead) +MI_CHECK_FULL:BOOL=OFF + +//Use full internal heap invariant checking in DEBUG mode (expensive) +MI_DEBUG_FULL:BOOL=OFF + +//Build with thread sanitizer (needs clang) +MI_DEBUG_TSAN:BOOL=OFF + +//Build with undefined-behavior sanitizer (needs clang++) +MI_DEBUG_UBSAN:BOOL=OFF + +//Use interpose to override standard malloc on macOS +MI_INTERPOSE:BOOL=ON + +//Use slightly slower, dlopen-compatible TLS mechanism (Unix) +MI_LOCAL_DYNAMIC_TLS:BOOL=OFF + +//Use malloc zone to override standard malloc on macOS +MI_OSX_ZONE:BOOL=OFF + +//Override the standard malloc interface (e.g. define entry points +// for malloc() etc) +MI_OVERRIDE:BOOL=ON + +//Enable padding to detect heap block overflow (used only in DEBUG +// mode) +MI_PADDING:BOOL=ON + +//Use full security mitigations (like guard pages, allocation randomization, +// double-free mitigation, and free-list corruption detection) +MI_SECURE:BOOL=OFF + +//Generate assembly files +MI_SEE_ASM:BOOL=OFF + +//Show error and warning messages by default (only enabled by default +// in DEBUG mode) +MI_SHOW_ERRORS:BOOL=OFF + +//Use the C++ compiler to compile the library (instead of the C +// compiler) +MI_USE_CXX:BOOL=OFF + +//Enable abort() call on memory allocation failure by default +MI_XMALLOC:BOOL=OFF + +//Value Computed by CMake +libmimalloc_BINARY_DIR:STATIC=/home/hbina/git/KeyDB/deps/mimalloc/bin + +//Value Computed by CMake +libmimalloc_SOURCE_DIR:STATIC=/home/hbina/git/KeyDB/deps/mimalloc + +//Dependencies for the target +mimalloc-static_LIB_DEPENDS:STATIC=general;pthread;general;/usr/lib/x86_64-linux-gnu/librt.so; + +//Dependencies for the target +mimalloc_LIB_DEPENDS:STATIC=general;pthread;general;/usr/lib/x86_64-linux-gnu/librt.so; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/hbina/git/KeyDB/deps/mimalloc/bin +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=18 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=20200806 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/local/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/local/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/local/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/hbina/git/KeyDB/deps/mimalloc +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/local/share/cmake-3.18 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCCompiler.cmake b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCCompiler.cmake new file mode 100644 index 000000000..8d055e410 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCCompiler.cmake @@ -0,0 +1,77 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "9.3.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCXXCompiler.cmake b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCXXCompiler.cmake new file mode 100644 index 000000000..7e6d7449c --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeCXXCompiler.cmake @@ -0,0 +1,89 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "9.3.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_C.bin b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..43681c87965b56a4cf0140a7576922e9f133ebfa GIT binary patch literal 16544 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

0Z+3<(jkqQE10K z1M3$ZkfW0rTqxK_tg=4u2QW_!Z<+OZ9m(_}v{?(8D?$gLhI<6o=k+GjyGWAz&vHy3 zg?8L?Fwg5!rW)xx`%kbKg$mv(>+?RSNJ)_WJMaGlwBtQ-JN&1j3Q^ww5n2o{^WTDs zRbL}LrfiPonP+<1q0j4PrYtv?{__s~5GgSIj$^=__Fi=8^E!$t?~mEPbN>F2^f~@Q zBT1t8d|8Xr|1Y2syU6;yu4lT{stk3f|5qIPLz+@xI;Gg+FONS1e}D?EN$IgK?h`nl z)+x_C(@UURWzpxq3ryDn2!-VoH^Vdj4m9B0WB2{bEUH}jy@gmOp zYl?`fu)dY@+_8!_ut9pT@i|6_`@`=)NVY8Y-KI|y_cn)d_RF%kJm-674C#&r#Z@{K H9IW^+FHn9F literal 0 HcmV?d00001 diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_CXX.bin b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..cdd77bdf6b3f48132f6b709a9441050afb8d4a1a GIT binary patch literal 16552 zcmeHOeQX>@6`%9j$)$1bE^Puwk~T}53J2@{3In%LAdAKSCaa=j zc6voRAWH2Oe+nu?QTT6#4of|vW<89}bfb`;ZnaWH#-%}0(nA*Ym@4F9I7E?jLi!_0 z@x++m5tQ+?Q$<**ble>+G|;bvISM(+|ZBTD}620b1Z z+5S$1hIyy-H{Uq;W&DZC@UnHOWPkI!zD8=E((g{-=PyT*Q@51dn7 z+j<$8nLtd2k&neP$z%I>_kZ;cW9nzCrVHM)f#_qudSu_xo5=?HL>VloPg8<;^no&X z{)g}WMxBy)v;nb2aQNV8i~RchXBM@;^5b(y51dK-B3-}viN)XhsXR97hp#?E`RBXz%lwXXKqgi%v| zSsVMg=OjOc@}^?|UoPMNO(4G24CR6Q3FkT(=ht88E}hw@mEO?C{y4p(Cpunt2$o*j z_!1u{ttY@zd3hdG{`$B!-ue_&wDG#5NLpr$<=}c7*1`3n@}zI|L3DglQjkw_`Az*u z)?U|2)7puPTeK51Zq0Q{J9FJw1_o}I20Z1-LEmcV7wKbv54K`6D}JO`8*8n>s#bc_ zsMn6PE&yg~ZMj^Yio?&Tx@+*%?b-{v7X7y#fJQXb3wou`pVvyo$(JHmv71LC=d~xb z@#QaiAv!;-_4{6!a7C^X`jQR3y7wfS3EvYPZ!N$RLikhNrB}ke-K8txo^a`EuQuKo z2Y6R>?KK>eDgAo6tev>#Hde2HO~xZyx*RQC>?r*yTweBjZS15=Yk9r+XB@BHd&7Ie zd&B#}`pLmT)wlXl>>nQ=97*)c$GI}HyxIA2BH%>8iGULUCjw3coCr7(a3bJDz=?np zf&Y^T;P)DH>E714eRBc6M`Z`~c+SZ0ZVK+jc8(?O z13ClrNuZwTav8t(T>|<%(BP$V`DLKTfd=G98T>Yi#r5D$<{I(4R@N`{JPvJ$uY%(^ z*up1u*0GR(@mT}ajd0`u=YZGW=?#3sxA+0iLAGVZ<`3Vw=2jF({XKB>ksN|h(53-L z3-pP9qlu>XV@Jl269UO+2sjaNBH%>8iNJq50<^D=_R-15vC3Y#dg>5=$YQY1Ta+oeAMXQ_r~P^>B~N?d zaK9)P+P8<#U0A67%Jp&<`Df*3J9+B ztd!S_6|ZMXReT9+s*2CKF}nV&I2cjPh^V_^$20A#H@CWBXY)u^`I{JB&sO#LSsD$gRKhWD!)+{bN;C+xi7 z__H?rgA%9vpRmH%N1+0Mod64GN+R&QO&3;_ypocER|@@dRz9n%{fDPz_`c*yq(Bxb97J#{DwjF4$jB z_X%==1LDG7+vbA@JIdz9VI{}s&QBF^v~SN3*v#>{^XgT=Yw*8;ZG3kCj{El~<^L=C z|8gJT3UzQysm^YZ}U)$$d_0I!x0aZJjykk!HWxqT~!+zWtL%S$-T?a$3ixBxns ze_+ptI4GZC`-P%7IWOX+bVn=k0G;s_hargN!;k%+6orcEu?g?O@q9?R!rqmYwe zLl;WcA@#CXVSA9iQG7-rC)672~-Z06{X3 z9?_&Ztz#!ZkgP$5yQ16M!cl#DXXma+kKPk*i$>5L&;EFKxgNHJkxH)%Jx>%`UlFBswru9IR7ZLn9Jm%HeOiYRRiMpWXq`-0GgQp_eR5q!6u-}y zORbrKdN&+qeOlKMRc!Kh{d=JOZ?Kl8{?qdV(H&A>F1su1cQPA;3O+lKKCKgp9>m~6 z!9HS@&YzwOl7QhUlRm8{iPG~4i0~rK5zFp}8a^wKKCL^6DpHdAPjW;bf_8lNAfDEz zL`mP?e`%JDLj_|>`iG?>q7zb({M*m}324W2qIUS_B8sH+94Jxli|RDDPMJN!R7Hs90#-D&!p@M5rdK{zY1>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) +# if (defined(_MSC_VER) && !defined(__clang__)) \ + || (defined(__ibmxl__) || defined(__IBMC__)) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdC/a.out b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdC/a.out new file mode 100755 index 0000000000000000000000000000000000000000..f6a7218120648759ee8a1adde4df323c4942a678 GIT binary patch literal 16704 zcmeHOZ)_Y#6`%9jiPJiFm(;;-($-6oN)FT)Cryl#*7VNyIeW-_t?d){ z$K35vyCM)sXnO=h5RoV!Kv9uEg7BeyXjLS@A+*p6P@|#{1c(SI7?h@NX^;!4kN0NZ zJMXT~MWTE_Xh+(6Gr#wD-^}jK?#_H7*56m-^9e3~@qU4=NXSAW%-GKr;E7JL9)52X zw}>?W*TNAYwwqq6u^3G2NzM-x^_sC#h2CPp;K3>!AyU*^t+Zl5P?!oj57ete2DRNZ zMsYG_e#M`H%1{*fTcMXw018vP9)_~eCfQ=4%Sj{TPbJEF*p#Obw&bBZtU`2-{4wQx zVovbrq@I`)JMx$ti37~?`8IHnE^ z4ht|dhZv<%_C+JLksoZj`uvIeql2m1hOwo?kNxngi`!me8|V{du%JE<32b8>eV~kW z{-1;zjb)%0jGt#Du*y#-;7S$VX23R9!G{1-s^E!L@EZZ&T18$!{t}q34xwp@XB zQF9`b%aW#MiB=Vq@mN{pT>2n`m_r^H#m%X8nB6-lcD_FOx==P)j77R`8NW;h>LV7P zac+lPxT08c%`QAoxZ=VeCA`&zf06J@_Xt^VEa3TYxopGvoRK$g!+C5XzF@=o8bf^1 zhRgdUf?n}5;AOzefR_O;16~Ha40sv%zsbPgg17xcJ$|KLJz4jwokFOeo-=F8FRI6X zRDWKcV|nir0KZhV7=+&k1iTXzwrrt0i^ zO_Hv2V5z(*4=Qh*QfIrKfr>g?_Z=kr7R^oIdJya2dR_T)u;my!K2H?nOHzLCr;zMe zQcDZ!xvTf6=NA2{?>Y6tlGz9bZYKlv<;&y27Kn@WG2UZcF<^`0dxzEIT{T!$OD~%Z z>dCG((3sy*E|=$%@bg^VtF5=;RJ{D-*mVq3J-O)xcv3$Z zyP`g>`d$n^C4%3d^Tn0RrZCcawk{XM}^dwO6%r$E}t3c$FHjd>iNXv2-TA*J#8dR_!Ky< z7t`j*u3e+Tx5a-Ke$T{jU*@ajavJCfpr?VJ28!P z-*e~ot;j~Z55O^hmE;hFf;LS!o(KIeAP@_L9;xYBzozCf@C{nWc$BJ3AsO$^F zgMHhs_M&X=-eCd%HWELqTy5r#vPt{lT?DUNx52O`+Anxrx)ZMzAFFDot}?!y@@p#N z%89QPJpP<`z2JUy;_C$WzZ1Vf@HlhgFly;~a^ej_sfw=`?N#wWWnYHVPEhdm>BPZ^ zVn?jHUu>wXySH=wup)fEs{Bor{R>X{#>#c>#Nn!}GA{k%U6t$7Dc=MyLhOiD_rq1* zUKQuN(6SC*f3@PZ@-kx8@P1Y!0%FRQPgrLm@iQ*`-GuY~(Xt}M`=A1&wh|Be!_o(b z58eXt{Z4}LgNyRfFW+w&pMi=`tjy=*fLDuuwe$Lxw6jtC0t0rHYIdHHGB>S=^98_t zco%i`*GnYN_jz{lCs|oJe%_RJR`&0cZ~`@A<@gT*z7g`%PX8|oA@P;t z zUzT{2aPI^72H=>7IofYvkfCRRhG4vPM%c1NCrCa*<8~*ppCXwsO4IXseMU2~W`0JD=k<)CC5xHN45-*z8c3QB(VhYQ!$waJy%>)tAv{g% zI}{y=X|cgx4R)tEb&^8sy?-z|5btqvg_(@0j{!CF7M>wiuqu z=cbIjIb(yyiYeF-mP!&7?T)vZ`h<|;lX_uNgp)H_aA8q1Z*e#dDMk$qczGkOqk;&_ zl!d3#rof-@L=GyZF%7>sL_snqdopZH(x9A7fAwv^>M(rs|y+?e%w{>M}Sp1oA=3j}rmwd)_D z`5@Enc4esZ{g~mnOP}YHOcfR+>ejyx@V~8-jgo>{2aiPpWoTPd;C64`ka5EkR;Kw z)MP?1H^mR2h9R>4SrTA+cSX{wxc&bOV7op)e=uEe>2v=x{7b0dT%I2TdA`c~eckfh zX8H%v4chd19>3TIAQYCfTFY(5Uj+t^J@#LjN5i^pEOXR>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdCXX/a.out b/deps/mimalloc/bin/CMakeFiles/3.18.20200806-g4daf76e/CompilerIdCXX/a.out new file mode 100755 index 0000000000000000000000000000000000000000..a177998297ce2cf112e26fd923a22b8c8a8fa211 GIT binary patch literal 16712 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 literal 0 HcmV?d00001 diff --git a/deps/mimalloc/bin/CMakeFiles/CMakeDirectoryInformation.cmake b/deps/mimalloc/bin/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 000000000..ec9829634 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/hbina/git/KeyDB/deps/mimalloc") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/hbina/git/KeyDB/deps/mimalloc/bin") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake b/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake new file mode 100644 index 000000000..a80eb8c91 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake @@ -0,0 +1,29 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "mimalloc" for configuration "Release" +set_property(TARGET mimalloc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(mimalloc PROPERTIES + IMPORTED_LOCATION_RELEASE "/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6" + IMPORTED_SONAME_RELEASE "libmimalloc.so.1.6" + ) + +list(APPEND _IMPORT_CHECK_TARGETS mimalloc ) +list(APPEND _IMPORT_CHECK_FILES_FOR_mimalloc "/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6" ) + +# Import target "mimalloc-static" for configuration "Release" +set_property(TARGET mimalloc-static APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(mimalloc-static PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "/usr/local/lib/mimalloc-1.6/libmimalloc.a" + ) + +list(APPEND _IMPORT_CHECK_TARGETS mimalloc-static ) +list(APPEND _IMPORT_CHECK_FILES_FOR_mimalloc-static "/usr/local/lib/mimalloc-1.6/libmimalloc.a" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake b/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake new file mode 100644 index 000000000..94fd29e4d --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake @@ -0,0 +1,101 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6...3.17) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget mimalloc mimalloc-static) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + unset(_targetsDefined) + unset(_targetsNotDefined) + unset(_expectedTargets) + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + + +# The installation prefix configured by this project. +set(_IMPORT_PREFIX "/usr/local") + +# Create imported target mimalloc +add_library(mimalloc SHARED IMPORTED) + +set_target_properties(mimalloc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "/usr/local/lib/mimalloc-1.6/include" + INTERFACE_LINK_LIBRARIES "pthread;/usr/lib/x86_64-linux-gnu/librt.so" +) + +# Create imported target mimalloc-static +add_library(mimalloc-static STATIC IMPORTED) + +set_target_properties(mimalloc-static PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "/usr/local/lib/mimalloc-1.6/include" + INTERFACE_LINK_LIBRARIES "pthread;/usr/lib/x86_64-linux-gnu/librt.so" +) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Load information for each installed configuration. +get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(GLOB CONFIG_FILES "${_DIR}/mimalloc-*.cmake") +foreach(f ${CONFIG_FILES}) + include(${f}) +endforeach() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/deps/mimalloc/bin/CMakeFiles/Makefile.cmake b/deps/mimalloc/bin/CMakeFiles/Makefile.cmake new file mode 100644 index 000000000..753775d80 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/Makefile.cmake @@ -0,0 +1,54 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.18.20200806-g4daf76e/CMakeCCompiler.cmake" + "CMakeFiles/3.18.20200806-g4daf76e/CMakeCXXCompiler.cmake" + "CMakeFiles/3.18.20200806-g4daf76e/CMakeSystem.cmake" + "../cmake/mimalloc-config-version.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeCInformation.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeCXXInformation.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeGenericSystem.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeInitializeConfigs.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeLanguageInformation.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/local/share/cmake-3.18/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/local/share/cmake-3.18/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/local/share/cmake-3.18/Modules/Compiler/GNU-C.cmake" + "/usr/local/share/cmake-3.18/Modules/Compiler/GNU-CXX.cmake" + "/usr/local/share/cmake-3.18/Modules/Compiler/GNU.cmake" + "/usr/local/share/cmake-3.18/Modules/Internal/CMakeCheckCompilerFlag.cmake" + "/usr/local/share/cmake-3.18/Modules/Platform/Linux-GNU-C.cmake" + "/usr/local/share/cmake-3.18/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/local/share/cmake-3.18/Modules/Platform/Linux-GNU.cmake" + "/usr/local/share/cmake-3.18/Modules/Platform/Linux.cmake" + "/usr/local/share/cmake-3.18/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake" + "CMakeFiles/mimalloc-obj.dir/DependInfo.cmake" + "CMakeFiles/mimalloc-static.dir/DependInfo.cmake" + "CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake" + "CMakeFiles/mimalloc.dir/DependInfo.cmake" + ) diff --git a/deps/mimalloc/bin/CMakeFiles/Makefile2 b/deps/mimalloc/bin/CMakeFiles/Makefile2 new file mode 100644 index 000000000..b18e52eba --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/Makefile2 @@ -0,0 +1,241 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/mimalloc-test-stress.dir/all +all: CMakeFiles/mimalloc-obj.dir/all +all: CMakeFiles/mimalloc-static.dir/all +all: CMakeFiles/mimalloc-test-api.dir/all +all: CMakeFiles/mimalloc.dir/all + +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: + +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/mimalloc-test-stress.dir/clean +clean: CMakeFiles/mimalloc-obj.dir/clean +clean: CMakeFiles/mimalloc-static.dir/clean +clean: CMakeFiles/mimalloc-test-api.dir/clean +clean: CMakeFiles/mimalloc.dir/clean + +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/mimalloc-test-stress.dir + +# All Build rule for target. +CMakeFiles/mimalloc-test-stress.dir/all: CMakeFiles/mimalloc.dir/all + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=32,33 "Built target mimalloc-test-stress" +.PHONY : CMakeFiles/mimalloc-test-stress.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/mimalloc-test-stress.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 16 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/mimalloc-test-stress.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : CMakeFiles/mimalloc-test-stress.dir/rule + +# Convenience name for target. +mimalloc-test-stress: CMakeFiles/mimalloc-test-stress.dir/rule + +.PHONY : mimalloc-test-stress + +# clean rule for target. +CMakeFiles/mimalloc-test-stress.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/clean +.PHONY : CMakeFiles/mimalloc-test-stress.dir/clean + +#============================================================================= +# Target rules for target CMakeFiles/mimalloc-obj.dir + +# All Build rule for target. +CMakeFiles/mimalloc-obj.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=15 "Built target mimalloc-obj" +.PHONY : CMakeFiles/mimalloc-obj.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/mimalloc-obj.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 1 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/mimalloc-obj.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : CMakeFiles/mimalloc-obj.dir/rule + +# Convenience name for target. +mimalloc-obj: CMakeFiles/mimalloc-obj.dir/rule + +.PHONY : mimalloc-obj + +# clean rule for target. +CMakeFiles/mimalloc-obj.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/clean +.PHONY : CMakeFiles/mimalloc-obj.dir/clean + +#============================================================================= +# Target rules for target CMakeFiles/mimalloc-static.dir + +# All Build rule for target. +CMakeFiles/mimalloc-static.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=16,17,18,19,20,21,22,23,24,25,26,27,28,29 "Built target mimalloc-static" +.PHONY : CMakeFiles/mimalloc-static.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/mimalloc-static.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 14 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/mimalloc-static.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : CMakeFiles/mimalloc-static.dir/rule + +# Convenience name for target. +mimalloc-static: CMakeFiles/mimalloc-static.dir/rule + +.PHONY : mimalloc-static + +# clean rule for target. +CMakeFiles/mimalloc-static.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/clean +.PHONY : CMakeFiles/mimalloc-static.dir/clean + +#============================================================================= +# Target rules for target CMakeFiles/mimalloc-test-api.dir + +# All Build rule for target. +CMakeFiles/mimalloc-test-api.dir/all: CMakeFiles/mimalloc-static.dir/all + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=30,31 "Built target mimalloc-test-api" +.PHONY : CMakeFiles/mimalloc-test-api.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/mimalloc-test-api.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 16 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/mimalloc-test-api.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : CMakeFiles/mimalloc-test-api.dir/rule + +# Convenience name for target. +mimalloc-test-api: CMakeFiles/mimalloc-test-api.dir/rule + +.PHONY : mimalloc-test-api + +# clean rule for target. +CMakeFiles/mimalloc-test-api.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/clean +.PHONY : CMakeFiles/mimalloc-test-api.dir/clean + +#============================================================================= +# Target rules for target CMakeFiles/mimalloc.dir + +# All Build rule for target. +CMakeFiles/mimalloc.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=1,2,3,4,5,6,7,8,9,10,11,12,13,14 "Built target mimalloc" +.PHONY : CMakeFiles/mimalloc.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/mimalloc.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 14 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/mimalloc.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : CMakeFiles/mimalloc.dir/rule + +# Convenience name for target. +mimalloc: CMakeFiles/mimalloc.dir/rule + +.PHONY : mimalloc + +# clean rule for target. +CMakeFiles/mimalloc.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/clean +.PHONY : CMakeFiles/mimalloc.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/deps/mimalloc/bin/CMakeFiles/TargetDirectories.txt b/deps/mimalloc/bin/CMakeFiles/TargetDirectories.txt new file mode 100644 index 000000000..958ed8cc9 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,12 @@ +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/install/local.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/install.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/list_install_components.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/rebuild_cache.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/edit_cache.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/test.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/install/strip.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir +/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir diff --git a/deps/mimalloc/bin/CMakeFiles/cmake.check_cache b/deps/mimalloc/bin/CMakeFiles/cmake.check_cache new file mode 100644 index 000000000..3dccd7317 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/C.includecache b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/C.includecache new file mode 100644 index 000000000..4d2786751 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/C.includecache @@ -0,0 +1,356 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/mimalloc-atomic.h +atomic +- +stdatomic.h +- +Windows.h +- +intrin.h +- +thread +- +windows.h +- +sched.h +- +unistd.h +- + +../include/mimalloc-internal.h +mimalloc-types.h +../include/mimalloc-types.h +errno.h +- +limits.h +- +pthread.h +- +pthread.h +- +windows.h +- + +../include/mimalloc-types.h +stddef.h +- +stdint.h +- +mimalloc-atomic.h +- + +../include/mimalloc.h +stddef.h +- +stdbool.h +- +cstdint +- +type_traits +- +utility +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override-osx.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +AvailabilityMacros.h +- +malloc/malloc.h +- +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +errno.h +- +string.h +- +stdlib.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdlib.h +- +alloc-override.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +Windows.h +- +unistd.h +- +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +errno.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +intrin.h +- +limits.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/init.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +stdlib.h +- +Windows.h +- +fibersapi.h +- +pthread.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/options.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +stdlib.h +- +string.h +- +ctype.h +- +stdarg.h +- +conio.h +- +Windows.h +- +crt_externs.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/os.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +Windows.h +- +sys/mman.h +- +unistd.h +- +features.h +- +linux/mman.h +- +sys/mman.h +- +TargetConditionals.h +- +mach/vm_statistics.h +- +winternl.h +- +sys/syscall.h +- +sys/syscall.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c +intrin.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +page-queue.c +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/random.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +bcrypt.h +- +stdlib.h +- +sys/syscall.h +- +unistd.h +- +sys/types.h +- +sys/stat.h +- +fcntl.h +- +errno.h +- +Windows.h +- +mach/mach_time.h +- +time.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/region.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/static.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +stats.c +/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c +random.c +/home/hbina/git/KeyDB/deps/mimalloc/src/random.c +os.c +/home/hbina/git/KeyDB/deps/mimalloc/src/os.c +arena.c +/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c +region.c +/home/hbina/git/KeyDB/deps/mimalloc/src/region.c +segment.c +/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +page.c +/home/hbina/git/KeyDB/deps/mimalloc/src/page.c +heap.c +/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +alloc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +alloc-aligned.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +alloc-posix.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +alloc-override-osx.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override-osx.c +init.c +/home/hbina/git/KeyDB/deps/mimalloc/src/init.c +options.c +/home/hbina/git/KeyDB/deps/mimalloc/src/options.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +string.h +- +Windows.h +- +time.h +- +Windows.h +- +psapi.h +- +stdio.h +- +unistd.h +- +sys/resource.h +- +mach/mach.h +- +kernel/OS.h +- + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/DependInfo.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/DependInfo.cmake new file mode 100644 index 000000000..8f7cbe548 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/DependInfo.cmake @@ -0,0 +1,26 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/hbina/git/KeyDB/deps/mimalloc/src/static.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/src/static.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "MI_MALLOC_OVERRIDE" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/build.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/build.make new file mode 100644 index 000000000..538f3d656 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/build.make @@ -0,0 +1,109 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +# Include any dependencies generated for this target. +include CMakeFiles/mimalloc-obj.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/mimalloc-obj.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/mimalloc-obj.dir/flags.make + +CMakeFiles/mimalloc-obj.dir/src/static.c.o: CMakeFiles/mimalloc-obj.dir/flags.make +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/static.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/mimalloc-obj.dir/src/static.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-obj.dir/src/static.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/static.c + +CMakeFiles/mimalloc-obj.dir/src/static.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-obj.dir/src/static.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/static.c > CMakeFiles/mimalloc-obj.dir/src/static.c.i + +CMakeFiles/mimalloc-obj.dir/src/static.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-obj.dir/src/static.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/static.c -o CMakeFiles/mimalloc-obj.dir/src/static.c.s + +mimalloc-obj: CMakeFiles/mimalloc-obj.dir/src/static.c.o +mimalloc-obj: CMakeFiles/mimalloc-obj.dir/build.make + +.PHONY : mimalloc-obj + +# Rule to build all files generated by this target. +CMakeFiles/mimalloc-obj.dir/build: mimalloc-obj + +.PHONY : CMakeFiles/mimalloc-obj.dir/build + +CMakeFiles/mimalloc-obj.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc-obj.dir/cmake_clean.cmake +.PHONY : CMakeFiles/mimalloc-obj.dir/clean + +CMakeFiles/mimalloc-obj.dir/depend: + cd /home/hbina/git/KeyDB/deps/mimalloc/bin && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/mimalloc-obj.dir/depend + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/cmake_clean.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/cmake_clean.cmake new file mode 100644 index 000000000..a299a0564 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/cmake_clean.cmake @@ -0,0 +1,8 @@ +file(REMOVE_RECURSE + "CMakeFiles/mimalloc-obj.dir/src/static.c.o" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/mimalloc-obj.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.internal b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.internal new file mode 100644 index 000000000..d00eaa98b --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.internal @@ -0,0 +1,26 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-obj.dir/src/static.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override-osx.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c + /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c + /home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c + /home/hbina/git/KeyDB/deps/mimalloc/src/init.c + /home/hbina/git/KeyDB/deps/mimalloc/src/options.c + /home/hbina/git/KeyDB/deps/mimalloc/src/os.c + /home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + /home/hbina/git/KeyDB/deps/mimalloc/src/page.c + /home/hbina/git/KeyDB/deps/mimalloc/src/random.c + /home/hbina/git/KeyDB/deps/mimalloc/src/region.c + /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c + /home/hbina/git/KeyDB/deps/mimalloc/src/static.c + /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.make new file mode 100644 index 000000000..cc4ded3f8 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/depend.make @@ -0,0 +1,26 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/alloc-aligned.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/alloc-override-osx.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/alloc-override.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/alloc-posix.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/alloc.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/arena.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/bitmap.inc.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/heap.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/init.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/options.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/os.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/page-queue.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/page.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/random.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/region.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/segment.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/static.c +CMakeFiles/mimalloc-obj.dir/src/static.c.o: ../src/stats.c + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/flags.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/flags.make new file mode 100644 index 000000000..8a2ebbfed --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = -DMI_MALLOC_OVERRIDE + +C_INCLUDES = -I/home/hbina/git/KeyDB/deps/mimalloc/include + +C_FLAGS = -O3 -DNDEBUG -fPIC -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden -Wno-invalid-memory-model -ftls-model=initial-exec -std=gnu11 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/progress.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/progress.make new file mode 100644 index 000000000..6bdbd1465 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/progress.make @@ -0,0 +1,2 @@ +CMAKE_PROGRESS_1 = 15 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/C.includecache b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/C.includecache new file mode 100644 index 000000000..bfa9dc8a9 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/C.includecache @@ -0,0 +1,310 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/mimalloc-atomic.h +atomic +- +stdatomic.h +- +Windows.h +- +intrin.h +- +thread +- +windows.h +- +sched.h +- +unistd.h +- + +../include/mimalloc-internal.h +mimalloc-types.h +../include/mimalloc-types.h +errno.h +- +limits.h +- +pthread.h +- +pthread.h +- +windows.h +- + +../include/mimalloc-types.h +stddef.h +- +stdint.h +- +mimalloc-atomic.h +- + +../include/mimalloc.h +stddef.h +- +stdbool.h +- +cstdint +- +type_traits +- +utility +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +errno.h +- +string.h +- +stdlib.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdlib.h +- +alloc-override.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +Windows.h +- +unistd.h +- +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +errno.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +intrin.h +- +limits.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/init.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +stdlib.h +- +Windows.h +- +fibersapi.h +- +pthread.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/options.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +stdlib.h +- +string.h +- +ctype.h +- +stdarg.h +- +conio.h +- +Windows.h +- +crt_externs.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/os.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +Windows.h +- +sys/mman.h +- +unistd.h +- +features.h +- +linux/mman.h +- +sys/mman.h +- +TargetConditionals.h +- +mach/vm_statistics.h +- +winternl.h +- +sys/syscall.h +- +sys/syscall.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c +intrin.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +page-queue.c +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/random.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +bcrypt.h +- +stdlib.h +- +sys/syscall.h +- +unistd.h +- +sys/types.h +- +sys/stat.h +- +fcntl.h +- +errno.h +- +Windows.h +- +mach/mach_time.h +- +time.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/region.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +string.h +- +Windows.h +- +time.h +- +Windows.h +- +psapi.h +- +stdio.h +- +unistd.h +- +sys/resource.h +- +mach/mach.h +- +kernel/OS.h +- + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake new file mode 100644 index 000000000..c3b96b291 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake @@ -0,0 +1,39 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/alloc.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/arena.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/heap.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/init.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/init.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/options.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/options.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/os.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/os.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/page.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/page.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/random.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/random.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/region.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/region.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/segment.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/src/stats.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "MI_MALLOC_OVERRIDE" + "MI_STATIC_LIB" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/build.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/build.make new file mode 100644 index 000000000..6d848faa1 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/build.make @@ -0,0 +1,298 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +# Include any dependencies generated for this target. +include CMakeFiles/mimalloc-static.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/mimalloc-static.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/mimalloc-static.dir/flags.make + +CMakeFiles/mimalloc-static.dir/src/stats.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../src/stats.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/mimalloc-static.dir/src/stats.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/stats.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c + +CMakeFiles/mimalloc-static.dir/src/stats.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/stats.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c > CMakeFiles/mimalloc-static.dir/src/stats.c.i + +CMakeFiles/mimalloc-static.dir/src/stats.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/stats.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c -o CMakeFiles/mimalloc-static.dir/src/stats.c.s + +CMakeFiles/mimalloc-static.dir/src/random.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../src/random.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/mimalloc-static.dir/src/random.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/random.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/random.c + +CMakeFiles/mimalloc-static.dir/src/random.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/random.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/random.c > CMakeFiles/mimalloc-static.dir/src/random.c.i + +CMakeFiles/mimalloc-static.dir/src/random.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/random.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/random.c -o CMakeFiles/mimalloc-static.dir/src/random.c.s + +CMakeFiles/mimalloc-static.dir/src/os.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../src/os.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building C object CMakeFiles/mimalloc-static.dir/src/os.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/os.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/os.c + +CMakeFiles/mimalloc-static.dir/src/os.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/os.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/os.c > CMakeFiles/mimalloc-static.dir/src/os.c.i + +CMakeFiles/mimalloc-static.dir/src/os.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/os.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/os.c -o CMakeFiles/mimalloc-static.dir/src/os.c.s + +CMakeFiles/mimalloc-static.dir/src/arena.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../src/arena.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building C object CMakeFiles/mimalloc-static.dir/src/arena.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/arena.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c + +CMakeFiles/mimalloc-static.dir/src/arena.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/arena.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c > CMakeFiles/mimalloc-static.dir/src/arena.c.i + +CMakeFiles/mimalloc-static.dir/src/arena.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/arena.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c -o CMakeFiles/mimalloc-static.dir/src/arena.c.s + +CMakeFiles/mimalloc-static.dir/src/region.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../src/region.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building C object CMakeFiles/mimalloc-static.dir/src/region.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/region.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/region.c + +CMakeFiles/mimalloc-static.dir/src/region.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/region.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/region.c > CMakeFiles/mimalloc-static.dir/src/region.c.i + +CMakeFiles/mimalloc-static.dir/src/region.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/region.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/region.c -o CMakeFiles/mimalloc-static.dir/src/region.c.s + +CMakeFiles/mimalloc-static.dir/src/segment.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../src/segment.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building C object CMakeFiles/mimalloc-static.dir/src/segment.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/segment.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c + +CMakeFiles/mimalloc-static.dir/src/segment.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/segment.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c > CMakeFiles/mimalloc-static.dir/src/segment.c.i + +CMakeFiles/mimalloc-static.dir/src/segment.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/segment.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c -o CMakeFiles/mimalloc-static.dir/src/segment.c.s + +CMakeFiles/mimalloc-static.dir/src/page.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../src/page.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building C object CMakeFiles/mimalloc-static.dir/src/page.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/page.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/page.c + +CMakeFiles/mimalloc-static.dir/src/page.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/page.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/page.c > CMakeFiles/mimalloc-static.dir/src/page.c.i + +CMakeFiles/mimalloc-static.dir/src/page.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/page.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/page.c -o CMakeFiles/mimalloc-static.dir/src/page.c.s + +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../src/alloc.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building C object CMakeFiles/mimalloc-static.dir/src/alloc.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/alloc.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c + +CMakeFiles/mimalloc-static.dir/src/alloc.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/alloc.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c > CMakeFiles/mimalloc-static.dir/src/alloc.c.i + +CMakeFiles/mimalloc-static.dir/src/alloc.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/alloc.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c -o CMakeFiles/mimalloc-static.dir/src/alloc.c.s + +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../src/alloc-aligned.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Building C object CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c + +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c > CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.i + +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c -o CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.s + +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../src/alloc-posix.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building C object CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c + +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c > CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.i + +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c -o CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.s + +CMakeFiles/mimalloc-static.dir/src/heap.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../src/heap.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_11) "Building C object CMakeFiles/mimalloc-static.dir/src/heap.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/heap.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c + +CMakeFiles/mimalloc-static.dir/src/heap.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/heap.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c > CMakeFiles/mimalloc-static.dir/src/heap.c.i + +CMakeFiles/mimalloc-static.dir/src/heap.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/heap.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c -o CMakeFiles/mimalloc-static.dir/src/heap.c.s + +CMakeFiles/mimalloc-static.dir/src/options.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../src/options.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_12) "Building C object CMakeFiles/mimalloc-static.dir/src/options.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/options.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/options.c + +CMakeFiles/mimalloc-static.dir/src/options.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/options.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/options.c > CMakeFiles/mimalloc-static.dir/src/options.c.i + +CMakeFiles/mimalloc-static.dir/src/options.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/options.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/options.c -o CMakeFiles/mimalloc-static.dir/src/options.c.s + +CMakeFiles/mimalloc-static.dir/src/init.c.o: CMakeFiles/mimalloc-static.dir/flags.make +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../src/init.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_13) "Building C object CMakeFiles/mimalloc-static.dir/src/init.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-static.dir/src/init.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/init.c + +CMakeFiles/mimalloc-static.dir/src/init.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-static.dir/src/init.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/init.c > CMakeFiles/mimalloc-static.dir/src/init.c.i + +CMakeFiles/mimalloc-static.dir/src/init.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-static.dir/src/init.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/init.c -o CMakeFiles/mimalloc-static.dir/src/init.c.s + +# Object files for target mimalloc-static +mimalloc__static_OBJECTS = \ +"CMakeFiles/mimalloc-static.dir/src/stats.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/random.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/os.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/arena.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/region.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/segment.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/page.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/alloc.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/heap.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/options.c.o" \ +"CMakeFiles/mimalloc-static.dir/src/init.c.o" + +# External object files for target mimalloc-static +mimalloc__static_EXTERNAL_OBJECTS = + +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/stats.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/random.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/os.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/arena.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/region.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/segment.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/page.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/alloc.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/heap.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/options.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/src/init.c.o +libmimalloc.a: CMakeFiles/mimalloc-static.dir/build.make +libmimalloc.a: CMakeFiles/mimalloc-static.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_14) "Linking C static library libmimalloc.a" + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc-static.dir/cmake_clean_target.cmake + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/mimalloc-static.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/mimalloc-static.dir/build: libmimalloc.a + +.PHONY : CMakeFiles/mimalloc-static.dir/build + +CMakeFiles/mimalloc-static.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc-static.dir/cmake_clean.cmake +.PHONY : CMakeFiles/mimalloc-static.dir/clean + +CMakeFiles/mimalloc-static.dir/depend: + cd /home/hbina/git/KeyDB/deps/mimalloc/bin && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/mimalloc-static.dir/depend + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean.cmake new file mode 100644 index 000000000..6d009991f --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean.cmake @@ -0,0 +1,22 @@ +file(REMOVE_RECURSE + "CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o" + "CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o" + "CMakeFiles/mimalloc-static.dir/src/alloc.c.o" + "CMakeFiles/mimalloc-static.dir/src/arena.c.o" + "CMakeFiles/mimalloc-static.dir/src/heap.c.o" + "CMakeFiles/mimalloc-static.dir/src/init.c.o" + "CMakeFiles/mimalloc-static.dir/src/options.c.o" + "CMakeFiles/mimalloc-static.dir/src/os.c.o" + "CMakeFiles/mimalloc-static.dir/src/page.c.o" + "CMakeFiles/mimalloc-static.dir/src/random.c.o" + "CMakeFiles/mimalloc-static.dir/src/region.c.o" + "CMakeFiles/mimalloc-static.dir/src/segment.c.o" + "CMakeFiles/mimalloc-static.dir/src/stats.c.o" + "libmimalloc.a" + "libmimalloc.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/mimalloc-static.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean_target.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean_target.cmake new file mode 100644 index 000000000..12ef1a0da --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/cmake_clean_target.cmake @@ -0,0 +1,3 @@ +file(REMOVE_RECURSE + "libmimalloc.a" +) diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.internal b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.internal new file mode 100644 index 000000000..984d9cc45 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.internal @@ -0,0 +1,85 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +CMakeFiles/mimalloc-static.dir/src/alloc.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +CMakeFiles/mimalloc-static.dir/src/arena.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c + /home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +CMakeFiles/mimalloc-static.dir/src/heap.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +CMakeFiles/mimalloc-static.dir/src/init.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/init.c +CMakeFiles/mimalloc-static.dir/src/options.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/options.c +CMakeFiles/mimalloc-static.dir/src/os.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/os.c +CMakeFiles/mimalloc-static.dir/src/page.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + /home/hbina/git/KeyDB/deps/mimalloc/src/page.c +CMakeFiles/mimalloc-static.dir/src/random.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/random.c +CMakeFiles/mimalloc-static.dir/src/region.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + /home/hbina/git/KeyDB/deps/mimalloc/src/region.c +CMakeFiles/mimalloc-static.dir/src/segment.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +CMakeFiles/mimalloc-static.dir/src/stats.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.make new file mode 100644 index 000000000..2f45e6179 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/depend.make @@ -0,0 +1,85 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o: ../src/alloc-aligned.c + +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o: ../src/alloc-posix.c + +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../src/alloc-override.c +CMakeFiles/mimalloc-static.dir/src/alloc.c.o: ../src/alloc.c + +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../src/arena.c +CMakeFiles/mimalloc-static.dir/src/arena.c.o: ../src/bitmap.inc.c + +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/heap.c.o: ../src/heap.c + +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/init.c.o: ../src/init.c + +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/options.c.o: ../src/options.c + +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/os.c.o: ../src/os.c + +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../src/page-queue.c +CMakeFiles/mimalloc-static.dir/src/page.c.o: ../src/page.c + +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/random.c.o: ../src/random.c + +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../src/bitmap.inc.c +CMakeFiles/mimalloc-static.dir/src/region.c.o: ../src/region.c + +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/segment.c.o: ../src/segment.c + +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-static.dir/src/stats.c.o: ../src/stats.c + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/flags.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/flags.make new file mode 100644 index 000000000..2305df0f6 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = -DMI_MALLOC_OVERRIDE -DMI_STATIC_LIB + +C_INCLUDES = -I/home/hbina/git/KeyDB/deps/mimalloc/include + +C_FLAGS = -O3 -DNDEBUG -fPIC -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden -Wno-invalid-memory-model -ftls-model=initial-exec -std=gnu11 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/link.txt b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/link.txt new file mode 100644 index 000000000..d3f0bece4 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/link.txt @@ -0,0 +1,2 @@ +/usr/bin/ar qc libmimalloc.a CMakeFiles/mimalloc-static.dir/src/stats.c.o CMakeFiles/mimalloc-static.dir/src/random.c.o CMakeFiles/mimalloc-static.dir/src/os.c.o CMakeFiles/mimalloc-static.dir/src/arena.c.o CMakeFiles/mimalloc-static.dir/src/region.c.o CMakeFiles/mimalloc-static.dir/src/segment.c.o CMakeFiles/mimalloc-static.dir/src/page.c.o CMakeFiles/mimalloc-static.dir/src/alloc.c.o CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o CMakeFiles/mimalloc-static.dir/src/heap.c.o CMakeFiles/mimalloc-static.dir/src/options.c.o CMakeFiles/mimalloc-static.dir/src/init.c.o +/usr/bin/ranlib libmimalloc.a diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/progress.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/progress.make new file mode 100644 index 000000000..3dba447b5 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/progress.make @@ -0,0 +1,15 @@ +CMAKE_PROGRESS_1 = 16 +CMAKE_PROGRESS_2 = 17 +CMAKE_PROGRESS_3 = 18 +CMAKE_PROGRESS_4 = 19 +CMAKE_PROGRESS_5 = 20 +CMAKE_PROGRESS_6 = 21 +CMAKE_PROGRESS_7 = 22 +CMAKE_PROGRESS_8 = 23 +CMAKE_PROGRESS_9 = 24 +CMAKE_PROGRESS_10 = 25 +CMAKE_PROGRESS_11 = 26 +CMAKE_PROGRESS_12 = 27 +CMAKE_PROGRESS_13 = 28 +CMAKE_PROGRESS_14 = 29 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/C.includecache b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/C.includecache new file mode 100644 index 000000000..330f7b854 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/C.includecache @@ -0,0 +1,36 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/mimalloc.h +stddef.h +- +stdbool.h +- +cstdint +- +type_traits +- +utility +- + +/home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c +stdio.h +- +assert.h +- +stdbool.h +- +stdint.h +- +errno.h +- +vector +- +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/test/mimalloc.h + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake new file mode 100644 index 000000000..31108d91e --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake @@ -0,0 +1,22 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-static.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/build.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/build.make new file mode 100644 index 000000000..0f1c3466e --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/build.make @@ -0,0 +1,119 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +# Include any dependencies generated for this target. +include CMakeFiles/mimalloc-test-api.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/mimalloc-test-api.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/mimalloc-test-api.dir/flags.make + +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o: CMakeFiles/mimalloc-test-api.dir/flags.make +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o: ../test/test-api.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c + +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-test-api.dir/test/test-api.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c > CMakeFiles/mimalloc-test-api.dir/test/test-api.c.i + +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-test-api.dir/test/test-api.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c -o CMakeFiles/mimalloc-test-api.dir/test/test-api.c.s + +# Object files for target mimalloc-test-api +mimalloc__test__api_OBJECTS = \ +"CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o" + +# External object files for target mimalloc-test-api +mimalloc__test__api_EXTERNAL_OBJECTS = + +mimalloc-test-api: CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o +mimalloc-test-api: CMakeFiles/mimalloc-test-api.dir/build.make +mimalloc-test-api: libmimalloc.a +mimalloc-test-api: /usr/lib/x86_64-linux-gnu/librt.so +mimalloc-test-api: CMakeFiles/mimalloc-test-api.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable mimalloc-test-api" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/mimalloc-test-api.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/mimalloc-test-api.dir/build: mimalloc-test-api + +.PHONY : CMakeFiles/mimalloc-test-api.dir/build + +CMakeFiles/mimalloc-test-api.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc-test-api.dir/cmake_clean.cmake +.PHONY : CMakeFiles/mimalloc-test-api.dir/clean + +CMakeFiles/mimalloc-test-api.dir/depend: + cd /home/hbina/git/KeyDB/deps/mimalloc/bin && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/mimalloc-test-api.dir/depend + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/cmake_clean.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/cmake_clean.cmake new file mode 100644 index 000000000..279fd2be3 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o" + "mimalloc-test-api" + "mimalloc-test-api.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/mimalloc-test-api.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.internal b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.internal new file mode 100644 index 000000000..0791e7541 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.internal @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/test/test-api.c diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.make new file mode 100644 index 000000000..5dc132d3b --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/depend.make @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o: ../test/test-api.c + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/flags.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/flags.make new file mode 100644 index 000000000..bc1f4bfa8 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = + +C_INCLUDES = -I/home/hbina/git/KeyDB/deps/mimalloc/include + +C_FLAGS = -O3 -DNDEBUG -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden -Wno-invalid-memory-model -ftls-model=initial-exec -std=gnu11 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/link.txt b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/link.txt new file mode 100644 index 000000000..771cdf40f --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/cc -O3 -DNDEBUG -rdynamic CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o -o mimalloc-test-api libmimalloc.a -lpthread -lrt diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/progress.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/progress.make new file mode 100644 index 000000000..335ef43aa --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-api.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 30 +CMAKE_PROGRESS_2 = 31 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/C.includecache b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/C.includecache new file mode 100644 index 000000000..2dc2e572b --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/C.includecache @@ -0,0 +1,42 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/mimalloc.h +stddef.h +- +stdbool.h +- +cstdint +- +type_traits +- +utility +- + +/home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c +stdio.h +- +stdlib.h +- +stdint.h +- +stdbool.h +- +string.h +- +mimalloc.h +- +Windows.h +- +pthread.h +- +atomic +- +stdatomic.h +- + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake new file mode 100644 index 000000000..819499bce --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake @@ -0,0 +1,22 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/build.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/build.make new file mode 100644 index 000000000..7466e38f6 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/build.make @@ -0,0 +1,119 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +# Include any dependencies generated for this target. +include CMakeFiles/mimalloc-test-stress.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/mimalloc-test-stress.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/mimalloc-test-stress.dir/flags.make + +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o: CMakeFiles/mimalloc-test-stress.dir/flags.make +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o: ../test/test-stress.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c + +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c > CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.i + +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c -o CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.s + +# Object files for target mimalloc-test-stress +mimalloc__test__stress_OBJECTS = \ +"CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o" + +# External object files for target mimalloc-test-stress +mimalloc__test__stress_EXTERNAL_OBJECTS = + +mimalloc-test-stress: CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o +mimalloc-test-stress: CMakeFiles/mimalloc-test-stress.dir/build.make +mimalloc-test-stress: libmimalloc.so.1.6 +mimalloc-test-stress: /usr/lib/x86_64-linux-gnu/librt.so +mimalloc-test-stress: CMakeFiles/mimalloc-test-stress.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable mimalloc-test-stress" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/mimalloc-test-stress.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/mimalloc-test-stress.dir/build: mimalloc-test-stress + +.PHONY : CMakeFiles/mimalloc-test-stress.dir/build + +CMakeFiles/mimalloc-test-stress.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc-test-stress.dir/cmake_clean.cmake +.PHONY : CMakeFiles/mimalloc-test-stress.dir/clean + +CMakeFiles/mimalloc-test-stress.dir/depend: + cd /home/hbina/git/KeyDB/deps/mimalloc/bin && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/mimalloc-test-stress.dir/depend + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/cmake_clean.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/cmake_clean.cmake new file mode 100644 index 000000000..d7ace7026 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o" + "mimalloc-test-stress" + "mimalloc-test-stress.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/mimalloc-test-stress.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.internal b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.internal new file mode 100644 index 000000000..0df76f564 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.internal @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/test/test-stress.c diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.make new file mode 100644 index 000000000..f03da92fb --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/depend.make @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o: ../test/test-stress.c + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/flags.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/flags.make new file mode 100644 index 000000000..bc1f4bfa8 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = + +C_INCLUDES = -I/home/hbina/git/KeyDB/deps/mimalloc/include + +C_FLAGS = -O3 -DNDEBUG -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden -Wno-invalid-memory-model -ftls-model=initial-exec -std=gnu11 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/link.txt b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/link.txt new file mode 100644 index 000000000..99de2438d --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/cc -O3 -DNDEBUG -rdynamic CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o -o mimalloc-test-stress -Wl,-rpath,/home/hbina/git/KeyDB/deps/mimalloc/bin libmimalloc.so.1.6 -lpthread -lrt diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/progress.make b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/progress.make new file mode 100644 index 000000000..e1615c182 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc-test-stress.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 32 +CMAKE_PROGRESS_2 = 33 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/C.includecache b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/C.includecache new file mode 100644 index 000000000..bfa9dc8a9 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/C.includecache @@ -0,0 +1,310 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/mimalloc-atomic.h +atomic +- +stdatomic.h +- +Windows.h +- +intrin.h +- +thread +- +windows.h +- +sched.h +- +unistd.h +- + +../include/mimalloc-internal.h +mimalloc-types.h +../include/mimalloc-types.h +errno.h +- +limits.h +- +pthread.h +- +pthread.h +- +windows.h +- + +../include/mimalloc-types.h +stddef.h +- +stdint.h +- +mimalloc-atomic.h +- + +../include/mimalloc.h +stddef.h +- +stdbool.h +- +cstdint +- +type_traits +- +utility +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +errno.h +- +string.h +- +stdlib.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdlib.h +- +alloc-override.c +/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c +Windows.h +- +unistd.h +- +new +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +errno.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +intrin.h +- +limits.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/init.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +stdlib.h +- +Windows.h +- +fibersapi.h +- +pthread.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/options.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +stdlib.h +- +string.h +- +ctype.h +- +stdarg.h +- +conio.h +- +Windows.h +- +crt_externs.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/os.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +Windows.h +- +sys/mman.h +- +unistd.h +- +features.h +- +linux/mman.h +- +sys/mman.h +- +TargetConditionals.h +- +mach/vm_statistics.h +- +winternl.h +- +sys/syscall.h +- +sys/syscall.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c +intrin.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/page.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +page-queue.c +/home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/random.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +string.h +- +bcrypt.h +- +stdlib.h +- +sys/syscall.h +- +unistd.h +- +sys/types.h +- +sys/stat.h +- +fcntl.h +- +errno.h +- +Windows.h +- +mach/mach_time.h +- +time.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/region.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +bitmap.inc.c +/home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + +/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +string.h +- +stdio.h +- + +/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c +mimalloc.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc.h +mimalloc-internal.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-internal.h +mimalloc-atomic.h +/home/hbina/git/KeyDB/deps/mimalloc/src/mimalloc-atomic.h +stdio.h +- +string.h +- +Windows.h +- +time.h +- +Windows.h +- +psapi.h +- +stdio.h +- +unistd.h +- +sys/resource.h +- +mach/mach.h +- +kernel/OS.h +- + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake new file mode 100644 index 000000000..feb8cf347 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake @@ -0,0 +1,47 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/alloc-posix.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/alloc.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/arena.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/arena.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/heap.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/heap.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/init.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/init.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/options.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/options.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/os.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/os.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/page.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/page.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/random.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/random.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/region.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/region.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/segment.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/segment.c.o" + "/home/hbina/git/KeyDB/deps/mimalloc/src/stats.c" "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/src/stats.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "MI_MALLOC_OVERRIDE" + "MI_SHARED_LIB" + "MI_SHARED_LIB_EXPORT" + "mimalloc_EXPORTS" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Pairs of files generated by the same build rule. +set(CMAKE_MULTIPLE_OUTPUT_PAIRS + "/home/hbina/git/KeyDB/deps/mimalloc/bin/libmimalloc.so" "/home/hbina/git/KeyDB/deps/mimalloc/bin/libmimalloc.so.1.6" + ) + + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/build.make b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/build.make new file mode 100644 index 000000000..b204bdd50 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/build.make @@ -0,0 +1,302 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +# Include any dependencies generated for this target. +include CMakeFiles/mimalloc.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/mimalloc.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/mimalloc.dir/flags.make + +CMakeFiles/mimalloc.dir/src/stats.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/stats.c.o: ../src/stats.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/mimalloc.dir/src/stats.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/stats.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c + +CMakeFiles/mimalloc.dir/src/stats.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/stats.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c > CMakeFiles/mimalloc.dir/src/stats.c.i + +CMakeFiles/mimalloc.dir/src/stats.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/stats.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c -o CMakeFiles/mimalloc.dir/src/stats.c.s + +CMakeFiles/mimalloc.dir/src/random.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/random.c.o: ../src/random.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/mimalloc.dir/src/random.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/random.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/random.c + +CMakeFiles/mimalloc.dir/src/random.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/random.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/random.c > CMakeFiles/mimalloc.dir/src/random.c.i + +CMakeFiles/mimalloc.dir/src/random.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/random.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/random.c -o CMakeFiles/mimalloc.dir/src/random.c.s + +CMakeFiles/mimalloc.dir/src/os.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/os.c.o: ../src/os.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building C object CMakeFiles/mimalloc.dir/src/os.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/os.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/os.c + +CMakeFiles/mimalloc.dir/src/os.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/os.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/os.c > CMakeFiles/mimalloc.dir/src/os.c.i + +CMakeFiles/mimalloc.dir/src/os.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/os.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/os.c -o CMakeFiles/mimalloc.dir/src/os.c.s + +CMakeFiles/mimalloc.dir/src/arena.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/arena.c.o: ../src/arena.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building C object CMakeFiles/mimalloc.dir/src/arena.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/arena.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c + +CMakeFiles/mimalloc.dir/src/arena.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/arena.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c > CMakeFiles/mimalloc.dir/src/arena.c.i + +CMakeFiles/mimalloc.dir/src/arena.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/arena.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c -o CMakeFiles/mimalloc.dir/src/arena.c.s + +CMakeFiles/mimalloc.dir/src/region.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/region.c.o: ../src/region.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building C object CMakeFiles/mimalloc.dir/src/region.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/region.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/region.c + +CMakeFiles/mimalloc.dir/src/region.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/region.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/region.c > CMakeFiles/mimalloc.dir/src/region.c.i + +CMakeFiles/mimalloc.dir/src/region.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/region.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/region.c -o CMakeFiles/mimalloc.dir/src/region.c.s + +CMakeFiles/mimalloc.dir/src/segment.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/segment.c.o: ../src/segment.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building C object CMakeFiles/mimalloc.dir/src/segment.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/segment.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c + +CMakeFiles/mimalloc.dir/src/segment.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/segment.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c > CMakeFiles/mimalloc.dir/src/segment.c.i + +CMakeFiles/mimalloc.dir/src/segment.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/segment.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c -o CMakeFiles/mimalloc.dir/src/segment.c.s + +CMakeFiles/mimalloc.dir/src/page.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/page.c.o: ../src/page.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building C object CMakeFiles/mimalloc.dir/src/page.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/page.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/page.c + +CMakeFiles/mimalloc.dir/src/page.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/page.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/page.c > CMakeFiles/mimalloc.dir/src/page.c.i + +CMakeFiles/mimalloc.dir/src/page.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/page.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/page.c -o CMakeFiles/mimalloc.dir/src/page.c.s + +CMakeFiles/mimalloc.dir/src/alloc.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../src/alloc.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building C object CMakeFiles/mimalloc.dir/src/alloc.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/alloc.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c + +CMakeFiles/mimalloc.dir/src/alloc.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/alloc.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c > CMakeFiles/mimalloc.dir/src/alloc.c.i + +CMakeFiles/mimalloc.dir/src/alloc.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/alloc.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c -o CMakeFiles/mimalloc.dir/src/alloc.c.s + +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../src/alloc-aligned.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Building C object CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c + +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/alloc-aligned.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c > CMakeFiles/mimalloc.dir/src/alloc-aligned.c.i + +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/alloc-aligned.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c -o CMakeFiles/mimalloc.dir/src/alloc-aligned.c.s + +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../src/alloc-posix.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building C object CMakeFiles/mimalloc.dir/src/alloc-posix.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/alloc-posix.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c + +CMakeFiles/mimalloc.dir/src/alloc-posix.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/alloc-posix.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c > CMakeFiles/mimalloc.dir/src/alloc-posix.c.i + +CMakeFiles/mimalloc.dir/src/alloc-posix.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/alloc-posix.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c -o CMakeFiles/mimalloc.dir/src/alloc-posix.c.s + +CMakeFiles/mimalloc.dir/src/heap.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/heap.c.o: ../src/heap.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_11) "Building C object CMakeFiles/mimalloc.dir/src/heap.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/heap.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c + +CMakeFiles/mimalloc.dir/src/heap.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/heap.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c > CMakeFiles/mimalloc.dir/src/heap.c.i + +CMakeFiles/mimalloc.dir/src/heap.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/heap.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c -o CMakeFiles/mimalloc.dir/src/heap.c.s + +CMakeFiles/mimalloc.dir/src/options.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/options.c.o: ../src/options.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_12) "Building C object CMakeFiles/mimalloc.dir/src/options.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/options.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/options.c + +CMakeFiles/mimalloc.dir/src/options.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/options.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/options.c > CMakeFiles/mimalloc.dir/src/options.c.i + +CMakeFiles/mimalloc.dir/src/options.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/options.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/options.c -o CMakeFiles/mimalloc.dir/src/options.c.s + +CMakeFiles/mimalloc.dir/src/init.c.o: CMakeFiles/mimalloc.dir/flags.make +CMakeFiles/mimalloc.dir/src/init.c.o: ../src/init.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_13) "Building C object CMakeFiles/mimalloc.dir/src/init.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/mimalloc.dir/src/init.c.o -c /home/hbina/git/KeyDB/deps/mimalloc/src/init.c + +CMakeFiles/mimalloc.dir/src/init.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/mimalloc.dir/src/init.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/hbina/git/KeyDB/deps/mimalloc/src/init.c > CMakeFiles/mimalloc.dir/src/init.c.i + +CMakeFiles/mimalloc.dir/src/init.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/mimalloc.dir/src/init.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/hbina/git/KeyDB/deps/mimalloc/src/init.c -o CMakeFiles/mimalloc.dir/src/init.c.s + +# Object files for target mimalloc +mimalloc_OBJECTS = \ +"CMakeFiles/mimalloc.dir/src/stats.c.o" \ +"CMakeFiles/mimalloc.dir/src/random.c.o" \ +"CMakeFiles/mimalloc.dir/src/os.c.o" \ +"CMakeFiles/mimalloc.dir/src/arena.c.o" \ +"CMakeFiles/mimalloc.dir/src/region.c.o" \ +"CMakeFiles/mimalloc.dir/src/segment.c.o" \ +"CMakeFiles/mimalloc.dir/src/page.c.o" \ +"CMakeFiles/mimalloc.dir/src/alloc.c.o" \ +"CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o" \ +"CMakeFiles/mimalloc.dir/src/alloc-posix.c.o" \ +"CMakeFiles/mimalloc.dir/src/heap.c.o" \ +"CMakeFiles/mimalloc.dir/src/options.c.o" \ +"CMakeFiles/mimalloc.dir/src/init.c.o" + +# External object files for target mimalloc +mimalloc_EXTERNAL_OBJECTS = + +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/stats.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/random.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/os.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/arena.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/region.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/segment.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/page.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/alloc.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/alloc-posix.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/heap.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/options.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/src/init.c.o +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/build.make +libmimalloc.so.1.6: /usr/lib/x86_64-linux-gnu/librt.so +libmimalloc.so.1.6: CMakeFiles/mimalloc.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles --progress-num=$(CMAKE_PROGRESS_14) "Linking C shared library libmimalloc.so" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/mimalloc.dir/link.txt --verbose=$(VERBOSE) + $(CMAKE_COMMAND) -E cmake_symlink_library libmimalloc.so.1.6 libmimalloc.so.1.6 libmimalloc.so + +libmimalloc.so: libmimalloc.so.1.6 + @$(CMAKE_COMMAND) -E touch_nocreate libmimalloc.so + +# Rule to build all files generated by this target. +CMakeFiles/mimalloc.dir/build: libmimalloc.so + +.PHONY : CMakeFiles/mimalloc.dir/build + +CMakeFiles/mimalloc.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/mimalloc.dir/cmake_clean.cmake +.PHONY : CMakeFiles/mimalloc.dir/clean + +CMakeFiles/mimalloc.dir/depend: + cd /home/hbina/git/KeyDB/deps/mimalloc/bin && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/mimalloc.dir/depend + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/cmake_clean.cmake b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/cmake_clean.cmake new file mode 100644 index 000000000..4cf861b2e --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/cmake_clean.cmake @@ -0,0 +1,23 @@ +file(REMOVE_RECURSE + "CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o" + "CMakeFiles/mimalloc.dir/src/alloc-posix.c.o" + "CMakeFiles/mimalloc.dir/src/alloc.c.o" + "CMakeFiles/mimalloc.dir/src/arena.c.o" + "CMakeFiles/mimalloc.dir/src/heap.c.o" + "CMakeFiles/mimalloc.dir/src/init.c.o" + "CMakeFiles/mimalloc.dir/src/options.c.o" + "CMakeFiles/mimalloc.dir/src/os.c.o" + "CMakeFiles/mimalloc.dir/src/page.c.o" + "CMakeFiles/mimalloc.dir/src/random.c.o" + "CMakeFiles/mimalloc.dir/src/region.c.o" + "CMakeFiles/mimalloc.dir/src/segment.c.o" + "CMakeFiles/mimalloc.dir/src/stats.c.o" + "libmimalloc.pdb" + "libmimalloc.so" + "libmimalloc.so.1.6" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/mimalloc.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.internal b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.internal new file mode 100644 index 000000000..9c217055b --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.internal @@ -0,0 +1,85 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-aligned.c +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-posix.c +CMakeFiles/mimalloc.dir/src/alloc.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc-override.c + /home/hbina/git/KeyDB/deps/mimalloc/src/alloc.c +CMakeFiles/mimalloc.dir/src/arena.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/arena.c + /home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c +CMakeFiles/mimalloc.dir/src/heap.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/heap.c +CMakeFiles/mimalloc.dir/src/init.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/init.c +CMakeFiles/mimalloc.dir/src/options.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/options.c +CMakeFiles/mimalloc.dir/src/os.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/os.c +CMakeFiles/mimalloc.dir/src/page.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/page-queue.c + /home/hbina/git/KeyDB/deps/mimalloc/src/page.c +CMakeFiles/mimalloc.dir/src/random.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/random.c +CMakeFiles/mimalloc.dir/src/region.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/bitmap.inc.c + /home/hbina/git/KeyDB/deps/mimalloc/src/region.c +CMakeFiles/mimalloc.dir/src/segment.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/segment.c +CMakeFiles/mimalloc.dir/src/stats.c.o + ../include/mimalloc-atomic.h + ../include/mimalloc-internal.h + ../include/mimalloc-types.h + ../include/mimalloc.h + /home/hbina/git/KeyDB/deps/mimalloc/src/stats.c diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.make b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.make new file mode 100644 index 000000000..f9c24968a --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/depend.make @@ -0,0 +1,85 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o: ../src/alloc-aligned.c + +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/alloc-posix.c.o: ../src/alloc-posix.c + +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../src/alloc-override.c +CMakeFiles/mimalloc.dir/src/alloc.c.o: ../src/alloc.c + +CMakeFiles/mimalloc.dir/src/arena.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/arena.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/arena.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/arena.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/arena.c.o: ../src/arena.c +CMakeFiles/mimalloc.dir/src/arena.c.o: ../src/bitmap.inc.c + +CMakeFiles/mimalloc.dir/src/heap.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/heap.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/heap.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/heap.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/heap.c.o: ../src/heap.c + +CMakeFiles/mimalloc.dir/src/init.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/init.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/init.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/init.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/init.c.o: ../src/init.c + +CMakeFiles/mimalloc.dir/src/options.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/options.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/options.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/options.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/options.c.o: ../src/options.c + +CMakeFiles/mimalloc.dir/src/os.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/os.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/os.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/os.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/os.c.o: ../src/os.c + +CMakeFiles/mimalloc.dir/src/page.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/page.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/page.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/page.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/page.c.o: ../src/page-queue.c +CMakeFiles/mimalloc.dir/src/page.c.o: ../src/page.c + +CMakeFiles/mimalloc.dir/src/random.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/random.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/random.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/random.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/random.c.o: ../src/random.c + +CMakeFiles/mimalloc.dir/src/region.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/region.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/region.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/region.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/region.c.o: ../src/bitmap.inc.c +CMakeFiles/mimalloc.dir/src/region.c.o: ../src/region.c + +CMakeFiles/mimalloc.dir/src/segment.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/segment.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/segment.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/segment.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/segment.c.o: ../src/segment.c + +CMakeFiles/mimalloc.dir/src/stats.c.o: ../include/mimalloc-atomic.h +CMakeFiles/mimalloc.dir/src/stats.c.o: ../include/mimalloc-internal.h +CMakeFiles/mimalloc.dir/src/stats.c.o: ../include/mimalloc-types.h +CMakeFiles/mimalloc.dir/src/stats.c.o: ../include/mimalloc.h +CMakeFiles/mimalloc.dir/src/stats.c.o: ../src/stats.c + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/flags.make b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/flags.make new file mode 100644 index 000000000..1a0c8a0e8 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# compile C with /usr/bin/cc +C_DEFINES = -DMI_MALLOC_OVERRIDE -DMI_SHARED_LIB -DMI_SHARED_LIB_EXPORT -Dmimalloc_EXPORTS + +C_INCLUDES = -I/home/hbina/git/KeyDB/deps/mimalloc/include + +C_FLAGS = -O3 -DNDEBUG -fPIC -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden -Wno-invalid-memory-model -ftls-model=initial-exec -std=gnu11 + diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/link.txt b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/link.txt new file mode 100644 index 000000000..7b2268334 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/cc -fPIC -O3 -DNDEBUG -shared -Wl,-soname,libmimalloc.so.1.6 -o libmimalloc.so.1.6 CMakeFiles/mimalloc.dir/src/stats.c.o CMakeFiles/mimalloc.dir/src/random.c.o CMakeFiles/mimalloc.dir/src/os.c.o CMakeFiles/mimalloc.dir/src/arena.c.o CMakeFiles/mimalloc.dir/src/region.c.o CMakeFiles/mimalloc.dir/src/segment.c.o CMakeFiles/mimalloc.dir/src/page.c.o CMakeFiles/mimalloc.dir/src/alloc.c.o CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o CMakeFiles/mimalloc.dir/src/alloc-posix.c.o CMakeFiles/mimalloc.dir/src/heap.c.o CMakeFiles/mimalloc.dir/src/options.c.o CMakeFiles/mimalloc.dir/src/init.c.o -lpthread -lrt diff --git a/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/progress.make b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/progress.make new file mode 100644 index 000000000..4f6e68a52 --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/mimalloc.dir/progress.make @@ -0,0 +1,15 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 +CMAKE_PROGRESS_4 = 4 +CMAKE_PROGRESS_5 = 5 +CMAKE_PROGRESS_6 = 6 +CMAKE_PROGRESS_7 = 7 +CMAKE_PROGRESS_8 = 8 +CMAKE_PROGRESS_9 = 9 +CMAKE_PROGRESS_10 = 10 +CMAKE_PROGRESS_11 = 11 +CMAKE_PROGRESS_12 = 12 +CMAKE_PROGRESS_13 = 13 +CMAKE_PROGRESS_14 = 14 + diff --git a/deps/mimalloc/bin/CMakeFiles/progress.marks b/deps/mimalloc/bin/CMakeFiles/progress.marks new file mode 100644 index 000000000..bb95160cb --- /dev/null +++ b/deps/mimalloc/bin/CMakeFiles/progress.marks @@ -0,0 +1 @@ +33 diff --git a/deps/mimalloc/bin/CTestTestfile.cmake b/deps/mimalloc/bin/CTestTestfile.cmake new file mode 100644 index 000000000..0bac176ee --- /dev/null +++ b/deps/mimalloc/bin/CTestTestfile.cmake @@ -0,0 +1,10 @@ +# CMake generated Testfile for +# Source directory: /home/hbina/git/KeyDB/deps/mimalloc +# Build directory: /home/hbina/git/KeyDB/deps/mimalloc/bin +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +add_test(test_api, "mimalloc-test-api") +set_tests_properties(test_api, PROPERTIES _BACKTRACE_TRIPLES "/home/hbina/git/KeyDB/deps/mimalloc/CMakeLists.txt;347;add_test;/home/hbina/git/KeyDB/deps/mimalloc/CMakeLists.txt;0;") +add_test(test_stress, "mimalloc-test-stress") +set_tests_properties(test_stress, PROPERTIES _BACKTRACE_TRIPLES "/home/hbina/git/KeyDB/deps/mimalloc/CMakeLists.txt;348;add_test;/home/hbina/git/KeyDB/deps/mimalloc/CMakeLists.txt;0;") diff --git a/deps/mimalloc/bin/Makefile b/deps/mimalloc/bin/Makefile new file mode 100644 index 000000000..2b3328a45 --- /dev/null +++ b/deps/mimalloc/bin/Makefile @@ -0,0 +1,804 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.18 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Disable VCS-based implicit rules. +% : %,v + + +# Disable VCS-based implicit rules. +% : RCS/% + + +# Disable VCS-based implicit rules. +% : RCS/%,v + + +# Disable VCS-based implicit rules. +% : SCCS/s.% + + +# Disable VCS-based implicit rules. +% : s.% + + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/bin/cmake + +# The command to remove a file. +RM = /usr/local/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/hbina/git/KeyDB/deps/mimalloc + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/hbina/git/KeyDB/deps/mimalloc/bin + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/local/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/local/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/local/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/local/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/local/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test + +.PHONY : test/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles /home/hbina/git/KeyDB/deps/mimalloc/bin//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named mimalloc-test-stress + +# Build rule for target. +mimalloc-test-stress: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 mimalloc-test-stress +.PHONY : mimalloc-test-stress + +# fast build rule for target. +mimalloc-test-stress/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/build +.PHONY : mimalloc-test-stress/fast + +#============================================================================= +# Target rules for targets named mimalloc-obj + +# Build rule for target. +mimalloc-obj: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 mimalloc-obj +.PHONY : mimalloc-obj + +# fast build rule for target. +mimalloc-obj/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/build +.PHONY : mimalloc-obj/fast + +#============================================================================= +# Target rules for targets named mimalloc-static + +# Build rule for target. +mimalloc-static: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 mimalloc-static +.PHONY : mimalloc-static + +# fast build rule for target. +mimalloc-static/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/build +.PHONY : mimalloc-static/fast + +#============================================================================= +# Target rules for targets named mimalloc-test-api + +# Build rule for target. +mimalloc-test-api: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 mimalloc-test-api +.PHONY : mimalloc-test-api + +# fast build rule for target. +mimalloc-test-api/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/build +.PHONY : mimalloc-test-api/fast + +#============================================================================= +# Target rules for targets named mimalloc + +# Build rule for target. +mimalloc: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 mimalloc +.PHONY : mimalloc + +# fast build rule for target. +mimalloc/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/build +.PHONY : mimalloc/fast + +src/alloc-aligned.o: src/alloc-aligned.c.o + +.PHONY : src/alloc-aligned.o + +# target to build an object file +src/alloc-aligned.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-aligned.c.o +.PHONY : src/alloc-aligned.c.o + +src/alloc-aligned.i: src/alloc-aligned.c.i + +.PHONY : src/alloc-aligned.i + +# target to preprocess a source file +src/alloc-aligned.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-aligned.c.i +.PHONY : src/alloc-aligned.c.i + +src/alloc-aligned.s: src/alloc-aligned.c.s + +.PHONY : src/alloc-aligned.s + +# target to generate assembly for a file +src/alloc-aligned.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-aligned.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-aligned.c.s +.PHONY : src/alloc-aligned.c.s + +src/alloc-posix.o: src/alloc-posix.c.o + +.PHONY : src/alloc-posix.o + +# target to build an object file +src/alloc-posix.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-posix.c.o +.PHONY : src/alloc-posix.c.o + +src/alloc-posix.i: src/alloc-posix.c.i + +.PHONY : src/alloc-posix.i + +# target to preprocess a source file +src/alloc-posix.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-posix.c.i +.PHONY : src/alloc-posix.c.i + +src/alloc-posix.s: src/alloc-posix.c.s + +.PHONY : src/alloc-posix.s + +# target to generate assembly for a file +src/alloc-posix.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc-posix.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc-posix.c.s +.PHONY : src/alloc-posix.c.s + +src/alloc.o: src/alloc.c.o + +.PHONY : src/alloc.o + +# target to build an object file +src/alloc.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc.c.o +.PHONY : src/alloc.c.o + +src/alloc.i: src/alloc.c.i + +.PHONY : src/alloc.i + +# target to preprocess a source file +src/alloc.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc.c.i +.PHONY : src/alloc.c.i + +src/alloc.s: src/alloc.c.s + +.PHONY : src/alloc.s + +# target to generate assembly for a file +src/alloc.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/alloc.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/alloc.c.s +.PHONY : src/alloc.c.s + +src/arena.o: src/arena.c.o + +.PHONY : src/arena.o + +# target to build an object file +src/arena.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/arena.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/arena.c.o +.PHONY : src/arena.c.o + +src/arena.i: src/arena.c.i + +.PHONY : src/arena.i + +# target to preprocess a source file +src/arena.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/arena.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/arena.c.i +.PHONY : src/arena.c.i + +src/arena.s: src/arena.c.s + +.PHONY : src/arena.s + +# target to generate assembly for a file +src/arena.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/arena.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/arena.c.s +.PHONY : src/arena.c.s + +src/heap.o: src/heap.c.o + +.PHONY : src/heap.o + +# target to build an object file +src/heap.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/heap.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/heap.c.o +.PHONY : src/heap.c.o + +src/heap.i: src/heap.c.i + +.PHONY : src/heap.i + +# target to preprocess a source file +src/heap.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/heap.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/heap.c.i +.PHONY : src/heap.c.i + +src/heap.s: src/heap.c.s + +.PHONY : src/heap.s + +# target to generate assembly for a file +src/heap.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/heap.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/heap.c.s +.PHONY : src/heap.c.s + +src/init.o: src/init.c.o + +.PHONY : src/init.o + +# target to build an object file +src/init.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/init.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/init.c.o +.PHONY : src/init.c.o + +src/init.i: src/init.c.i + +.PHONY : src/init.i + +# target to preprocess a source file +src/init.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/init.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/init.c.i +.PHONY : src/init.c.i + +src/init.s: src/init.c.s + +.PHONY : src/init.s + +# target to generate assembly for a file +src/init.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/init.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/init.c.s +.PHONY : src/init.c.s + +src/options.o: src/options.c.o + +.PHONY : src/options.o + +# target to build an object file +src/options.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/options.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/options.c.o +.PHONY : src/options.c.o + +src/options.i: src/options.c.i + +.PHONY : src/options.i + +# target to preprocess a source file +src/options.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/options.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/options.c.i +.PHONY : src/options.c.i + +src/options.s: src/options.c.s + +.PHONY : src/options.s + +# target to generate assembly for a file +src/options.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/options.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/options.c.s +.PHONY : src/options.c.s + +src/os.o: src/os.c.o + +.PHONY : src/os.o + +# target to build an object file +src/os.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/os.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/os.c.o +.PHONY : src/os.c.o + +src/os.i: src/os.c.i + +.PHONY : src/os.i + +# target to preprocess a source file +src/os.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/os.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/os.c.i +.PHONY : src/os.c.i + +src/os.s: src/os.c.s + +.PHONY : src/os.s + +# target to generate assembly for a file +src/os.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/os.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/os.c.s +.PHONY : src/os.c.s + +src/page.o: src/page.c.o + +.PHONY : src/page.o + +# target to build an object file +src/page.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/page.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/page.c.o +.PHONY : src/page.c.o + +src/page.i: src/page.c.i + +.PHONY : src/page.i + +# target to preprocess a source file +src/page.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/page.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/page.c.i +.PHONY : src/page.c.i + +src/page.s: src/page.c.s + +.PHONY : src/page.s + +# target to generate assembly for a file +src/page.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/page.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/page.c.s +.PHONY : src/page.c.s + +src/random.o: src/random.c.o + +.PHONY : src/random.o + +# target to build an object file +src/random.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/random.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/random.c.o +.PHONY : src/random.c.o + +src/random.i: src/random.c.i + +.PHONY : src/random.i + +# target to preprocess a source file +src/random.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/random.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/random.c.i +.PHONY : src/random.c.i + +src/random.s: src/random.c.s + +.PHONY : src/random.s + +# target to generate assembly for a file +src/random.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/random.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/random.c.s +.PHONY : src/random.c.s + +src/region.o: src/region.c.o + +.PHONY : src/region.o + +# target to build an object file +src/region.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/region.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/region.c.o +.PHONY : src/region.c.o + +src/region.i: src/region.c.i + +.PHONY : src/region.i + +# target to preprocess a source file +src/region.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/region.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/region.c.i +.PHONY : src/region.c.i + +src/region.s: src/region.c.s + +.PHONY : src/region.s + +# target to generate assembly for a file +src/region.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/region.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/region.c.s +.PHONY : src/region.c.s + +src/segment.o: src/segment.c.o + +.PHONY : src/segment.o + +# target to build an object file +src/segment.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/segment.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/segment.c.o +.PHONY : src/segment.c.o + +src/segment.i: src/segment.c.i + +.PHONY : src/segment.i + +# target to preprocess a source file +src/segment.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/segment.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/segment.c.i +.PHONY : src/segment.c.i + +src/segment.s: src/segment.c.s + +.PHONY : src/segment.s + +# target to generate assembly for a file +src/segment.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/segment.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/segment.c.s +.PHONY : src/segment.c.s + +src/static.o: src/static.c.o + +.PHONY : src/static.o + +# target to build an object file +src/static.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/src/static.c.o +.PHONY : src/static.c.o + +src/static.i: src/static.c.i + +.PHONY : src/static.i + +# target to preprocess a source file +src/static.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/src/static.c.i +.PHONY : src/static.c.i + +src/static.s: src/static.c.s + +.PHONY : src/static.s + +# target to generate assembly for a file +src/static.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-obj.dir/build.make CMakeFiles/mimalloc-obj.dir/src/static.c.s +.PHONY : src/static.c.s + +src/stats.o: src/stats.c.o + +.PHONY : src/stats.o + +# target to build an object file +src/stats.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/stats.c.o + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/stats.c.o +.PHONY : src/stats.c.o + +src/stats.i: src/stats.c.i + +.PHONY : src/stats.i + +# target to preprocess a source file +src/stats.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/stats.c.i + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/stats.c.i +.PHONY : src/stats.c.i + +src/stats.s: src/stats.c.s + +.PHONY : src/stats.s + +# target to generate assembly for a file +src/stats.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-static.dir/build.make CMakeFiles/mimalloc-static.dir/src/stats.c.s + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc.dir/build.make CMakeFiles/mimalloc.dir/src/stats.c.s +.PHONY : src/stats.c.s + +test/test-api.o: test/test-api.c.o + +.PHONY : test/test-api.o + +# target to build an object file +test/test-api.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/test/test-api.c.o +.PHONY : test/test-api.c.o + +test/test-api.i: test/test-api.c.i + +.PHONY : test/test-api.i + +# target to preprocess a source file +test/test-api.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/test/test-api.c.i +.PHONY : test/test-api.c.i + +test/test-api.s: test/test-api.c.s + +.PHONY : test/test-api.s + +# target to generate assembly for a file +test/test-api.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-api.dir/build.make CMakeFiles/mimalloc-test-api.dir/test/test-api.c.s +.PHONY : test/test-api.c.s + +test/test-stress.o: test/test-stress.c.o + +.PHONY : test/test-stress.o + +# target to build an object file +test/test-stress.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.o +.PHONY : test/test-stress.c.o + +test/test-stress.i: test/test-stress.c.i + +.PHONY : test/test-stress.i + +# target to preprocess a source file +test/test-stress.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.i +.PHONY : test/test-stress.c.i + +test/test-stress.s: test/test-stress.c.s + +.PHONY : test/test-stress.s + +# target to generate assembly for a file +test/test-stress.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/mimalloc-test-stress.dir/build.make CMakeFiles/mimalloc-test-stress.dir/test/test-stress.c.s +.PHONY : test/test-stress.c.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... rebuild_cache" + @echo "... test" + @echo "... mimalloc" + @echo "... mimalloc-obj" + @echo "... mimalloc-static" + @echo "... mimalloc-test-api" + @echo "... mimalloc-test-stress" + @echo "... src/alloc-aligned.o" + @echo "... src/alloc-aligned.i" + @echo "... src/alloc-aligned.s" + @echo "... src/alloc-posix.o" + @echo "... src/alloc-posix.i" + @echo "... src/alloc-posix.s" + @echo "... src/alloc.o" + @echo "... src/alloc.i" + @echo "... src/alloc.s" + @echo "... src/arena.o" + @echo "... src/arena.i" + @echo "... src/arena.s" + @echo "... src/heap.o" + @echo "... src/heap.i" + @echo "... src/heap.s" + @echo "... src/init.o" + @echo "... src/init.i" + @echo "... src/init.s" + @echo "... src/options.o" + @echo "... src/options.i" + @echo "... src/options.s" + @echo "... src/os.o" + @echo "... src/os.i" + @echo "... src/os.s" + @echo "... src/page.o" + @echo "... src/page.i" + @echo "... src/page.s" + @echo "... src/random.o" + @echo "... src/random.i" + @echo "... src/random.s" + @echo "... src/region.o" + @echo "... src/region.i" + @echo "... src/region.s" + @echo "... src/segment.o" + @echo "... src/segment.i" + @echo "... src/segment.s" + @echo "... src/static.o" + @echo "... src/static.i" + @echo "... src/static.s" + @echo "... src/stats.o" + @echo "... src/stats.i" + @echo "... src/stats.s" + @echo "... test/test-api.o" + @echo "... test/test-api.i" + @echo "... test/test-api.s" + @echo "... test/test-stress.o" + @echo "... test/test-stress.i" + @echo "... test/test-stress.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/deps/mimalloc/bin/cmake_install.cmake b/deps/mimalloc/bin/cmake_install.cmake new file mode 100644 index 000000000..ac4b46920 --- /dev/null +++ b/deps/mimalloc/bin/cmake_install.cmake @@ -0,0 +1,229 @@ +# Install script for directory: /home/hbina/git/KeyDB/deps/mimalloc + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Release") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6" + RPATH "") + endif() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6" TYPE SHARED_LIBRARY FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/libmimalloc.so.1.6") + if(EXISTS "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so.1.6") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so" + RPATH "") + endif() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/libmimalloc.so") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6" TYPE SHARED_LIBRARY FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/libmimalloc.so") + if(EXISTS "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/libmimalloc.so") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake") + file(DIFFERENT EXPORT_FILE_CHANGED FILES + "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake" + "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake") + if(EXPORT_FILE_CHANGED) + file(GLOB OLD_CONFIG_FILES "$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/cmake/mimalloc-*.cmake") + if(OLD_CONFIG_FILES) + message(STATUS "Old export file \"$ENV{DESTDIR}/usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake\" will be replaced. Removing files [${OLD_CONFIG_FILES}].") + file(REMOVE ${OLD_CONFIG_FILES}) + endif() + endif() + endif() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/cmake" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc.cmake") + if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$") + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/cmake" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/Export/_usr/local/lib/mimalloc-1.6/cmake/mimalloc-release.cmake") + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/libmimalloc.a") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6" TYPE STATIC_LIBRARY FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/libmimalloc.a") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/include/mimalloc.h") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/include" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/include/mimalloc.h") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/include/mimalloc-override.h") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/include" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/include/mimalloc-override.h") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/include/mimalloc-new-delete.h") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/include" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/include/mimalloc-new-delete.h") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/cmake/mimalloc-config.cmake") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/cmake" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/cmake/mimalloc-config.cmake") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/cmake/mimalloc-config-version.cmake") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6/cmake" TYPE FILE FILES "/home/hbina/git/KeyDB/deps/mimalloc/cmake/mimalloc-config-version.cmake") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + execute_process(COMMAND /usr/local/bin/cmake -E create_symlink mimalloc-1.6/libmimalloc.so.1.6 libmimalloc.so WORKING_DIRECTORY /usr/local/lib/mimalloc-1.6/..) +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + MESSAGE("-- Symbolic link: /usr/local/lib/libmimalloc.so -> mimalloc-1.6/libmimalloc.so.1.6") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/local/lib/mimalloc-1.6/mimalloc.o") + if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() + if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + endif() +file(INSTALL DESTINATION "/usr/local/lib/mimalloc-1.6" TYPE FILE RENAME "mimalloc.o" FILES "/home/hbina/git/KeyDB/deps/mimalloc/bin/CMakeFiles/mimalloc-obj.dir/src/static.c.o") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/hbina/git/KeyDB/deps/mimalloc/bin/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/deps/mimalloc/bin/libmimalloc.a b/deps/mimalloc/bin/libmimalloc.a new file mode 100644 index 0000000000000000000000000000000000000000..646c78ae688a83a8d054c8fa08ccae024063fc58 GIT binary patch literal 187350 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 W9>vw4e1p~J>zj^T`x@RL^M3$|1rc`u literal 0 HcmV?d00001 diff --git a/deps/mimalloc/bin/mimalloc-test-api b/deps/mimalloc/bin/mimalloc-test-api new file mode 100755 index 0000000000000000000000000000000000000000..ced5bdfe15515971d3b6bdaf9c8ff66c13830c53 GIT binary patch literal 143799 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

}d-x`(fd0X&JU@^1CI}L2>?`pgD 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 ZP2i?p!$|M+1(iQ_v6NroE8x4e{u4N=Jiq_| literal 0 HcmV?d00001 diff --git a/deps/mimalloc/bin/mimalloc-test-stress b/deps/mimalloc/bin/mimalloc-test-stress new file mode 100755 index 0000000000000000000000000000000000000000..fca151168ef4a54faf18f8951e4730d83d5e586d GIT binary patch literal 17616 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 J4h09x{s)rtqptt} literal 0 HcmV?d00001 diff --git a/src/Makefile b/src/Makefile index 5783dc2b8..c6488d916 100644 --- a/src/Makefile +++ b/src/Makefile @@ -246,6 +246,13 @@ ifeq ($(MIMALLOC),memkind) FINAL_LIBS := ../deps/memkind/src/.libs/libmemkind.a -lnuma $(FINAL_LIBS) endif +ifeq ($(MALLOC),mimalloc) + DEPENDENCY_TARGETS+= mimalloc + FINAL_CFLAGS+= -DUSE_MIMALLOC -I../deps/mimalloc/include + FINAL_CXXFLAGS+= -DUSE_MIMALLOC -I../deps/mimalloc/include + FINAL_LIBS := ../deps/mimalloc/bin/libmimalloc.a $(FINAL_LIBS) +endif + ifeq ($(BUILD_TLS),yes) FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CXXFLAGS) FINAL_CXXFLAGS+=-DUSE_OPENSSL $(OPENSSL_CXXFLAGS) diff --git a/src/zmalloc.cpp b/src/zmalloc.cpp index f88fee638..9bfe33a8c 100644 --- a/src/zmalloc.cpp +++ b/src/zmalloc.cpp @@ -77,6 +77,11 @@ static_assert((PREFIX_SIZE % 16) == 0, "Our prefix must be modulo 16-bytes or ou #define free(ptr) je_free(ptr) #define mallocx(size,flags) je_mallocx(size,flags) #define dallocx(ptr,flags) je_dallocx(ptr,flags) +#elif defined(USE_MIMALLOC) +#define malloc(size, type) mi_malloc(size) +#define calloc(count,size,type) mi_calloc(count,size) +#define realloc(ptr,size,type) mi_realloc(ptr,size) +#define free(ptr) mi_free(ptr) #else #define malloc(size, type) malloc(size) #define calloc(count,size,type) calloc(count,size) diff --git a/src/zmalloc.h b/src/zmalloc.h index 64497fa8d..222d4eda5 100644 --- a/src/zmalloc.h +++ b/src/zmalloc.h @@ -60,6 +60,10 @@ #error "Newer version of jemalloc required" #endif +#elif defined(USE_MIMALLOC) +#define ZMALLOC_LIB ("mimalloc-" __xstr(MIMALLOC_VERSION_MAJOR) "." __xstr(MIMALLOC_VERSION_MINOR) "." __xstr(MIMALLOC_VERSION_BUGFIX)) +#include + #elif defined(__APPLE__) #include #define HAVE_MALLOC_SIZE 1