diff --git a/.gitattributes b/.gitattributes
index 1534e778..0332e031 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9,3 +9,4 @@
*.patch binary
*.dll binary
*.lib binary
+*.exe binary
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 76c26666..544656a3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,7 @@ option(MI_XMALLOC "Enable abort() call on memory allocation failure by
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" OFF)
+option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON)
option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" ON)
option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF)
option(MI_BUILD_SHARED "Build shared library" ON)
@@ -21,10 +21,14 @@ 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)
+
+# deprecated options
option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF)
-option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF)
+option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version (deprecated)" OFF)
+option(MI_USE_LIBATOMIC "Explicitly link with -latomic (on older systems) (deprecated and detected automatically)" OFF)
option(MI_SKIP_COLLECT_ON_EXIT, "Skip collecting memory on exit" OFF)
+include(GNUInstallDirs)
include("cmake/mimalloc-config-version.cmake")
set(mi_sources
@@ -43,10 +47,12 @@ set(mi_sources
src/options.c
src/init.c)
+
# -----------------------------------------------------------------------------
-# Converience: set default build type depending on the build directory
+# Convenience: set default build type depending on the build directory
# -----------------------------------------------------------------------------
+message(STATUS "")
if (NOT CMAKE_BUILD_TYPE)
if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR MI_DEBUG_FULL)
message(STATUS "No build type selected, default to: Debug")
@@ -62,6 +68,7 @@ if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$")
set(MI_SECURE "ON")
endif()
+
# -----------------------------------------------------------------------------
# Process options
# -----------------------------------------------------------------------------
@@ -78,12 +85,20 @@ if(MI_OVERRIDE)
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_OSX_INTERPOSE)
+ message(STATUS " WARNING: zone overriding usually also needs interpose (use -DMI_OSX_INTERPOSE=ON)")
+ endif()
endif()
- if(MI_INTERPOSE)
+ if(MI_OSX_INTERPOSE)
# use interpose on macOS
- message(STATUS " Use interpose to override malloc (MI_INTERPOSE=ON)")
- message(STATUS " WARNING: interpose does not seem to work reliably on the M1; use -DMI_OSX_ZONE=ON instead")
- list(APPEND mi_defines MI_INTERPOSE)
+ message(STATUS " Use interpose to override malloc (MI_OSX_INTERPOSE=ON)")
+ list(APPEND mi_defines MI_OSX_INTERPOSE=1)
+ if (NOT MI_OSX_ZONE)
+ message(STATUS " WARNING: interpose usually also needs zone overriding (use -DMI_OSX_INTERPOSE=ON)")
+ endif()
+ endif()
+ if((NOT MI_USE_CXX) AND MI_OVERRIDE)
+ message(STATUS " WARNING: if overriding C++ new/delete, it is best to build mimalloc with a C++ compiler (use -DMI_USE_CXX=ON)")
endif()
endif()
endif()
@@ -171,9 +186,9 @@ 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()
+ if(NOT MI_USE_CXX)
+ list(APPEND mi_cflags -Wstrict-prototypes)
+ endif()
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang")
list(APPEND mi_cflags -Wpedantic -Wno-static-in-inline)
endif()
@@ -189,6 +204,9 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM
else()
list(APPEND mi_cflags -ftls-model=initial-exec)
endif()
+ if(MI_OVERRIDE)
+ list(APPEND mi_cflags -fno-builtin-malloc)
+ endif()
endif()
if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914)
@@ -199,12 +217,17 @@ endif()
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()
+ find_library(MI_LIBPTHREAD pthread)
+ if (MI_LIBPTHREAD)
+ list(APPEND mi_libraries ${MI_LIBPTHREAD})
+ endif()
+ find_library(MI_LIBRT rt)
+ if(MI_LIBRT)
+ list(APPEND mi_libraries ${MI_LIBRT})
+ endif()
+ find_library(MI_LIBATOMIC atomic)
+ if (MI_LIBATOMIC OR MI_USE_LIBATOMIC)
+ list(APPEND mi_libraries atomic)
endif()
endif()
@@ -212,14 +235,19 @@ endif()
# Install and output names
# -----------------------------------------------------------------------------
+# dynamic/shared library and symlinks always go to /usr/local/lib equivalent
+set(mi_install_libdir "${CMAKE_INSTALL_LIBDIR}")
+
+# static libraries and object files, includes, and cmake config files
+# are either installed at top level, or use versioned directories for side-by-side installation (default)
if (MI_INSTALL_TOPLEVEL)
- set(mi_install_libdir "lib")
- set(mi_install_incdir "include")
- set(mi_install_cmakedir "cmake")
+ set(mi_install_objdir "${CMAKE_INSTALL_LIBDIR}")
+ set(mi_install_incdir "${CMAKE_INSTALL_INCLUDEDIR}")
+ set(mi_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/mimalloc")
else()
- set(mi_install_libdir "lib/mimalloc-${mi_version}")
- set(mi_install_incdir "include/mimalloc-${mi_version}")
- set(mi_install_cmakedir "share/mimalloc-${mi_version}/cmake")
+ set(mi_install_objdir "${CMAKE_INSTALL_LIBDIR}/mimalloc-${mi_version}") # for static library and object files
+ set(mi_install_incdir "${CMAKE_INSTALL_INCLUDEDIR}/mimalloc-${mi_version}") # for includes
+ set(mi_install_cmakedir "${CMAKE_INSTALL_LIBDIR}/cmake/mimalloc-${mi_version}") # for cmake package info
endif()
if(MI_SECURE)
@@ -229,7 +257,7 @@ else()
endif()
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC)
-if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel)$"))
+if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel|none)$"))
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)
@@ -247,13 +275,16 @@ endif()
message(STATUS "")
message(STATUS "Library base name: ${mi_basename}")
+message(STATUS "Version : ${mi_version}")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE_LC}")
if(MI_USE_CXX)
- message(STATUS "Compiler : ${CMAKE_CXX_COMPILER}")
+ message(STATUS "C++ Compiler : ${CMAKE_CXX_COMPILER}")
else()
- message(STATUS "Compiler : ${CMAKE_C_COMPILER}")
+ message(STATUS "C Compiler : ${CMAKE_C_COMPILER}")
endif()
-message(STATUS "Version : ${mi_version}")
+message(STATUS "Compiler flags : ${mi_cflags}")
+message(STATUS "Compiler defines : ${mi_defines}")
+message(STATUS "Link libraries : ${mi_libraries}")
message(STATUS "Build targets : ${mi_build_targets}")
message(STATUS "")
@@ -264,7 +295,7 @@ message(STATUS "")
# shared library
if(MI_BUILD_SHARED)
add_library(mimalloc SHARED ${mi_sources})
- set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} OUTPUT_NAME ${mi_basename} )
+ set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} SOVERSION ${mi_version_major} 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})
@@ -310,7 +341,8 @@ if (MI_BUILD_STATIC)
set_target_properties(mimalloc-static PROPERTIES OUTPUT_NAME ${mi_basename})
endif()
- install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_libdir} LIBRARY)
+ install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_objdir} LIBRARY)
+ install(EXPORT mimalloc DESTINATION ${mi_install_cmakedir})
endif()
# install include files
@@ -320,16 +352,6 @@ install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_incdir})
install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_cmakedir})
install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_cmakedir})
-if(NOT WIN32 AND MI_BUILD_SHARED AND NOT MI_INSTALL_TOPLEVEL)
- # install a symlink in the /usr/local/lib to the versioned library
- # note: use delayed prefix expansion as \${CMAKE_INSTALL_PREFIX}
- 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 \${CMAKE_INSTALL_PREFIX}/lib)")
- install(CODE "MESSAGE(\"-- Symbolic link: \${CMAKE_INSTALL_PREFIX}/lib/${mi_symlink} -> ${mi_soname}\")")
- install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${mi_soname} ${mi_symlink}.${mi_version} WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/lib)")
- install(CODE "MESSAGE(\"-- Symbolic link: \${CMAKE_INSTALL_PREFIX}/lib/${mi_symlink}.${mi_version} -> ${mi_soname}\")")
-endif()
# single object file for more predictable static overriding
if (MI_BUILD_OBJECT)
@@ -343,12 +365,12 @@ if (MI_BUILD_OBJECT)
)
# the following seems to lead to cmake warnings/errors on some systems, disable for now :-(
- # install(TARGETS mimalloc-obj EXPORT mimalloc DESTINATION ${mi_install_libdir})
+ # install(TARGETS mimalloc-obj EXPORT mimalloc DESTINATION ${mi_install_objdir})
# 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_libdir}
+ DESTINATION ${mi_install_objdir}
RENAME ${mi_basename}${CMAKE_C_OUTPUT_EXTENSION} )
endif()
@@ -357,21 +379,17 @@ endif()
# -----------------------------------------------------------------------------
if (MI_BUILD_TESTS)
- 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)
+
+ foreach(TEST_NAME api api-fill stress)
+ add_executable(mimalloc-test-${TEST_NAME} test/test-${TEST_NAME}.c)
+ target_compile_definitions(mimalloc-test-${TEST_NAME} PRIVATE ${mi_defines})
+ target_compile_options(mimalloc-test-${TEST_NAME} PRIVATE ${mi_cflags})
+ target_include_directories(mimalloc-test-${TEST_NAME} PRIVATE include)
+ target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc ${mi_libraries})
+
+ add_test(NAME test-${TEST_NAME} COMMAND mimalloc-test-${TEST_NAME})
+ endforeach()
endif()
# -----------------------------------------------------------------------------
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index aeb2908b..cfaf1876 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -43,7 +43,7 @@ jobs:
solution: $(BuildType)/libmimalloc.sln
configuration: '$(MSBuildConfiguration)'
msbuildArguments: -m
- - script: ctest --verbose --timeout 120
+ - script: ctest --verbose --timeout 120 -C $(MSBuildConfiguration)
workingDirectory: $(BuildType)
displayName: CTest
#- script: $(BuildType)\$(BuildType)\mimalloc-test-stress
@@ -115,7 +115,7 @@ jobs:
displayName: macOS
pool:
vmImage:
- macOS-10.14
+ macOS-latest
strategy:
matrix:
Debug:
diff --git a/bin/mimalloc-redirect.dll b/bin/mimalloc-redirect.dll
index b7bf1d09..83b6bd4f 100644
Binary files a/bin/mimalloc-redirect.dll and b/bin/mimalloc-redirect.dll differ
diff --git a/bin/mimalloc-redirect.lib b/bin/mimalloc-redirect.lib
index 550db8ec..059fb870 100644
Binary files a/bin/mimalloc-redirect.lib and b/bin/mimalloc-redirect.lib differ
diff --git a/bin/mimalloc-redirect32.dll b/bin/mimalloc-redirect32.dll
index 7ba303af..2892d459 100644
Binary files a/bin/mimalloc-redirect32.dll and b/bin/mimalloc-redirect32.dll differ
diff --git a/bin/mimalloc-redirect32.lib b/bin/mimalloc-redirect32.lib
index 66173060..7dadab3d 100644
Binary files a/bin/mimalloc-redirect32.lib and b/bin/mimalloc-redirect32.lib differ
diff --git a/bin/minject.exe b/bin/minject.exe
new file mode 100644
index 00000000..e5f87800
Binary files /dev/null and b/bin/minject.exe differ
diff --git a/bin/minject32.exe b/bin/minject32.exe
new file mode 100644
index 00000000..d0181028
Binary files /dev/null and b/bin/minject32.exe differ
diff --git a/cmake/mimalloc-config-version.cmake b/cmake/mimalloc-config-version.cmake
index ed95c19e..7bbd7313 100644
--- a/cmake/mimalloc-config-version.cmake
+++ b/cmake/mimalloc-config-version.cmake
@@ -1,5 +1,6 @@
set(mi_version_major 1)
set(mi_version_minor 7)
+set(mi_version_patch 4)
set(mi_version ${mi_version_major}.${mi_version_minor})
set(PACKAGE_VERSION ${mi_version})
diff --git a/cmake/mimalloc-config.cmake b/cmake/mimalloc-config.cmake
index 024c97d9..8a28e37e 100644
--- a/cmake/mimalloc-config.cmake
+++ b/cmake/mimalloc-config.cmake
@@ -1,11 +1,14 @@
include(${CMAKE_CURRENT_LIST_DIR}/mimalloc.cmake)
-get_filename_component(MIMALLOC_SHARE_DIR "${CMAKE_CURRENT_LIST_DIR}" PATH) # one up from the cmake dir, e.g. /usr/local/share/mimalloc-2.0
-if (MIMALLOC_SHARE_DIR MATCHES "/share/")
- string(REPLACE "/share/" "/lib/" MIMALLOC_LIBRARY_DIR ${MIMALLOC_SHARE_DIR})
- string(REPLACE "/share/" "/include/" MIMALLOC_INCLUDE_DIR ${MIMALLOC_SHARE_DIR})
-else()
- # if MI_INSTALL_TOPLEVEL==ON
- set(MIMALLOC_LIBRARY_DIR "${MIMALLOC_SHARE_DIR}/lib")
- set(MIMALLOC_INCLUDE_DIR "${MIMALLOC_SHARE_DIR}/include")
+get_filename_component(MIMALLOC_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}" PATH) # one up from the cmake dir, e.g. /usr/local/lib/cmake/mimalloc-2.0
+get_filename_component(MIMALLOC_VERSION_DIR "${CMAKE_CURRENT_LIST_DIR}" NAME)
+string(REPLACE "/lib/cmake" "/lib" MIMALLOC_LIBRARY_DIR "${MIMALLOC_CMAKE_DIR}")
+if("${MIMALLOC_VERSION_DIR}" EQUAL "mimalloc")
+ # top level install
+ string(REPLACE "/lib/cmake" "/include" MIMALLOC_INCLUDE_DIR "${MIMALLOC_CMAKE_DIR}")
+ set(MIMALLOC_OBJECT_DIR "${MIMALLOC_LIBRARY_DIR}")
+else()
+ # versioned
+ string(REPLACE "/lib/cmake/" "/include/" MIMALLOC_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}")
+ string(REPLACE "/lib/cmake/" "/lib/" MIMALLOC_OBJECT_DIR "${CMAKE_CURRENT_LIST_DIR}")
endif()
set(MIMALLOC_TARGET_DIR "${MIMALLOC_LIBRARY_DIR}") # legacy
diff --git a/doc/doxyfile b/doc/doxyfile
index 6c1e30a0..73266f4e 100644
--- a/doc/doxyfile
+++ b/doc/doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.15
+# Doxyfile 1.9.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -38,7 +38,7 @@ PROJECT_NAME = mi-malloc
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 1.6
+PROJECT_NUMBER = 1.7/2.0
# 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
@@ -197,6 +197,16 @@ SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# 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
@@ -217,6 +227,14 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# 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.
@@ -253,12 +271,6 @@ TAB_SIZE = 2
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
@@ -299,19 +311,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
# 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,
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
# 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.
+# default for Fortran type files). 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.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
@@ -329,7 +344,7 @@ MARKDOWN_SUPPORT = YES
# 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.
+# Minimum value: 0, maximum value: 99, default value: 5.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
TOC_INCLUDE_HEADINGS = 0
@@ -445,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = YES
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which efficively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -465,6 +493,12 @@ EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = 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.
@@ -502,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# 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
@@ -519,8 +560,8 @@ HIDE_UNDOC_MEMBERS = 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.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
@@ -539,11 +580,18 @@ HIDE_IN_BODY_DOCS = 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.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
# The default value is: system dependent.
CASE_SENSE_NAMES = NO
@@ -782,7 +830,10 @@ WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# The default value is: NO.
WARN_AS_ERROR = NO
@@ -818,8 +869,8 @@ 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.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
@@ -832,11 +883,15 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
# 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.
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
+# *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \
*.cc \
@@ -1094,16 +1149,22 @@ USE_HTAGS = NO
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.
+# 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 and the CLANG_ADD_INC_PATHS tag is set to
+# YES then doxygen will add the directory of each input to the include path.
+# The default value is: YES.
+
+CLANG_ADD_INC_PATHS = YES
+
# 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
@@ -1113,10 +1174,13 @@ CLANG_ASSISTED_PARSING = NO
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.
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source 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. Any options specified with CLANG_OPTIONS
+# will be added as well.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse_libclang=ON option for CMake.
@@ -1133,13 +1197,6 @@ CLANG_DATABASE_PATH =
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
@@ -1278,9 +1335,9 @@ 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
+# 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,
+# 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.
@@ -1310,10 +1367,11 @@ 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
+# 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.
@@ -1355,8 +1413,8 @@ 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.
+# (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
@@ -1386,7 +1444,7 @@ CHM_FILE =
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).
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1431,7 +1489,8 @@ 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).
+# (see:
+# https://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.
@@ -1439,8 +1498,8 @@ 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).
+# Folders (see:
+# https://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.
@@ -1448,30 +1507,30 @@ 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).
+# Filters (see:
+# https://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).
+# Filters (see:
+# https://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).
+# https://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.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) 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 =
@@ -1548,6 +1607,17 @@ TREEVIEW_WIDTH = 180
EXT_LINKS_IN_WINDOW = NO
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# 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
@@ -1568,8 +1638,14 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# https://www.mathjax.org) which uses client side Javascript for the rendering
+# 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
@@ -1581,7 +1657,7 @@ 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.
+# http://docs.mathjax.org/en/v2.7-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.
@@ -1597,7 +1673,7 @@ MATHJAX_FORMAT = HTML-CSS
# 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/.
+# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
@@ -1611,7 +1687,8 @@ 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
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1639,7 +1716,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
@@ -1658,7 +1735,8 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1671,8 +1749,9 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
@@ -1743,10 +1822,11 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
-# generate index for LaTeX.
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
# Note: This tag is used in the generated output file (.tex).
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
-# The default value is: \makeindex.
+# The default value is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_MAKEINDEX_CMD = \makeindex
@@ -1835,9 +1915,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -2076,6 +2158,10 @@ DOCBOOK_PROGRAMLISTING = NO
GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
@@ -2238,12 +2324,6 @@ EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of 'which perl').
-# The default file (with absolute path) is: /usr/bin/perl.
-
-PERL_PATH = /usr/bin/perl
-
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
@@ -2257,15 +2337,6 @@ PERL_PATH = /usr/bin/perl
CLASS_DIAGRAMS = YES
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see:
-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH =
-
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2363,10 +2434,32 @@ UML_LOOK = NO
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
@@ -2556,9 +2649,11 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc and
+# plantuml temporary files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/doc/ds-logo.jpg b/doc/ds-logo.jpg
index 853a7279..c9abb1a9 100644
Binary files a/doc/ds-logo.jpg and b/doc/ds-logo.jpg differ
diff --git a/doc/ds-logo.png b/doc/ds-logo.png
new file mode 100644
index 00000000..93b84e44
Binary files /dev/null and b/doc/ds-logo.png differ
diff --git a/doc/mimalloc-doc.h b/doc/mimalloc-doc.h
index b448f14a..ea2a1ad5 100644
--- a/doc/mimalloc-doc.h
+++ b/doc/mimalloc-doc.h
@@ -51,7 +51,7 @@ Notable aspects of the design include:
programs.
- __secure__: _mimalloc_ can be build in secure mode, adding guard pages,
randomized allocation, encrypted free lists, etc. to protect against various
- heap vulnerabilities. The performance penalty is only around 3% on average
+ heap vulnerabilities. The performance penalty is only around 5% 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.
@@ -413,6 +413,28 @@ void mi_register_error(mi_error_fun* errfun, void* arg);
/// This function is relatively fast.
bool mi_is_in_heap_region(const void* p);
+/// Reserve OS memory for use by mimalloc. Reserved areas are used
+/// before allocating from the OS again. By reserving a large area upfront,
+/// allocation can be more efficient, and can be better managed on systems
+/// without `mmap`/`VirtualAlloc` (like WASM for example).
+/// @param size The size to reserve.
+/// @param commit Commit the memory upfront.
+/// @param allow_large Allow large OS pages (2MiB) to be used?
+/// @return \a 0 if successful, and an error code otherwise (e.g. `ENOMEM`).
+int mi_reserve_os_memory(size_t size, bool commit, bool allow_large);
+
+/// Manage a particular memory area for use by mimalloc.
+/// This is just like `mi_reserve_os_memory` except that the area should already be
+/// allocated in some manner and available for use my mimalloc.
+/// @param start Start of the memory area
+/// @param size The size of the memory area.
+/// @param commit Is the area already committed?
+/// @param is_large Does it consist of large OS pages? Set this to \a true as well for memory
+/// that should not be decommitted or protected (like rdma etc.)
+/// @param is_zero Does the area consists of zero's?
+/// @param numa_node Possible associated numa node or `-1`.
+/// @return \a true if successful, and \a false on error.
+bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node);
/// Reserve \a pages of huge OS pages (1GiB) evenly divided over \a numa_nodes nodes,
/// but stops after at most `timeout_msecs` seconds.
@@ -476,9 +498,12 @@ void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_m
///
/// \{
+/// The maximum supported alignment size (currently 1MiB).
+#define MI_ALIGNMENT_MAX (1024*1024UL)
+
/// Allocate \a size bytes aligned by \a alignment.
/// @param size number of bytes to allocate.
-/// @param alignment the minimal alignment of the allocated memory.
+/// @param alignment the minimal alignment of the allocated memory. Must be less than #MI_ALIGNMENT_MAX.
/// @returns pointer to the allocated memory or \a NULL if out of memory.
/// The returned pointer is aligned by \a alignment, i.e.
/// `(uintptr_t)p % alignment == 0`.
@@ -777,19 +802,32 @@ typedef enum mi_option_e {
mi_option_show_errors, ///< Print error messages to `stderr`.
mi_option_show_stats, ///< Print statistics to `stderr` when the program is done.
mi_option_verbose, ///< Print verbose messages to `stderr`.
+
// the following options are experimental
mi_option_eager_commit, ///< Eagerly commit segments (4MiB) (enabled by default).
- mi_option_eager_region_commit, ///< Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
mi_option_large_os_pages, ///< Use large OS pages (2MiB in size) if possible
mi_option_reserve_huge_os_pages, ///< The number of huge OS pages (1GiB in size) to reserve at the start of the program.
- mi_option_segment_cache, ///< The number of segments per thread to keep cached.
+ mi_option_reserve_huge_os_pages_at, ///< Reserve huge OS pages at node N.
+ mi_option_reserve_os_memory, ///< Reserve specified amount of OS memory at startup, e.g. "1g" or "512m".
+ mi_option_segment_cache, ///< The number of segments per thread to keep cached (0).
mi_option_page_reset, ///< Reset page memory after \a mi_option_reset_delay milliseconds when it becomes free.
+ mi_option_abandoned_page_reset, //< Reset free page memory when a thread terminates.
+ mi_option_use_numa_nodes, ///< Pretend there are at most N NUMA nodes; Use 0 to use the actual detected NUMA nodes at runtime.
+ mi_option_eager_commit_delay, ///< the first N segments per thread are not eagerly committed (=1).
+ mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory
+ mi_option_limit_os_alloc, ///< If set to 1, do not use OS memory for allocation (but only pre-reserved arenas)
+
+ // v1.x specific options
+ mi_option_eager_region_commit, ///< Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
mi_option_segment_reset, ///< Experimental
mi_option_reset_delay, ///< Delay in milli-seconds before resetting a page (100ms by default)
- mi_option_use_numa_nodes, ///< Pretend there are at most N NUMA nodes
mi_option_reset_decommits, ///< Experimental
- mi_option_eager_commit_delay, ///< Experimental
- mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory
+
+ // v2.x specific options
+ mi_option_allow_decommit, ///< Enable decommitting memory (=on)
+ mi_option_decommit_delay, ///< Decommit page memory after N milli-seconds delay (25ms).
+ mi_option_segment_decommit_delay, ///< Decommit large segment memory after N milli-seconds delay (500ms).
+
_mi_option_last
} mi_option_t;
@@ -828,8 +866,14 @@ void* mi_valloc(size_t size);
void* mi_pvalloc(size_t size);
void* mi_aligned_alloc(size_t alignment, size_t size);
+
+/// Correspond s to [reallocarray](https://www.freebsd.org/cgi/man.cgi?query=reallocarray&sektion=3&manpath=freebsd-release-ports)
+/// in FreeBSD.
void* mi_reallocarray(void* p, size_t count, size_t size);
+/// Corresponds to [reallocarr](https://man.netbsd.org/reallocarr.3) in NetBSD.
+int mi_reallocarr(void* p, size_t count, size_t size);
+
void mi_free_size(void* p, size_t size);
void mi_free_size_aligned(void* p, size_t size, size_t alignment);
void mi_free_aligned(void* p, size_t alignment);
@@ -1053,6 +1097,8 @@ or via environment variables.
`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).
+- `MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N`: where N is the numa node. This reserves the huge pages at a specific numa node.
+ (`N` is -1 by default to reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected))
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
@@ -1158,6 +1204,12 @@ void* calloc(size_t size, size_t n);
void* realloc(void* p, size_t newsize);
void free(void* p);
+void* aligned_alloc(size_t alignment, size_t size);
+char* strdup(const char* s);
+char* strndup(const char* s, size_t n);
+char* realpath(const char* fname, char* resolved_name);
+
+
// C++
void operator delete(void* p);
void operator delete[](void* p);
@@ -1177,16 +1229,24 @@ int posix_memalign(void** p, size_t alignment, size_t size);
// Linux
void* memalign(size_t alignment, size_t size);
-void* aligned_alloc(size_t alignment, size_t size);
void* valloc(size_t size);
void* pvalloc(size_t size);
size_t malloc_usable_size(void *p);
+void* reallocf(void* p, size_t newsize);
+
+// macOS
+void vfree(void* p);
+size_t malloc_size(const void* p);
+size_t malloc_good_size(size_t size);
// BSD
void* reallocarray( void* p, size_t count, size_t size );
void* reallocf(void* p, size_t newsize);
void cfree(void* p);
+// NetBSD
+int reallocarr(void* p, size_t count, size_t size);
+
// Windows
void* _expand(void* p, size_t newsize);
size_t _msize(void* p);
diff --git a/doc/spades-logo.png b/doc/spades-logo.png
new file mode 100644
index 00000000..d8c73fef
Binary files /dev/null and b/doc/spades-logo.png differ
diff --git a/doc/unreal-logo.svg b/doc/unreal-logo.svg
new file mode 100644
index 00000000..5d5192a2
--- /dev/null
+++ b/doc/unreal-logo.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/annotated.html b/docs/annotated.html
index feba2438..f3e392a4 100644
--- a/docs/annotated.html
+++ b/docs/annotated.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Data Structures
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -113,9 +109,7 @@ $(document).ready(function(){initNavTree('annotated.html','');});
diff --git a/docs/bench.html b/docs/bench.html
index f39fade6..6c472895 100644
--- a/docs/bench.html
+++ b/docs/bench.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Performance
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -103,17 +99,15 @@ $(document).ready(function(){initNavTree('bench.html','');});
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 benchmarks, mimalloc always outperforms all other leading allocators (jemalloc , tcmalloc , Hoard , etc) (Apr 2019), and usually uses less memory (up to 25% more in the worst case). A nice property is that it does consistently well over the wide range of benchmarks.
+
In our benchmarks, mimalloc always outperforms all other leading allocators (jemalloc , tcmalloc , Hoard , etc) (Jan 2021), and usually uses less memory (up to 25% more in the worst case). A nice property is that it does consistently well over the wide range of benchmarks.
See the Performance section in the mimalloc repository for benchmark results, or the the technical report for detailed benchmark results.
-
-
+
+
diff --git a/docs/build.html b/docs/build.html
index 2bd06f13..dbcc0d75 100644
--- a/docs/build.html
+++ b/docs/build.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Building
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -102,28 +98,39 @@ $(document).ready(function(){initNavTree('build.html','');});
Building
-
Checkout the sources from Github:
Windows
+
Checkout the sources from Github:
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
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
).
+
> 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.
+
> 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:
Install CMake: sudo apt-get install cmake
Install CCMake: sudo apt-get install cmake-curses-gui
-
-
+
+
diff --git a/docs/classes.html b/docs/classes.html
index e74a0a24..b744c4d9 100644
--- a/docs/classes.html
+++ b/docs/classes.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Data Structure Index
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -102,23 +98,18 @@ $(document).ready(function(){initNavTree('classes.html','');});
Data Structure Index
diff --git a/docs/doxygen.css b/docs/doxygen.css
index 72384716..f090ef79 100644
--- a/docs/doxygen.css
+++ b/docs/doxygen.css
@@ -1,4 +1,4 @@
-/* The standard CSS for doxygen 1.8.15 */
+/* The standard CSS for doxygen 1.9.1 */
body, table, div, p, dl {
font: 400 14px/22px Roboto,sans-serif;
@@ -53,17 +53,24 @@ dt {
font-weight: bold;
}
-div.multicol {
+ul.multicol {
-moz-column-gap: 1em;
-webkit-column-gap: 1em;
+ column-gap: 1em;
-moz-column-count: 3;
-webkit-column-count: 3;
+ column-count: 3;
}
p.startli, p.startdd {
margin-top: 2px;
}
+th p.starttd, th p.intertd, th p.endtd {
+ font-size: 100%;
+ font-weight: 700;
+}
+
p.starttd {
margin-top: 0px;
}
@@ -96,30 +103,96 @@ caption {
}
span.legend {
- font-size: 70%;
- text-align: center;
-}
-
-h3.version {
- font-size: 90%;
- text-align: center;
-}
-
-div.qindex, div.navtab{
- background-color: #D6D9D9;
- border: 1px solid #636C6D;
+ font-size: 70%;
text-align: center;
}
-div.qindex, div.navpath {
- width: 100%;
- line-height: 140%;
+h3.version {
+ font-size: 90%;
+ text-align: center;
}
div.navtab {
- margin-right: 15px;
+ border-right: 1px solid #636C6D;
+ padding-right: 15px;
+ text-align: right;
+ line-height: 110%;
}
+div.navtab table {
+ border-spacing: 0;
+}
+
+td.navtab {
+ padding-right: 6px;
+ padding-left: 6px;
+}
+td.navtabHL {
+ background-image: url('tab_a.png');
+ background-repeat:repeat-x;
+ padding-right: 6px;
+ padding-left: 6px;
+}
+
+td.navtabHL a, td.navtabHL a:visited {
+ color: #fff;
+ text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
+}
+
+a.navtab {
+ font-weight: bold;
+}
+
+div.qindex{
+ text-align: center;
+ width: 100%;
+ line-height: 140%;
+ font-size: 130%;
+ color: #A0A0A0;
+}
+
+dt.alphachar{
+ font-size: 180%;
+ font-weight: bold;
+}
+
+.alphachar a{
+ color: black;
+}
+
+.alphachar a:hover, .alphachar a:visited{
+ text-decoration: none;
+}
+
+.classindex dl {
+ padding: 25px;
+ column-count:1
+}
+
+.classindex dd {
+ display:inline-block;
+ margin-left: 50px;
+ width: 90%;
+ line-height: 1.15em;
+}
+
+.classindex dl.odd {
+ background-color: #F0F1F1;
+}
+
+@media(min-width: 1120px) {
+ .classindex dl {
+ column-count:2
+ }
+}
+
+@media(min-width: 1320px) {
+ .classindex dl {
+ column-count:3
+ }
+}
+
+
/* @group Link Styling */
a {
@@ -136,17 +209,6 @@ a:hover {
text-decoration: underline;
}
-a.qindex {
- font-weight: bold;
-}
-
-a.qindexHL {
- font-weight: bold;
- background-color: #5B6364;
- color: #FFFFFF;
- border: 1px double #464C4D;
-}
-
.contents a.qindexHL:visited {
color: #FFFFFF;
}
@@ -533,7 +595,7 @@ table.memberdecls {
white-space: nowrap;
}
-.memItemRight {
+.memItemRight, .memTemplItemRight {
width: 100%;
}
@@ -701,7 +763,7 @@ dl.reflist dd {
padding-left: 0px;
}
-.params .paramname, .retval .paramname, .tparams .paramname {
+.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname {
font-weight: bold;
vertical-align: top;
}
@@ -1351,10 +1413,12 @@ dl.citelist dt {
font-weight:bold;
margin-right:10px;
padding:5px;
+ text-align:right;
+ width:52px;
}
dl.citelist dd {
- margin:2px 0;
+ margin:2px 0 2px 72px;
padding:5px 0;
}
@@ -1417,6 +1481,12 @@ div.toc li.level4 {
margin-left: 45px;
}
+span.emoji {
+ /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html
+ * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;
+ */
+}
+
.PageDocRTL-title div.toc li.level1 {
margin-left: 0 !important;
margin-right: 0;
@@ -1654,47 +1724,6 @@ tr.heading h2 {
/* @group Markdown */
-/*
-table.markdownTable {
- border-collapse:collapse;
- margin-top: 4px;
- margin-bottom: 4px;
-}
-
-table.markdownTable td, table.markdownTable th {
- border: 1px solid #060606;
- padding: 3px 7px 2px;
-}
-
-table.markdownTableHead tr {
-}
-
-table.markdownTableBodyLeft td, table.markdownTable th {
- border: 1px solid #060606;
- padding: 3px 7px 2px;
-}
-
-th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone {
- background-color: #0B0C0C;
- color: #FFFFFF;
- font-size: 110%;
- padding-bottom: 4px;
- padding-top: 5px;
-}
-
-th.markdownTableHeadLeft {
- text-align: left
-}
-
-th.markdownTableHeadRight {
- text-align: right
-}
-
-th.markdownTableHeadCenter {
- text-align: center
-}
-*/
-
table.markdownTable {
border-collapse:collapse;
margin-top: 4px;
diff --git a/docs/dynsections.js b/docs/dynsections.js
index ea0a7b39..3174bd7b 100644
--- a/docs/dynsections.js
+++ b/docs/dynsections.js
@@ -1,25 +1,26 @@
/*
- @licstart The following is the entire license notice for the
- JavaScript code in this file.
+ @licstart The following is the entire license notice for the JavaScript code in this file.
- Copyright (C) 1997-2017 by Dimitri van Heesch
+ The MIT License (MIT)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ Copyright (C) 1997-2020 by Dimitri van Heesch
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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:
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
- @licend The above is the entire license notice
- for the JavaScript code in this file
+ 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.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
*/
function toggleVisibility(linkObj)
{
diff --git a/docs/environment.html b/docs/environment.html
index 87d67e4a..f571f95f 100644
--- a/docs/environment.html
+++ b/docs/environment.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Environment Options
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -110,17 +106,16 @@ $(document).ready(function(){initNavTree('environment.html','');});
MIMALLOC_PAGE_RESET=0
: by default, mimalloc will reset (or purge) OS pages when 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
no such page resets will be done which can improve performance for programs that are not long running. As an alternative, the MIMALLOC_RESET_DELAY=
<msecs> can be set higher (100ms by default) to make the page reset occur less frequently instead of turning it off completely.
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 and Linux ). 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 when 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 and Linux )). 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).
+
MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N
: where N is the numa node. This reserves the huge pages at a specific numa node. (N
is -1 by default to reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected))
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.
-
-
+
+
diff --git a/docs/functions.html b/docs/functions.html
index 62021210..373fafe2 100644
--- a/docs/functions.html
+++ b/docs/functions.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Data Fields
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -120,9 +116,7 @@ $(document).ready(function(){initNavTree('functions.html','');});
diff --git a/docs/functions_vars.html b/docs/functions_vars.html
index 7d41d10e..a12ef622 100644
--- a/docs/functions_vars.html
+++ b/docs/functions_vars.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Data Fields - Variables
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -120,9 +116,7 @@ $(document).ready(function(){initNavTree('functions_vars.html','');});
diff --git a/docs/group__aligned.html b/docs/group__aligned.html
index a3eaacf0..bd11f30f 100644
--- a/docs/group__aligned.html
+++ b/docs/group__aligned.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Aligned Allocation
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -99,6 +95,7 @@ $(document).ready(function(){initNavTree('group__aligned.html','');});
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -119,22 +115,22 @@ Data Structures
typedef bool() mi_block_visit_fun (const mi_heap_t *heap, const mi_heap_area_t *area, void *block, size_t block_size, void *arg)
-
Visitor function passed to mi_heap_visit_blocks() More...
+
Visitor function passed to mi_heap_visit_blocks() More...
@@ -376,9 +372,7 @@ bytes in use by allocated blocks
diff --git a/docs/group__cpp.html b/docs/group__cpp.html
index 88c75888..e81179fe 100644
--- a/docs/group__cpp.html
+++ b/docs/group__cpp.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: C++ wrappers
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -118,25 +114,25 @@ Data Structures
void * mi_new (std::size_t n) noexcept(false)
-
like mi_malloc() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
+
like mi_malloc() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
void * mi_new_n (size_t count, size_t size) noexcept(false)
-
like mi_mallocn() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
+
like mi_mallocn() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
void * mi_new_aligned (std::size_t n, std::align_val_t alignment) noexcept(false)
-
like mi_malloc_aligned() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
+
like mi_malloc_aligned() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
void * mi_new_nothrow (size_t n)
-
like mi_malloc
, but when out of memory, use std::get_new_handler
but return NULL on failure. More...
+
like mi_malloc
, but when out of memory, use std::get_new_handler
but return NULL on failure. More...
void * mi_new_aligned_nothrow (size_t n, size_t alignment)
-
like mi_malloc_aligned
, but when out of memory, use std::get_new_handler
but return NULL on failure. More...
+
like mi_malloc_aligned
, but when out of memory, use std::get_new_handler
but return NULL on failure. More...
void * mi_new_realloc (void *p, size_t newsize)
-
like mi_realloc() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
+
like mi_realloc() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
void * mi_new_reallocn (void *p, size_t newcount, size_t size)
-
like mi_reallocn() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
+
like mi_reallocn() , but when out of memory, use std::get_new_handler
and raise std::bad_alloc
exception on failure. More...
@@ -158,7 +154,10 @@ Functions
struct mi_stl_allocator< T >
std::allocator implementation for mimalloc for use in STL containers.
-
For example:
std::vector<int, mi_stl_allocator<int> > vec;
vec.push_back(1);
vec.pop_back();
+For example:
std::vector<int, mi_stl_allocator<int> > vec;
+
vec.push_back(1);
+
vec.pop_back();
+
@@ -387,9 +386,7 @@ struct mi_stl_allocator< T >
diff --git a/docs/group__extended.html b/docs/group__extended.html
index 12e51cbb..e5499118 100644
--- a/docs/group__extended.html
+++ b/docs/group__extended.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Extended Functions
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -113,82 +109,88 @@ $(document).ready(function(){initNavTree('group__extended.html','');});
#define MI_SMALL_SIZE_MAX
-
Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof(void*)
(= 1KB on 64-bit systems)) More...
+
Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof(void*)
(= 1KB on 64-bit systems)) More...
typedef void() mi_deferred_free_fun (bool force, unsigned long long heartbeat, void *arg)
- Type of deferred free functions. More...
+ Type of deferred free functions. More...
typedef void() mi_output_fun (const char *msg, void *arg)
- Type of output functions. More...
+ Type of output functions. More...
typedef void() mi_error_fun (int err, void *arg)
- Type of error callback functions. More...
+ Type of error callback functions. More...
void * mi_malloc_small (size_t size)
- Allocate a small object. More...
+ Allocate a small object. More...
void * mi_zalloc_small (size_t size)
- Allocate a zero initialized small object. More...
+ Allocate a zero initialized small object. More...
size_t mi_usable_size (void *p)
- Return the available bytes in a memory block. More...
+ Return the available bytes in a memory block. More...
size_t mi_good_size (size_t size)
- Return the used allocation size. More...
+ Return the used allocation size. More...
void mi_collect (bool force)
- Eagerly free memory. More...
+ Eagerly free memory. More...
void mi_stats_print (void *out)
- Deprecated. More...
+ Deprecated. More...
void mi_stats_print_out (mi_output_fun *out, void *arg)
- Print the main statistics. More...
+ Print the main statistics. More...
void mi_stats_reset (void)
- Reset statistics. More...
+ Reset statistics. More...
void mi_stats_merge (void)
- Merge thread local statistics with the main statistics and reset. More...
+ Merge thread local statistics with the main statistics and reset. More...
void mi_thread_init (void)
- Initialize mimalloc on a thread. More...
+ Initialize mimalloc on a thread. More...
void mi_thread_done (void)
- Uninitialize mimalloc on a thread. More...
+ Uninitialize mimalloc on a thread. More...
void mi_thread_stats_print_out (mi_output_fun *out, void *arg)
- Print out heap statistics for this thread. More...
+ Print out heap statistics for this thread. More...
void mi_register_deferred_free (mi_deferred_free_fun *deferred_free, void *arg)
- Register a deferred free function. More...
+ Register a deferred free function. More...
void mi_register_output (mi_output_fun *out, void *arg)
- Register an output function. More...
+ Register an output function. More...
void mi_register_error (mi_error_fun *errfun, void *arg)
- Register an error callback function. More...
+ Register an error callback function. More...
bool mi_is_in_heap_region (const void *p)
- Is a pointer part of our heap? More...
+ Is a pointer part of our heap? More...
+int mi_reserve_os_memory (size_t size, bool commit, bool allow_large)
+ Reserve OS memory for use by mimalloc. More...
+
+bool mi_manage_os_memory (void *start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node)
+ Manage a particular memory area for use by mimalloc. More...
+
int mi_reserve_huge_os_pages_interleave (size_t pages, size_t numa_nodes, size_t timeout_msecs)
- Reserve pages of huge OS pages (1GiB) evenly divided over numa_nodes nodes, but stops after at most timeout_msecs
seconds. More...
+ Reserve pages of huge OS pages (1GiB) evenly divided over numa_nodes nodes, but stops after at most timeout_msecs
seconds. More...
int mi_reserve_huge_os_pages_at (size_t pages, int numa_node, size_t timeout_msecs)
- Reserve pages of huge OS pages (1GiB) at a specific numa_node , but stops after at most timeout_msecs
seconds. More...
+ Reserve pages of huge OS pages (1GiB) at a specific numa_node , but stops after at most timeout_msecs
seconds. More...
bool mi_is_redirected ()
- Is the C runtime malloc API redirected? More...
+ Is the C runtime malloc API redirected? More...
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)
- Return process information (time and memory usage). More...
+ Return process information (time and memory usage). More...
@@ -414,6 +416,72 @@ Functions
Returns a pointer to newly allocated memory of at least size bytes, or NULL if out of memory. This function is meant for use in run-time systems for best performance and does not check if size was indeed small – use with care!
+
+
+
+◆ mi_manage_os_memory()
+
+
+
+
+
+ bool mi_manage_os_memory
+ (
+ void *
+ start ,
+
+
+
+
+ size_t
+ size ,
+
+
+
+
+ bool
+ is_committed ,
+
+
+
+
+ bool
+ is_large ,
+
+
+
+
+ bool
+ is_zero ,
+
+
+
+
+ int
+ numa_node
+
+
+
+ )
+
+
+
+
+
+
Manage a particular memory area for use by mimalloc.
+
This is just like mi_reserve_os_memory
except that the area should already be allocated in some manner and available for use my mimalloc.
Parameters
+
+ start Start of the memory area
+ size The size of the memory area.
+ commit Is the area already committed?
+ is_large Does it consist of large OS pages? Set this to true as well for memory that should not be decommitted or protected (like rdma etc.)
+ is_zero Does the area consists of zero's?
+ numa_node Possible associated numa node or -1
.
+
+
+
+
Returns true if successful, and false on error.
+
@@ -706,6 +774,51 @@ Functions
Returns 0 if successfull, ENOMEM if running out of memory, or ETIMEDOUT if timed out.
The reserved memory is used by mimalloc to satisfy allocations. May quit before timeout_msecs are expired if it estimates it will take more than 1.5 times timeout_msecs . The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented.
+
+
+
+◆ mi_reserve_os_memory()
+
+
+
+
+
+ int mi_reserve_os_memory
+ (
+ size_t
+ size ,
+
+
+
+
+ bool
+ commit ,
+
+
+
+
+ bool
+ allow_large
+
+
+
+ )
+
+
+
+
+
+
Reserve OS memory for use by mimalloc.
+
Reserved areas are used before allocating from the OS again. By reserving a large area upfront, allocation can be more efficient, and can be better managed on systems without mmap
/VirtualAlloc
(like WASM for example).
Parameters
+
+ size The size to reserve.
+ commit Commit the memory upfront.
+ allow_large Allow large OS pages (2MiB) to be used?
+
+
+
+
Returns 0 if successful, and an error code otherwise (e.g. ENOMEM
).
+
@@ -958,9 +1071,7 @@ Functions
diff --git a/docs/group__extended.js b/docs/group__extended.js
index ed4a8b46..c217aaca 100644
--- a/docs/group__extended.js
+++ b/docs/group__extended.js
@@ -9,12 +9,14 @@ var group__extended =
[ "mi_is_in_heap_region", "group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6", null ],
[ "mi_is_redirected", "group__extended.html#gaad25050b19f30cd79397b227e0157a3f", null ],
[ "mi_malloc_small", "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99", null ],
+ [ "mi_manage_os_memory", "group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf", null ],
[ "mi_process_info", "group__extended.html#ga7d862c2affd5790381da14eb102a364d", null ],
[ "mi_register_deferred_free", "group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece", null ],
[ "mi_register_error", "group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45", null ],
[ "mi_register_output", "group__extended.html#gae5b17ff027cd2150b43a33040250cf3f", null ],
[ "mi_reserve_huge_os_pages_at", "group__extended.html#ga7795a13d20087447281858d2c771cca1", null ],
[ "mi_reserve_huge_os_pages_interleave", "group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50", null ],
+ [ "mi_reserve_os_memory", "group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767", null ],
[ "mi_stats_merge", "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1", null ],
[ "mi_stats_print", "group__extended.html#ga2d126e5c62d3badc35445e5d84166df2", null ],
[ "mi_stats_print_out", "group__extended.html#ga537f13b299ddf801e49a5a94fde02c79", null ],
diff --git a/docs/group__heap.html b/docs/group__heap.html
index 1a38c936..0f21ea42 100644
--- a/docs/group__heap.html
+++ b/docs/group__heap.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Heap Allocation
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -112,55 +108,55 @@ $(document).ready(function(){initNavTree('group__heap.html','');});
typedef struct mi_heap_s mi_heap_t
-
Type of first-class heaps. More...
+
Type of first-class heaps. More...
mi_heap_t * mi_heap_new ()
- Create a new heap that can be used for allocation. More...
+ Create a new heap that can be used for allocation. More...
void mi_heap_delete (mi_heap_t *heap)
- Delete a previously allocated heap. More...
+ Delete a previously allocated heap. More...
void mi_heap_destroy (mi_heap_t *heap)
- Destroy a heap, freeing all its still allocated blocks. More...
+ Destroy a heap, freeing all its still allocated blocks. More...
mi_heap_t * mi_heap_set_default (mi_heap_t *heap)
- Set the default heap to use for mi_malloc() et al. More...
+ Set the default heap to use for mi_malloc() et al. More...
mi_heap_t * mi_heap_get_default ()
- Get the default heap that is used for mi_malloc() et al. More...
+ Get the default heap that is used for mi_malloc() et al. More...
mi_heap_t * mi_heap_get_backing ()
- Get the backing heap. More...
+ Get the backing heap. More...
void mi_heap_collect (mi_heap_t *heap, bool force)
- Release outstanding resources in a specific heap. More...
+ Release outstanding resources in a specific heap. More...
void * mi_heap_malloc (mi_heap_t *heap, size_t size)
- Allocate in a specific heap. More...
+ Allocate in a specific heap. More...
void * mi_heap_malloc_small (mi_heap_t *heap, size_t size)
- Allocate a small object in a specific heap. More...
+ Allocate a small object in a specific heap. More...
void * mi_heap_zalloc (mi_heap_t *heap, size_t size)
- Allocate zero-initialized in a specific heap. More...
+ Allocate zero-initialized in a specific heap. More...
void * mi_heap_calloc (mi_heap_t *heap, size_t count, size_t size)
- Allocate count zero-initialized elements in a specific heap. More...
+ Allocate count zero-initialized elements in a specific heap. More...
void * mi_heap_mallocn (mi_heap_t *heap, size_t count, size_t size)
- Allocate count elements in a specific heap. More...
+ Allocate count elements in a specific heap. More...
char * mi_heap_strdup (mi_heap_t *heap, const char *s)
- Duplicate a string in a specific heap. More...
+ Duplicate a string in a specific heap. More...
char * mi_heap_strndup (mi_heap_t *heap, const char *s, size_t n)
- Duplicate a string of at most length n in a specific heap. More...
+ Duplicate a string of at most length n in a specific heap. More...
char * mi_heap_realpath (mi_heap_t *heap, const char *fname, char *resolved_name)
- Resolve a file path name using a specific heap to allocate the result. More...
+ Resolve a file path name using a specific heap to allocate the result. More...
void * mi_heap_realloc (mi_heap_t *heap, void *p, size_t newsize)
@@ -1071,9 +1067,7 @@ Functions
diff --git a/docs/group__malloc.html b/docs/group__malloc.html
index 224c4b08..2dc16656 100644
--- a/docs/group__malloc.html
+++ b/docs/group__malloc.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Basic Allocation
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -111,43 +107,43 @@ $(document).ready(function(){initNavTree('group__malloc.html','');});
void mi_free (void *p)
-
Free previously allocated memory. More...
+
Free previously allocated memory. More...
void * mi_malloc (size_t size)
-
Allocate size bytes. More...
+
Allocate size bytes. More...
void * mi_zalloc (size_t size)
-
Allocate zero-initialized size
bytes. More...
+
Allocate zero-initialized size
bytes. More...
void * mi_calloc (size_t count, size_t size)
-
Allocate zero-initialized count elements of size bytes. More...
+
Allocate zero-initialized count elements of size bytes. More...
void * mi_realloc (void *p, size_t newsize)
-
Re-allocate memory to newsize bytes. More...
+
Re-allocate memory to newsize bytes. More...
void * mi_recalloc (void *p, size_t count, size_t size)
-
Re-allocate memory to count elements of size bytes, with extra memory initialized to zero. More...
+
Re-allocate memory to count elements of size bytes, with extra memory initialized to zero. More...
void * mi_expand (void *p, size_t newsize)
-
Try to re-allocate memory to newsize bytes in place . More...
+
Try to re-allocate memory to newsize bytes in place . More...
void * mi_mallocn (size_t count, size_t size)
-
Allocate count elements of size bytes. More...
+
Allocate count elements of size bytes. More...
void * mi_reallocn (void *p, size_t count, size_t size)
-
Re-allocate memory to count elements of size bytes. More...
+
Re-allocate memory to count elements of size bytes. More...
void * mi_reallocf (void *p, size_t newsize)
-
Re-allocate memory to newsize bytes,. More...
+
Re-allocate memory to newsize bytes,. More...
char * mi_strdup (const char *s)
-
Allocate and duplicate a string. More...
+
Allocate and duplicate a string. More...
char * mi_strndup (const char *s, size_t n)
-
Allocate and duplicate a string up to n bytes. More...
+
Allocate and duplicate a string up to n bytes. More...
char * mi_realpath (const char *fname, char *resolved_name)
-
Resolve a file path name. More...
+
Resolve a file path name. More...
@@ -635,9 +631,7 @@ mi_zallocn()
diff --git a/docs/group__options.html b/docs/group__options.html
index 9425765e..f92905d4 100644
--- a/docs/group__options.html
+++ b/docs/group__options.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Runtime Options
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -112,25 +108,27 @@ $(document).ready(function(){initNavTree('group__options.html','');});
enum mi_option_t {
- mi_option_show_errors ,
-mi_option_show_stats ,
-mi_option_verbose ,
-mi_option_eager_commit ,
-
- mi_option_eager_region_commit ,
-mi_option_large_os_pages ,
-mi_option_reserve_huge_os_pages ,
-mi_option_segment_cache ,
-
- mi_option_page_reset ,
-mi_option_segment_reset ,
-mi_option_reset_delay ,
-mi_option_use_numa_nodes ,
-
- mi_option_reset_decommits ,
-mi_option_eager_commit_delay ,
-mi_option_os_tag ,
-_mi_option_last
+ mi_option_show_errors
+, mi_option_show_stats
+, mi_option_verbose
+, mi_option_eager_commit
+,
+ mi_option_eager_region_commit
+, mi_option_large_os_pages
+, mi_option_reserve_huge_os_pages
+, mi_option_reserve_huge_os_pages_at
+,
+ mi_option_segment_cache
+, mi_option_page_reset
+, mi_option_segment_reset
+, mi_option_reset_delay
+,
+ mi_option_use_numa_nodes
+, mi_option_reset_decommits
+, mi_option_eager_commit_delay
+, mi_option_os_tag
+,
+ _mi_option_last
}
Runtime options. More...
@@ -186,6 +184,8 @@ Functions
mi_option_reserve_huge_os_pages The number of huge OS pages (1GiB in size) to reserve at the start of the program.
+
mi_option_reserve_huge_os_pages_at Reserve huge OS pages at node N.
+
mi_option_segment_cache The number of segments per thread to keep cached.
mi_option_page_reset Reset page memory after mi_option_reset_delay milliseconds when it becomes free.
@@ -397,9 +397,7 @@ Functions
diff --git a/docs/group__options.js b/docs/group__options.js
index 9aaf2318..c8836cdc 100644
--- a/docs/group__options.js
+++ b/docs/group__options.js
@@ -8,6 +8,7 @@ var group__options =
[ "mi_option_eager_region_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad", null ],
[ "mi_option_large_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e", null ],
[ "mi_option_reserve_huge_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2", null ],
+ [ "mi_option_reserve_huge_os_pages_at", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c", null ],
[ "mi_option_segment_cache", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1", null ],
[ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ],
[ "mi_option_segment_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d", null ],
diff --git a/docs/group__posix.html b/docs/group__posix.html
index fe3a88e1..539f7ec6 100644
--- a/docs/group__posix.html
+++ b/docs/group__posix.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Posix
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -115,7 +111,7 @@ Functions
size_t mi_malloc_usable_size (const void *p)
void mi_cfree (void *p)
-
Just as free
but also checks if the pointer p
belongs to our heap. More...
+
Just as free
but also checks if the pointer p
belongs to our heap. More...
int mi_posix_memalign (void **p, size_t alignment, size_t size)
@@ -130,7 +126,11 @@ Functions
void * mi_aligned_alloc (size_t alignment, size_t size)
void * mi_reallocarray (void *p, size_t count, size_t size)
+
Correspond s to reallocarray in FreeBSD. More...
+
int mi_reallocarr (void *p, size_t count, size_t size)
+
Corresponds to reallocarr in NetBSD. More...
+
void mi_free_size (void *p, size_t size)
void mi_free_size_aligned (void *p, size_t size, size_t alignment)
@@ -428,6 +428,42 @@ Functions
+
+
+
+◆ mi_reallocarr()
+
+
+
+
+
+ int mi_reallocarr
+ (
+ void *
+ p ,
+
+
+
+
+ size_t
+ count ,
+
+
+
+
+ size_t
+ size
+
+
+
+ )
+
+
+
+
@@ -462,6 +498,8 @@ Functions
@@ -487,9 +525,7 @@ Functions
diff --git a/docs/group__posix.js b/docs/group__posix.js
index e43453d9..50c248c8 100644
--- a/docs/group__posix.js
+++ b/docs/group__posix.js
@@ -11,6 +11,7 @@ var group__posix =
[ "mi_memalign", "group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e", null ],
[ "mi_posix_memalign", "group__posix.html#gacff84f226ba9feb2031b8992e5579447", null ],
[ "mi_pvalloc", "group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e", null ],
+ [ "mi_reallocarr", "group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5", null ],
[ "mi_reallocarray", "group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088", null ],
[ "mi_valloc", "group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b", null ]
];
\ No newline at end of file
diff --git a/docs/group__typed.html b/docs/group__typed.html
index 5cbfbd6b..c19c7f4a 100644
--- a/docs/group__typed.html
+++ b/docs/group__typed.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Typed Macros
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -111,42 +107,44 @@ $(document).ready(function(){initNavTree('group__typed.html','');});
#define mi_malloc_tp (tp)
-
Allocate a block of type tp . More...
+
Allocate a block of type tp . More...
#define mi_zalloc_tp (tp)
-
Allocate a zero-initialized block of type tp . More...
+
Allocate a zero-initialized block of type tp . More...
#define mi_calloc_tp (tp, count)
-
Allocate count zero-initialized blocks of type tp . More...
+
Allocate count zero-initialized blocks of type tp . More...
#define mi_mallocn_tp (tp, count)
-
Allocate count blocks of type tp . More...
+
Allocate count blocks of type tp . More...
#define mi_reallocn_tp (p, tp, count)
-
Re-allocate to count blocks of type tp . More...
+
Re-allocate to count blocks of type tp . More...
#define mi_heap_malloc_tp (hp, tp)
-
Allocate a block of type tp in a heap hp . More...
+
Allocate a block of type tp in a heap hp . More...
#define mi_heap_zalloc_tp (hp, tp)
-
Allocate a zero-initialized block of type tp in a heap hp . More...
+
Allocate a zero-initialized block of type tp in a heap hp . More...
#define mi_heap_calloc_tp (hp, tp, count)
-
Allocate count zero-initialized blocks of type tp in a heap hp . More...
+
Allocate count zero-initialized blocks of type tp in a heap hp . More...
#define mi_heap_mallocn_tp (hp, tp, count)
-
Allocate count blocks of type tp in a heap hp . More...
+
Allocate count blocks of type tp in a heap hp . More...
#define mi_heap_reallocn_tp (hp, p, tp, count)
-
Re-allocate to count blocks of type tp in a heap hp . More...
+
Re-allocate to count blocks of type tp in a heap hp . More...
#define mi_heap_recalloc_tp (hp, p, tp, count)
-
Re-allocate to count zero initialized blocks of type tp in a heap hp . More...
+
Re-allocate to count zero initialized blocks of type tp in a heap hp . More...
Typed allocation macros.
-
For example:
+
For example:
+
#define mi_malloc_tp(tp)
Allocate a block of type tp.
Definition: mimalloc-doc.h:692
+
◆ mi_calloc_tp
@@ -417,7 +415,8 @@ Macros
Returns A pointer to an object of type tp , or NULL if out of memory.
-
Example:
See also mi_malloc()
+
Example:
See also mi_malloc()
@@ -512,9 +511,7 @@ Macros
diff --git a/docs/group__zeroinit.html b/docs/group__zeroinit.html
index 3c04a5a6..329a7739 100644
--- a/docs/group__zeroinit.html
+++ b/docs/group__zeroinit.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Zero initialized re-allocation
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -588,9 +584,7 @@ Functions
diff --git a/docs/index.html b/docs/index.html
index 01af9bec..2ea91215 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Main Page
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -103,13 +99,14 @@ $(document).ready(function(){initNavTree('index.html','');});
This is the API documentation of the mimalloc allocator (pronounced "me-malloc") – a general purpose allocator with excellent performance characteristics. Initially developed by Daan Leijen for the run-time systems of the Koka and Lean languages.
-
It is a drop-in replacement for malloc
and can be used in other programs without code changes, for example, on Unix you can use it as:
> LD_PRELOAD=/usr/bin/libmimalloc.so myprogram
Notable aspects of the design include:
+
It is a drop-in replacement for malloc
and can be used in other programs without code changes, for example, on Unix you can use it as:
> LD_PRELOAD=/usr/bin/libmimalloc.so myprogram
+
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 build in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. The performance penalty is only around 3% on average over our benchmarks.
+secure : mimalloc can be build in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. The performance penalty is only around 5% 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 ), mimalloc outperforms all 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.
@@ -138,9 +135,7 @@ $(document).ready(function(){initNavTree('index.html','');});
diff --git a/docs/jquery.js b/docs/jquery.js
index 1ee895ca..103c32d7 100644
--- a/docs/jquery.js
+++ b/docs/jquery.js
@@ -1,71 +1,26 @@
+/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML=" ";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""," "],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -102,154 +98,463 @@ $(document).ready(function(){initNavTree('mimalloc-doc_8h_source.html','');});
mimalloc-doc.h
-
8 #error "documentation file only!" 122 void *
mi_calloc (
size_t count,
size_t size);
148 void *
mi_recalloc (
void * p,
size_t count,
size_t size);
163 void *
mi_expand (
void * p,
size_t newsize);
185 void *
mi_reallocn (
void * p,
size_t count,
size_t size);
239 char *
mi_realpath (
const char * fname,
char * resolved_name);
253 #define MI_SMALL_SIZE_MAX (128*sizeof(void*)) 465 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);
630 void *
mi_recalloc (
void * p,
size_t newcount,
size_t size) ;
667 #define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp))) 670 #define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp))) 673 #define mi_calloc_tp(tp,count) ((tp*)mi_calloc(count,sizeof(tp))) 676 #define mi_mallocn_tp(tp,count) ((tp*)mi_mallocn(count,sizeof(tp))) 679 #define mi_reallocn_tp(p,tp,count) ((tp*)mi_reallocn(p,count,sizeof(tp))) 682 #define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp))) 685 #define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp))) 688 #define mi_heap_calloc_tp(hp,tp,count) ((tp*)mi_heap_calloc(hp,count,sizeof(tp))) 691 #define mi_heap_mallocn_tp(hp,tp,count) ((tp*)mi_heap_mallocn(hp,count,sizeof(tp))) 694 #define mi_heap_reallocn_tp(hp,p,tp,count) ((tp*)mi_heap_reallocn(p,count,sizeof(tp))) 697 #define mi_heap_recalloc_tp(hp,p,tp,count) ((tp*)mi_heap_recalloc(p,count,sizeof(tp))) 736 typedef struct mi_heap_area_s {
775 typedef enum mi_option_e {
817 void *
mi_recalloc (
void * p,
size_t count,
size_t size);
853 void *
mi_new (std::size_t n) noexcept(
false );
856 void *
mi_new_n (
size_t count,
size_t size) noexcept(
false );
859 void *
mi_new_aligned (std::size_t n, std::align_val_t alignment) noexcept(
false );
size_t mi_usable_size(void *p)
Return the available bytes in a memory block.
-
void * mi_new_nothrow(size_t n)
like mi_malloc, but when out of memory, use std::get_new_handler but return NULL on failure.
-
void * mi_reallocn(void *p, size_t count, size_t size)
Re-allocate memory to count elements of size bytes.
-
void * mi_malloc_aligned(size_t size, size_t alignment)
Allocate size bytes aligned by alignment.
-
void * mi_recalloc_aligned_at(void *p, size_t newcount, size_t size, size_t alignment, size_t offset)
-
void mi_stats_reset(void)
Reset statistics.
-
void * mi_heap_realloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)
-
bool mi_option_is_enabled(mi_option_t option)
-
void * mi_new_realloc(void *p, size_t newsize)
like mi_realloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...
-
void * mi_recalloc(void *p, size_t count, size_t size)
Re-allocate memory to count elements of size bytes, with extra memory initialized to zero.
-
void * mi_mallocn(size_t count, size_t size)
Allocate count elements of size bytes.
-
size_t mi_malloc_size(const void *p)
-
void mi_option_set_enabled(mi_option_t option, bool enable)
-
int mi_posix_memalign(void **p, size_t alignment, size_t size)
-
void mi_stats_merge(void)
Merge thread local statistics with the main statistics and reset.
-
void * mi_new_n(size_t count, size_t size) noexcept(false)
like mi_mallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...
-
void mi_option_set_default(mi_option_t option, long value)
-
void mi_stats_print_out(mi_output_fun *out, void *arg)
Print the main statistics.
-
void() mi_error_fun(int err, void *arg)
Type of error callback functions.
Definition: mimalloc-doc.h:391
-
void * mi_rezalloc(void *p, size_t newsize)
-
Eagerly commit segments (4MiB) (enabled by default).
Definition: mimalloc-doc.h:781
-
void * mi_heap_zalloc(mi_heap_t *heap, size_t size)
Allocate zero-initialized in a specific heap.
-
void mi_option_set(mi_option_t option, long value)
-
Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
Definition: mimalloc-doc.h:782
-
void mi_cfree(void *p)
Just as free but also checks if the pointer p belongs to our heap.
-
void * mi_recalloc_aligned(void *p, size_t newcount, size_t size, size_t alignment)
-
Definition: mimalloc-doc.h:793
-
void * mi_realloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)
-
void * blocks
start of the area containing heap blocks
Definition: mimalloc-doc.h:737
-
void * mi_realloc_aligned(void *p, size_t newsize, size_t alignment)
-
void mi_option_enable(mi_option_t option)
-
int mi__posix_memalign(void **p, size_t alignment, size_t size)
-
void mi_free(void *p)
Free previously allocated memory.
-
char * mi_heap_strdup(mi_heap_t *heap, const char *s)
Duplicate a string in a specific heap.
-
char * mi_heap_realpath(mi_heap_t *heap, const char *fname, char *resolved_name)
Resolve a file path name using a specific heap to allocate the result.
-
void * mi_heap_calloc_aligned_at(mi_heap_t *heap, size_t count, size_t size, size_t alignment, size_t offset)
-
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)
Return process information (time and memory usage).
-
void * mi_calloc_aligned(size_t count, size_t size, size_t alignment)
-
void * mi_heap_zalloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)
-
void * mi_zalloc_small(size_t size)
Allocate a zero initialized small object.
-
char * mi_strndup(const char *s, size_t n)
Allocate and duplicate a string up to n bytes.
-
void * mi_expand(void *p, size_t newsize)
Try to re-allocate memory to newsize bytes in place.
-
void * mi_pvalloc(size_t size)
-
void mi_option_set_enabled_default(mi_option_t option, bool enable)
-
void * mi_heap_rezalloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)
-
void * mi_zalloc(size_t size)
Allocate zero-initialized size bytes.
-
void * mi_heap_rezalloc(mi_heap_t *heap, void *p, size_t newsize)
-
The number of segments per thread to keep cached.
Definition: mimalloc-doc.h:785
-
void * mi_heap_calloc(mi_heap_t *heap, size_t count, size_t size)
Allocate count zero-initialized elements in a specific heap.
-
void * mi_heap_calloc_aligned(mi_heap_t *heap, size_t count, size_t size, size_t alignment)
-
bool mi_is_redirected()
Is the C runtime malloc API redirected?
-
size_t block_size
size in bytes of one block
Definition: mimalloc-doc.h:741
-
void * mi_reallocarray(void *p, size_t count, size_t size)
-
int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs)
Reserve pages of huge OS pages (1GiB) evenly divided over numa_nodes nodes, but stops after at most t...
-
void() mi_deferred_free_fun(bool force, unsigned long long heartbeat, void *arg)
Type of deferred free functions.
Definition: mimalloc-doc.h:352
-
bool mi_is_in_heap_region(const void *p)
Is a pointer part of our heap?
-
void * mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false)
like mi_malloc_aligned(), but when out of memory, use std::get_new_handler and raise std::bad_alloc e...
-
void * mi_realloc(void *p, size_t newsize)
Re-allocate memory to newsize bytes.
-
The number of huge OS pages (1GiB in size) to reserve at the start of the program.
Definition: mimalloc-doc.h:784
-
void * mi_heap_reallocf(mi_heap_t *heap, void *p, size_t newsize)
-
void mi_free_size_aligned(void *p, size_t size, size_t alignment)
-
void * mi_rezalloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)
-
Reset page memory after mi_option_reset_delay milliseconds when it becomes free.
Definition: mimalloc-doc.h:786
-
void mi_thread_done(void)
Uninitialize mimalloc on a thread.
-
bool mi_heap_visit_blocks(const mi_heap_t *heap, bool visit_all_blocks, mi_block_visit_fun *visitor, void *arg)
Visit all areas and blocks in a heap.
-
Pretend there are at most N NUMA nodes.
Definition: mimalloc-doc.h:789
-
void * mi_malloc(size_t size)
Allocate size bytes.
-
void mi_register_error(mi_error_fun *errfun, void *arg)
Register an error callback function.
-
Experimental.
Definition: mimalloc-doc.h:790
-
char * mi_heap_strndup(mi_heap_t *heap, const char *s, size_t n)
Duplicate a string of at most length n in a specific heap.
-
bool() mi_block_visit_fun(const mi_heap_t *heap, const mi_heap_area_t *area, void *block, size_t block_size, void *arg)
Visitor function passed to mi_heap_visit_blocks()
Definition: mimalloc-doc.h:751
-
void * mi_heap_recalloc(mi_heap_t *heap, void *p, size_t newcount, size_t size)
-
void * mi_heap_malloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)
-
char * mi_realpath(const char *fname, char *resolved_name)
Resolve a file path name.
-
Print error messages to stderr.
Definition: mimalloc-doc.h:777
-
Experimental.
Definition: mimalloc-doc.h:787
-
void * mi_heap_rezalloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)
-
void * mi_new_aligned_nothrow(size_t n, size_t alignment)
like mi_malloc_aligned, but when out of memory, use std::get_new_handler but return NULL on failure.
-
void * mi_memalign(size_t alignment, size_t size)
-
void * mi_rezalloc_aligned(void *p, size_t newsize, size_t alignment)
-
bool mi_heap_contains_block(mi_heap_t *heap, const void *p)
Does a heap contain a pointer to a previously allocated block?
-
void mi_heap_collect(mi_heap_t *heap, bool force)
Release outstanding resources in a specific heap.
-
void * mi_heap_recalloc_aligned_at(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment, size_t offset)
-
Print verbose messages to stderr.
Definition: mimalloc-doc.h:779
-
void * mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset)
-
void * mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset)
Allocate size bytes aligned by alignment at a specified offset.
-
void mi_heap_delete(mi_heap_t *heap)
Delete a previously allocated heap.
-
OS tag to assign to mimalloc'd memory.
Definition: mimalloc-doc.h:792
-
mi_heap_t * mi_heap_get_default()
Get the default heap that is used for mi_malloc() et al.
-
int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs)
Reserve pages of huge OS pages (1GiB) at a specific numa_node, but stops after at most timeout_msecs ...
-
void mi_option_disable(mi_option_t option)
-
void * mi_aligned_alloc(size_t alignment, size_t size)
-
void * mi_valloc(size_t size)
-
void mi_thread_init(void)
Initialize mimalloc on a thread.
-
size_t mi_good_size(size_t size)
Return the used allocation size.
-
void mi_stats_print(void *out)
Deprecated.
-
Experimental.
Definition: mimalloc-doc.h:791
-
void * mi_heap_recalloc_aligned(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment)
-
void * mi_heap_mallocn(mi_heap_t *heap, size_t count, size_t size)
Allocate count elements in a specific heap.
-
An area of heap space contains blocks of a single size.
Definition: mimalloc-doc.h:736
-
void mi_thread_stats_print_out(mi_output_fun *out, void *arg)
Print out heap statistics for this thread.
-
Print statistics to stderr when the program is done.
Definition: mimalloc-doc.h:778
-
void * mi_zalloc_aligned(size_t size, size_t alignment)
-
size_t reserved
bytes reserved for this area
Definition: mimalloc-doc.h:738
-
struct mi_heap_s mi_heap_t
Type of first-class heaps.
Definition: mimalloc-doc.h:529
-
size_t used
bytes in use by allocated blocks
Definition: mimalloc-doc.h:740
-
void mi_register_deferred_free(mi_deferred_free_fun *deferred_free, void *arg)
Register a deferred free function.
-
void mi_free_size(void *p, size_t size)
-
void mi_collect(bool force)
Eagerly free memory.
-
void * mi_new_reallocn(void *p, size_t newcount, size_t size)
like mi_reallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc excepti...
-
void mi_heap_destroy(mi_heap_t *heap)
Destroy a heap, freeing all its still allocated blocks.
-
void * mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset)
-
Use large OS pages (2MiB in size) if possible.
Definition: mimalloc-doc.h:783
-
void * mi_heap_reallocn(mi_heap_t *heap, void *p, size_t count, size_t size)
-
void mi_register_output(mi_output_fun *out, void *arg)
Register an output function.
-
std::allocator implementation for mimalloc for use in STL containers.
Definition: mimalloc-doc.h:880
-
void * mi_heap_malloc_small(mi_heap_t *heap, size_t size)
Allocate a small object in a specific heap.
-
void * mi_heap_realloc(mi_heap_t *heap, void *p, size_t newsize)
-
size_t mi_malloc_usable_size(const void *p)
-
void() mi_output_fun(const char *msg, void *arg)
Type of output functions.
Definition: mimalloc-doc.h:376
-
char * mi_strdup(const char *s)
Allocate and duplicate a string.
-
void * mi_heap_realloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)
-
void * mi_reallocf(void *p, size_t newsize)
Re-allocate memory to newsize bytes,.
-
void * mi_calloc(size_t count, size_t size)
Allocate zero-initialized count elements of size bytes.
-
void * mi_heap_zalloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)
-
void * mi_malloc_small(size_t size)
Allocate a small object.
-
bool mi_check_owned(const void *p)
Check safely if any pointer is part of the default heap of this thread.
-
void * mi_heap_malloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)
-
long mi_option_get(mi_option_t option)
-
mi_heap_t * mi_heap_get_backing()
Get the backing heap.
-
void mi_free_aligned(void *p, size_t alignment)
-
void * mi_new(std::size_t n) noexcept(false)
like mi_malloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exception...
-
Delay in milli-seconds before resetting a page (100ms by default)
Definition: mimalloc-doc.h:788
-
mi_heap_t * mi_heap_new()
Create a new heap that can be used for allocation.
-
void * mi_heap_malloc(mi_heap_t *heap, size_t size)
Allocate in a specific heap.
-
size_t committed
current committed bytes of this area
Definition: mimalloc-doc.h:739
-
mi_option_t
Runtime options.
Definition: mimalloc-doc.h:775
-
bool mi_heap_check_owned(mi_heap_t *heap, const void *p)
Check safely if any pointer is part of a heap.
-
mi_heap_t * mi_heap_set_default(mi_heap_t *heap)
Set the default heap to use for mi_malloc() et al.
+
+
+
+
+
+
+
+
8 #error "documentation file only!"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
253 #define MI_SMALL_SIZE_MAX (128*sizeof(void*))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
437 bool mi_manage_os_memory (
void * start,
size_t size,
bool is_committed,
bool is_large,
bool is_zero,
int numa_node);
+
+
+
+
+
+
+
+
+
487 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);
+
+
+
+
+
+
+
+
502 #define MI_ALIGNMENT_MAX (1024*1024UL)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
655 void *
mi_recalloc (
void * p,
size_t newcount,
size_t size) ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
692 #define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
+
+
695 #define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
+
+
698 #define mi_calloc_tp(tp,count) ((tp*)mi_calloc(count,sizeof(tp)))
+
+
701 #define mi_mallocn_tp(tp,count) ((tp*)mi_mallocn(count,sizeof(tp)))
+
+
704 #define mi_reallocn_tp(p,tp,count) ((tp*)mi_reallocn(p,count,sizeof(tp)))
+
+
707 #define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
+
+
710 #define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
+
+
713 #define mi_heap_calloc_tp(hp,tp,count) ((tp*)mi_heap_calloc(hp,count,sizeof(tp)))
+
+
716 #define mi_heap_mallocn_tp(hp,tp,count) ((tp*)mi_heap_mallocn(hp,count,sizeof(tp)))
+
+
719 #define mi_heap_reallocn_tp(hp,p,tp,count) ((tp*)mi_heap_reallocn(p,count,sizeof(tp)))
+
+
722 #define mi_heap_recalloc_tp(hp,p,tp,count) ((tp*)mi_heap_recalloc(p,count,sizeof(tp)))
+
+
+
+
+
+
+
+
+
+
761 typedef struct mi_heap_area_s {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
800 typedef enum mi_option_e {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
843 void *
mi_recalloc (
void * p,
size_t count,
size_t size);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
885 void *
mi_new (std::size_t n) noexcept(
false );
+
+
888 void *
mi_new_n (
size_t count,
size_t size) noexcept(
false );
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
void * mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset)
+
void * mi_zalloc_aligned(size_t size, size_t alignment)
+
void * mi_realloc_aligned(void *p, size_t newsize, size_t alignment)
+
void * mi_calloc_aligned(size_t count, size_t size, size_t alignment)
+
void * mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset)
Allocate size bytes aligned by alignment at a specified offset.
+
void * mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset)
+
void * mi_malloc_aligned(size_t size, size_t alignment)
Allocate size bytes aligned by alignment.
+
void * mi_realloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)
+
size_t block_size
size in bytes of one block
Definition: mimalloc-doc.h:766
+
size_t committed
current committed bytes of this area
Definition: mimalloc-doc.h:764
+
size_t used
bytes in use by allocated blocks
Definition: mimalloc-doc.h:765
+
void * blocks
start of the area containing heap blocks
Definition: mimalloc-doc.h:762
+
size_t reserved
bytes reserved for this area
Definition: mimalloc-doc.h:763
+
bool mi_heap_check_owned(mi_heap_t *heap, const void *p)
Check safely if any pointer is part of a heap.
+
bool mi_check_owned(const void *p)
Check safely if any pointer is part of the default heap of this thread.
+
bool mi_heap_visit_blocks(const mi_heap_t *heap, bool visit_all_blocks, mi_block_visit_fun *visitor, void *arg)
Visit all areas and blocks in a heap.
+
bool mi_heap_contains_block(mi_heap_t *heap, const void *p)
Does a heap contain a pointer to a previously allocated block?
+
bool() mi_block_visit_fun(const mi_heap_t *heap, const mi_heap_area_t *area, void *block, size_t block_size, void *arg)
Visitor function passed to mi_heap_visit_blocks()
Definition: mimalloc-doc.h:776
+
An area of heap space contains blocks of a single size.
Definition: mimalloc-doc.h:761
+
void * mi_new_reallocn(void *p, size_t newcount, size_t size)
like mi_reallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc excepti...
+
void * mi_new_realloc(void *p, size_t newsize)
like mi_realloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...
+
void * mi_new(std::size_t n) noexcept(false)
like mi_malloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exception...
+
void * mi_new_aligned_nothrow(size_t n, size_t alignment)
like mi_malloc_aligned, but when out of memory, use std::get_new_handler but return NULL on failure.
+
void * mi_new_n(size_t count, size_t size) noexcept(false)
like mi_mallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...
+
void * mi_new_nothrow(size_t n)
like mi_malloc, but when out of memory, use std::get_new_handler but return NULL on failure.
+
void * mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false)
like mi_malloc_aligned(), but when out of memory, use std::get_new_handler and raise std::bad_alloc e...
+
std::allocator implementation for mimalloc for use in STL containers.
Definition: mimalloc-doc.h:912
+
int mi_reserve_os_memory(size_t size, bool commit, bool allow_large)
Reserve OS memory for use by mimalloc.
+
size_t mi_usable_size(void *p)
Return the available bytes in a memory block.
+
void mi_thread_done(void)
Uninitialize mimalloc on a thread.
+
void * mi_zalloc_small(size_t size)
Allocate a zero initialized small object.
+
void() mi_error_fun(int err, void *arg)
Type of error callback functions.
Definition: mimalloc-doc.h:391
+
void() mi_deferred_free_fun(bool force, unsigned long long heartbeat, void *arg)
Type of deferred free functions.
Definition: mimalloc-doc.h:352
+
void mi_stats_print(void *out)
Deprecated.
+
int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs)
Reserve pages of huge OS pages (1GiB) evenly divided over numa_nodes nodes, but stops after at most t...
+
void mi_register_deferred_free(mi_deferred_free_fun *deferred_free, void *arg)
Register a deferred free function.
+
void mi_stats_reset(void)
Reset statistics.
+
void mi_collect(bool force)
Eagerly free memory.
+
bool mi_manage_os_memory(void *start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node)
Manage a particular memory area for use by mimalloc.
+
void mi_stats_print_out(mi_output_fun *out, void *arg)
Print the main statistics.
+
bool mi_is_in_heap_region(const void *p)
Is a pointer part of our heap?
+
void * mi_malloc_small(size_t size)
Allocate a small object.
+
int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs)
Reserve pages of huge OS pages (1GiB) at a specific numa_node, but stops after at most timeout_msecs ...
+
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)
Return process information (time and memory usage).
+
void mi_stats_merge(void)
Merge thread local statistics with the main statistics and reset.
+
void mi_register_error(mi_error_fun *errfun, void *arg)
Register an error callback function.
+
bool mi_is_redirected()
Is the C runtime malloc API redirected?
+
void mi_thread_stats_print_out(mi_output_fun *out, void *arg)
Print out heap statistics for this thread.
+
size_t mi_good_size(size_t size)
Return the used allocation size.
+
void() mi_output_fun(const char *msg, void *arg)
Type of output functions.
Definition: mimalloc-doc.h:376
+
void mi_register_output(mi_output_fun *out, void *arg)
Register an output function.
+
void mi_thread_init(void)
Initialize mimalloc on a thread.
+
char * mi_heap_realpath(mi_heap_t *heap, const char *fname, char *resolved_name)
Resolve a file path name using a specific heap to allocate the result.
+
void * mi_heap_calloc_aligned_at(mi_heap_t *heap, size_t count, size_t size, size_t alignment, size_t offset)
+
char * mi_heap_strdup(mi_heap_t *heap, const char *s)
Duplicate a string in a specific heap.
+
void * mi_heap_malloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)
+
void mi_heap_delete(mi_heap_t *heap)
Delete a previously allocated heap.
+
struct mi_heap_s mi_heap_t
Type of first-class heaps.
Definition: mimalloc-doc.h:554
+
void * mi_heap_zalloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)
+
void * mi_heap_reallocf(mi_heap_t *heap, void *p, size_t newsize)
+
void * mi_heap_calloc_aligned(mi_heap_t *heap, size_t count, size_t size, size_t alignment)
+
mi_heap_t * mi_heap_get_backing()
Get the backing heap.
+
mi_heap_t * mi_heap_new()
Create a new heap that can be used for allocation.
+
void mi_heap_collect(mi_heap_t *heap, bool force)
Release outstanding resources in a specific heap.
+
void * mi_heap_mallocn(mi_heap_t *heap, size_t count, size_t size)
Allocate count elements in a specific heap.
+
mi_heap_t * mi_heap_get_default()
Get the default heap that is used for mi_malloc() et al.
+
char * mi_heap_strndup(mi_heap_t *heap, const char *s, size_t n)
Duplicate a string of at most length n in a specific heap.
+
void * mi_heap_zalloc(mi_heap_t *heap, size_t size)
Allocate zero-initialized in a specific heap.
+
void * mi_heap_malloc(mi_heap_t *heap, size_t size)
Allocate in a specific heap.
+
void mi_heap_destroy(mi_heap_t *heap)
Destroy a heap, freeing all its still allocated blocks.
+
void * mi_heap_malloc_small(mi_heap_t *heap, size_t size)
Allocate a small object in a specific heap.
+
void * mi_heap_zalloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)
+
void * mi_heap_calloc(mi_heap_t *heap, size_t count, size_t size)
Allocate count zero-initialized elements in a specific heap.
+
void * mi_heap_realloc(mi_heap_t *heap, void *p, size_t newsize)
+
void * mi_heap_malloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)
+
mi_heap_t * mi_heap_set_default(mi_heap_t *heap)
Set the default heap to use for mi_malloc() et al.
+
void * mi_heap_reallocn(mi_heap_t *heap, void *p, size_t count, size_t size)
+
void * mi_heap_realloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)
+
void * mi_heap_realloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)
+
char * mi_realpath(const char *fname, char *resolved_name)
Resolve a file path name.
+
void * mi_mallocn(size_t count, size_t size)
Allocate count elements of size bytes.
+
void * mi_recalloc(void *p, size_t count, size_t size)
Re-allocate memory to count elements of size bytes, with extra memory initialized to zero.
+
void * mi_malloc(size_t size)
Allocate size bytes.
+
void * mi_reallocn(void *p, size_t count, size_t size)
Re-allocate memory to count elements of size bytes.
+
void * mi_calloc(size_t count, size_t size)
Allocate zero-initialized count elements of size bytes.
+
char * mi_strndup(const char *s, size_t n)
Allocate and duplicate a string up to n bytes.
+
void * mi_expand(void *p, size_t newsize)
Try to re-allocate memory to newsize bytes in place.
+
char * mi_strdup(const char *s)
Allocate and duplicate a string.
+
void * mi_realloc(void *p, size_t newsize)
Re-allocate memory to newsize bytes.
+
void mi_free(void *p)
Free previously allocated memory.
+
void * mi_zalloc(size_t size)
Allocate zero-initialized size bytes.
+
void * mi_reallocf(void *p, size_t newsize)
Re-allocate memory to newsize bytes,.
+
void mi_option_enable(mi_option_t option)
+
bool mi_option_is_enabled(mi_option_t option)
+
void mi_option_set_enabled_default(mi_option_t option, bool enable)
+
long mi_option_get(mi_option_t option)
+
void mi_option_set_default(mi_option_t option, long value)
+
void mi_option_set_enabled(mi_option_t option, bool enable)
+
void mi_option_disable(mi_option_t option)
+
void mi_option_set(mi_option_t option, long value)
+
mi_option_t
Runtime options.
Definition: mimalloc-doc.h:800
+
@ mi_option_show_stats
Print statistics to stderr when the program is done.
Definition: mimalloc-doc.h:803
+
@ mi_option_use_numa_nodes
Pretend there are at most N NUMA nodes.
Definition: mimalloc-doc.h:815
+
@ mi_option_reset_delay
Delay in milli-seconds before resetting a page (100ms by default)
Definition: mimalloc-doc.h:814
+
@ mi_option_eager_commit_delay
Experimental.
Definition: mimalloc-doc.h:817
+
@ mi_option_eager_commit
Eagerly commit segments (4MiB) (enabled by default).
Definition: mimalloc-doc.h:806
+
@ mi_option_segment_cache
The number of segments per thread to keep cached.
Definition: mimalloc-doc.h:811
+
@ mi_option_eager_region_commit
Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
Definition: mimalloc-doc.h:807
+
@ mi_option_large_os_pages
Use large OS pages (2MiB in size) if possible.
Definition: mimalloc-doc.h:808
+
@ mi_option_os_tag
OS tag to assign to mimalloc'd memory.
Definition: mimalloc-doc.h:818
+
@ _mi_option_last
Definition: mimalloc-doc.h:819
+
@ mi_option_verbose
Print verbose messages to stderr.
Definition: mimalloc-doc.h:804
+
@ mi_option_reserve_huge_os_pages_at
Reserve huge OS pages at node N.
Definition: mimalloc-doc.h:810
+
@ mi_option_reset_decommits
Experimental.
Definition: mimalloc-doc.h:816
+
@ mi_option_reserve_huge_os_pages
The number of huge OS pages (1GiB in size) to reserve at the start of the program.
Definition: mimalloc-doc.h:809
+
@ mi_option_page_reset
Reset page memory after mi_option_reset_delay milliseconds when it becomes free.
Definition: mimalloc-doc.h:812
+
@ mi_option_segment_reset
Experimental.
Definition: mimalloc-doc.h:813
+
@ mi_option_show_errors
Print error messages to stderr.
Definition: mimalloc-doc.h:802
+
size_t mi_malloc_usable_size(const void *p)
+
void mi_free_aligned(void *p, size_t alignment)
+
void * mi_aligned_alloc(size_t alignment, size_t size)
+
size_t mi_malloc_size(const void *p)
+
void * mi_reallocarray(void *p, size_t count, size_t size)
Correspond s to reallocarray in FreeBSD.
+
void mi_cfree(void *p)
Just as free but also checks if the pointer p belongs to our heap.
+
void mi_free_size_aligned(void *p, size_t size, size_t alignment)
+
void * mi_valloc(size_t size)
+
int mi_reallocarr(void *p, size_t count, size_t size)
Corresponds to reallocarr in NetBSD.
+
void * mi_memalign(size_t alignment, size_t size)
+
int mi_posix_memalign(void **p, size_t alignment, size_t size)
+
int mi__posix_memalign(void **p, size_t alignment, size_t size)
+
void mi_free_size(void *p, size_t size)
+
void * mi_pvalloc(size_t size)
+
void * mi_heap_rezalloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)
+
void * mi_recalloc_aligned(void *p, size_t newcount, size_t size, size_t alignment)
+
void * mi_heap_recalloc_aligned_at(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment, size_t offset)
+
void * mi_recalloc_aligned_at(void *p, size_t newcount, size_t size, size_t alignment, size_t offset)
+
void * mi_heap_recalloc(mi_heap_t *heap, void *p, size_t newcount, size_t size)
+
void * mi_rezalloc(void *p, size_t newsize)
+
void * mi_heap_recalloc_aligned(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment)
+
void * mi_heap_rezalloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)
+
void * mi_rezalloc_aligned(void *p, size_t newsize, size_t alignment)
+
void * mi_heap_rezalloc(mi_heap_t *heap, void *p, size_t newsize)
+
void * mi_rezalloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)
diff --git a/docs/modules.html b/docs/modules.html
index 9858d6ad..7457cb9f 100644
--- a/docs/modules.html
+++ b/docs/modules.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Modules
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -121,9 +117,7 @@ $(document).ready(function(){initNavTree('modules.html','');});
diff --git a/docs/navtree.js b/docs/navtree.js
index 7ce29352..1e272d31 100644
--- a/docs/navtree.js
+++ b/docs/navtree.js
@@ -1,25 +1,26 @@
/*
- @licstart The following is the entire license notice for the
- JavaScript code in this file.
+ @licstart The following is the entire license notice for the JavaScript code in this file.
- Copyright (C) 1997-2017 by Dimitri van Heesch
+ The MIT License (MIT)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ Copyright (C) 1997-2020 by Dimitri van Heesch
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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:
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
- @licend The above is the entire license notice
- for the JavaScript code in this file
+ 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.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
*/
var navTreeSubIndices = new Array();
var arrowDown = '▼';
@@ -70,7 +71,6 @@ function localStorageSupported()
}
}
-
function storeLink(link)
{
if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) {
@@ -102,14 +102,6 @@ function getScript(scriptName,func,show)
script.type = 'text/javascript';
script.onload = func;
script.src = scriptName+'.js';
- if ($.browser.msie && $.browser.version<=8) {
- // script.onload does not work with older versions of IE
- script.onreadystatechange = function() {
- if (script.readyState=='complete' || script.readyState=='loaded') {
- func(); if (show) showRoot();
- }
- }
- }
head.appendChild(script);
}
@@ -153,6 +145,7 @@ function gotoAnchor(anchor,aname,updateLocation)
var pos, docContent = $('#doc-content');
var ancParent = $(anchor.parent());
if (ancParent.hasClass('memItemLeft') ||
+ ancParent.hasClass('memtitle') ||
ancParent.hasClass('fieldname') ||
ancParent.hasClass('fieldtype') ||
ancParent.is(':header'))
@@ -265,7 +258,7 @@ function showRoot()
(function (){ // retry until we can scroll to the selected item
try {
var navtree=$('#nav-tree');
- navtree.scrollTo('#selected',0,{offset:-windowHeight/2});
+ navtree.scrollTo('#selected',100,{offset:-windowHeight/2});
} catch (err) {
setTimeout(arguments.callee, 0);
}
@@ -284,12 +277,8 @@ function expandNode(o, node, imm, showRoot)
} else {
if (!node.childrenVisited) {
getNode(o, node);
- } if (imm || ($.browser.msie && $.browser.version>8)) {
- // somehow slideDown jumps to the start of tree for IE9 :-(
- $(node.getChildrenUL()).show();
- } else {
- $(node.getChildrenUL()).slideDown("fast");
}
+ $(node.getChildrenUL()).slideDown("fast");
node.plus_img.innerHTML = arrowDown;
node.expanded = true;
}
@@ -319,7 +308,6 @@ function highlightAnchor()
} else {
glowEffect(anchor.next(),1000); // normal member
}
- gotoAnchor(anchor,aname,false);
}
function selectAndHighlight(hash,n)
@@ -481,6 +469,18 @@ function toggleSyncButton(relpath)
}
}
+var loadTriggered = false;
+var readyTriggered = false;
+var loadObject,loadToRoot,loadUrl,loadRelPath;
+
+$(window).on('load',function(){
+ if (readyTriggered) { // ready first
+ navTo(loadObject,loadToRoot,loadUrl,loadRelPath);
+ showRoot();
+ }
+ loadTriggered=true;
+});
+
function initNavTree(toroot,relpath)
{
var o = new Object();
@@ -511,10 +511,16 @@ function initNavTree(toroot,relpath)
navSync.click(function(){ toggleSyncButton(relpath); });
}
- $(window).load(function(){
+ if (loadTriggered) { // load before ready
navTo(o,toroot,hashUrl(),relpath);
showRoot();
- });
+ } else { // ready before load
+ loadObject = o;
+ loadToRoot = toroot;
+ loadUrl = hashUrl();
+ loadRelPath = relpath;
+ readyTriggered=true;
+ }
$(window).bind('hashchange', function(){
if (window.location.hash && window.location.hash.length>1){
diff --git a/docs/navtreedata.js b/docs/navtreedata.js
index e6dc7bc0..8dd5a555 100644
--- a/docs/navtreedata.js
+++ b/docs/navtreedata.js
@@ -1,25 +1,26 @@
/*
-@ @licstart The following is the entire license notice for the
-JavaScript code in this file.
+ @licstart The following is the entire license notice for the JavaScript code in this file.
-Copyright (C) 1997-2017 by Dimitri van Heesch
+ The MIT License (MIT)
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ Copyright (C) 1997-2020 by Dimitri van Heesch
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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:
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
-@licend The above is the entire license notice
-for the JavaScript code in this file
+ 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.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
*/
var NAVTREE =
[
diff --git a/docs/navtreeindex0.js b/docs/navtreeindex0.js
index 4a1e93fa..72181708 100644
--- a/docs/navtreeindex0.js
+++ b/docs/navtreeindex0.js
@@ -8,14 +8,15 @@ var NAVTREEINDEX0 =
"functions.html":[6,2,0],
"functions_vars.html":[6,2,1],
"group__aligned.html":[5,2],
-"group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3":[5,2,1],
-"group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819":[5,2,6],
-"group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae":[5,2,4],
-"group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9":[5,2,0],
-"group__aligned.html#ga5850da130c936bd77db039dcfbc8295d":[5,2,3],
-"group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8":[5,2,7],
-"group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56":[5,2,2],
-"group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb":[5,2,5],
+"group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3":[5,2,2],
+"group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819":[5,2,7],
+"group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae":[5,2,5],
+"group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9":[5,2,1],
+"group__aligned.html#ga5850da130c936bd77db039dcfbc8295d":[5,2,4],
+"group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8":[5,2,8],
+"group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56":[5,2,3],
+"group__aligned.html#ga83c03016066b438f51a8095e9140be06":[5,2,0],
+"group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb":[5,2,6],
"group__analysis.html":[5,6],
"group__analysis.html#a332a6c14d736a99699d5453a1cb04b41":[5,6,0,0],
"group__analysis.html#ab47526df656d8837ec3e97f11b83f835":[5,6,0,2],
@@ -38,30 +39,32 @@ var NAVTREEINDEX0 =
"group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3":[5,9,2],
"group__cpp.html#structmi__stl__allocator":[5,9,0],
"group__extended.html":[5,1],
-"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,22],
-"group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,19],
+"group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767":[5,1,16],
+"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,24],
+"group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,21],
"group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[5,1,0],
-"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,23],
+"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,25],
"group__extended.html#ga251d369cda3f1c2a955c555486ed90e5":[5,1,2],
"group__extended.html#ga299dae78d25ce112e384a98b7309c5be":[5,1,1],
-"group__extended.html#ga2d126e5c62d3badc35445e5d84166df2":[5,1,16],
-"group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50":[5,1,14],
-"group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece":[5,1,10],
-"group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,18],
+"group__extended.html#ga2d126e5c62d3badc35445e5d84166df2":[5,1,18],
+"group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50":[5,1,15],
+"group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece":[5,1,11],
+"group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,20],
"group__extended.html#ga421430e2226d7d468529cec457396756":[5,1,4],
-"group__extended.html#ga537f13b299ddf801e49a5a94fde02c79":[5,1,17],
+"group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf":[5,1,9],
+"group__extended.html#ga537f13b299ddf801e49a5a94fde02c79":[5,1,19],
"group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6":[5,1,6],
"group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[5,1,8],
-"group__extended.html#ga7795a13d20087447281858d2c771cca1":[5,1,13],
-"group__extended.html#ga7d862c2affd5790381da14eb102a364d":[5,1,9],
-"group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,15],
-"group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45":[5,1,11],
+"group__extended.html#ga7795a13d20087447281858d2c771cca1":[5,1,14],
+"group__extended.html#ga7d862c2affd5790381da14eb102a364d":[5,1,10],
+"group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,17],
+"group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45":[5,1,12],
"group__extended.html#gaad25050b19f30cd79397b227e0157a3f":[5,1,7],
-"group__extended.html#gab1dac8476c46cb9eecab767eb40c1525":[5,1,21],
+"group__extended.html#gab1dac8476c46cb9eecab767eb40c1525":[5,1,23],
"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[5,1,5],
"group__extended.html#gad823d23444a4b77a40f66bf075a98a0c":[5,1,3],
-"group__extended.html#gae5b17ff027cd2150b43a33040250cf3f":[5,1,12],
-"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,20],
+"group__extended.html#gae5b17ff027cd2150b43a33040250cf3f":[5,1,13],
+"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,22],
"group__heap.html":[5,3],
"group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[5,3,20],
"group__heap.html#ga08ca6419a5c057a4d965868998eef487":[5,3,3],
@@ -115,30 +118,32 @@ var NAVTREEINDEX0 =
"group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[5,7,5],
"group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[5,7,0],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[5,7,0,1],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74":[5,7,0,11],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5":[5,7,0,10],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,13],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74":[5,7,0,12],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5":[5,7,0,11],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,14],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[5,7,0,3],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,7],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,8],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[5,7,0,4],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[5,7,0,5],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,14],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,15],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,15],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,16],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[5,7,0,2],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,12],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c":[5,7,0,7],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,13],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2":[5,7,0,6],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,8],
-"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,9],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,9],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,10],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[5,7,0,0],
"group__posix.html":[5,8],
"group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[5,8,7],
"group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[5,8,3],
"group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[5,8,1],
"group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[5,8,6],
-"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,11],
+"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,12],
"group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[5,8,2],
"group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[5,8,5],
-"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,12],
+"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,13],
+"group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5":[5,8,11],
"group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[5,8,8],
"group__posix.html#gacff84f226ba9feb2031b8992e5579447":[5,8,9],
"group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[5,8,0],
diff --git a/docs/overrides.html b/docs/overrides.html
index 2a6c51e9..0e7fd0ec 100644
--- a/docs/overrides.html
+++ b/docs/overrides.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Overriding Malloc
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -110,7 +106,9 @@ $(document).ready(function(){initNavTree('overrides.html','');});
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
MacOS
+
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
+
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
@@ -125,17 +123,75 @@ $(document).ready(function(){initNavTree('overrides.html','');});
(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 ).
Static override
On Unix 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 ...
List of Overrides:
+gcc -o myprogram mimalloc-override .o myfile1.c ...
+
List of Overrides:
The specific functions that get redirected to the mimalloc library are:
-
void * malloc(size_t size);
void * calloc(size_t size, size_t n);
void * realloc(void * p, size_t newsize);
void free(void * p);
void operator delete (void * p);
void operator delete [](void * p);
void * operator new (std::size_t n) noexcept(false );
void * operator new [](std::size_t n) noexcept(false );
void * operator new ( std::size_t n, std::align_val_t align) noexcept(false );
void * operator new []( std::size_t n, std::align_val_t align) noexcept(false );
void * operator new ( std::size_t count, const std::nothrow_t& tag);
void * operator new []( std::size_t count, const std::nothrow_t& tag);
void * operator new ( std::size_t count, std::align_val_t al, const std::nothrow_t&);
void * operator new []( std::size_t count, std::align_val_t al, const std::nothrow_t&);
int posix_memalign(void ** p, size_t alignment, size_t size);
void * memalign(size_t alignment, size_t size);
void * aligned_alloc(size_t alignment, size_t size);
void * valloc(size_t size);
void * pvalloc(size_t size);
size_t malloc_usable_size(void *p);
void * reallocarray( void * p, size_t count, size_t size );
void * reallocf(void * p, size_t newsize);
void cfree(void * p);
void * _expand(void * p, size_t newsize);
size_t _msize(void * p);
void * _malloc_dbg(size_t size, int block_type, const char * fname, int line);
void * _realloc_dbg(void * p, size_t newsize, int block_type, const char * fname, int line);
void * _calloc_dbg(size_t count, size_t size, int block_type, const char * fname, int line);
void * _expand_dbg(void * p, size_t size, int block_type, const char * fname, int line);
size_t _msize_dbg(void * p, int block_type);
void _free_dbg(void * p, int block_type);
-
+
+
void * malloc(size_t size);
+
void * calloc(size_t size, size_t n);
+
void * realloc(void * p, size_t newsize);
+
void free(void * p);
+
+
void * aligned_alloc(size_t alignment, size_t size);
+
char * strdup(const char * s);
+
char * strndup(const char * s, size_t n);
+
char * realpath(const char * fname, char * resolved_name);
+
+
+
+
void operator delete (void * p);
+
void operator delete [](void * p);
+
+
void * operator new (std::size_t n) noexcept(false );
+
void * operator new [](std::size_t n) noexcept(false );
+
void * operator new ( std::size_t n, std::align_val_t align) noexcept(false );
+
void * operator new []( std::size_t n, std::align_val_t align) noexcept(false );
+
+
void * operator new ( std::size_t count, const std::nothrow_t& tag);
+
void * operator new []( std::size_t count, const std::nothrow_t& tag);
+
void * operator new ( std::size_t count, std::align_val_t al, const std::nothrow_t&);
+
void * operator new []( std::size_t count, std::align_val_t al, const std::nothrow_t&);
+
+
+
int posix_memalign(void ** p, size_t alignment, size_t size);
+
+
+
void * memalign(size_t alignment, size_t size);
+
void * valloc(size_t size);
+
void * pvalloc(size_t size);
+
size_t malloc_usable_size(void *p);
+
void * reallocf(void * p, size_t newsize);
+
+
+
void vfree(void * p);
+
size_t malloc_size(const void * p);
+
size_t malloc_good_size(size_t size);
+
+
+
void * reallocarray( void * p, size_t count, size_t size );
+
void * reallocf(void * p, size_t newsize);
+
void cfree(void * p);
+
+
+
int reallocarr(void * p, size_t count, size_t size);
+
+
+
void * _expand(void * p, size_t newsize);
+
size_t _msize(void * p);
+
+
void * _malloc_dbg(size_t size, int block_type, const char * fname, int line);
+
void * _realloc_dbg(void * p, size_t newsize, int block_type, const char * fname, int line);
+
void * _calloc_dbg(size_t count, size_t size, int block_type, const char * fname, int line);
+
void * _expand_dbg(void * p, size_t size, int block_type, const char * fname, int line);
+
size_t _msize_dbg(void * p, int block_type);
+
void _free_dbg(void * p, int block_type);
+
+
diff --git a/docs/pages.html b/docs/pages.html
index 8fcd6f08..6999a810 100644
--- a/docs/pages.html
+++ b/docs/pages.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Related Pages
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -116,9 +112,7 @@ $(document).ready(function(){initNavTree('pages.html','');});
diff --git a/docs/resize.js b/docs/resize.js
index 6617aee8..e1ad0fe3 100644
--- a/docs/resize.js
+++ b/docs/resize.js
@@ -1,25 +1,26 @@
/*
- @licstart The following is the entire license notice for the
- JavaScript code in this file.
+ @licstart The following is the entire license notice for the JavaScript code in this file.
- Copyright (C) 1997-2017 by Dimitri van Heesch
+ The MIT License (MIT)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ Copyright (C) 1997-2020 by Dimitri van Heesch
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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:
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
- @licend The above is the entire license notice
- for the JavaScript code in this file
+ 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.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
*/
function initResizable()
{
@@ -91,6 +92,9 @@ function initResizable()
}
collapsedWidth=width;
}
+ if (location.hash.slice(1)) {
+ (document.getElementById(location.hash.slice(1))||document.body).scrollIntoView();
+ }
}
function collapseExpand()
@@ -131,6 +135,6 @@ function initResizable()
var _preventDefault = function(evt) { evt.preventDefault(); };
$("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault);
$(".ui-resizable-handle").dblclick(collapseExpand);
- $(window).load(resizeHeight);
+ $(window).on('load',resizeHeight);
}
/* @license-end */
diff --git a/docs/search/all_0.html b/docs/search/all_0.html
index 5330204c..1ec5b2d5 100644
--- a/docs/search/all_0.html
+++ b/docs/search/all_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_0.js b/docs/search/all_0.js
index 7054b6d4..cd7bb419 100644
--- a/docs/search/all_0.js
+++ b/docs/search/all_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['_5fmi_5foption_5flast',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
+ ['_5fmi_5foption_5flast_0',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/all_1.html b/docs/search/all_1.html
index 2f467936..9f80e904 100644
--- a/docs/search/all_1.html
+++ b/docs/search/all_1.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_1.js b/docs/search/all_1.js
index bbb4b544..7f1097c0 100644
--- a/docs/search/all_1.js
+++ b/docs/search/all_1.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['aligned_20allocation',['Aligned Allocation',['../group__aligned.html',1,'']]]
+ ['aligned_20allocation_1',['Aligned Allocation',['../group__aligned.html',1,'']]]
];
diff --git a/docs/search/all_2.html b/docs/search/all_2.html
index 4c33d855..02cfffc2 100644
--- a/docs/search/all_2.html
+++ b/docs/search/all_2.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_2.js b/docs/search/all_2.js
index 829288c6..00576d78 100644
--- a/docs/search/all_2.js
+++ b/docs/search/all_2.js
@@ -1,7 +1,7 @@
var searchData=
[
- ['block_5fsize',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
- ['blocks',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]],
- ['building',['Building',['../build.html',1,'']]],
- ['basic_20allocation',['Basic Allocation',['../group__malloc.html',1,'']]]
+ ['basic_20allocation_2',['Basic Allocation',['../group__malloc.html',1,'']]],
+ ['block_5fsize_3',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
+ ['blocks_4',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]],
+ ['building_5',['Building',['../build.html',1,'']]]
];
diff --git a/docs/search/all_3.html b/docs/search/all_3.html
index b634070b..39767b85 100644
--- a/docs/search/all_3.html
+++ b/docs/search/all_3.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_3.js b/docs/search/all_3.js
index 2e08411f..9a029ee0 100644
--- a/docs/search/all_3.js
+++ b/docs/search/all_3.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['committed',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]],
- ['c_2b_2b_20wrappers',['C++ wrappers',['../group__cpp.html',1,'']]]
+ ['c_2b_2b_20wrappers_6',['C++ wrappers',['../group__cpp.html',1,'']]],
+ ['committed_7',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]]
];
diff --git a/docs/search/all_4.html b/docs/search/all_4.html
index dd062aea..fc40463c 100644
--- a/docs/search/all_4.html
+++ b/docs/search/all_4.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_4.js b/docs/search/all_4.js
index 059f44c7..5dc51286 100644
--- a/docs/search/all_4.js
+++ b/docs/search/all_4.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['environment_20options',['Environment Options',['../environment.html',1,'']]],
- ['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]]
+ ['environment_20options_8',['Environment Options',['../environment.html',1,'']]],
+ ['extended_20functions_9',['Extended Functions',['../group__extended.html',1,'']]]
];
diff --git a/docs/search/all_5.html b/docs/search/all_5.html
index f0780fdd..9dd9344b 100644
--- a/docs/search/all_5.html
+++ b/docs/search/all_5.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_5.js b/docs/search/all_5.js
index e7e40934..7441d853 100644
--- a/docs/search/all_5.js
+++ b/docs/search/all_5.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['heap_20introspection',['Heap Introspection',['../group__analysis.html',1,'']]],
- ['heap_20allocation',['Heap Allocation',['../group__heap.html',1,'']]]
+ ['heap_20allocation_10',['Heap Allocation',['../group__heap.html',1,'']]],
+ ['heap_20introspection_11',['Heap Introspection',['../group__analysis.html',1,'']]]
];
diff --git a/docs/search/all_6.html b/docs/search/all_6.html
index 39b0f555..f1e516d7 100644
--- a/docs/search/all_6.html
+++ b/docs/search/all_6.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_6.js b/docs/search/all_6.js
index 491883f4..6d32b7b1 100644
--- a/docs/search/all_6.js
+++ b/docs/search/all_6.js
@@ -1,148 +1,153 @@
var searchData=
[
- ['mi_5f_5fposix_5fmemalign',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
- ['mi_5faligned_5falloc',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
- ['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc_5faligned',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc_5faligned_5fat',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc_5ftp',['mi_calloc_tp',['../group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07',1,'mimalloc-doc.h']]],
- ['mi_5fcfree',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
- ['mi_5fcheck_5fowned',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
- ['mi_5fcollect',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
- ['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
- ['mi_5ferror_5ffun',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
- ['mi_5fexpand',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
- ['mi_5ffree',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5faligned',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5fsize',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5fsize_5faligned',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
- ['mi_5fgood_5fsize',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5farea_5ft',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
- ['mi_5fheap_5fcalloc',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc_5faligned',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc_5faligned_5fat',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc_5ftp',['mi_heap_calloc_tp',['../group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcheck_5fowned',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcollect',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcontains_5fblock',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fdelete',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fdestroy',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fget_5fbacking',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fget_5fdefault',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5faligned',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5faligned_5fat',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5fsmall',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5ftp',['mi_heap_malloc_tp',['../group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmallocn',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmallocn_5ftp',['mi_heap_mallocn_tp',['../group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fnew',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc_5faligned',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc_5faligned_5fat',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5freallocf',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5freallocn',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5freallocn_5ftp',['mi_heap_reallocn_tp',['../group__typed.html#gaf213d5422ec35e7f6caad827c79bc948',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealpath',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc_5faligned',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc_5faligned_5fat',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc_5ftp',['mi_heap_recalloc_tp',['../group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc_5faligned',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc_5faligned_5fat',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fset_5fdefault',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fstrdup',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fstrndup',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fvisit_5fblocks',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc_5faligned',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc_5faligned_5fat',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc_5ftp',['mi_heap_zalloc_tp',['../group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe',1,'mimalloc-doc.h']]],
- ['mi_5fis_5fin_5fheap_5fregion',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
- ['mi_5fis_5fredirected',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5faligned',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5faligned_5fat',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fsize',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fsmall',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5ftp',['mi_malloc_tp',['../group__typed.html#ga0619a62c5fd886f1016030abe91f0557',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fusable_5fsize',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
- ['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
- ['mi_5fmallocn_5ftp',['mi_mallocn_tp',['../group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b',1,'mimalloc-doc.h']]],
- ['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
- ['mi_5fnew',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5faligned',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5fn',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5frealloc',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5freallocn',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fdisable',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
- ['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
- ['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
- ['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fenable',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fget',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fis_5fenabled',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
- ['mi_5foption_5flarge_5fos_5fpages',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fos_5ftag',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freset_5fdelay',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fdefault',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fenabled',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fenabled_5fdefault',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
- ['mi_5foption_5ft',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fuse_5fnuma_5fnodes',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]],
- ['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]],
- ['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
- ['mi_5fprocess_5finfo',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
- ['mi_5fpvalloc',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
- ['mi_5frealloc',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
- ['mi_5frealloc_5faligned',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
- ['mi_5frealloc_5faligned_5fat',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
- ['mi_5freallocarray',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
- ['mi_5freallocf',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
- ['mi_5freallocn',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
- ['mi_5freallocn_5ftp',['mi_reallocn_tp',['../group__typed.html#ga1158b49a55dfa81f58a4426a7578f523',1,'mimalloc-doc.h']]],
- ['mi_5frealpath',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5ferror',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
- ['mi_5freserve_5fhuge_5fos_5fpages_5fat',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
- ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
- ['mi_5fsmall_5fsize_5fmax',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fprint_5fout',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
- ['mi_5fstl_5fallocator',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]],
- ['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
- ['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5fstats_5fprint_5fout',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
- ['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
- ['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5faligned',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5faligned_5fat',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5fsmall',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5ftp',['mi_zalloc_tp',['../group__typed.html#gac77a61bdaf680a803785fe307820b48c',1,'mimalloc-doc.h']]]
+ ['mi_5f_5fposix_5fmemalign_12',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
+ ['mi_5faligned_5falloc_13',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
+ ['mi_5falignment_5fmax_14',['MI_ALIGNMENT_MAX',['../group__aligned.html#ga83c03016066b438f51a8095e9140be06',1,'mimalloc-doc.h']]],
+ ['mi_5fblock_5fvisit_5ffun_15',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_16',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_5faligned_17',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_5faligned_5fat_18',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_5ftp_19',['mi_calloc_tp',['../group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07',1,'mimalloc-doc.h']]],
+ ['mi_5fcfree_20',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
+ ['mi_5fcheck_5fowned_21',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
+ ['mi_5fcollect_22',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
+ ['mi_5fdeferred_5ffree_5ffun_23',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
+ ['mi_5ferror_5ffun_24',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
+ ['mi_5fexpand_25',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_26',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5faligned_27',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5fsize_28',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5fsize_5faligned_29',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
+ ['mi_5fgood_5fsize_30',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5farea_5ft_31',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
+ ['mi_5fheap_5fcalloc_32',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_5faligned_33',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_5faligned_5fat_34',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_5ftp_35',['mi_heap_calloc_tp',['../group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcheck_5fowned_36',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcollect_37',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcontains_5fblock_38',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fdelete_39',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fdestroy_40',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fget_5fbacking_41',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fget_5fdefault_42',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_43',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5faligned_44',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5faligned_5fat_45',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5fsmall_46',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5ftp_47',['mi_heap_malloc_tp',['../group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmallocn_48',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmallocn_5ftp_49',['mi_heap_mallocn_tp',['../group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fnew_50',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_51',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_5faligned_52',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_5faligned_5fat_53',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5freallocf_54',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5freallocn_55',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5freallocn_5ftp_56',['mi_heap_reallocn_tp',['../group__typed.html#gaf213d5422ec35e7f6caad827c79bc948',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealpath_57',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_58',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_5faligned_59',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_5faligned_5fat_60',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_5ftp_61',['mi_heap_recalloc_tp',['../group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_62',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_5faligned_63',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_5faligned_5fat_64',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fset_5fdefault_65',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fstrdup_66',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fstrndup_67',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5ft_68',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fvisit_5fblocks_69',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_70',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_5faligned_71',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_5faligned_5fat_72',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_5ftp_73',['mi_heap_zalloc_tp',['../group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe',1,'mimalloc-doc.h']]],
+ ['mi_5fis_5fin_5fheap_5fregion_74',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
+ ['mi_5fis_5fredirected_75',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_76',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5faligned_77',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5faligned_5fat_78',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fsize_79',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fsmall_80',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5ftp_81',['mi_malloc_tp',['../group__typed.html#ga0619a62c5fd886f1016030abe91f0557',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fusable_5fsize_82',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
+ ['mi_5fmallocn_83',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
+ ['mi_5fmallocn_5ftp_84',['mi_mallocn_tp',['../group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b',1,'mimalloc-doc.h']]],
+ ['mi_5fmanage_5fos_5fmemory_85',['mi_manage_os_memory',['../group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf',1,'mimalloc-doc.h']]],
+ ['mi_5fmemalign_86',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_87',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5faligned_88',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5faligned_5fnothrow_89',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5fn_90',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5fnothrow_91',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5frealloc_92',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5freallocn_93',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fdisable_94',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5feager_5fcommit_95',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5feager_5fcommit_5fdelay_96',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5feager_5fregion_5fcommit_97',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fenable_98',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fget_99',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fis_5fenabled_100',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5flarge_5fos_5fpages_101',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fos_5ftag_102',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fpage_5freset_103',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freserve_5fhuge_5fos_5fpages_104',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freserve_5fhuge_5fos_5fpages_5fat_105',['mi_option_reserve_huge_os_pages_at',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freset_5fdecommits_106',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freset_5fdelay_107',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fsegment_5fcache_108',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fsegment_5freset_109',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_110',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fdefault_111',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fenabled_112',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fenabled_5fdefault_113',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fshow_5ferrors_114',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fshow_5fstats_115',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5ft_116',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fuse_5fnuma_5fnodes_117',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fverbose_118',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]],
+ ['mi_5foutput_5ffun_119',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]],
+ ['mi_5fposix_5fmemalign_120',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
+ ['mi_5fprocess_5finfo_121',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
+ ['mi_5fpvalloc_122',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_123',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_5faligned_124',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_5faligned_5fat_125',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
+ ['mi_5freallocarr_126',['mi_reallocarr',['../group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5',1,'mimalloc-doc.h']]],
+ ['mi_5freallocarray_127',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
+ ['mi_5freallocf_128',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
+ ['mi_5freallocn_129',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
+ ['mi_5freallocn_5ftp_130',['mi_reallocn_tp',['../group__typed.html#ga1158b49a55dfa81f58a4426a7578f523',1,'mimalloc-doc.h']]],
+ ['mi_5frealpath_131',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_132',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_5faligned_133',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_5faligned_5fat_134',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5fdeferred_5ffree_135',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5ferror_136',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5foutput_137',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fhuge_5fos_5fpages_5fat_138',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave_139',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fos_5fmemory_140',['mi_reserve_os_memory',['../group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_141',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_5faligned_142',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_5faligned_5fat_143',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
+ ['mi_5fsmall_5fsize_5fmax_144',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fmerge_145',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fprint_146',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fprint_5fout_147',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5freset_148',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
+ ['mi_5fstl_5fallocator_149',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]],
+ ['mi_5fstrdup_150',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
+ ['mi_5fstrndup_151',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5fdone_152',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5finit_153',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5fstats_5fprint_5fout_154',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
+ ['mi_5fusable_5fsize_155',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
+ ['mi_5fvalloc_156',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_157',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5faligned_158',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5faligned_5fat_159',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5fsmall_160',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5ftp_161',['mi_zalloc_tp',['../group__typed.html#gac77a61bdaf680a803785fe307820b48c',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/all_7.html b/docs/search/all_7.html
index 9cd0196e..8ddbf6c8 100644
--- a/docs/search/all_7.html
+++ b/docs/search/all_7.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_7.js b/docs/search/all_7.js
index df03c8d8..8f296aa5 100644
--- a/docs/search/all_7.js
+++ b/docs/search/all_7.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['overriding_20malloc',['Overriding Malloc',['../overrides.html',1,'']]]
+ ['overriding_20malloc_162',['Overriding Malloc',['../overrides.html',1,'']]]
];
diff --git a/docs/search/all_8.html b/docs/search/all_8.html
index 1e8fb9ce..83c55ae2 100644
--- a/docs/search/all_8.html
+++ b/docs/search/all_8.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_8.js b/docs/search/all_8.js
index 0651bcc3..a9caa77c 100644
--- a/docs/search/all_8.js
+++ b/docs/search/all_8.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['performance',['Performance',['../bench.html',1,'']]],
- ['posix',['Posix',['../group__posix.html',1,'']]]
+ ['performance_163',['Performance',['../bench.html',1,'']]],
+ ['posix_164',['Posix',['../group__posix.html',1,'']]]
];
diff --git a/docs/search/all_9.html b/docs/search/all_9.html
index 27df366b..1e263c13 100644
--- a/docs/search/all_9.html
+++ b/docs/search/all_9.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_9.js b/docs/search/all_9.js
index cd78624d..f6b4ba35 100644
--- a/docs/search/all_9.js
+++ b/docs/search/all_9.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['runtime_20options',['Runtime Options',['../group__options.html',1,'']]],
- ['reserved',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]]
+ ['reserved_165',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]],
+ ['runtime_20options_166',['Runtime Options',['../group__options.html',1,'']]]
];
diff --git a/docs/search/all_a.html b/docs/search/all_a.html
index 63f9254d..3a6cac10 100644
--- a/docs/search/all_a.html
+++ b/docs/search/all_a.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_a.js b/docs/search/all_a.js
index 647887f5..699b5456 100644
--- a/docs/search/all_a.js
+++ b/docs/search/all_a.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['typed_20macros',['Typed Macros',['../group__typed.html',1,'']]]
+ ['typed_20macros_167',['Typed Macros',['../group__typed.html',1,'']]]
];
diff --git a/docs/search/all_b.html b/docs/search/all_b.html
index 44ae3e47..130deb4e 100644
--- a/docs/search/all_b.html
+++ b/docs/search/all_b.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_b.js b/docs/search/all_b.js
index 2bc3fb6d..73a2671d 100644
--- a/docs/search/all_b.js
+++ b/docs/search/all_b.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['used',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]],
- ['using_20the_20library',['Using the library',['../using.html',1,'']]]
+ ['used_168',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]],
+ ['using_20the_20library_169',['Using the library',['../using.html',1,'']]]
];
diff --git a/docs/search/all_c.html b/docs/search/all_c.html
index 3de15867..3dd5af06 100644
--- a/docs/search/all_c.html
+++ b/docs/search/all_c.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/all_c.js b/docs/search/all_c.js
index 2b9b4cea..192fb1cb 100644
--- a/docs/search/all_c.js
+++ b/docs/search/all_c.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
+ ['zero_20initialized_20re_2dallocation_170',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
];
diff --git a/docs/search/classes_0.html b/docs/search/classes_0.html
index b3c6ec6a..af8159ee 100644
--- a/docs/search/classes_0.html
+++ b/docs/search/classes_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/classes_0.js b/docs/search/classes_0.js
index 0010dd97..e3770fb4 100644
--- a/docs/search/classes_0.js
+++ b/docs/search/classes_0.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['mi_5fheap_5farea_5ft',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
- ['mi_5fstl_5fallocator',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]]
+ ['mi_5fheap_5farea_5ft_171',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
+ ['mi_5fstl_5fallocator_172',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]]
];
diff --git a/docs/search/enums_0.html b/docs/search/enums_0.html
index 7040a9c5..141fff57 100644
--- a/docs/search/enums_0.html
+++ b/docs/search/enums_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/enums_0.js b/docs/search/enums_0.js
index f0c1ba50..6f1f3833 100644
--- a/docs/search/enums_0.js
+++ b/docs/search/enums_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['mi_5foption_5ft',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]]
+ ['mi_5foption_5ft_296',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/enumvalues_0.html b/docs/search/enumvalues_0.html
index 78895c79..0d131d95 100644
--- a/docs/search/enumvalues_0.html
+++ b/docs/search/enumvalues_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/enumvalues_0.js b/docs/search/enumvalues_0.js
index 7054b6d4..1aca63bb 100644
--- a/docs/search/enumvalues_0.js
+++ b/docs/search/enumvalues_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['_5fmi_5foption_5flast',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
+ ['_5fmi_5foption_5flast_297',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/enumvalues_1.html b/docs/search/enumvalues_1.html
index 9b02a4b3..cd9187ab 100644
--- a/docs/search/enumvalues_1.html
+++ b/docs/search/enumvalues_1.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/enumvalues_1.js b/docs/search/enumvalues_1.js
index 3b712708..bd525bb8 100644
--- a/docs/search/enumvalues_1.js
+++ b/docs/search/enumvalues_1.js
@@ -1,18 +1,19 @@
var searchData=
[
- ['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
- ['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
- ['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
- ['mi_5foption_5flarge_5fos_5fpages',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fos_5ftag',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
- ['mi_5foption_5freset_5fdelay',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fuse_5fnuma_5fnodes',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
+ ['mi_5foption_5feager_5fcommit_298',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5feager_5fcommit_5fdelay_299',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5feager_5fregion_5fcommit_300',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5flarge_5fos_5fpages_301',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fos_5ftag_302',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fpage_5freset_303',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freserve_5fhuge_5fos_5fpages_304',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freserve_5fhuge_5fos_5fpages_5fat_305',['mi_option_reserve_huge_os_pages_at',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freset_5fdecommits_306',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5freset_5fdelay_307',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fsegment_5fcache_308',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fsegment_5freset_309',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fshow_5ferrors_310',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fshow_5fstats_311',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fuse_5fnuma_5fnodes_312',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fverbose_313',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/functions_0.html b/docs/search/functions_0.html
index bc73761f..eb4c5014 100644
--- a/docs/search/functions_0.html
+++ b/docs/search/functions_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/functions_0.js b/docs/search/functions_0.js
index b188b270..b44917a5 100644
--- a/docs/search/functions_0.js
+++ b/docs/search/functions_0.js
@@ -1,113 +1,116 @@
var searchData=
[
- ['mi_5f_5fposix_5fmemalign',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
- ['mi_5faligned_5falloc',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc_5faligned',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
- ['mi_5fcalloc_5faligned_5fat',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
- ['mi_5fcfree',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
- ['mi_5fcheck_5fowned',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
- ['mi_5fcollect',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
- ['mi_5fexpand',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
- ['mi_5ffree',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5faligned',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5fsize',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
- ['mi_5ffree_5fsize_5faligned',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
- ['mi_5fgood_5fsize',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc_5faligned',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcalloc_5faligned_5fat',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcheck_5fowned',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcollect',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fcontains_5fblock',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fdelete',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fdestroy',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fget_5fbacking',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fget_5fdefault',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5faligned',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5faligned_5fat',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmalloc_5fsmall',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fmallocn',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fnew',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc_5faligned',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealloc_5faligned_5fat',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5freallocf',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5freallocn',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frealpath',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc_5faligned',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frecalloc_5faligned_5fat',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc_5faligned',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5frezalloc_5faligned_5fat',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fset_5fdefault',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fstrdup',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fstrndup',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fvisit_5fblocks',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc_5faligned',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5fzalloc_5faligned_5fat',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
- ['mi_5fis_5fin_5fheap_5fregion',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
- ['mi_5fis_5fredirected',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5faligned',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5faligned_5fat',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fsize',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fsmall',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
- ['mi_5fmalloc_5fusable_5fsize',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
- ['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
- ['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
- ['mi_5fnew',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5faligned',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5fn',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5frealloc',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
- ['mi_5fnew_5freallocn',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fdisable',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fenable',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fget',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fis_5fenabled',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fdefault',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fenabled',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
- ['mi_5foption_5fset_5fenabled_5fdefault',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
- ['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
- ['mi_5fprocess_5finfo',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
- ['mi_5fpvalloc',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
- ['mi_5frealloc',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
- ['mi_5frealloc_5faligned',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
- ['mi_5frealloc_5faligned_5fat',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
- ['mi_5freallocarray',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
- ['mi_5freallocf',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
- ['mi_5freallocn',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
- ['mi_5frealpath',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
- ['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5ferror',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
- ['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
- ['mi_5freserve_5fhuge_5fos_5fpages_5fat',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
- ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
- ['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5fprint_5fout',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
- ['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
- ['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
- ['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
- ['mi_5fthread_5fstats_5fprint_5fout',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
- ['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
- ['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5faligned',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5faligned_5fat',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
- ['mi_5fzalloc_5fsmall',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]]
+ ['mi_5f_5fposix_5fmemalign_173',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
+ ['mi_5faligned_5falloc_174',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_175',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_5faligned_176',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
+ ['mi_5fcalloc_5faligned_5fat_177',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
+ ['mi_5fcfree_178',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
+ ['mi_5fcheck_5fowned_179',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
+ ['mi_5fcollect_180',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
+ ['mi_5fexpand_181',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_182',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5faligned_183',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5fsize_184',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
+ ['mi_5ffree_5fsize_5faligned_185',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
+ ['mi_5fgood_5fsize_186',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_187',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_5faligned_188',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcalloc_5faligned_5fat_189',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcheck_5fowned_190',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcollect_191',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fcontains_5fblock_192',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fdelete_193',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fdestroy_194',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fget_5fbacking_195',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fget_5fdefault_196',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_197',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5faligned_198',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5faligned_5fat_199',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmalloc_5fsmall_200',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fmallocn_201',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fnew_202',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_203',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_5faligned_204',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealloc_5faligned_5fat_205',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5freallocf_206',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5freallocn_207',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frealpath_208',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_209',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_5faligned_210',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frecalloc_5faligned_5fat_211',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_212',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_5faligned_213',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5frezalloc_5faligned_5fat_214',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fset_5fdefault_215',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fstrdup_216',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fstrndup_217',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fvisit_5fblocks_218',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_219',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_5faligned_220',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5fzalloc_5faligned_5fat_221',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
+ ['mi_5fis_5fin_5fheap_5fregion_222',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
+ ['mi_5fis_5fredirected_223',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_224',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5faligned_225',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5faligned_5fat_226',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fsize_227',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fsmall_228',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
+ ['mi_5fmalloc_5fusable_5fsize_229',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
+ ['mi_5fmallocn_230',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
+ ['mi_5fmanage_5fos_5fmemory_231',['mi_manage_os_memory',['../group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf',1,'mimalloc-doc.h']]],
+ ['mi_5fmemalign_232',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_233',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5faligned_234',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5faligned_5fnothrow_235',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5fn_236',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5fnothrow_237',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5frealloc_238',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
+ ['mi_5fnew_5freallocn_239',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fdisable_240',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fenable_241',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fget_242',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fis_5fenabled_243',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_244',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fdefault_245',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fenabled_246',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
+ ['mi_5foption_5fset_5fenabled_5fdefault_247',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
+ ['mi_5fposix_5fmemalign_248',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
+ ['mi_5fprocess_5finfo_249',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
+ ['mi_5fpvalloc_250',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_251',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_5faligned_252',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
+ ['mi_5frealloc_5faligned_5fat_253',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
+ ['mi_5freallocarr_254',['mi_reallocarr',['../group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5',1,'mimalloc-doc.h']]],
+ ['mi_5freallocarray_255',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
+ ['mi_5freallocf_256',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
+ ['mi_5freallocn_257',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
+ ['mi_5frealpath_258',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_259',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_5faligned_260',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
+ ['mi_5frecalloc_5faligned_5fat_261',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5fdeferred_5ffree_262',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5ferror_263',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
+ ['mi_5fregister_5foutput_264',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fhuge_5fos_5fpages_5fat_265',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave_266',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
+ ['mi_5freserve_5fos_5fmemory_267',['mi_reserve_os_memory',['../group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_268',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_5faligned_269',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
+ ['mi_5frezalloc_5faligned_5fat_270',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fmerge_271',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fprint_272',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5fprint_5fout_273',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
+ ['mi_5fstats_5freset_274',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
+ ['mi_5fstrdup_275',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
+ ['mi_5fstrndup_276',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5fdone_277',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5finit_278',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
+ ['mi_5fthread_5fstats_5fprint_5fout_279',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
+ ['mi_5fusable_5fsize_280',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
+ ['mi_5fvalloc_281',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_282',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5faligned_283',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5faligned_5fat_284',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
+ ['mi_5fzalloc_5fsmall_285',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/groups_0.html b/docs/search/groups_0.html
index 194bb7bc..c600b497 100644
--- a/docs/search/groups_0.html
+++ b/docs/search/groups_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_0.js b/docs/search/groups_0.js
index bbb4b544..0ed99b80 100644
--- a/docs/search/groups_0.js
+++ b/docs/search/groups_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['aligned_20allocation',['Aligned Allocation',['../group__aligned.html',1,'']]]
+ ['aligned_20allocation_314',['Aligned Allocation',['../group__aligned.html',1,'']]]
];
diff --git a/docs/search/groups_1.html b/docs/search/groups_1.html
index ed9b5c61..2eb3550d 100644
--- a/docs/search/groups_1.html
+++ b/docs/search/groups_1.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_1.js b/docs/search/groups_1.js
index b258fac4..f27c5847 100644
--- a/docs/search/groups_1.js
+++ b/docs/search/groups_1.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['basic_20allocation',['Basic Allocation',['../group__malloc.html',1,'']]]
+ ['basic_20allocation_315',['Basic Allocation',['../group__malloc.html',1,'']]]
];
diff --git a/docs/search/groups_2.html b/docs/search/groups_2.html
index 17d4e06a..12f4af7a 100644
--- a/docs/search/groups_2.html
+++ b/docs/search/groups_2.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_2.js b/docs/search/groups_2.js
index 29185761..6da64b68 100644
--- a/docs/search/groups_2.js
+++ b/docs/search/groups_2.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['c_2b_2b_20wrappers',['C++ wrappers',['../group__cpp.html',1,'']]]
+ ['c_2b_2b_20wrappers_316',['C++ wrappers',['../group__cpp.html',1,'']]]
];
diff --git a/docs/search/groups_3.html b/docs/search/groups_3.html
index 7d4a624e..5e235b53 100644
--- a/docs/search/groups_3.html
+++ b/docs/search/groups_3.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_3.js b/docs/search/groups_3.js
index 68c73dbe..cdfbe640 100644
--- a/docs/search/groups_3.js
+++ b/docs/search/groups_3.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]]
+ ['extended_20functions_317',['Extended Functions',['../group__extended.html',1,'']]]
];
diff --git a/docs/search/groups_4.html b/docs/search/groups_4.html
index 5e5ae2ac..99405e15 100644
--- a/docs/search/groups_4.html
+++ b/docs/search/groups_4.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_4.js b/docs/search/groups_4.js
index e7e40934..687f1ea7 100644
--- a/docs/search/groups_4.js
+++ b/docs/search/groups_4.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['heap_20introspection',['Heap Introspection',['../group__analysis.html',1,'']]],
- ['heap_20allocation',['Heap Allocation',['../group__heap.html',1,'']]]
+ ['heap_20allocation_318',['Heap Allocation',['../group__heap.html',1,'']]],
+ ['heap_20introspection_319',['Heap Introspection',['../group__analysis.html',1,'']]]
];
diff --git a/docs/search/groups_5.html b/docs/search/groups_5.html
index fbd14605..583f5f58 100644
--- a/docs/search/groups_5.html
+++ b/docs/search/groups_5.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_5.js b/docs/search/groups_5.js
index 4f005682..43c8b1fc 100644
--- a/docs/search/groups_5.js
+++ b/docs/search/groups_5.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['posix',['Posix',['../group__posix.html',1,'']]]
+ ['posix_320',['Posix',['../group__posix.html',1,'']]]
];
diff --git a/docs/search/groups_6.html b/docs/search/groups_6.html
index 277d80e1..df6a310f 100644
--- a/docs/search/groups_6.html
+++ b/docs/search/groups_6.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_6.js b/docs/search/groups_6.js
index 2533cb94..34631879 100644
--- a/docs/search/groups_6.js
+++ b/docs/search/groups_6.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['runtime_20options',['Runtime Options',['../group__options.html',1,'']]]
+ ['runtime_20options_321',['Runtime Options',['../group__options.html',1,'']]]
];
diff --git a/docs/search/groups_7.html b/docs/search/groups_7.html
index 6a24e7cf..8964e050 100644
--- a/docs/search/groups_7.html
+++ b/docs/search/groups_7.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_7.js b/docs/search/groups_7.js
index 647887f5..aa150e97 100644
--- a/docs/search/groups_7.js
+++ b/docs/search/groups_7.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['typed_20macros',['Typed Macros',['../group__typed.html',1,'']]]
+ ['typed_20macros_322',['Typed Macros',['../group__typed.html',1,'']]]
];
diff --git a/docs/search/groups_8.html b/docs/search/groups_8.html
index 81ac9508..7987ca39 100644
--- a/docs/search/groups_8.html
+++ b/docs/search/groups_8.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/groups_8.js b/docs/search/groups_8.js
index 2b9b4cea..f9c29fe3 100644
--- a/docs/search/groups_8.js
+++ b/docs/search/groups_8.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
+ ['zero_20initialized_20re_2dallocation_323',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
];
diff --git a/docs/search/nomatches.html b/docs/search/nomatches.html
index 43773208..2b9360b6 100644
--- a/docs/search/nomatches.html
+++ b/docs/search/nomatches.html
@@ -1,5 +1,6 @@
-
+
+
diff --git a/docs/search/pages_0.html b/docs/search/pages_0.html
index 3d06b052..8517b48f 100644
--- a/docs/search/pages_0.html
+++ b/docs/search/pages_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/pages_0.js b/docs/search/pages_0.js
index 33f3d051..07922dae 100644
--- a/docs/search/pages_0.js
+++ b/docs/search/pages_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['building',['Building',['../build.html',1,'']]]
+ ['building_324',['Building',['../build.html',1,'']]]
];
diff --git a/docs/search/pages_1.html b/docs/search/pages_1.html
index 06f1e40f..a0fb6796 100644
--- a/docs/search/pages_1.html
+++ b/docs/search/pages_1.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/pages_1.js b/docs/search/pages_1.js
index 0f2757cb..6433daec 100644
--- a/docs/search/pages_1.js
+++ b/docs/search/pages_1.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['environment_20options',['Environment Options',['../environment.html',1,'']]]
+ ['environment_20options_325',['Environment Options',['../environment.html',1,'']]]
];
diff --git a/docs/search/pages_2.html b/docs/search/pages_2.html
index 703f781b..084edfd0 100644
--- a/docs/search/pages_2.html
+++ b/docs/search/pages_2.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/pages_2.js b/docs/search/pages_2.js
index df03c8d8..7577377b 100644
--- a/docs/search/pages_2.js
+++ b/docs/search/pages_2.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['overriding_20malloc',['Overriding Malloc',['../overrides.html',1,'']]]
+ ['overriding_20malloc_326',['Overriding Malloc',['../overrides.html',1,'']]]
];
diff --git a/docs/search/pages_3.html b/docs/search/pages_3.html
index 299228a4..c0b45b0f 100644
--- a/docs/search/pages_3.html
+++ b/docs/search/pages_3.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/pages_3.js b/docs/search/pages_3.js
index d7454039..d62a3cfd 100644
--- a/docs/search/pages_3.js
+++ b/docs/search/pages_3.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['performance',['Performance',['../bench.html',1,'']]]
+ ['performance_327',['Performance',['../bench.html',1,'']]]
];
diff --git a/docs/search/pages_4.html b/docs/search/pages_4.html
index 021d277a..0f05c2e7 100644
--- a/docs/search/pages_4.html
+++ b/docs/search/pages_4.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/pages_4.js b/docs/search/pages_4.js
index b47682a4..4e4e64dc 100644
--- a/docs/search/pages_4.js
+++ b/docs/search/pages_4.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['using_20the_20library',['Using the library',['../using.html',1,'']]]
+ ['using_20the_20library_328',['Using the library',['../using.html',1,'']]]
];
diff --git a/docs/search/search.js b/docs/search/search.js
index a554ab9c..fb226f73 100644
--- a/docs/search/search.js
+++ b/docs/search/search.js
@@ -1,25 +1,26 @@
/*
- @licstart The following is the entire license notice for the
- JavaScript code in this file.
+ @licstart The following is the entire license notice for the JavaScript code in this file.
- Copyright (C) 1997-2017 by Dimitri van Heesch
+ The MIT License (MIT)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ Copyright (C) 1997-2020 by Dimitri van Heesch
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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:
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
- @licend The above is the entire license notice
- for the JavaScript code in this file
+ 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.
+
+ @licend The above is the entire license notice for the JavaScript code in this file
*/
function convertToId(search)
{
@@ -79,9 +80,10 @@ function getYPos(item)
storing this instance. Is needed to be able to set timeouts.
resultPath - path to use for external files
*/
-function SearchBox(name, resultsPath, inFrame, label)
+function SearchBox(name, resultsPath, inFrame, label, extension)
{
if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
+ if (!extension || extension == "") { extension = ".html"; }
// ---------- Instance variables
this.name = name;
@@ -96,6 +98,7 @@ function SearchBox(name, resultsPath, inFrame, label)
this.searchActive = false;
this.insideFrame = inFrame;
this.searchLabel = label;
+ this.extension = extension;
// ----------- DOM Elements
@@ -200,10 +203,9 @@ function SearchBox(name, resultsPath, inFrame, label)
}
return;
}
- else if (window.frames.MSearchResults.searchResults)
+ else
{
- var elem = window.frames.MSearchResults.searchResults.NavNext(0);
- if (elem) elem.focus();
+ window.frames.MSearchResults.postMessage("take_focus", "*");
}
}
else if (e.keyCode==27) // Escape out of the search field
@@ -347,13 +349,13 @@ function SearchBox(name, resultsPath, inFrame, label)
if (idx!=-1)
{
var hexCode=idx.toString(16);
- resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
+ resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + this.extension;
resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
hasResultsPage = true;
}
else // nothing available for this search term
{
- resultsPage = this.resultsPath + '/nomatches.html';
+ resultsPage = this.resultsPath + '/nomatches' + this.extension;
resultsPageWithSearch = resultsPage;
hasResultsPage = false;
}
@@ -364,7 +366,7 @@ function SearchBox(name, resultsPath, inFrame, label)
if (domPopupSearchResultsWindow.style.display!='block')
{
var domSearchBox = this.DOMSearchBox();
- this.DOMSearchClose().style.display = 'inline';
+ this.DOMSearchClose().style.display = 'inline-block';
if (this.insideFrame)
{
var domPopupSearchResults = this.DOMPopupSearchResults();
@@ -439,12 +441,12 @@ function SearchResults(name)
while (element && element!=parentElement)
{
- if (element.nodeName == 'DIV' && element.className == 'SRChildren')
+ if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren')
{
return element;
}
- if (element.nodeName == 'DIV' && element.hasChildNodes())
+ if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes())
{
element = element.firstChild;
}
diff --git a/docs/search/typedefs_0.html b/docs/search/typedefs_0.html
index 3848b20e..a4684c4a 100644
--- a/docs/search/typedefs_0.html
+++ b/docs/search/typedefs_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/typedefs_0.js b/docs/search/typedefs_0.js
index 44a0a6c6..ac67dcd0 100644
--- a/docs/search/typedefs_0.js
+++ b/docs/search/typedefs_0.js
@@ -1,8 +1,8 @@
var searchData=
[
- ['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
- ['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
- ['mi_5ferror_5ffun',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
- ['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
- ['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]]
+ ['mi_5fblock_5fvisit_5ffun_291',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
+ ['mi_5fdeferred_5ffree_5ffun_292',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
+ ['mi_5ferror_5ffun_293',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
+ ['mi_5fheap_5ft_294',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
+ ['mi_5foutput_5ffun_295',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]]
];
diff --git a/docs/search/variables_0.html b/docs/search/variables_0.html
index 12104bcb..1e477c08 100644
--- a/docs/search/variables_0.html
+++ b/docs/search/variables_0.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/variables_0.js b/docs/search/variables_0.js
index 330c8000..4c0d7728 100644
--- a/docs/search/variables_0.js
+++ b/docs/search/variables_0.js
@@ -1,5 +1,5 @@
var searchData=
[
- ['block_5fsize',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
- ['blocks',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]]
+ ['block_5fsize_286',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
+ ['blocks_287',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]]
];
diff --git a/docs/search/variables_1.html b/docs/search/variables_1.html
index b784017a..ea73d9a4 100644
--- a/docs/search/variables_1.html
+++ b/docs/search/variables_1.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/variables_1.js b/docs/search/variables_1.js
index af76e9c8..449fd615 100644
--- a/docs/search/variables_1.js
+++ b/docs/search/variables_1.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['committed',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]]
+ ['committed_288',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]]
];
diff --git a/docs/search/variables_2.html b/docs/search/variables_2.html
index 0cb98d30..0580462e 100644
--- a/docs/search/variables_2.html
+++ b/docs/search/variables_2.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/variables_2.js b/docs/search/variables_2.js
index 304ad434..713c68e0 100644
--- a/docs/search/variables_2.js
+++ b/docs/search/variables_2.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['reserved',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]]
+ ['reserved_289',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]]
];
diff --git a/docs/search/variables_3.html b/docs/search/variables_3.html
index 1e83bf5a..0d69e761 100644
--- a/docs/search/variables_3.html
+++ b/docs/search/variables_3.html
@@ -1,7 +1,8 @@
-
+
+
-
+
@@ -10,21 +11,27 @@
Loading...
-
+
Searching...
No Matches
-
+
diff --git a/docs/search/variables_3.js b/docs/search/variables_3.js
index c889d4fa..08ec3bae 100644
--- a/docs/search/variables_3.js
+++ b/docs/search/variables_3.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['used',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]]
+ ['used_290',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]]
];
diff --git a/docs/using.html b/docs/using.html
index 047e35ec..e6aad1a2 100644
--- a/docs/using.html
+++ b/docs/using.html
@@ -3,7 +3,7 @@
-
+
mi-malloc: Using the library
@@ -13,10 +13,6 @@
-
@@ -37,12 +33,12 @@
mi-malloc
- 1.6
+ 1.7/2.0
-
@@ -51,7 +47,7 @@
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
-
+
@@ -60,10 +56,10 @@
-
+
@@ -79,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
@@ -103,21 +99,56 @@ $(document).ready(function(){initNavTree('using.html','');});
Build
-
The preferred usage is including <mimalloc.h>
, 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.0 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.
+
The preferred usage is including <mimalloc.h>
, 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.0 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.
C++
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
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. For example:
std::vector<some_struct, mi_stl_allocator<some_struct>> vec;
vec.push_back(some_struct());
Statistics
-
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.
+
In C++, mimalloc also provides the mi_stl_allocator
struct which implements the std::allocator
interface. For example:
std::vector<some_struct, mi_stl_allocator<some_struct>> vec;
+
vec.push_back(some_struct());
+
Statistics
+
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.
See Overriding Malloc for more info.
-
-
+
+
diff --git a/ide/vs2019/mimalloc.vcxproj b/ide/vs2019/mimalloc.vcxproj
index 6c7e276c..c12955c3 100644
--- a/ide/vs2019/mimalloc.vcxproj
+++ b/ide/vs2019/mimalloc.vcxproj
@@ -92,7 +92,7 @@
- Level3
+ Level4
Disabled
true
true
@@ -138,7 +138,7 @@
- Level3
+ Level4
MaxSpeed
true
true
@@ -166,7 +166,7 @@
- Level3
+ Level4
MaxSpeed
true
true
diff --git a/include/mimalloc-atomic.h b/include/mimalloc-atomic.h
index dc48f0a2..e07df84d 100644
--- a/include/mimalloc-atomic.h
+++ b/include/mimalloc-atomic.h
@@ -25,7 +25,7 @@ terms of the MIT license. A copy of the license can be found in the file
#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(tp) tp
#define ATOMIC_VAR_INIT(x) x
#define mi_atomic(name) mi_atomic_##name
#define mi_memory_order(name) mi_memory_order_##name
@@ -173,7 +173,7 @@ static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintpt
}
static inline void mi_atomic_thread_fence(mi_memory_order mo) {
(void)(mo);
- _Atomic(uintptr_t)x = 0;
+ _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) {
diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h
index 1e1a7966..16be1251 100644
--- a/include/mimalloc-internal.h
+++ b/include/mimalloc-internal.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
-Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, 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.
@@ -22,7 +22,7 @@ terms of the MIT license. A copy of the license can be found in the file
#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
+#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) // 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)))
@@ -32,6 +32,21 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_decl_cache_align
#endif
+#if defined(__EMSCRIPTEN__) && !defined(__wasi__)
+#define __wasi__
+#endif
+
+#if defined(__cplusplus)
+#define mi_decl_externc extern "C"
+#else
+#define mi_decl_externc
+#endif
+
+#if !defined(_WIN32) && !defined(__wasi__)
+#define MI_USE_PTHREADS
+#include
+#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, ...);
@@ -46,14 +61,15 @@ 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);
+uintptr_t _mi_os_random_weak(uintptr_t extra_seed);
static inline uintptr_t _mi_random_shuffle(uintptr_t x);
// init.c
extern mi_decl_cache_align mi_stats_t _mi_stats_main;
extern mi_decl_cache_align const mi_page_t _mi_page_empty;
bool _mi_is_main_thread(void);
-bool _mi_preloading(); // true while the C runtime is not ready
+size_t _mi_current_thread_count(void);
+bool _mi_preloading(void); // true while the C runtime is not ready
// os.c
size_t _mi_os_page_size(void);
@@ -61,6 +77,7 @@ void _mi_os_init(void); // called fro
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);
+bool _mi_os_has_overcommit(void);
// memory.c
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* id, mi_os_tld_t* tld);
@@ -90,7 +107,7 @@ 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_retire(mi_page_t* page) mi_attr_noexcept; // 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...
@@ -137,8 +154,8 @@ bool _mi_page_is_valid(mi_page_t* page);
// ------------------------------------------------------
#if defined(__GNUC__) || defined(__clang__)
-#define mi_unlikely(x) __builtin_expect((x),0)
-#define mi_likely(x) __builtin_expect((x),1)
+#define mi_unlikely(x) __builtin_expect(!!(x),false)
+#define mi_likely(x) __builtin_expect(!!(x),true)
#else
#define mi_unlikely(x) (x)
#define mi_likely(x) (x)
@@ -176,11 +193,11 @@ bool _mi_page_is_valid(mi_page_t* page);
/* -----------------------------------------------------------
Inlined definitions
----------------------------------------------------------- */
-#define UNUSED(x) (void)(x)
+#define MI_UNUSED(x) (void)(x)
#if (MI_DEBUG>0)
-#define UNUSED_RELEASE(x)
+#define MI_UNUSED_RELEASE(x)
#else
-#define UNUSED_RELEASE(x) UNUSED(x)
+#define MI_UNUSED_RELEASE(x) MI_UNUSED(x)
#endif
#define MI_INIT4(x) x(),x(),x(),x()
@@ -230,24 +247,19 @@ static inline size_t _mi_wsize_from_size(size_t size) {
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
+#if __has_builtin(__builtin_umul_overflow) || (defined(__GNUC__) && (__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);
+ #if (SIZE_MAX == ULONG_MAX)
+ return __builtin_umull_overflow(count, size, (unsigned long *)total);
+ #elif (SIZE_MAX == UINT_MAX)
+ return __builtin_umul_overflow(count, size, (unsigned int *)total);
#else
- return __builtin_umulll_overflow(count, size, total);
+ return __builtin_umulll_overflow(count, size, (unsigned long long *)total);
#endif
}
#else /* __builtin_umul_overflow is unavailable */
@@ -285,7 +297,7 @@ 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: the uniqueid use is buggy but kept for reference.
+- DragonFly: defaults are working but seem slow compared to freeBSD (see PR #323)
------------------------------------------------------------------------------------------- */
extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap
@@ -295,22 +307,25 @@ mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing hea
#if defined(MI_MALLOC_OVERRIDE)
#if defined(__APPLE__) // macOS
#define MI_TLS_SLOT 89 // seems unused?
+// #define MI_TLS_RECURSE_GUARD 1
// 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?)
+// #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?)
+#elif defined(__ANDROID__)
+// See issue #381
+#define MI_TLS_PTHREAD
#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__)
@@ -322,7 +337,6 @@ static inline mi_heap_t** mi_tls_pthread_heap_slot(void) {
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;
#endif
@@ -335,7 +349,13 @@ extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate
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);
+ if (mi_unlikely(heap == NULL)) {
+ #ifdef __GNUC__
+ __asm(""); // prevent conditional load of the address of _mi_heap_empty
+ #endif
+ heap = (mi_heap_t*)&_mi_heap_empty;
+ }
+ return 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);
@@ -343,7 +363,7 @@ static inline mi_heap_t* mi_get_default_heap(void) {
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 defined(MI_TLS_RECURSE_GUARD)
if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get();
#endif
return _mi_heap_default;
@@ -399,11 +419,11 @@ static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) {
}
// used internally
-static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) {
+static inline size_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;
+ size_t idx = (size_t)diff >> segment->page_shift;
mi_assert_internal(idx < segment->capacity);
mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0);
return idx;
@@ -411,7 +431,7 @@ static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, con
// 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);
+ size_t idx = _mi_segment_page_idx_of(segment, p);
return &((mi_segment_t*)segment)->pages[idx];
}
@@ -427,7 +447,7 @@ 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)
+// Get the block size of a page (special case 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);
@@ -569,8 +589,8 @@ static inline bool mi_is_in_same_page(const void* p, const void* q) {
mi_segment_t* segmentp = _mi_ptr_segment(p);
mi_segment_t* segmentq = _mi_ptr_segment(q);
if (segmentp != segmentq) return false;
- uintptr_t idxp = _mi_segment_page_idx_of(segmentp, p);
- uintptr_t idxq = _mi_segment_page_idx_of(segmentq, q);
+ size_t idxp = _mi_segment_page_idx_of(segmentp, p);
+ size_t idxq = _mi_segment_page_idx_of(segmentq, q);
return (idxp == idxq);
}
@@ -597,7 +617,7 @@ static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* bl
#ifdef MI_ENCODE_FREELIST
return (mi_block_t*)mi_ptr_decode(null, block->next, keys);
#else
- UNUSED(keys); UNUSED(null);
+ MI_UNUSED(keys); MI_UNUSED(null);
return (mi_block_t*)block->next;
#endif
}
@@ -606,7 +626,7 @@ static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const
#ifdef MI_ENCODE_FREELIST
block->next = mi_ptr_encode(null, next, keys);
#else
- UNUSED(keys); UNUSED(null);
+ MI_UNUSED(keys); MI_UNUSED(null);
block->next = (mi_encoded_t)next;
#endif
}
@@ -622,7 +642,7 @@ static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t*
}
return next;
#else
- UNUSED(page);
+ MI_UNUSED(page);
return mi_block_nextx(page,block,NULL);
#endif
}
@@ -631,7 +651,7 @@ static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, c
#ifdef MI_ENCODE_FREELIST
mi_block_set_nextx(page,block,next, page->keys);
#else
- UNUSED(page);
+ MI_UNUSED(page);
mi_block_set_nextx(page,block,next,NULL);
#endif
}
@@ -682,90 +702,105 @@ static inline size_t _mi_os_numa_node_count(void) {
// -------------------------------------------------------------------
// Getting the thread id should be performant as it is called in the
// fast path of `_mi_free` and we specialize for various platforms.
+// We only require _mi_threadid() to return a unique id for each thread.
// -------------------------------------------------------------------
#if defined(_WIN32)
+
#define WIN32_LEAN_AND_MEAN
#include
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
+static inline mi_threadid_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__))
+// We use assembly for a fast thread id on the main platforms. The TLS layout depends on
+// both the OS and libc implementation so we use specific tests for each main platform.
+// If you test on another platform and it works please send a PR :-)
+// see also https://akkadia.org/drepper/tls.pdf for more info on the TLS register.
+#elif defined(__GNUC__) && ( \
+ (defined(__GLIBC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \
+ || (defined(__APPLE__) && (defined(__x86_64__) || defined(__aarch64__))) \
+ || (defined(__BIONIC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \
+ || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \
+ || (defined(__OpenBSD__) && (defined(__x86_64__) || defined(__i386__) || 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(__APPLE__) && defined(__x86_64__)
- __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS
-#elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
- __asm__("movl %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x32 ABI
-#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);
-#if defined(__APPLE__) // M1, issue #343
- __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tcb));
- tcb = (void**)((uintptr_t)tcb & ~0x07UL); // clear lower 3 bits
-#else
- __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
-#endif
- res = tcb[slot];
-#endif
+ #if defined(__i386__)
+ __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86 32-bit always uses GS
+ #elif defined(__APPLE__) && defined(__x86_64__)
+ __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS
+ #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
+ __asm__("movl %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x32 ABI
+ #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; MI_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; MI_UNUSED(ofs);
+ #if defined(__APPLE__) // M1, issue #343
+ __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+ #else
+ __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+ #endif
+ res = tcb[slot];
+ #endif
return res;
}
-// setting is only used on macOSX for now
+// setting a tls slot is only used on macOS 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(__APPLE__) && defined(__x86_64__)
- __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOSX uses GS
-#elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
- __asm__("movl %1,%%fs:%1" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x32 ABI
-#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);
-#if defined(__APPLE__) // M1, issue #343
- __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tcb));
- tcb = (void**)((uintptr_t)tcb & ~0x07UL); // clear lower 3 bits
-#else
- __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
-#endif
- tcb[slot] = value;
-#endif
+ #if defined(__i386__)
+ __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // 32-bit always uses GS
+ #elif defined(__APPLE__) && defined(__x86_64__)
+ __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOS uses GS
+ #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
+ __asm__("movl %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x32 ABI
+ #elif defined(__x86_64__)
+ __asm__("movq %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 Linux, BSD uses FS
+ #elif defined(__arm__)
+ void** tcb; MI_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; MI_UNUSED(ofs);
+ #if defined(__APPLE__) // M1, issue #343
+ __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+ #else
+ __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+ #endif
+ tcb[slot] = value;
+ #endif
}
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
-#if defined(__BIONIC__) && (defined(__arm__) || defined(__aarch64__))
- // on Android, slot 1 is the thread ID (pointer to pthread internal struct)
- return (uintptr_t)mi_tls_slot(1);
-#else
- // in all our other targets, slot 0 is the pointer to the thread control block
- return (uintptr_t)mi_tls_slot(0);
-#endif
+static inline mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
+ #if defined(__BIONIC__)
+ // issue #384, #495: on the Bionic libc (Android), slot 1 is the thread id
+ // see: https://github.com/aosp-mirror/platform_bionic/blob/c44b1d0676ded732df4b3b21c5f798eacae93228/libc/platform/bionic/tls_defines.h#L86
+ return (uintptr_t)mi_tls_slot(1);
+ #else
+ // in all our other targets, slot 0 is the thread id
+ // glibc: https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/x86_64/nptl/tls.h
+ // apple: https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L36
+ return (uintptr_t)mi_tls_slot(0);
+ #endif
}
+
#else
-// otherwise use standard C
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
+
+// otherwise use portable C, taking the address of a thread local variable (this is still very fast on most platforms).
+static inline mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
return (uintptr_t)&_mi_heap_default;
}
+
#endif
+
// -----------------------------------------------------------------------
// Count bits: trailing or leading zeros (with MI_INTPTR_BITS on all zero)
// -----------------------------------------------------------------------
@@ -903,7 +938,7 @@ static inline void _mi_memcpy(void* dst, const void* src, size_t n) {
// This is used for example in `mi_realloc`.
// -------------------------------------------------------------------------------
-#if (__GNUC__ >= 4) || defined(__clang__)
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
// On GCC/CLang we provide a hint that the pointers are word aligned.
#include
static inline void _mi_memcpy_aligned(void* dst, const void* src, size_t n) {
diff --git a/include/mimalloc-override.h b/include/mimalloc-override.h
index 7d9f3e7d..c63b0b91 100644
--- a/include/mimalloc-override.h
+++ b/include/mimalloc-override.h
@@ -48,6 +48,7 @@ not accidentally mix pointers from different allocators).
#define valloc(n) mi_valloc(n)
#define pvalloc(n) mi_pvalloc(n)
#define reallocarray(p,s,n) mi_reallocarray(p,s,n)
+#define reallocarr(p,s,n) mi_reallocarr(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)
diff --git a/include/mimalloc-types.h b/include/mimalloc-types.h
index caf161d6..6eeffeb8 100644
--- a/include/mimalloc-types.h
+++ b/include/mimalloc-types.h
@@ -17,7 +17,7 @@ terms of the MIT license. A copy of the license can be found in the file
#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`
+// due to SSE registers for example. This must be at least `sizeof(void*)`
#ifndef MI_MAX_ALIGN_SIZE
#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t)
#endif
@@ -67,6 +67,7 @@ terms of the MIT license. A copy of the license can be found in the file
#define MI_ENCODE_FREELIST 1
#endif
+
// ------------------------------------------------------
// Platform specific values
// ------------------------------------------------------
@@ -83,20 +84,43 @@ terms of the MIT license. A copy of the license can be found in the file
// or otherwise one might define an intptr_t type that is larger than a pointer...
// ------------------------------------------------------
-#if INTPTR_MAX == 9223372036854775807LL
+#if INTPTR_MAX > INT64_MAX
+# define MI_INTPTR_SHIFT (4) // assume 128-bit (as on arm CHERI for example)
+#elif INTPTR_MAX == INT64_MAX
# define MI_INTPTR_SHIFT (3)
-#elif INTPTR_MAX == 2147483647LL
+#elif INTPTR_MAX == INT32_MAX
# define MI_INTPTR_SHIFT (2)
#else
-#error platform must be 32 or 64 bits
+#error platform pointers must be 32, 64, or 128 bits
+#endif
+
+#if SIZE_MAX == UINT64_MAX
+# define MI_SIZE_SHIFT (3)
+typedef int64_t mi_ssize_t;
+#elif SIZE_MAX == UINT32_MAX
+# define MI_SIZE_SHIFT (2)
+typedef int32_t mi_ssize_t;
+#else
+#error platform objects must be 32 or 64 bits
+#endif
+
+#if (SIZE_MAX/2) > LONG_MAX
+# define MI_ZU(x) x##ULL
+# define MI_ZI(x) x##LL
+#else
+# define MI_ZU(x) x##UL
+# define MI_ZI(x) x##L
#endif
#define MI_INTPTR_SIZE (1<= 655360)
-#error "define more bins"
+#error "mimalloc internal: define more bins"
+#endif
+#if (MI_ALIGNMENT_MAX > MI_SEGMENT_SIZE/2)
+#error "mimalloc internal: the max aligned boundary is too large for the segment size"
#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)
+
+// ------------------------------------------------------
+// Mimalloc pages contain allocated blocks
+// ------------------------------------------------------
+
// The free lists use encoded next fields
// (Only actually encodes when MI_ENCODED_FREELIST is defined.)
-typedef uintptr_t mi_encoded_t;
+typedef uintptr_t mi_encoded_t;
+
+// thread id's
+typedef size_t mi_threadid_t;
// free lists contain blocks
typedef struct mi_block_s {
@@ -249,13 +284,13 @@ typedef struct mi_page_s {
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_SMALL, // small blocks go into 64KiB pages inside a segment
+ MI_PAGE_MEDIUM, // medium blocks go into 512KiB 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_HUGE // huge blocks (>512KiB) are put into a single page in a segment of the exact size (but still 2MiB aligned)
} mi_page_kind_t;
-// Segments are large allocated memory blocks (2mb on 64 bit) from
+// Segments are large allocated memory blocks (2MiB on 64 bit) from
// the OS. Inside segments we allocated fixed size _pages_ that
// contain blocks.
typedef struct mi_segment_s {
@@ -279,8 +314,8 @@ typedef struct mi_segment_s {
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
+ size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`).
+ _Atomic(mi_threadid_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;
@@ -319,7 +354,7 @@ typedef struct mi_random_cxt_s {
} mi_random_ctx_t;
-// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows
+// In debug mode there is a padding structure 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)
@@ -341,7 +376,7 @@ struct mi_heap_s {
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
+ mi_threadid_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
@@ -358,9 +393,15 @@ struct mi_heap_s {
// Debug
// ------------------------------------------------------
+#if !defined(MI_DEBUG_UNINIT)
#define MI_DEBUG_UNINIT (0xD0)
+#endif
+#if !defined(MI_DEBUG_FREED)
#define MI_DEBUG_FREED (0xDF)
+#endif
+#if !defined(MI_DEBUG_PADDING)
#define MI_DEBUG_PADDING (0xDE)
+#endif
#if (MI_DEBUG)
// use our own assertion to print without memory allocation
diff --git a/include/mimalloc.h b/include/mimalloc.h
index fe5aa8f3..0b84f6c3 100644
--- a/include/mimalloc.h
+++ b/include/mimalloc.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
-Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, 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.
@@ -8,7 +8,7 @@ terms of the MIT license. A copy of the license can be found in the file
#ifndef MIMALLOC_H
#define MIMALLOC_H
-#define MI_MALLOC_VERSION 171 // major + 2 digits minor
+#define MI_MALLOC_VERSION 174 // major + 2 digits minor
// ------------------------------------------------------
// Compiler specific attributes
@@ -26,7 +26,7 @@ terms of the MIT license. A copy of the license can be found in the file
#if defined(__cplusplus) && (__cplusplus >= 201703)
#define mi_decl_nodiscard [[nodiscard]]
-#elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl
+#elif (defined(__GNUC__) && (__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_
@@ -58,8 +58,12 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_attr_alloc_size2(s1,s2)
#define mi_attr_alloc_align(p)
#elif defined(__GNUC__) // includes clang and icc
+ #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT)
+ #define mi_decl_export __attribute__((visibility("default")))
+ #else
+ #define mi_decl_export
+ #endif
#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)
@@ -162,6 +166,7 @@ mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, s
// Note that `alignment` always follows `size` for consistency with unaligned
// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
// -------------------------------------------------------------------------------------
+#define MI_ALIGNMENT_MAX (1024*1024UL) // maximum supported alignment is 1MiB
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);
@@ -249,7 +254,7 @@ 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 used; // number of allocated blocks
size_t block_size; // size in bytes of each block
} mi_heap_area_t;
@@ -267,7 +272,6 @@ mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size
mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) 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;
@@ -292,29 +296,30 @@ mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size
// ------------------------------------------------------
-// Options, all `false` by default
+// Options
// ------------------------------------------------------
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_show_errors, // print error messages
+ mi_option_show_stats, // print statistics on termination
+ mi_option_verbose, // print verbose messages
+ // the following options are experimental (see src/options.h)
+ 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_reserve_os_memory,
- mi_option_segment_cache,
- mi_option_page_reset,
- mi_option_abandoned_page_reset,
+ mi_option_large_os_pages, // use large (2MiB) OS pages, implies eager commit
+ mi_option_reserve_huge_os_pages, // reserve N huge OS pages (1GiB) at startup
+ mi_option_reserve_huge_os_pages_at, // reserve huge OS pages at a specific NUMA node
+ mi_option_reserve_os_memory, // reserve specified amount of OS memory at startup
+ 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_limit_os_alloc,
+ mi_option_use_numa_nodes, // 0 = use available numa nodes, otherwise use at most N nodes.
+ mi_option_limit_os_alloc, // 1 = do not use OS memory for allocation (but only reserved arenas)
mi_option_os_tag,
mi_option_max_errors,
mi_option_max_warnings,
@@ -342,6 +347,7 @@ mi_decl_export void mi_option_set_default(mi_option_t option, long value);
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_good_size(size_t size) 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;
@@ -351,6 +357,7 @@ mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size)
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 int mi_reallocarr(void* p, size_t count, size_t size) mi_attr_noexcept;
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;
@@ -383,6 +390,7 @@ mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount,
// ---------------------------------------------------------------------------------------------
#ifdef __cplusplus
+#include // std::size_t
#include // PTRDIFF_MAX
#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
#include // std::true_type
diff --git a/readme.md b/readme.md
index cdb1b82a..635d983e 100644
--- a/readme.md
+++ b/readme.md
@@ -12,13 +12,13 @@ is a general purpose allocator with excellent [performance](#performance) charac
Initially developed by Daan Leijen for the run-time systems of the
[Koka](https://koka-lang.github.io) and [Lean](https://github.com/leanprover/lean) languages.
-Latest release tag: `v2.0.2` (beta, 2021-06-17).
-Latest stable tag: `v1.7.2` (2021-06-17).
+Latest release tag: `v2.0.3` (beta, 2021-11-14).
+Latest stable tag: `v1.7.3` (2021-11-14).
mimalloc 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
+> LD_PRELOAD=/usr/lib/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:
@@ -77,6 +77,10 @@ Note: the `v2.x` beta has a new algorithm for managing internal mimalloc pages t
and fragmentation compared to mimalloc `v1.x` (especially for large workloads). Should otherwise have similar performance
(see [below](#performance)); please report if you observe any significant performance regression.
+* 2021-11-14, `v1.7.3`, `v2.0.3` (beta): improved WASM support, improved macOS support and performance (including
+ M1), improved performance for v2 for large objects, Python integration improvements, more standard
+ installation directories, various small fixes.
+
* 2021-06-17, `v1.7.2`, `v2.0.2` (beta): support M1, better installation layout on Linux, fix
thread_id on Android, prefer 2-6TiB area for aligned allocation to work better on pre-windows 8, various small fixes.
@@ -87,34 +91,7 @@ Note: the `v2.x` beta has a new algorithm for managing internal mimalloc pages t
* 2021-01-31, `v1.7.0`: stable release 1.7: support explicit user provided memory regions, more precise statistics,
improve macOS overriding, initial support for Apple M1, improved DragonFly support, faster memcpy on Windows, various small fixes.
-### Older 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.
+* [Older release notes](#older-release-notes)
Special thanks to:
@@ -126,7 +103,9 @@ Special thanks to:
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.
+* Manuel Pöter (@mpoeter) and Sam Gross(@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation. Sam also created the [no GIL](https://github.com/colesbury/nogil) Python fork which
+ uses mimalloc internally.
+
[genMC]: https://plv.mpi-sws.org/genmc/
@@ -134,15 +113,18 @@ Special thanks to:
mimalloc is used in various large scale low-latency services and programs, for example:
-
-
-
+
+
+
+
+
+
# Building
## Windows
-Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`).
+Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build.
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.
@@ -191,6 +173,11 @@ Notes:
2. Install CCMake: `sudo apt-get install cmake-curses-gui`
+## Single source
+
+You can also directly build the single `src/static.c` file as part of your project without
+needing `cmake` at all. Make sure to also add the mimalloc `include` directory to the include path.
+
# Using the library
@@ -302,6 +289,9 @@ or via environment variables:
`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).
+ The huge pages are usually allocated evenly among NUMA nodes.
+ We can use `MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N` where `N` is the numa node (starting at 0) to allocate all
+ the huge pages at a specific numa node instead.
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
@@ -337,9 +327,9 @@ When _mimalloc_ is built using debug mode, various checks are done at runtime to
- Corrupted free-lists and some forms of use-after-free are detected.
-# Overriding Malloc
+# Overriding Standard Malloc
-Overriding the standard `malloc` can be done either _dynamically_ or _statically_.
+Overriding the standard `malloc` (and `new`) can be done either _dynamically_ or _statically_.
## Dynamic override
@@ -370,13 +360,12 @@ 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
+> env 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
@@ -386,7 +375,7 @@ 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
+Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be put
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`).
@@ -636,6 +625,7 @@ see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks
-->
+
# References
- \[1] Emery D. Berger, Kathryn S. McKinley, Robert D. Blumofe, and Paul R. Wilson.
@@ -673,7 +663,6 @@ see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks
In Proceedings of the 2019 ACM SIGPLAN International Symposium on Memory Management, 122–135. ACM. 2019.
-->
-
# Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
@@ -683,3 +672,34 @@ the rights to use your contribution. For details, visit https://cla.microsoft.co
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.
+
+
+# Older Release Notes
+
+* 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.
+
diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c
index 724c0a1b..6b15e653 100644
--- a/src/alloc-aligned.c
+++ b/src/alloc-aligned.c
@@ -14,31 +14,14 @@ terms of the MIT license. A copy of the license can be found in the file
// 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 )
+// Fallback primitive aligned allocation -- split out for better codegen
+static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept
+{
+ mi_assert_internal(size <= PTRDIFF_MAX);
+ mi_assert_internal(alignment!=0 && _mi_is_power_of_two(alignment) && alignment <= MI_ALIGNMENT_MAX);
+
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) {
@@ -46,7 +29,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
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;
@@ -55,21 +38,90 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
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);
+ 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) );
+ mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p), _mi_ptr_page(aligned_p), aligned_p));
return aligned_p;
}
+// Primitive 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(alignment==0 || !_mi_is_power_of_two(alignment))) { // require power-of-two (see )
+ #if MI_DEBUG > 0
+ _mi_error_message(EOVERFLOW, "aligned allocation requires the alignment to be a power-of-two (size %zu, alignment %zu)\n", size, alignment);
+ #endif
+ return NULL;
+ }
+ if (mi_unlikely(alignment > MI_ALIGNMENT_MAX)) { // we cannot align at a boundary larger than this (or otherwise we cannot find segment headers)
+ #if MI_DEBUG > 0
+ _mi_error_message(EOVERFLOW, "aligned allocation has a maximum alignment of %zu (size %zu, alignment %zu)\n", MI_ALIGNMENT_MAX, size, alignment);
+ #endif
+ return NULL;
+ }
+ if (mi_unlikely(size > PTRDIFF_MAX)) { // we don't allocate more than PTRDIFF_MAX (see )
+ #if MI_DEBUG > 0
+ _mi_error_message(EOVERFLOW, "aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment);
+ #endif
+ return NULL;
+ }
+ const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)`
+ const size_t padsize = size + MI_PADDING_SIZE; // note: cannot overflow due to earlier size > PTRDIFF_MAX check
+
+ // try first if there happens to be a small block available with just the right alignment
+ 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;
+ }
+ }
+ // fallback
+ return mi_heap_malloc_zero_aligned_at_fallback(heap, size, alignment, offset, zero);
+}
+
+
+// ------------------------------------------------------
+// Optimized mi_heap_malloc_aligned / mi_malloc_aligned
+// ------------------------------------------------------
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);
+ #if !MI_PADDING
+ // without padding, any small sized allocation is naturally aligned (see also `_mi_segment_page_start`)
+ if (!_mi_is_power_of_two(alignment)) return NULL;
+ if (mi_likely(_mi_is_power_of_two(size) && size >= alignment && size <= MI_SMALL_SIZE_MAX))
+ #else
+ // with padding, we can only guarantee this for fixed alignments
+ if (mi_likely((alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2)))
+ && size <= MI_SMALL_SIZE_MAX))
+ #endif
+ {
+ // fast path for common alignment and size
+ return mi_heap_malloc_small(heap, size);
+ }
+ else {
+ return mi_heap_malloc_aligned_at(heap, size, alignment, 0);
+ }
}
+// ------------------------------------------------------
+// Aligned Allocation
+// ------------------------------------------------------
+
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);
}
@@ -113,6 +165,10 @@ mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t align
}
+// ------------------------------------------------------
+// Aligned re-allocation
+// ------------------------------------------------------
+
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);
diff --git a/src/alloc-override-osx.c b/src/alloc-override-osx.c
index f506d30a..34cde0b4 100644
--- a/src/alloc-override-osx.c
+++ b/src/alloc-override-osx.c
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
-Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, 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.
@@ -17,20 +17,22 @@ terms of the MIT license. A copy of the license can be found in the file
/* ------------------------------------------------------
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.
+ It seems to be most robust in combination with interposing
+ though or otherwise we may get zone errors as there are could
+ be allocations done by the time we take over the
+ zone.
------------------------------------------------------ */
#include
#include
#include // memset
+#include
-#if defined(MAC_OS_X_VERSION_10_6) && \
- MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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
@@ -40,45 +42,43 @@ extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_im
------------------------------------------------------ */
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
-
+ MI_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);
+ MI_UNUSED(zone);
return mi_malloc(size);
}
static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return mi_calloc(count, size);
}
static void* zone_valloc(malloc_zone_t* zone, size_t size) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return mi_malloc_aligned(size, _mi_os_page_size());
}
static void zone_free(malloc_zone_t* zone, void* p) {
- UNUSED(zone);
+ MI_UNUSED(zone);
mi_free(p);
}
static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return mi_realloc(p, newsize);
}
static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return mi_malloc_aligned(size,alignment);
}
static void zone_destroy(malloc_zone_t* zone) {
- UNUSED(zone);
+ MI_UNUSED(zone);
// todo: ignore for now?
}
@@ -99,16 +99,21 @@ static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) {
}
static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) {
- UNUSED(zone); UNUSED(size);
+ MI_UNUSED(zone); MI_UNUSED(size);
mi_collect(false);
return 0;
}
static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) {
- UNUSED(size);
+ MI_UNUSED(size);
zone_free(zone,p);
}
+static boolean_t zone_claimed_address(malloc_zone_t* zone, void* p) {
+ MI_UNUSED(zone);
+ return mi_is_in_heap_region(p);
+}
+
/* ------------------------------------------------------
Introspection members
@@ -120,43 +125,43 @@ static kern_return_t intro_enumerator(task_t task, void* p,
vm_range_recorder_t recorder)
{
// todo: enumerate all memory
- UNUSED(task); UNUSED(p); UNUSED(type_mask); UNUSED(zone_address);
- UNUSED(reader); UNUSED(recorder);
+ MI_UNUSED(task); MI_UNUSED(p); MI_UNUSED(type_mask); MI_UNUSED(zone_address);
+ MI_UNUSED(reader); MI_UNUSED(recorder);
return KERN_SUCCESS;
}
static size_t intro_good_size(malloc_zone_t* zone, size_t size) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return mi_good_size(size);
}
static boolean_t intro_check(malloc_zone_t* zone) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return true;
}
static void intro_print(malloc_zone_t* zone, boolean_t verbose) {
- UNUSED(zone); UNUSED(verbose);
+ MI_UNUSED(zone); MI_UNUSED(verbose);
mi_stats_print(NULL);
}
static void intro_log(malloc_zone_t* zone, void* p) {
- UNUSED(zone); UNUSED(p);
+ MI_UNUSED(zone); MI_UNUSED(p);
// todo?
}
static void intro_force_lock(malloc_zone_t* zone) {
- UNUSED(zone);
+ MI_UNUSED(zone);
// todo?
}
static void intro_force_unlock(malloc_zone_t* zone) {
- UNUSED(zone);
+ MI_UNUSED(zone);
// todo?
}
static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
- UNUSED(zone);
+ MI_UNUSED(zone);
// todo...
stats->blocks_in_use = 0;
stats->size_in_use = 0;
@@ -165,7 +170,7 @@ static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
}
static boolean_t intro_zone_locked(malloc_zone_t* zone) {
- UNUSED(zone);
+ MI_UNUSED(zone);
return false;
}
@@ -174,7 +179,228 @@ static boolean_t intro_zone_locked(malloc_zone_t* zone) {
At process start, override the default allocator
------------------------------------------------------ */
-static malloc_zone_t* mi_get_default_zone()
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wc99-extensions"
+#endif
+
+static malloc_introspection_t mi_introspect = {
+ .enumerator = &intro_enumerator,
+ .good_size = &intro_good_size,
+ .check = &intro_check,
+ .print = &intro_print,
+ .log = &intro_log,
+ .force_lock = &intro_force_lock,
+ .force_unlock = &intro_force_unlock,
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+ .statistics = &intro_statistics,
+ .zone_locked = &intro_zone_locked,
+#endif
+};
+
+static malloc_zone_t mi_malloc_zone = {
+ // note: even with designators, the order is important for C++ compilation
+ //.reserved1 = NULL,
+ //.reserved2 = NULL,
+ .size = &zone_size,
+ .malloc = &zone_malloc,
+ .calloc = &zone_calloc,
+ .valloc = &zone_valloc,
+ .free = &zone_free,
+ .realloc = &zone_realloc,
+ .destroy = &zone_destroy,
+ .zone_name = "mimalloc",
+ .batch_malloc = &zone_batch_malloc,
+ .batch_free = &zone_batch_free,
+ .introspect = &mi_introspect,
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+ #if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
+ .version = 10,
+ #else
+ .version = 9,
+ #endif
+ // switch to version 9+ on OSX 10.6 to support memalign.
+ .memalign = &zone_memalign,
+ .free_definite_size = &zone_free_definite_size,
+ .pressure_relief = &zone_pressure_relief,
+ #if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
+ .claimed_address = &zone_claimed_address,
+ #endif
+#else
+ .version = 4,
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined(MI_OSX_INTERPOSE) && defined(MI_SHARED_LIB_EXPORT)
+
+// ------------------------------------------------------
+// Override malloc_xxx and malloc_zone_xxx api's to use only
+// our mimalloc zone. Since even the loader uses malloc
+// on macOS, this ensures that all allocations go through
+// mimalloc (as all calls are interposed).
+// The main `malloc`, `free`, etc calls are interposed in `alloc-override.c`,
+// Here, we also override macOS specific API's like
+// `malloc_zone_calloc` etc. see
+// ------------------------------------------------------
+
+static inline malloc_zone_t* mi_get_default_zone(void)
+{
+ static bool init;
+ if (mi_unlikely(!init)) {
+ init = true;
+ malloc_zone_register(&mi_malloc_zone); // by calling register we avoid a zone error on free (see )
+ }
+ return &mi_malloc_zone;
+}
+
+mi_decl_externc int malloc_jumpstart(uintptr_t cookie);
+mi_decl_externc void _malloc_fork_prepare(void);
+mi_decl_externc void _malloc_fork_parent(void);
+mi_decl_externc void _malloc_fork_child(void);
+
+
+static malloc_zone_t* mi_malloc_create_zone(vm_size_t size, unsigned flags) {
+ MI_UNUSED(size); MI_UNUSED(flags);
+ return mi_get_default_zone();
+}
+
+static malloc_zone_t* mi_malloc_default_zone (void) {
+ return mi_get_default_zone();
+}
+
+static malloc_zone_t* mi_malloc_default_purgeable_zone(void) {
+ return mi_get_default_zone();
+}
+
+static void mi_malloc_destroy_zone(malloc_zone_t* zone) {
+ MI_UNUSED(zone);
+ // nothing.
+}
+
+static kern_return_t mi_malloc_get_all_zones (task_t task, memory_reader_t mr, vm_address_t** addresses, unsigned* count) {
+ MI_UNUSED(task); MI_UNUSED(mr);
+ if (addresses != NULL) *addresses = NULL;
+ if (count != NULL) *count = 0;
+ return KERN_SUCCESS;
+}
+
+static const char* mi_malloc_get_zone_name(malloc_zone_t* zone) {
+ return (zone == NULL ? mi_malloc_zone.zone_name : zone->zone_name);
+}
+
+static void mi_malloc_set_zone_name(malloc_zone_t* zone, const char* name) {
+ MI_UNUSED(zone); MI_UNUSED(name);
+}
+
+static int mi_malloc_jumpstart(uintptr_t cookie) {
+ MI_UNUSED(cookie);
+ return 1; // or 0 for no error?
+}
+
+static void mi__malloc_fork_prepare(void) {
+ // nothing
+}
+static void mi__malloc_fork_parent(void) {
+ // nothing
+}
+static void mi__malloc_fork_child(void) {
+ // nothing
+}
+
+static void mi_malloc_printf(const char* fmt, ...) {
+ MI_UNUSED(fmt);
+}
+
+static bool zone_check(malloc_zone_t* zone) {
+ MI_UNUSED(zone);
+ return true;
+}
+
+static malloc_zone_t* zone_from_ptr(const void* p) {
+ MI_UNUSED(p);
+ return mi_get_default_zone();
+}
+
+static void zone_log(malloc_zone_t* zone, void* p) {
+ MI_UNUSED(zone); MI_UNUSED(p);
+}
+
+static void zone_print(malloc_zone_t* zone, bool b) {
+ MI_UNUSED(zone); MI_UNUSED(b);
+}
+
+static void zone_print_ptr_info(void* p) {
+ MI_UNUSED(p);
+}
+
+static void zone_register(malloc_zone_t* zone) {
+ MI_UNUSED(zone);
+}
+
+static void zone_unregister(malloc_zone_t* zone) {
+ MI_UNUSED(zone);
+}
+
+// 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)
+#define MI_INTERPOSE_ZONE(fun) MI_INTERPOSE_FUN(malloc_##fun,fun)
+__attribute__((used)) static const struct mi_interpose_s _mi_zone_interposes[] __attribute__((section("__DATA, __interpose"))) =
+{
+
+ MI_INTERPOSE_MI(malloc_create_zone),
+ MI_INTERPOSE_MI(malloc_default_purgeable_zone),
+ MI_INTERPOSE_MI(malloc_default_zone),
+ MI_INTERPOSE_MI(malloc_destroy_zone),
+ MI_INTERPOSE_MI(malloc_get_all_zones),
+ MI_INTERPOSE_MI(malloc_get_zone_name),
+ MI_INTERPOSE_MI(malloc_jumpstart),
+ MI_INTERPOSE_MI(malloc_printf),
+ MI_INTERPOSE_MI(malloc_set_zone_name),
+ MI_INTERPOSE_MI(_malloc_fork_child),
+ MI_INTERPOSE_MI(_malloc_fork_parent),
+ MI_INTERPOSE_MI(_malloc_fork_prepare),
+
+ MI_INTERPOSE_ZONE(zone_batch_free),
+ MI_INTERPOSE_ZONE(zone_batch_malloc),
+ MI_INTERPOSE_ZONE(zone_calloc),
+ MI_INTERPOSE_ZONE(zone_check),
+ MI_INTERPOSE_ZONE(zone_free),
+ MI_INTERPOSE_ZONE(zone_from_ptr),
+ MI_INTERPOSE_ZONE(zone_log),
+ MI_INTERPOSE_ZONE(zone_malloc),
+ MI_INTERPOSE_ZONE(zone_memalign),
+ MI_INTERPOSE_ZONE(zone_print),
+ MI_INTERPOSE_ZONE(zone_print_ptr_info),
+ MI_INTERPOSE_ZONE(zone_realloc),
+ MI_INTERPOSE_ZONE(zone_register),
+ MI_INTERPOSE_ZONE(zone_unregister),
+ MI_INTERPOSE_ZONE(zone_valloc)
+};
+
+
+#else
+
+// ------------------------------------------------------
+// hook into the zone api's without interposing
+// This is the official way of adding an allocator but
+// it seems less robust than using interpose.
+// ------------------------------------------------------
+
+static inline malloc_zone_t* mi_get_default_zone(void)
{
// The first returned zone is the real default
malloc_zone_t** zones = NULL;
@@ -189,70 +415,20 @@ static malloc_zone_t* mi_get_default_zone()
}
}
-static malloc_introspection_t mi_introspect = {
- .enumerator = &intro_enumerator,
- .good_size = &intro_good_size,
- .check = &intro_check,
- .print = &intro_print,
- .log = &intro_log,
- .force_lock = &intro_force_lock,
- .force_unlock = &intro_force_unlock,
-#if defined(MAC_OS_X_VERSION_10_6) && \
- MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- .zone_locked = &intro_zone_locked,
- .statistics = &intro_statistics,
-#endif
-};
-
-static malloc_zone_t mi_malloc_zone = {
- .size = &zone_size,
- .zone_name = "mimalloc",
- .introspect = &mi_introspect,
- .malloc = &zone_malloc,
- .calloc = &zone_calloc,
- .valloc = &zone_valloc,
- .free = &zone_free,
- .realloc = &zone_realloc,
- .destroy = &zone_destroy,
- .batch_malloc = &zone_batch_malloc,
- .batch_free = &zone_batch_free,
-#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.
- .version = 9,
- .memalign = &zone_memalign,
- .free_definite_size = &zone_free_definite_size,
- .pressure_relief = &zone_pressure_relief,
+#if defined(__clang__)
+__attribute__((constructor(0)))
#else
- .version = 4,
+__attribute__((constructor)) // seems not supported by g++-11 on the M1
#endif
-};
-
-
-#if defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE)
-
-static malloc_zone_t *mi_malloc_default_zone(void) {
- return &mi_malloc_zone;
-}
-// TODO: should use the macros in alloc-override but they aren't available here.
-__attribute__((used)) static struct {
- const void *replacement;
- const void *target;
-} replace_malloc_default_zone[] __attribute__((section("__DATA, __interpose"))) = {
- { (const void*)mi_malloc_default_zone, (const void*)malloc_default_zone },
-};
-#endif
-
-static void __attribute__((constructor(0))) _mi_macos_override_malloc() {
+static void _mi_macos_override_malloc() {
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
+ #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
// force the purgeable zone to exist to avoid strange bugs
if (malloc_default_purgeable_zone) {
purgeable_zone = malloc_default_purgeable_zone();
}
-#endif
+ #endif
// Register our zone.
// thomcc: I think this is still needed to put us in the zone list.
@@ -277,5 +453,6 @@ static void __attribute__((constructor(0))) _mi_macos_override_malloc() {
}
}
+#endif // MI_OSX_INTERPOSE
#endif // MI_MALLOC_OVERRIDE
diff --git a/src/alloc-override.c b/src/alloc-override.c
index 6a87e7bd..6bbe4aac 100644
--- a/src/alloc-override.c
+++ b/src/alloc-override.c
@@ -13,15 +13,25 @@ terms of the MIT license. A copy of the license can be found in the file
#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(__APPLE__) && !defined(MI_INTERPOSE)))
+#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32))
+
+#if defined(__APPLE__)
+mi_decl_externc void vfree(void* p);
+mi_decl_externc size_t malloc_size(const void* p);
+mi_decl_externc size_t malloc_good_size(size_t size);
+#endif
+
+// helper definition for C override of C++ new
+typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t;
// ------------------------------------------------------
// Override system malloc
// ------------------------------------------------------
-#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__)
- // use aliasing to alias the exported function to one of our `mi_` functions
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) && !defined(MI_VALGRIND)
+ // gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions
#if (defined(__GNUC__) && __GNUC__ >= 9)
+ #pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward
#define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun)));
#else
#define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default")));
@@ -32,7 +42,7 @@ terms of the MIT license. A copy of the license can be found in the file
#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
+ // otherwise 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); }
@@ -40,7 +50,11 @@ terms of the MIT license. A copy of the license can be found in the file
#define MI_FORWARD02(fun,x,y) { fun(x,y); }
#endif
-#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE)
+#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_OSX_INTERPOSE)
+ // define MI_OSX_IS_INTERPOSED as we should not provide forwarding definitions for
+ // functions that are interposed (or the interposing does not work)
+ #define MI_OSX_IS_INTERPOSED
+
// use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1`
// See:
struct mi_interpose_s {
@@ -49,6 +63,7 @@ terms of the MIT license. A copy of the license can be found in the file
};
#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),
@@ -60,21 +75,49 @@ terms of the MIT license. A copy of the license can be found in the file
MI_INTERPOSE_MI(posix_memalign),
MI_INTERPOSE_MI(reallocf),
MI_INTERPOSE_MI(valloc),
- #ifndef MI_OSX_ZONE
- // some code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity )
- MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us
- #else
- // We interpose malloc_default_zone in alloc-override-osx.c
+ MI_INTERPOSE_MI(malloc_size),
+ MI_INTERPOSE_MI(malloc_good_size),
+ MI_INTERPOSE_MI(aligned_alloc),
+ #ifdef MI_OSX_ZONE
+ // we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely
MI_INTERPOSE_MI(free),
- #endif
- // some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity )
+ MI_INTERPOSE_FUN(vfree,mi_free),
+ #else
+ // sometimes code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity )
MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us
+ MI_INTERPOSE_FUN(vfree,mi_cfree),
+ #endif
};
+
+ #ifdef __cplusplus
+ extern "C" {
+ void _ZdlPv(void* p); // delete
+ void _ZdaPv(void* p); // delete[]
+ void _ZdlPvm(void* p, size_t n); // delete
+ void _ZdaPvm(void* p, size_t n); // delete[]
+ void* _Znwm(size_t n); // new
+ void* _Znam(size_t n); // new[]
+ void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new nothrow
+ void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new[] nothrow
+ }
+ __attribute__((used)) static struct mi_interpose_s _mi_cxx_interposes[] __attribute__((section("__DATA, __interpose"))) =
+ {
+ MI_INTERPOSE_FUN(_ZdlPv,mi_free),
+ MI_INTERPOSE_FUN(_ZdaPv,mi_free),
+ MI_INTERPOSE_FUN(_ZdlPvm,mi_free_size),
+ MI_INTERPOSE_FUN(_ZdaPvm,mi_free_size),
+ MI_INTERPOSE_FUN(_Znwm,mi_new),
+ MI_INTERPOSE_FUN(_Znam,mi_new),
+ MI_INTERPOSE_FUN(_ZnwmRKSt9nothrow_t,mi_new_nothrow),
+ MI_INTERPOSE_FUN(_ZnamRKSt9nothrow_t,mi_new_nothrow),
+ };
+ #endif // __cplusplus
+
#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
+ // 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)
@@ -96,18 +139,21 @@ terms of the MIT license. A copy of the license can be found in the file
// 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)
+ #ifndef MI_OSX_IS_INTERPOSED
+ 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, 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); }
+ 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)
- #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)
+ void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { MI_UNUSED(tag); return mi_new_nothrow(n); }
+ void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { MI_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
#endif
#if (__cplusplus > 201402L && defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5))
@@ -122,12 +168,13 @@ terms of the MIT license. A copy of the license can be found in the file
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__))
+#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)
@@ -136,78 +183,83 @@ terms of the MIT license. A copy of the license can be found in the file
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 { int _tag; } 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* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
+ void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
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); }
+ void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+ void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_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* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
+ void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
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); }
+ void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+ void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_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)"
+ #error "define overloads for new/delete for this platform (just for performance, can be skipped)"
#endif
#endif // __cplusplus
+// ------------------------------------------------------
+// Further Posix & Unix functions definitions
+// ------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
-// ------------------------------------------------------
-// Posix & Unix functions definitions
-// ------------------------------------------------------
+#ifndef MI_OSX_IS_INTERPOSED
+ // Forward Posix/Unix calls as well
+ 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__) && !defined(__FreeBSD__)
+ 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
-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)
+ // No forwarding here due to aliasing/name mangling issues
+ void* valloc(size_t size) { return mi_valloc(size); }
+ void vfree(void* p) { mi_free(p); }
+ size_t malloc_good_size(size_t size) { return mi_malloc_good_size(size); }
+ int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); }
+
+ // `aligned_alloc` is only available when __USE_ISOC11 is defined.
+ // Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot
+ // override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9.
+ // Fortunately, in the case where `aligned_alloc` is declared as `static inline` it
+ // uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we can avoid overriding it ourselves.
+ #if __USE_ISOC11
+ void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
+ #endif
#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); }
-
-// `aligned_alloc` is only available when __USE_ISOC11 is defined.
-// Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot
-// override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9.
-// Fortunately, in the case where `aligned_alloc` is declared as `static inline` it
-// uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we can avoid overriding it ourselves.
-#if __USE_ISOC11
-void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
-#endif
-
+void cfree(void* p) { mi_free(p); }
+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); }
+int reallocarr(void* p, size_t count, size_t size) { return mi_reallocarr(p, count, size); }
+void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); }
+void* _aligned_malloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
#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_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); }
+ 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
diff --git a/src/alloc-posix.c b/src/alloc-posix.c
index 43931e56..ee5babe1 100644
--- a/src/alloc-posix.c
+++ b/src/alloc-posix.c
@@ -33,13 +33,19 @@ terms of the MIT license. A copy of the license can be found in the file
size_t mi_malloc_size(const void* p) mi_attr_noexcept {
+ //if (!mi_is_in_heap_region(p)) return 0;
return mi_usable_size(p);
}
size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept {
+ //if (!mi_is_in_heap_region(p)) return 0;
return mi_usable_size(p);
}
+size_t mi_malloc_good_size(size_t size) mi_attr_noexcept {
+ return mi_good_size(size);
+}
+
void mi_cfree(void* p) mi_attr_noexcept {
if (mi_is_in_heap_region(p)) {
mi_free(p);
@@ -50,9 +56,9 @@ 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 (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment
+ if (alignment==0 || !_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2
+ void* q = mi_malloc_aligned(size, alignment);
if (q==NULL && size != 0) return ENOMEM;
mi_assert_internal(((uintptr_t)q % alignment) == 0);
*p = q;
@@ -60,7 +66,7 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept
}
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));
+ void* p = mi_malloc_aligned(size, alignment);
mi_assert_internal(((uintptr_t)p % alignment) == 0);
return p;
}
@@ -77,22 +83,40 @@ mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept {
}
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));
+ if (mi_unlikely((size&(alignment-1)) != 0)) { // C11 requires alignment>0 && integral multiple, see
+ #if MI_DEBUG > 0
+ _mi_error_message(EOVERFLOW, "(mi_)aligned_alloc requires the size to be an integral multiple of the alignment (size %zu, alignment %zu)\n", size, alignment);
+ #endif
+ return NULL;
+ }
+ // C11 also requires alignment to be a power-of-two which is checked in mi_malloc_aligned
+ void* p = 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;
+ if (newp==NULL) { errno = ENOMEM; }
return newp;
}
+int mi_reallocarr( void* p, size_t count, size_t size ) mi_attr_noexcept { // NetBSD
+ mi_assert(p != NULL);
+ if (p == NULL) {
+ errno = EINVAL;
+ return EINVAL;
+ }
+ void** op = (void**)p;
+ void* newp = mi_reallocarray(*op, count, size);
+ if (mi_unlikely(newp == NULL)) return errno;
+ *op = newp;
+ return 0;
+}
+
void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft
void* res = mi_expand(p, newsize);
- if (res == NULL) errno = ENOMEM;
+ if (res == NULL) { errno = ENOMEM; }
return res;
}
diff --git a/src/alloc.c b/src/alloc.c
index 8acff783..cd4afa1e 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1,9 +1,13 @@
/* ----------------------------------------------------------------------------
-Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, 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 // for realpath() on Linux
+#endif
+
#include "mimalloc.h"
#include "mimalloc-internal.h"
#include "mimalloc-atomic.h"
@@ -119,7 +123,7 @@ extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept {
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_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);
@@ -201,8 +205,8 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
}
#else
static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) {
- UNUSED(page);
- UNUSED(block);
+ MI_UNUSED(page);
+ MI_UNUSED(block);
return false;
}
#endif
@@ -274,19 +278,19 @@ static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, co
}
#else
static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
- UNUSED(page);
- UNUSED(block);
+ MI_UNUSED(page);
+ MI_UNUSED(block);
}
static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) {
- UNUSED(block);
+ MI_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);
+ MI_UNUSED(page);
+ MI_UNUSED(block);
+ MI_UNUSED(min_size);
}
#endif
@@ -294,7 +298,7 @@ static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, co
#if (MI_STAT>0)
static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
#if (MI_STAT < 2)
- UNUSED(block);
+ MI_UNUSED(block);
#endif
mi_heap_t* const heap = mi_heap_get_default();
const size_t bsize = mi_page_usable_block_size(page);
@@ -311,7 +315,7 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
}
#else
static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
- UNUSED(page); UNUSED(block);
+ MI_UNUSED(page); MI_UNUSED(block);
}
#endif
@@ -329,7 +333,7 @@ static void mi_stat_huge_free(const mi_page_t* page) {
}
#else
static void mi_stat_huge_free(const mi_page_t* page) {
- UNUSED(page);
+ MI_UNUSED(page);
}
#endif
@@ -431,7 +435,7 @@ mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* p
}
-static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) {
+static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) mi_attr_noexcept {
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_stat_free(page, block);
@@ -443,7 +447,7 @@ static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool l
// (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);
+ MI_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);
@@ -465,24 +469,23 @@ static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* ms
#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);
+ _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", msg, p);
}
#endif
return segment;
}
-
-// Free a block
+// Free a block
void mi_free(void* p) mi_attr_noexcept
{
- const mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free");
+ 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_threadid_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_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
+
+ if (mi_likely(tid == mi_atomic_load_relaxed(&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);
@@ -570,19 +573,19 @@ void* _mi_externs[] = {
// ------------------------------------------------------
void mi_free_size(void* p, size_t size) mi_attr_noexcept {
- UNUSED_RELEASE(size);
+ MI_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_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_UNUSED_RELEASE(alignment);
mi_assert(((uintptr_t)p % alignment) == 0);
mi_free(p);
}
@@ -747,7 +750,7 @@ mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char
}
#else
#include // pathconf
-static size_t mi_path_max() {
+static size_t mi_path_max(void) {
static size_t path_max = 0;
if (path_max <= 0) {
long m = pathconf("/",_PC_PATH_MAX);
@@ -798,7 +801,10 @@ static bool mi_try_new_handler(bool nothrow) {
std::set_new_handler(h);
#endif
if (h==NULL) {
- if (!nothrow) throw std::bad_alloc();
+ _mi_error_message(ENOMEM, "out of memory in 'new'");
+ if (!nothrow) {
+ throw std::bad_alloc();
+ }
return false;
}
else {
@@ -807,13 +813,13 @@ static bool mi_try_new_handler(bool nothrow) {
}
}
#else
-typedef void (*std_new_handler_t)();
+typedef void (*std_new_handler_t)(void);
#if (defined(__GNUC__) || defined(__clang__))
-std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv() {
+std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv(void) {
return NULL;
}
-static std_new_handler_t mi_get_new_handler() {
+static std_new_handler_t mi_get_new_handler(void) {
return _ZSt15get_new_handlerv();
}
#else
@@ -826,7 +832,10 @@ static std_new_handler_t mi_get_new_handler() {
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.
+ _mi_error_message(ENOMEM, "out of memory in 'new'");
+ if (!nothrow) {
+ abort(); // cannot throw in plain C, use abort
+ }
return false;
}
else {
diff --git a/src/arena.c b/src/arena.c
index 0e6615a4..133f1546 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -20,7 +20,7 @@ which is sometimes needed for embedded devices or shared memory for example.
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
+only do this within a field (`size_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.
@@ -62,18 +62,18 @@ typedef struct mi_arena_s {
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 fully committed? (if so, block_committed == NULL)
+ bool allow_decommit; // is decommit allowed? if true, is_large should be false and blocks_committed != NULL
bool is_large; // large- or huge OS pages (always committed)
- _Atomic(uintptr_t) search_idx; // optimization to start the search for free blocks
+ _Atomic(size_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_committed; // are the blocks committed? (can be NULL for memory that cannot be decommitted)
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
+static mi_decl_cache_align _Atomic(size_t) mi_arena_count; // = 0
/* -----------------------------------------------------------
@@ -129,8 +129,8 @@ static void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t n
*memid = mi_arena_id_create(arena_index, bitmap_index);
*is_zero = _mi_bitmap_claim_across(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL);
*large = arena->is_large;
- *is_pinned = (arena->is_large || arena->is_committed);
- if (arena->is_committed) {
+ *is_pinned = (arena->is_large || !arena->allow_decommit);
+ if (arena->blocks_committed == NULL) {
// always committed
*commit = true;
}
@@ -245,12 +245,13 @@ void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_s
return;
}
// potentially decommit
- if (arena->is_committed) {
- mi_assert_internal(all_committed);
+ if (!arena->allow_decommit || arena->blocks_committed == NULL) {
+ mi_assert_internal(all_committed); // note: may be not true as we may "pretend" to be not committed (in segment.c)
}
else {
mi_assert_internal(arena->blocks_committed != NULL);
_mi_os_decommit(p, blocks * MI_ARENA_BLOCK_SIZE, stats); // ok if this fails
+ // todo: use reset instead of decommit on windows?
_mi_bitmap_unclaim_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx);
}
// and make it available to others again
@@ -271,7 +272,7 @@ static bool mi_arena_add(mi_arena_t* arena) {
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);
+ size_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;
@@ -282,12 +283,14 @@ static bool mi_arena_add(mi_arena_t* arena) {
bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept
{
+ if (size < MI_ARENA_BLOCK_SIZE) return false;
+
if (is_large) {
mi_assert_internal(is_committed);
is_committed = true;
}
- const size_t bcount = mi_block_count_of_size(size);
+ const size_t bcount = size / MI_ARENA_BLOCK_SIZE;
const size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS);
const size_t bitmaps = (is_committed ? 2 : 3);
const size_t asize = sizeof(mi_arena_t) + (bitmaps*fields*sizeof(mi_bitmap_field_t));
@@ -300,12 +303,16 @@ bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_la
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 = is_large;
arena->is_zero_init = is_zero;
- arena->is_committed = is_committed;
+ arena->allow_decommit = !is_large && !is_committed; // only allow decommit for initially uncommitted memory
arena->search_idx = 0;
arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap
- arena->blocks_committed = (is_committed ? NULL : &arena->blocks_inuse[2*fields]); // just after dirty bitmap
+ arena->blocks_committed = (!arena->allow_decommit ? NULL : &arena->blocks_inuse[2*fields]); // just after dirty bitmap
// the bitmaps are already zero initialized due to os_alloc
- // just claim leftover blocks if needed
+ // initialize committed bitmap?
+ if (arena->blocks_committed != NULL && is_committed) {
+ memset((void*)arena->blocks_committed, 0xFF, fields*sizeof(mi_bitmap_field_t)); // cast to void* to avoid atomic warning
+ }
+ // and claim leftover blocks if needed (so we never allocate there)
ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount;
mi_assert_internal(post >= 0);
if (post > 0) {
@@ -321,7 +328,7 @@ bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_la
// Reserve a range of regular OS memory
int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept
{
- size = _mi_os_good_alloc_size(size);
+ size = _mi_align_up(size, MI_ARENA_BLOCK_SIZE); // at least one block
bool large = allow_large;
void* start = _mi_os_alloc_aligned(size, MI_SEGMENT_ALIGN, commit, &large, &_mi_stats_main);
if (start==NULL) return ENOMEM;
@@ -330,7 +337,7 @@ int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noe
_mi_verbose_message("failed to reserve %zu k memory\n", _mi_divide_up(size,1024));
return ENOMEM;
}
- _mi_verbose_message("reserved %zu kb memory%s\n", _mi_divide_up(size,1024), large ? " (in large os pages)" : "");
+ _mi_verbose_message("reserved %zu KiB memory%s\n", _mi_divide_up(size,1024), large ? " (in large os pages)" : "");
return 0;
}
@@ -347,10 +354,10 @@ int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msec
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);
+ _mi_warning_message("failed to reserve %zu GiB 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);
+ _mi_verbose_message("numa node %i: reserved %zu GiB huge pages (of the %zu GiB requested)\n", numa_node, pages_reserved, pages);
if (!mi_manage_os_memory(p, hsize, true, true, true, numa_node)) {
_mi_os_free_huge_pages(p, hsize, &_mi_stats_main);
@@ -389,7 +396,7 @@ int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t
}
int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept {
- UNUSED(max_secs);
+ MI_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));
diff --git a/src/bitmap.c b/src/bitmap.c
index 3b5c8199..51926bbd 100644
--- a/src/bitmap.c
+++ b/src/bitmap.c
@@ -7,7 +7,7 @@ terms of the MIT license. A copy of the license can be found in the file
/* ----------------------------------------------------------------------------
Concurrent bitmap that can set/reset sequences of bits atomically,
-represeted as an array of fields where each field is a machine word (`uintptr_t`)
+represeted as an array of fields where each field is a machine word (`size_t`)
There are two api's; the standard one cannot have sequences that cross
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
@@ -26,12 +26,12 @@ between the fields. (This is used in arena allocation)
----------------------------------------------------------- */
// 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) {
+static inline size_t mi_bitmap_mask_(size_t count, size_t bitidx) {
mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS);
mi_assert_internal(count > 0);
if (count >= MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL;
if (count == 0) return 0;
- return ((((uintptr_t)1 << count) - 1) << bitidx);
+ return ((((size_t)1 << count) - 1) << bitidx);
}
@@ -46,27 +46,27 @@ bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_
{
mi_assert_internal(bitmap_idx != NULL);
mi_assert_internal(count <= MI_BITMAP_FIELD_BITS);
- _Atomic(uintptr_t)* field = &bitmap[idx];
- uintptr_t map = mi_atomic_load_relaxed(field);
+ mi_bitmap_field_t* field = &bitmap[idx];
+ size_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;
+ const size_t mask = mi_bitmap_mask_(count, 0);
+ const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count;
#ifdef MI_HAVE_FAST_BITSCAN
size_t bitidx = mi_ctz(~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
+ size_t m = (mask << bitidx); // invariant: m == mask shifted by bitidx
// scan linearly for a free range of zero bits
while (bitidx <= bitidx_max) {
- const uintptr_t mapm = map & m;
+ const size_t mapm = map & m;
if (mapm == 0) { // are the mask bits free at bitidx?
mi_assert_internal((m >> bitidx) == mask); // no overflow?
- const uintptr_t newmap = map | m;
+ const size_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`)
@@ -121,10 +121,10 @@ bool _mi_bitmap_try_find_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, c
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);
+ const size_t mask = mi_bitmap_mask_(count, bitidx);
+ mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
// mi_assert_internal((bitmap[idx] & mask) == mask);
- uintptr_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
+ size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
return ((prev & mask) == mask);
}
@@ -134,10 +134,10 @@ bool mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, m
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);
+ const size_t mask = mi_bitmap_mask_(count, bitidx);
+ mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
//mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
- uintptr_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
+ size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
if (any_zero != NULL) *any_zero = ((prev & mask) != mask);
return ((prev & mask) == 0);
}
@@ -146,9 +146,9 @@ bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi
static bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) {
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]);
+ const size_t mask = mi_bitmap_mask_(count, bitidx);
+ mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
+ size_t field = mi_atomic_load_relaxed(&bitmap[idx]);
if (any_ones != NULL) *any_ones = ((field & mask) != 0);
return ((field & mask) == mask);
}
@@ -176,8 +176,8 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
mi_assert_internal(bitmap_idx != NULL);
// check initial trailing zeros
- _Atomic(uintptr_t)* field = &bitmap[idx];
- uintptr_t map = mi_atomic_load_relaxed(field);
+ mi_bitmap_field_t* field = &bitmap[idx];
+ size_t map = mi_atomic_load_relaxed(field);
const size_t initial = mi_clz(map); // count of initial zeros starting at idx
mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS);
if (initial == 0) return false;
@@ -186,11 +186,11 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
// scan ahead
size_t found = initial;
- uintptr_t mask = 0; // mask bits for the final field
+ size_t mask = 0; // mask bits for the final field
while(found < count) {
field++;
map = mi_atomic_load_relaxed(field);
- const uintptr_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
+ const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
mask = mi_bitmap_mask_(mask_bits, 0);
if ((map & mask) != 0) return false;
found += mask_bits;
@@ -199,13 +199,13 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
// found range of zeros up to the final field; mask contains mask in the final field
// now claim it atomically
- _Atomic(uintptr_t)* const final_field = field;
- const uintptr_t final_mask = mask;
- _Atomic(uintptr_t)* const initial_field = &bitmap[idx];
- const uintptr_t initial_mask = mi_bitmap_mask_(initial, MI_BITMAP_FIELD_BITS - initial);
+ mi_bitmap_field_t* const final_field = field;
+ const size_t final_mask = mask;
+ mi_bitmap_field_t* const initial_field = &bitmap[idx];
+ const size_t initial_mask = mi_bitmap_mask_(initial, MI_BITMAP_FIELD_BITS - initial);
// initial field
- uintptr_t newmap;
+ size_t newmap;
field = initial_field;
map = mi_atomic_load_relaxed(field);
do {
@@ -280,8 +280,8 @@ bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitm
}
// Helper for masks across fields; returns the mid count, post_mask may be 0
-static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_fields, size_t count, uintptr_t* pre_mask, uintptr_t* mid_mask, uintptr_t* post_mask) {
- UNUSED_RELEASE(bitmap_fields);
+static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_fields, size_t count, size_t* pre_mask, size_t* mid_mask, size_t* post_mask) {
+ MI_UNUSED_RELEASE(bitmap_fields);
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
if (mi_likely(bitidx + count <= MI_BITMAP_FIELD_BITS)) {
*pre_mask = mi_bitmap_mask_(count, bitidx);
@@ -308,13 +308,13 @@ static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_
// Returns `true` if all `count` bits were 1 previously.
bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
size_t idx = mi_bitmap_index_field(bitmap_idx);
- uintptr_t pre_mask;
- uintptr_t mid_mask;
- uintptr_t post_mask;
+ size_t pre_mask;
+ size_t mid_mask;
+ size_t post_mask;
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
bool all_one = true;
- _Atomic(uintptr_t)*field = &bitmap[idx];
- uintptr_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask);
+ mi_bitmap_field_t* field = &bitmap[idx];
+ size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask);
if ((prev & pre_mask) != pre_mask) all_one = false;
while(mid_count-- > 0) {
prev = mi_atomic_and_acq_rel(field++, ~mid_mask);
@@ -331,14 +331,14 @@ bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t
// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero) {
size_t idx = mi_bitmap_index_field(bitmap_idx);
- uintptr_t pre_mask;
- uintptr_t mid_mask;
- uintptr_t post_mask;
+ size_t pre_mask;
+ size_t mid_mask;
+ size_t post_mask;
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
bool all_zero = true;
bool any_zero = false;
- _Atomic(uintptr_t)*field = &bitmap[idx];
- uintptr_t prev = mi_atomic_or_acq_rel(field++, pre_mask);
+ _Atomic(size_t)*field = &bitmap[idx];
+ size_t prev = mi_atomic_or_acq_rel(field++, pre_mask);
if ((prev & pre_mask) != 0) all_zero = false;
if ((prev & pre_mask) != pre_mask) any_zero = true;
while (mid_count-- > 0) {
@@ -360,14 +360,14 @@ bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t co
// `any_ones` is `true` if there was at least one bit set to one.
static bool mi_bitmap_is_claimedx_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_ones) {
size_t idx = mi_bitmap_index_field(bitmap_idx);
- uintptr_t pre_mask;
- uintptr_t mid_mask;
- uintptr_t post_mask;
+ size_t pre_mask;
+ size_t mid_mask;
+ size_t post_mask;
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
bool all_ones = true;
bool any_ones = false;
- _Atomic(uintptr_t)* field = &bitmap[idx];
- uintptr_t prev = mi_atomic_load_relaxed(field++);
+ mi_bitmap_field_t* field = &bitmap[idx];
+ size_t prev = mi_atomic_load_relaxed(field++);
if ((prev & pre_mask) != pre_mask) all_ones = false;
if ((prev & pre_mask) != 0) any_ones = true;
while (mid_count-- > 0) {
diff --git a/src/bitmap.h b/src/bitmap.h
index 21fd4e13..39ca55b2 100644
--- a/src/bitmap.h
+++ b/src/bitmap.h
@@ -7,7 +7,7 @@ terms of the MIT license. A copy of the license can be found in the file
/* ----------------------------------------------------------------------------
Concurrent bitmap that can set/reset sequences of bits atomically,
-represeted as an array of fields where each field is a machine word (`uintptr_t`)
+represeted as an array of fields where each field is a machine word (`size_t`)
There are two api's; the standard one cannot have sequences that cross
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
@@ -24,11 +24,11 @@ between the fields. (This is used in arena allocation)
Bitmap definition
----------------------------------------------------------- */
-#define MI_BITMAP_FIELD_BITS (8*MI_INTPTR_SIZE)
-#define MI_BITMAP_FIELD_FULL (~((uintptr_t)0)) // all bits set
+#define MI_BITMAP_FIELD_BITS (8*MI_SIZE_SIZE)
+#define MI_BITMAP_FIELD_FULL (~((size_t)0)) // all bits set
-// An atomic bitmap of `uintptr_t` fields
-typedef _Atomic(uintptr_t) mi_bitmap_field_t;
+// An atomic bitmap of `size_t` fields
+typedef _Atomic(size_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.
diff --git a/src/heap.c b/src/heap.c
index bda10699..d560fbc6 100644
--- a/src/heap.c
+++ b/src/heap.c
@@ -50,9 +50,9 @@ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void
#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_UNUSED(arg1);
+ MI_UNUSED(arg2);
+ MI_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);
@@ -86,8 +86,8 @@ typedef enum mi_collect_e {
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_UNUSED(arg2);
+ MI_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);
@@ -104,10 +104,10 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t
}
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_UNUSED(arg1);
+ MI_UNUSED(arg2);
+ MI_UNUSED(heap);
+ MI_UNUSED(pq);
_mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
return true; // don't break
}
@@ -262,10 +262,10 @@ static void mi_heap_free(mi_heap_t* heap) {
----------------------------------------------------------- */
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);
+ MI_UNUSED(arg1);
+ MI_UNUSED(arg2);
+ MI_UNUSED(heap);
+ MI_UNUSED(pq);
// ensure no more thread_delayed_free will be added
_mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
@@ -333,7 +333,7 @@ void mi_heap_destroy(mi_heap_t* heap) {
Safe Heap delete
----------------------------------------------------------- */
-// Tranfer the pages from one heap to the other
+// Transfer 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;
@@ -422,8 +422,8 @@ bool mi_heap_contains_block(mi_heap_t* heap, const void* 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);
+ MI_UNUSED(heap);
+ MI_UNUSED(pq);
bool* found = (bool*)vfound;
mi_segment_t* segment = _mi_page_segment(page);
void* start = _mi_page_start(segment, page, NULL);
@@ -521,8 +521,8 @@ typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_
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_UNUSED(heap);
+ MI_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);
diff --git a/src/init.c b/src/init.c
index 998649e3..854a2228 100644
--- a/src/init.c
+++ b/src/init.c
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
-Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, 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.
@@ -102,6 +102,7 @@ mi_decl_cache_align const mi_heap_t _mi_heap_empty = {
false
};
+
// the thread-local default heap for allocation
mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty;
@@ -141,7 +142,7 @@ 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_heap_main.cookie = _mi_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);
@@ -274,12 +275,6 @@ static bool _mi_heap_done(mi_heap_t* heap) {
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)
@@ -299,7 +294,6 @@ static void _mi_thread_done(mi_heap_t* default_heap);
#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);
@@ -331,6 +325,12 @@ bool _mi_is_main_thread(void) {
return (_mi_heap_main.thread_id==0 || _mi_heap_main.thread_id == _mi_thread_id());
}
+static _Atomic(size_t) thread_count = ATOMIC_VAR_INIT(1);
+
+size_t _mi_current_thread_count(void) {
+ return mi_atomic_load_relaxed(&thread_count);
+}
+
// This is called from the `mi_malloc_generic`
void mi_thread_init(void) mi_attr_noexcept
{
@@ -343,6 +343,7 @@ void mi_thread_init(void) mi_attr_noexcept
if (_mi_heap_init()) return; // returns true if already initialized
_mi_stat_increase(&_mi_stats_main.threads, 1);
+ mi_atomic_increment_relaxed(&thread_count);
//_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
}
@@ -351,6 +352,7 @@ void mi_thread_done(void) mi_attr_noexcept {
}
static void _mi_thread_done(mi_heap_t* heap) {
+ mi_atomic_decrement_relaxed(&thread_count);
_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...
@@ -441,10 +443,12 @@ 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);
+ MI_UNUSED(dummy);
#endif
os_preloading = false;
- atexit(&mi_process_done);
+ #if !(defined(_WIN32) && defined(MI_SHARED_LIB)) // use Dll process detach (see below) instead of atexit (issue #521)
+ atexit(&mi_process_done);
+ #endif
_mi_options_init();
mi_process_init();
//mi_stats_reset();-
@@ -478,10 +482,11 @@ static void mi_detect_cpu_features(void) {
void mi_process_init(void) mi_attr_noexcept {
// ensure we are called once
if (_mi_process_is_initialized) return;
+ _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id());
_mi_process_is_initialized = true;
mi_process_setup_auto_thread_done();
- _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id());
+
mi_detect_cpu_features();
_mi_os_init();
mi_heap_main_init();
@@ -490,15 +495,30 @@ void mi_process_init(void) mi_attr_noexcept {
#endif
_mi_verbose_message("secure level: %d\n", MI_SECURE);
mi_thread_init();
+
+ #if defined(_WIN32) && !defined(MI_SHARED_LIB)
+ // When building as a static lib the FLS cleanup happens to early for the main thread.
+ // To avoid this, set the FLS value for the main thread to NULL so the fls cleanup
+ // will not call _mi_thread_done on the (still executing) main thread. See issue #508.
+ FlsSetValue(mi_fls_key, NULL);
+ #endif
+
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);
+ long reserve_at = mi_option_get(mi_option_reserve_huge_os_pages_at);
+ if (reserve_at != -1) {
+ mi_reserve_huge_os_pages_at(pages, reserve_at, pages*500);
+ } else {
+ mi_reserve_huge_os_pages_interleave(pages, 0, pages*500);
+ }
}
if (mi_option_is_enabled(mi_option_reserve_os_memory)) {
long ksize = mi_option_get(mi_option_reserve_os_memory);
- if (ksize > 0) mi_reserve_os_memory((size_t)ksize*KiB, true, true);
+ if (ksize > 0) {
+ mi_reserve_os_memory((size_t)ksize*MI_KiB, true, true);
+ }
}
}
@@ -512,8 +532,7 @@ static void mi_process_done(void) {
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
+ FlsFree(mi_fls_key); // call thread-done on all threads (except the main thread) to prevent dangling callback pointer if statically linked with a DLL; Issue #208
#endif
#ifndef MI_SKIP_COLLECT_ON_EXIT
@@ -538,17 +557,40 @@ static void mi_process_done(void) {
#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);
+ MI_UNUSED(reserved);
+ MI_UNUSED(inst);
if (reason==DLL_PROCESS_ATTACH) {
mi_process_load();
}
- else if (reason==DLL_THREAD_DETACH) {
- if (!mi_is_redirected()) mi_thread_done();
+ else if (reason==DLL_PROCESS_DETACH) {
+ mi_process_done();
}
+ else if (reason==DLL_THREAD_DETACH) {
+ if (!mi_is_redirected()) {
+ mi_thread_done();
+ }
+ }
return TRUE;
}
+#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(*_mi_crt_callback_t)(void);
+ #if defined(_M_X64) || defined(_M_ARM64)
+ __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")
+ mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &_mi_process_init };
+ #pragma data_seg()
+
#elif defined(__cplusplus)
// C++: use static initialization to detect process start
static bool _mi_process_init(void) {
@@ -563,24 +605,6 @@ static void mi_process_done(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/src/options.c b/src/options.c
index 30025db2..c4ed91cb 100644
--- a/src/options.c
+++ b/src/options.c
@@ -19,10 +19,10 @@ terms of the MIT license. A copy of the license can be found in the file
#endif
-static uintptr_t mi_max_error_count = 16; // stop outputting errors after this
-static uintptr_t mi_max_warning_count = 16; // stop outputting warnings after this
+static size_t mi_max_error_count = 16; // stop outputting errors after this
+static size_t mi_max_warning_count = 16; // stop outputting warnings after this
-static void mi_add_stderr_output();
+static void mi_add_stderr_output(void);
int mi_version(void) mi_attr_noexcept {
return MI_MALLOC_VERSION;
@@ -76,6 +76,7 @@ static mi_option_desc_t options[_mi_option_last] =
#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) }, // per 1GiB huge pages
+ { -1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N
{ 0, UNINIT, MI_OPTION(reserve_os_memory) },
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
{ 1, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free
@@ -103,7 +104,7 @@ void _mi_options_init(void) {
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
+ long l = mi_option_get(option); MI_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);
@@ -113,7 +114,7 @@ void _mi_options_init(void) {
mi_max_warning_count = mi_option_get(mi_option_max_warnings);
}
-long mi_option_get(mi_option_t option) {
+mi_decl_nodiscard 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
@@ -139,7 +140,7 @@ void mi_option_set_default(mi_option_t option, long value) {
}
}
-bool mi_option_is_enabled(mi_option_t option) {
+mi_decl_nodiscard bool mi_option_is_enabled(mi_option_t option) {
return (mi_option_get(option) != 0);
}
@@ -161,7 +162,7 @@ void mi_option_disable(mi_option_t option) {
static void mi_out_stderr(const char* msg, void* arg) {
- UNUSED(arg);
+ MI_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.
@@ -176,19 +177,19 @@ static void mi_out_stderr(const char* msg, void* arg) {
// 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))
+#define MI_MAX_DELAY_OUTPUT ((size_t)(32*1024))
#endif
static char out_buf[MI_MAX_DELAY_OUTPUT+1];
-static _Atomic(uintptr_t) out_len;
+static _Atomic(size_t) out_len;
static void mi_out_buf(const char* msg, void* arg) {
- UNUSED(arg);
+ MI_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);
+ size_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) {
@@ -251,27 +252,42 @@ static void mi_add_stderr_output() {
// --------------------------------------------------------
// Messages, all end up calling `_mi_fputs`.
// --------------------------------------------------------
-static _Atomic(uintptr_t) error_count; // = 0; // when >= max_error_count stop emitting errors
-static _Atomic(uintptr_t) warning_count; // = 0; // when >= max_warning_count stop emitting warnings
+static _Atomic(size_t) error_count; // = 0; // when >= max_error_count stop emitting errors
+static _Atomic(size_t) warning_count; // = 0; // when >= max_warning_count stop emitting warnings
// When overriding malloc, we may recurse into mi_vfprintf if an allocation
// inside the C runtime causes another message.
+// In some cases (like on macOS) the loader already allocates which
+// calls into mimalloc; if we then access thread locals (like `recurse`)
+// this may crash as the access may call _tlv_bootstrap that tries to
+// (recursively) invoke malloc again to allocate space for the thread local
+// variables on demand. This is why we use a _mi_preloading test on such
+// platforms. However, C code generator may move the initial thread local address
+// load before the `if` and we therefore split it out in a separate funcion.
static mi_decl_thread bool recurse = false;
+static mi_decl_noinline bool mi_recurse_enter_prim(void) {
+ if (recurse) return false;
+ recurse = true;
+ return true;
+}
+
+static mi_decl_noinline void mi_recurse_exit_prim(void) {
+ recurse = false;
+}
+
static bool mi_recurse_enter(void) {
#if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
if (_mi_preloading()) return true;
#endif
- if (recurse) return false;
- recurse = true;
- return true;
+ return mi_recurse_enter_prim();
}
static void mi_recurse_exit(void) {
#if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
if (_mi_preloading()) return;
#endif
- recurse = false;
+ mi_recurse_exit_prim();
}
void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) {
@@ -353,7 +369,7 @@ 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);
+ MI_UNUSED(err);
#if (MI_DEBUG>0)
if (err==EFAULT) {
#ifdef _MSC_VER
@@ -399,16 +415,35 @@ void _mi_error_message(int err, const char* fmt, ...) {
// --------------------------------------------------------
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;
+ if (dest==NULL || src==NULL || dest_size == 0) return;
+ // copy until end of src, or when dest is (almost) full
+ while (*src != 0 && dest_size > 1) {
+ *dest++ = *src++;
+ dest_size--;
+ }
+ // always zero terminate
+ *dest = 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;
+ if (dest==NULL || src==NULL || dest_size == 0) return;
+ // find end of string in the dest buffer
+ while (*dest != 0 && dest_size > 1) {
+ dest++;
+ dest_size--;
+ }
+ // and catenate
+ mi_strlcpy(dest, src, dest_size);
}
+#ifdef MI_NO_GETENV
+static bool mi_getenv(const char* name, char* result, size_t result_size) {
+ MI_UNUSED(name);
+ MI_UNUSED(result);
+ MI_UNUSED(result_size);
+ return false;
+}
+#else
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--) {
@@ -416,7 +451,6 @@ static inline int mi_strnicmp(const char* s, const char* t, size_t n) {
}
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.
@@ -484,7 +518,8 @@ static bool mi_getenv(const char* name, char* result, size_t result_size) {
return false;
}
}
-#endif
+#endif // !MI_USE_ENVIRON
+#endif // !MI_NO_GETENV
static void mi_option_init(mi_option_desc_t* desc) {
// Read option value from the environment
@@ -513,18 +548,29 @@ static void mi_option_init(mi_option_desc_t* desc) {
if (desc->option == mi_option_reserve_os_memory) {
// this option is interpreted in KiB to prevent overflow of `long`
if (*end == 'K') { end++; }
- else if (*end == 'M') { value *= KiB; end++; }
- else if (*end == 'G') { value *= MiB; end++; }
- else { value = (value + KiB - 1) / KiB; }
- if (*end == 'B') { end++; }
+ else if (*end == 'M') { value *= MI_KiB; end++; }
+ else if (*end == 'G') { value *= MI_MiB; end++; }
+ else { value = (value + MI_KiB - 1) / MI_KiB; }
+ if (end[0] == 'I' && end[1] == 'B') { end += 2; }
+ else if (*end == 'B') { end++; }
}
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);
+ // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose.
desc->init = DEFAULTED;
+ if (desc->option == mi_option_verbose && desc->value == 0) {
+ // if the 'mimalloc_verbose' env var has a bogus value we'd never know
+ // (since the value defaults to 'off') so in that case briefly enable verbose
+ desc->value = 1;
+ _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name );
+ desc->value = 0;
+ }
+ else {
+ _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name );
+ }
}
}
mi_assert_internal(desc->init != UNINIT);
diff --git a/src/os.c b/src/os.c
index 85415232..1939156c 100644
--- a/src/os.c
+++ b/src/os.c
@@ -26,16 +26,20 @@ terms of the MIT license. A copy of the license can be found in the file
#pragma warning(disable:4996) // strerror
#endif
+#if defined(__wasi__)
+#define MI_USE_SBRK
+#endif
#if defined(_WIN32)
#include
#elif defined(__wasi__)
-// stdlib.h is all we need, and has already been included in mimalloc.h
+#include // sbrk
#else
#include // mmap
#include // sysconf
#if defined(__linux__)
#include
+#include
#if defined(__GLIBC__)
#include // linux mmap flags
#else
@@ -48,9 +52,13 @@ terms of the MIT license. A copy of the license can be found in the file
#include
#endif
#endif
-#if defined(__HAIKU__)
-#define madvise posix_madvise
-#define MADV_DONTNEED POSIX_MADV_DONTNEED
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include
+#if __FreeBSD_version >= 1200000
+#include
+#include
+#endif
+#include
#endif
#endif
@@ -80,6 +88,7 @@ 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;
@@ -89,30 +98,40 @@ static size_t os_alloc_granularity = 4096;
// if non-zero, use large page allocation
static size_t large_os_page_size = 0;
+// is memory overcommit allowed?
+// set dynamically in _mi_os_init (and if true we use MAP_NORESERVE)
+static bool os_overcommit = true;
+
+bool _mi_os_has_overcommit(void) {
+ return os_overcommit;
+}
+
// 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() {
+size_t _mi_os_large_page_size(void) {
return (large_os_page_size != 0 ? large_os_page_size : _mi_os_page_size());
}
+#if !defined(MI_USE_SBRK) && !defined(__wasi__)
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);
}
+#endif
// 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 < 512*MI_KiB) align_size = _mi_os_page_size();
+ else if (size < 2*MI_MiB) align_size = 64*MI_KiB;
+ else if (size < 8*MI_MiB) align_size = 256*MI_KiB;
+ else if (size < 32*MI_MiB) align_size = 1*MI_MiB;
+ else align_size = 4*MI_MiB;
if (mi_unlikely(size >= (SIZE_MAX - align_size))) return size; // possible overflow?
return _mi_align_up(size, align_size);
}
@@ -175,7 +194,9 @@ static bool mi_win_enable_large_os_pages()
return (ok!=0);
}
-void _mi_os_init(void) {
+void _mi_os_init(void)
+{
+ os_overcommit = false;
// get the page size
SYSTEM_INFO si;
GetSystemInfo(&si);
@@ -210,10 +231,36 @@ void _mi_os_init(void) {
}
#elif defined(__wasi__)
void _mi_os_init() {
- os_page_size = 0x10000; // WebAssembly has a fixed page size: 64KB
+ os_overcommit = false;
+ os_page_size = 64*MI_KiB; // WebAssembly has a fixed page size: 64KiB
os_alloc_granularity = 16;
}
+
+#else // generic unix
+
+static void os_detect_overcommit(void) {
+#if defined(__linux__)
+ int fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
+ if (fd < 0) return;
+ char buf[32];
+ ssize_t nread = read(fd, &buf, sizeof(buf));
+ close(fd);
+ //
+ // 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE)
+ if (nread >= 1) {
+ os_overcommit = (buf[0] == '0' || buf[0] == '1');
+ }
+#elif defined(__FreeBSD__)
+ int val = 0;
+ size_t olen = sizeof(val);
+ if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) {
+ os_overcommit = (val != 0);
+ }
#else
+ // default: overcommit is true
+#endif
+}
+
void _mi_os_init() {
// get the page size
long result = sysconf(_SC_PAGESIZE);
@@ -221,14 +268,26 @@ void _mi_os_init() {
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?
+ large_os_page_size = 2*MI_MiB; // TODO: can we query the OS for this?
+ os_detect_overcommit();
+}
+#endif
+
+
+#if defined(MADV_NORMAL)
+static int mi_madvise(void* addr, size_t length, int advice) {
+ #if defined(__sun)
+ return madvise((caddr_t)addr, length, advice); // Solaris needs cast (issue #520)
+ #else
+ return madvise(addr, length, advice);
+ #endif
}
#endif
/* -----------------------------------------------------------
- Raw allocation on Windows (VirtualAlloc) and Unix's (mmap).
------------------------------------------------------------ */
+ free memory
+-------------------------------------------------------------- */
static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats)
{
@@ -236,8 +295,8 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats
bool err = false;
#if defined(_WIN32)
err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
-#elif defined(__wasi__)
- err = 0; // WebAssembly's heap cannot be shrunk
+#elif defined(MI_USE_SBRK) || defined(__wasi__)
+ err = 0; // sbrk heap cannot be shrunk
#else
err = (munmap(addr, size) == -1);
#endif
@@ -252,33 +311,47 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats
}
}
+#if !defined(MI_USE_SBRK) && !defined(__wasi__)
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size);
+#endif
+
+/* -----------------------------------------------------------
+ Raw allocation on Windows (VirtualAlloc)
+-------------------------------------------------------------- */
#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;
+ // on 64-bit systems, try to use the virtual address area after 2TiB for 4MiB aligned allocations
+ if (addr == NULL) {
+ void* hint = mi_os_get_aligned_hint(try_alignment,size);
+ if (hint != NULL) {
+ void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE);
+ if (p != NULL) return p;
+ // for robustness always fall through in case of an error
+ /*
+ 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;
+ }
+ */
+ _mi_warning_message("unable to allocate hinted aligned OS memory (%zu bytes, error code: %x, address: %p, alignment: %d, flags: %x)\n", size, GetLastError(), hint, try_alignment, flags);
}
- // 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) {
+ if (try_alignment > 1 && (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);
+ void* p = (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, ¶m, 1);
+ if (p != NULL) return p;
+ _mi_warning_message("unable to allocate aligned OS memory (%zu bytes, error code: %x, address: %p, alignment: %d, flags: %x)\n", size, GetLastError(), addr, try_alignment, flags);
+ // fall through on error
}
#endif
// last resort
@@ -287,11 +360,11 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
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;
+ static _Atomic(size_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);
+ size_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.
@@ -318,39 +391,124 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment,
return p;
}
+/* -----------------------------------------------------------
+ Raw allocation using `sbrk` or `wasm_memory_grow`
+-------------------------------------------------------------- */
+
+#elif defined(MI_USE_SBRK) || defined(__wasi__)
+#if defined(MI_USE_SBRK)
+ static void* mi_memory_grow( size_t size ) {
+ void* p = sbrk(size);
+ if (p == (void*)(-1)) return NULL;
+ #if !defined(__wasi__) // on wasi this is always zero initialized already (?)
+ memset(p,0,size);
+ #endif
+ 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) {
+ static void* mi_memory_grow( size_t size ) {
+ size_t base = (size > 0 ? __builtin_wasm_memory_grow(0,_mi_divide_up(size, _mi_os_page_size()))
+ : __builtin_wasm_memory_size(0));
+ if (base == SIZE_MAX) return NULL;
+ return (void*)(base * _mi_os_page_size());
+ }
+#endif
+
+#if defined(MI_USE_PTHREADS)
+static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static void* mi_heap_grow(size_t size, size_t try_alignment) {
+ void* p = NULL;
+ if (try_alignment <= 1) {
+ // `sbrk` is not thread safe in general so try to protect it (we could skip this on WASM but leave it in for now)
+ #if defined(MI_USE_PTHREADS)
+ pthread_mutex_lock(&mi_heap_grow_mutex);
+ #endif
+ p = mi_memory_grow(size);
+ #if defined(MI_USE_PTHREADS)
+ pthread_mutex_unlock(&mi_heap_grow_mutex);
+ #endif
+ }
+ else {
+ void* base = NULL;
+ size_t alloc_size = 0;
+ // to allocate aligned use a lock to try to avoid thread interaction
+ // between getting the current size and actual allocation
+ // (also, `sbrk` is not thread safe in general)
+ #if defined(MI_USE_PTHREADS)
+ pthread_mutex_lock(&mi_heap_grow_mutex);
+ #endif
+ {
+ void* current = mi_memory_grow(0); // get current size
+ if (current != NULL) {
+ void* aligned_current = mi_align_up_ptr(current, try_alignment); // and align from there to minimize wasted space
+ alloc_size = _mi_align_up( ((uint8_t*)aligned_current - (uint8_t*)current) + size, _mi_os_page_size());
+ base = mi_memory_grow(alloc_size);
+ }
+ }
+ #if defined(MI_USE_PTHREADS)
+ pthread_mutex_unlock(&mi_heap_grow_mutex);
+ #endif
+ if (base != NULL) {
+ p = mi_align_up_ptr(base, try_alignment);
+ if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
+ // another thread used wasm_memory_grow/sbrk in-between and we do not have enough
+ // space after alignment. Give up (and waste the space as we cannot shrink :-( )
+ // (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align)
+ p = NULL;
+ }
+ }
+ }
+ if (p == NULL) {
+ _mi_warning_message("unable to allocate sbrk/wasm_memory_grow OS memory (%zu bytes, %zu alignment)\n", size, try_alignment);
errno = ENOMEM;
return NULL;
}
- return (void*)aligned_base;
+ mi_assert_internal( try_alignment == 0 || (uintptr_t)p % try_alignment == 0 );
+ return p;
}
-#else
+
+/* -----------------------------------------------------------
+ Raw allocation on Unix's (mmap)
+-------------------------------------------------------------- */
+#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
+ MI_UNUSED(try_alignment);
+ #if defined(MAP_ALIGNED) // BSD
+ if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 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);
+ void* p = mmap(addr, size, protect_flags, flags | MAP_ALIGNED(n), fd, 0);
+ if (p!=MAP_FAILED) return p;
+ // fall back to regular mmap
+ }
+ }
+ #elif defined(MAP_ALIGN) // Solaris
+ if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) {
+ void* p = mmap((void*)try_alignment, size, protect_flags, flags | MAP_ALIGN, fd, 0); // addr parameter is the required alignment
+ if (p!=MAP_FAILED) return p;
+ // 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;
+ #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
+ // on 64-bit systems, use the virtual address area after 2TiB for 4MiB aligned allocations
+ if (addr == NULL) {
+ void* hint = mi_os_get_aligned_hint(try_alignment, size);
+ if (hint != NULL) {
+ void* p = mmap(hint, size, protect_flags, flags, fd, 0);
+ if (p!=MAP_FAILED) return p;
+ // fall back to regular mmap
+ }
}
- return p;
+ #endif
+ // regular mmap
+ void* p = mmap(addr, size, protect_flags, flags, fd, 0);
+ if (p!=MAP_FAILED) return p;
+ // failed to allocate
+ return NULL;
}
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) {
@@ -361,28 +519,24 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
#if !defined(MAP_NORESERVE)
#define MAP_NORESERVE 0
#endif
- int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
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 (_mi_os_has_overcommit()) {
+ flags |= MAP_NORESERVE;
+ }
#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;
+ if (os_tag < 100 || os_tag > 255) { os_tag = 100; }
fd = VM_MAKE_TAG(os_tag);
#endif
+ // huge page allocation
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);
+ static _Atomic(size_t) large_page_try_ok; // = 0;
+ size_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).
@@ -401,7 +555,7 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
#endif
#ifdef MAP_HUGE_1GB
static bool mi_huge_pages_available = true;
- if ((size % GiB) == 0 && mi_huge_pages_available) {
+ if ((size % MI_GiB) == 0 && mi_huge_pages_available) {
lflags |= MAP_HUGE_1GB;
}
else
@@ -428,37 +582,39 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
#endif
if (large_only) return p;
if (p == NULL) {
- mi_atomic_store_release(&large_page_try_ok, (uintptr_t)10); // on error, don't try again for the next N allocations
+ mi_atomic_store_release(&large_page_try_ok, (size_t)8); // on error, don't try again for the next N allocations
}
}
}
}
+ // regular allocation
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 `madvise` 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;
+ if (p != NULL) {
+ #if defined(MADV_HUGEPAGE)
+ // Many Linux systems don't allow MAP_HUGETLB but they support instead
+ // transparent huge pages (THP). Generally, 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 `madvise` anyways.
+ if (allow_large && use_large_os_page(size, try_alignment)) {
+ if (mi_madvise(p, size, MADV_HUGEPAGE) == 0) {
+ *is_large = true; // possibly
+ };
}
+ #elif 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((caddr_t)p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) {
+ *is_large = true;
+ }
+ }
+ #endif
}
- #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);
@@ -468,8 +624,8 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
#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)))
+// the 2TiB to 30TiB area to allocate them.
+#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || defined(MI_OS_USE_MMAP))
static mi_decl_cache_align _Atomic(uintptr_t) aligned_base;
// Return a 4MiB aligned address that is probably available.
@@ -479,47 +635,52 @@ static mi_decl_cache_align _Atomic(uintptr_t) aligned_base;
// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses
// in the middle of the 2TiB - 6TiB address range (see issue #372))
-#define KK_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
-#define KK_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes)
-#define KK_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
+#define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
+#define MI_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes)
+#define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
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;
- if (size > 1*GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(KK_HINT_AREA / 1<<30) = 1/4096.
+ if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL;
+ size = _mi_align_up(size, MI_SEGMENT_SIZE);
+ if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096.
#if (MI_SECURE>0)
size += MI_SEGMENT_SIZE; // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
#endif
uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
- if (hint == 0 || hint > KK_HINT_MAX) { // wrap or initialize
- uintptr_t init = KK_HINT_BASE;
+ if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize
+ uintptr_t init = MI_HINT_BASE;
#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)) % KK_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB
+ init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (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 > KK_HINT_MAX but that is ok, it is a hint after all
+ hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
}
if (hint%try_alignment != 0) return NULL;
return (void*)hint;
}
+#elif defined(__wasi__) || defined(MI_USE_SBRK)
+// no need for mi_os_get_aligned_hint
#else
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
- UNUSED(try_alignment); UNUSED(size);
+ MI_UNUSED(try_alignment); MI_UNUSED(size);
return NULL;
}
#endif
+/* -----------------------------------------------------------
+ Primitive allocation from the OS.
+-------------------------------------------------------------- */
-// 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;
+ if (try_alignment == 0) try_alignment = 1; // avoid 0 to ensure there will be no divide by zero when aligning
void* p = NULL;
/*
@@ -536,9 +697,10 @@ static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, boo
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__)
+ #elif defined(MI_USE_SBRK) || defined(__wasi__)
+ MI_UNUSED(allow_large);
*is_large = false;
- p = mi_wasm_heap_grow(size, try_alignment);
+ p = mi_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);
@@ -593,6 +755,10 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
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 != NULL) {
+ _mi_stat_increase(&stats->reserved, size);
+ if (commit) { _mi_stat_increase(&stats->committed, size); }
+ }
if (p == aligned_p) break; // success!
if (p != NULL) { // should not happen?
mi_os_mem_free(p, size, commit, stats);
@@ -602,9 +768,9 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
}
#else
// overallocate...
- p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats);
+ p = mi_os_mem_alloc(over_size, 1, commit, false, is_large, stats);
if (p == NULL) return NULL;
- // and selectively unmap parts around the over-allocated area.
+ // and selectively unmap parts around the over-allocated area. (noop on sbrk)
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());
@@ -612,7 +778,7 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
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
+ // we can return the aligned pointer on `mmap` (and sbrk) systems
p = aligned_p;
#endif
}
@@ -626,7 +792,7 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
----------------------------------------------------------- */
void* _mi_os_alloc(size_t size, mi_stats_t* tld_stats) {
- UNUSED(tld_stats);
+ MI_UNUSED(tld_stats);
mi_stats_t* stats = &_mi_stats_main;
if (size == 0) return NULL;
size = _mi_os_good_alloc_size(size);
@@ -635,7 +801,7 @@ void* _mi_os_alloc(size_t size, mi_stats_t* tld_stats) {
}
void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* tld_stats) {
- UNUSED(tld_stats);
+ MI_UNUSED(tld_stats);
mi_stats_t* stats = &_mi_stats_main;
if (size == 0 || p == NULL) return;
size = _mi_os_good_alloc_size(size);
@@ -648,7 +814,7 @@ void _mi_os_free(void* p, size_t size, mi_stats_t* stats) {
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_stats_t* tld_stats)
{
- UNUSED(tld_stats);
+ MI_UNUSED(tld_stats);
if (size == 0) return NULL;
size = _mi_os_good_alloc_size(size);
alignment = _mi_align_up(alignment, _mi_os_page_size());
@@ -699,7 +865,7 @@ static void mi_mprotect_hint(int err) {
" > sudo sysctl -w vm.max_map_count=262144\n");
}
#else
- UNUSED(err);
+ MI_UNUSED(err);
#endif
}
@@ -723,8 +889,7 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
#if defined(_WIN32)
if (commit) {
- // if the memory was already committed, the call succeeds but it is not zero'd
- // *is_zero = true;
+ // *is_zero = true; // note: if the memory was already committed, the call succeeds but the memory is not zero'd
void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE);
err = (p == start ? 0 : GetLastError());
}
@@ -734,26 +899,43 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
}
#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
+ #elif 0 && defined(MAP_FIXED) && !defined(__APPLE__)
+ // Linux: disabled for now as mmap fixed seems much more expensive than MADV_DONTNEED (and splits VMA's?)
+ if (commit) {
+ // commit: just change the protection
err = mprotect(start, csize, (PROT_READ | PROT_WRITE));
if (err != 0) { err = errno; }
- #if defined(MADV_FREE_REUSE)
- while ((err = madvise(start, csize, MADV_FREE_REUSE)) != 0 && errno == EAGAIN) { errno = 0; }
- #endif
+ }
+ else {
+ // decommit: use mmap with MAP_FIXED to discard the existing memory (and reduce rss)
+ const int fd = mi_unix_mmap_fd();
+ void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), fd, 0);
+ if (p != start) { err = errno; }
}
#else
- err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE));
- if (err != 0) { err = errno; }
+ // Linux, macOSX and others.
+ if (commit) {
+ // commit: ensure we can access the area
+ err = mprotect(start, csize, (PROT_READ | PROT_WRITE));
+ if (err != 0) { err = errno; }
+ }
+ else {
+ #if defined(MADV_DONTNEED) && MI_DEBUG == 0 && MI_SECURE == 0
+ // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
+ // (on the other hand, MADV_FREE would be good enough.. it is just not reflected in the stats :-( )
+ err = madvise(start, csize, MADV_DONTNEED);
+ #else
+ // decommit: just disable access (also used in debug and secure mode to trap on illegal access)
+ err = mprotect(start, csize, PROT_NONE);
+ if (err != 0) { err = errno; }
+ #endif
+ //#if defined(MADV_FREE_REUSE)
+ // while ((err = mi_madvise(start, csize, MADV_FREE_REUSE)) != 0 && errno == EAGAIN) { errno = 0; }
+ //#endif
+ }
#endif
if (err != 0) {
- _mi_warning_message("%s error: start: %p, csize: 0x%x, err: %i\n", commit ? "commit" : "decommit", start, csize, err);
+ _mi_warning_message("%s error: start: %p, csize: 0x%zx, err: %i\n", commit ? "commit" : "decommit", start, csize, err);
mi_mprotect_hint(err);
}
mi_assert_internal(err == 0);
@@ -761,13 +943,13 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
}
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
- UNUSED(tld_stats);
+ MI_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_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);
@@ -808,27 +990,22 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
if (p != start) return false;
#else
#if defined(MADV_FREE)
- #if defined(MADV_FREE_REUSABLE)
- #define KK_MADV_FREE_INITIAL MADV_FREE_REUSABLE
- #else
- #define KK_MADV_FREE_INITIAL MADV_FREE
- #endif
- static _Atomic(uintptr_t) advice = ATOMIC_VAR_INIT(KK_MADV_FREE_INITIAL);
+ static _Atomic(size_t) advice = ATOMIC_VAR_INIT(MADV_FREE);
int oadvice = (int)mi_atomic_load_relaxed(&advice);
int err;
- while ((err = madvise(start, csize, oadvice)) != 0 && errno == EAGAIN) { errno = 0; };
- if (err != 0 && errno == EINVAL && oadvice == KK_MADV_FREE_INITIAL) {
- // if MADV_FREE/MADV_FREE_REUSABLE 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);
+ while ((err = mi_madvise(start, csize, oadvice)) != 0 && errno == EAGAIN) { errno = 0; };
+ if (err != 0 && errno == EINVAL && oadvice == MADV_FREE) {
+ // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
+ mi_atomic_store_release(&advice, (size_t)MADV_DONTNEED);
+ err = mi_madvise(start, csize, MADV_DONTNEED);
}
#elif defined(__wasi__)
int err = 0;
#else
- int err = madvise(start, csize, MADV_DONTNEED);
+ int err = mi_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_warning_message("madvise reset error: start: %p, csize: 0x%zx, errno: %i\n", start, csize, errno);
}
//mi_assert(err == 0);
if (err != 0) return false;
@@ -841,7 +1018,7 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
// 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_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);
@@ -852,7 +1029,7 @@ bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats) {
}
bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
- UNUSED(tld_stats);
+ MI_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!)
@@ -887,7 +1064,7 @@ static bool mi_os_protectx(void* addr, size_t size, bool protect) {
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_warning_message("mprotect error: start: %p, csize: 0x%zx, err: %i\n", start, csize, err);
mi_mprotect_hint(err);
}
return (err == 0);
@@ -928,12 +1105,12 @@ bool _mi_os_shrink(void* p, size_t oldsize, size_t newsize, mi_stats_t* stats) {
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)
+#define MI_HUGE_OS_PAGE_SIZE (MI_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(size%MI_GiB == 0);
mi_assert_internal(addr != NULL);
const DWORD flags = MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE;
@@ -964,7 +1141,7 @@ static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node)
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);
+ _mi_warning_message("unable to allocate using huge (1GiB) pages, trying large (2MiB) pages instead (status 0x%lx)\n", err);
}
}
// on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation
@@ -974,7 +1151,7 @@ static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node)
return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, params, 1);
}
#else
- UNUSED(numa_node);
+ MI_UNUSED(numa_node);
#endif
// otherwise use regular virtual alloc on older windows
return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
@@ -991,30 +1168,30 @@ static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, cons
}
#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);
+ MI_UNUSED(start); MI_UNUSED(len); MI_UNUSED(mode); MI_UNUSED(nmask); MI_UNUSED(maxnode); MI_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);
+ mi_assert_internal(size%MI_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);
+ unsigned long 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));
+ _mi_warning_message("failed to bind huge (1GiB) 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);
+ MI_UNUSED(addr); MI_UNUSED(size); MI_UNUSED(numa_node);
return NULL;
}
#endif
@@ -1050,7 +1227,7 @@ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
}
#else
static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
- UNUSED(pages);
+ MI_UNUSED(pages);
if (total_size != NULL) *total_size = 0;
return NULL;
}
@@ -1104,8 +1281,8 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse
}
}
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;
+ if (pages_reserved != NULL) { *pages_reserved = page; }
+ if (psize != NULL) { *psize = page * MI_HUGE_OS_PAGE_SIZE; }
return (page == 0 ? NULL : start);
}
@@ -1117,6 +1294,7 @@ void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats) {
while (size >= MI_HUGE_OS_PAGE_SIZE) {
_mi_os_free(base, MI_HUGE_OS_PAGE_SIZE, stats);
size -= MI_HUGE_OS_PAGE_SIZE;
+ base += MI_HUGE_OS_PAGE_SIZE;
}
}
@@ -1193,6 +1371,35 @@ static size_t mi_os_numa_node_countx(void) {
}
return (node+1);
}
+#elif defined(__FreeBSD__) && __FreeBSD_version >= 1200000
+static size_t mi_os_numa_nodex(void) {
+ domainset_t dom;
+ size_t node;
+ int policy;
+ if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul;
+ for (node = 0; node < MAXMEMDOM; node++) {
+ if (DOMAINSET_ISSET(node, &dom)) return node;
+ }
+ return 0ul;
+}
+static size_t mi_os_numa_node_countx(void) {
+ size_t ndomains = 0;
+ size_t len = sizeof(ndomains);
+ if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul;
+ return ndomains;
+}
+#elif defined(__DragonFly__)
+static size_t mi_os_numa_nodex(void) {
+ // TODO: DragonFly does not seem to provide any userland means to get this information.
+ return 0ul;
+}
+static size_t mi_os_numa_node_countx(void) {
+ size_t ncpus = 0, nvirtcoresperphys = 0;
+ size_t len = sizeof(size_t);
+ if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul;
+ if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul;
+ return nvirtcoresperphys * ncpus;
+}
#else
static size_t mi_os_numa_nodex(void) {
return 0;
@@ -1222,7 +1429,7 @@ size_t _mi_os_numa_node_count_get(void) {
}
int _mi_os_numa_node_get(mi_os_tld_t* tld) {
- UNUSED(tld);
+ MI_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
diff --git a/src/page-queue.c b/src/page-queue.c
index 365257e7..26b10800 100644
--- a/src/page-queue.c
+++ b/src/page-queue.c
@@ -53,7 +53,7 @@ static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) {
// 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) {
+static inline uint8_t mi_bin(size_t size) {
size_t wsize = _mi_wsize_from_size(size);
uint8_t bin;
if (wsize <= 1) {
@@ -98,6 +98,10 @@ extern inline uint8_t _mi_bin(size_t size) {
Queue of pages with free blocks
----------------------------------------------------------- */
+uint8_t _mi_bin(size_t size) {
+ return mi_bin(size);
+}
+
size_t _mi_bin_size(uint8_t bin) {
return _mi_heap_empty.pages[bin].block_size;
}
@@ -105,7 +109,7 @@ size_t _mi_bin_size(uint8_t bin) {
// 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));
+ return _mi_bin_size(mi_bin(size));
}
else {
return _mi_align_up(size,_mi_os_page_size());
@@ -134,7 +138,7 @@ static bool mi_heap_contains_queue(const mi_heap_t* heap, const mi_page_queue_t*
#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));
+ 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];
@@ -144,7 +148,7 @@ static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) {
}
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));
+ 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);
@@ -177,9 +181,9 @@ static inline void mi_heap_queue_first_update(mi_heap_t* heap, const mi_page_que
}
else {
// find previous size; due to minimal alignment upto 3 previous bins may need to be skipped
- uint8_t bin = _mi_bin(size);
+ 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]) {
+ while( bin == mi_bin(prev->block_size) && prev > &heap->pages[0]) {
prev--;
}
start = 1 + _mi_wsize_from_size(prev->block_size);
diff --git a/src/page.c b/src/page.c
index c08be9c0..6efeba2a 100644
--- a/src/page.c
+++ b/src/page.c
@@ -7,7 +7,7 @@ terms of the MIT license. A copy of the license can be found in the file
/* -----------------------------------------------------------
The core of the allocator. Every segment contains
- pages of a {certain block size. The main function
+ pages of a certain block size. The main function
exported is `mi_malloc_generic`.
----------------------------------------------------------- */
@@ -30,7 +30,7 @@ terms of the MIT license. A copy of the license can be found in the file
// 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_UNUSED(page);
mi_assert_internal(page != NULL);
mi_assert_internal(i <= page->reserved);
return (mi_block_t*)((uint8_t*)page_start + (i * block_size));
@@ -84,9 +84,10 @@ static bool mi_page_is_valid_init(mi_page_t* page) {
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)));
+ if (page->is_zero) {
+ const size_t ubsize = mi_page_usable_block_size(page);
+ for(mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) {
+ mi_assert_expensive(mi_mem_is_zero(block + 1, ubsize - sizeof(mi_block_t)));
}
}
#endif
@@ -385,7 +386,7 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) {
// 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) {
+void _mi_page_retire(mi_page_t* page) mi_attr_noexcept {
mi_assert_internal(page != NULL);
mi_assert_expensive(_mi_page_is_valid(page));
mi_assert_internal(mi_page_all_free(page));
@@ -458,7 +459,7 @@ void _mi_heap_collect_retired(mi_heap_t* heap, bool force) {
#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);
+ MI_UNUSED(stats);
#if (MI_SECURE<=2)
mi_assert_internal(page->free == NULL);
mi_assert_internal(page->local_free == NULL);
@@ -516,7 +517,7 @@ static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* co
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);
+ MI_UNUSED(stats);
#if (MI_SECURE <= 2)
mi_assert_internal(page->free == NULL);
mi_assert_internal(page->local_free == NULL);
@@ -573,13 +574,16 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld)
// 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;
+ mi_assert_internal(extend > 0);
+ 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; }
+ mi_assert_internal(max_extend > 0);
+
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);
+ extend = max_extend;
}
mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved);
@@ -620,7 +624,11 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
page->keys[0] = _mi_heap_random_next(heap);
page->keys[1] = _mi_heap_random_next(heap);
#endif
+ #if MI_DEBUG > 0
+ page->is_zero = false; // ensure in debug mode we initialize with MI_DEBUG_UNINIT, see issue #501
+ #else
page->is_zero = page->is_zero_init;
+ #endif
mi_assert_internal(page->capacity == 0);
mi_assert_internal(page->free == NULL);
@@ -760,7 +768,7 @@ void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noex
// 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_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
diff --git a/src/random.c b/src/random.c
index 255bede4..0b44c8b9 100644
--- a/src/random.c
+++ b/src/random.c
@@ -4,6 +4,10 @@ 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 // for syscall() on Linux
+#endif
+
#include "mimalloc.h"
#include "mimalloc-internal.h"
@@ -156,7 +160,8 @@ uintptr_t _mi_random_next(mi_random_ctx_t* ctx) {
/* ----------------------------------------------------------------------------
To initialize a fresh random context we rely on the OS:
- Windows : BCryptGenRandom (or RtlGenRandom)
-- osX,bsd,wasi: arc4random_buf
+- macOS : CCRandomGenerateBytes, arc4random_buf
+- 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.
-----------------------------------------------------------------------------*/
@@ -164,7 +169,8 @@ If we cannot get good randomness, we fall back to weak randomness based on a tim
#if defined(_WIN32)
#if !defined(MI_USE_RTLGENRANDOM)
-// We prefer BCryptGenRandom over RtlGenRandom
+// We prefer to use BCryptGenRandom instead of RtlGenRandom but it can lead to a deadlock
+// under the VS debugger when using dynamic overriding.
#pragma comment (lib,"bcrypt.lib")
#include
static bool os_random_buf(void* buf, size_t buf_len) {
@@ -186,16 +192,35 @@ static bool os_random_buf(void* buf, size_t buf_len) {
}
#endif
-#elif defined(ANDROID) || defined(XP_DARWIN) || defined(__APPLE__) || defined(__DragonFly__) || \
+#elif defined(__APPLE__)
+#include
+#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
+#include
+#endif
+static bool os_random_buf(void* buf, size_t buf_len) {
+ #if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
+ // We prefere CCRandomGenerateBytes as it returns an error code while arc4random_buf
+ // may fail silently on macOS. See PR #390, and
+ return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess);
+ #else
+ // fall back on older macOS
+ arc4random_buf(buf, buf_len);
+ return true;
+ #endif
+}
+
+#elif defined(__ANDROID__) || defined(__DragonFly__) || \
defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
- defined(__sun) || defined(__wasi__)
+ defined(__sun) // todo: what to use with __wasi__?
#include
static bool os_random_buf(void* buf, size_t buf_len) {
arc4random_buf(buf, buf_len);
return true;
}
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__HAIKU__)
+#if defined(__linux__)
#include
+#endif
#include
#include
#include
@@ -214,7 +239,7 @@ static bool os_random_buf(void* buf, size_t buf_len) {
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;
+ if (errno != ENOSYS) return false;
mi_atomic_store_release(&no_getrandom, 1UL); // don't call again, and fall back to /dev/urandom
}
#endif
@@ -251,8 +276,8 @@ static bool os_random_buf(void* buf, size_t buf_len) {
#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
+uintptr_t _mi_os_random_weak(uintptr_t extra_seed) {
+ uintptr_t x = (uintptr_t)&_mi_os_random_weak ^ extra_seed; // ASLR makes the address random
#if defined(_WIN32)
LARGE_INTEGER pcount;
@@ -280,8 +305,10 @@ void _mi_random_init(mi_random_ctx_t* ctx) {
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
+ #if !defined(__wasi__)
_mi_warning_message("unable to use secure randomness\n");
- uintptr_t x = _os_random_weak(0);
+ #endif
+ uintptr_t x = _mi_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;
diff --git a/src/region.c b/src/region.c
index 79540730..2d73025e 100644
--- a/src/region.c
+++ b/src/region.c
@@ -40,7 +40,7 @@ Possible issues:
#include "bitmap.h"
// Internal raw OS interface
-size_t _mi_os_large_page_size();
+size_t _mi_os_large_page_size(void);
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);
@@ -57,9 +57,9 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, boo
// Constants
#if (MI_INTPTR_SIZE==8)
-#define MI_HEAP_REGION_MAX_SIZE (256 * GiB) // 64KiB for the region map
+#define MI_HEAP_REGION_MAX_SIZE (256 * MI_GiB) // 64KiB for the region map
#elif (MI_INTPTR_SIZE==4)
-#define MI_HEAP_REGION_MAX_SIZE (3 * GiB) // ~ KiB for the region map
+#define MI_HEAP_REGION_MAX_SIZE (3 * MI_GiB) // ~ KiB for the region map
#else
#error "define the maximum heap space allowed for regions on this platform"
#endif
@@ -74,7 +74,7 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, boo
// Region info
typedef union mi_region_info_u {
- uintptr_t value;
+ size_t value;
struct {
bool valid; // initialized?
bool is_large:1; // allocated in fixed large/huge OS pages
@@ -87,21 +87,21 @@ typedef union mi_region_info_u {
// 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(size_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
+ _Atomic(size_t) arena_memid; // if allocated from a (huge page) arena
+ _Atomic(size_t) padding; // round to 8 fields (needs to be atomic for msvc, see issue #508)
} mem_region_t;
// The region map
static mem_region_t regions[MI_REGION_MAX];
// Allocated regions
-static _Atomic(uintptr_t) regions_count; // = 0;
+static _Atomic(size_t) regions_count; // = 0;
/* ----------------------------------------------------------------------------
@@ -186,21 +186,21 @@ static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large,
mi_assert_internal(!region_large || region_commit);
// claim a fresh slot
- const uintptr_t idx = mi_atomic_increment_acq_rel(®ions_count);
+ const size_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));
+ _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, MI_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->in_use, (size_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);
+ mi_atomic_store_release(&r->reset, (size_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);
@@ -441,7 +441,7 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
// and unclaim
bool all_unclaimed = mi_bitmap_unclaim(®ion->in_use, 1, blocks, bit_idx);
- mi_assert_internal(all_unclaimed); UNUSED(all_unclaimed);
+ mi_assert_internal(all_unclaimed); MI_UNUSED(all_unclaimed);
}
}
@@ -451,21 +451,21 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
-----------------------------------------------------------------------------*/
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);
+ size_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);
+ size_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));
+ size_t commit = mi_atomic_load_relaxed(®ions[i].commit);
+ memset((void*)®ions[i], 0, sizeof(mem_region_t)); // cast to void* to avoid atomic warning
// and release the whole region
- mi_atomic_store_release(®ion->info, (uintptr_t)0);
+ mi_atomic_store_release(®ion->info, (size_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);
diff --git a/src/segment.c b/src/segment.c
index 1d59be9d..1aadf5c2 100644
--- a/src/segment.c
+++ b/src/segment.c
@@ -17,14 +17,14 @@ static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_
/* --------------------------------------------------------------------------------
Segment allocation
- We allocate pages inside bigger "segments" (4mb on 64-bit). This is to avoid
+ We allocate pages inside bigger "segments" (4MiB 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
+ - small pages (64KiB), 64 in one segment
+ - medium pages (512KiB), 8 in one segment
+ - large pages (4MiB), 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.
@@ -579,7 +579,10 @@ static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_
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_delayed = (page_kind <= MI_PAGE_MEDIUM && // don't delay for large objects
+ !_mi_os_has_overcommit() && // never delay on overcommit systems
+ _mi_current_thread_count() > 2 && // do not delay for the first N threads
+ 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;
@@ -655,8 +658,9 @@ static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_
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;
+ for (size_t i = 0; i < capacity; i++) {
+ mi_assert_internal(i <= 255);
+ segment->pages[i].segment_idx = (uint8_t)i;
segment->pages[i].is_reset = false;
segment->pages[i].is_committed = commit;
segment->pages[i].is_zero_init = is_zero;
@@ -695,7 +699,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
}
static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) {
- UNUSED(force);
+ MI_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));
@@ -896,13 +900,13 @@ static mi_decl_cache_align _Atomic(mi_segment_t*) abandoned_visited; // =
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;
+static mi_decl_cache_align _Atomic(size_t) abandoned_count;
+static mi_decl_cache_align _Atomic(size_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
+static mi_decl_cache_align _Atomic(size_t) abandoned_readers; // = 0
// Push on the visited list
static void mi_abandoned_visited_push(mi_segment_t* segment) {
@@ -931,7 +935,7 @@ static bool mi_abandoned_visited_revisit(void)
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);
+ size_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);
@@ -950,7 +954,7 @@ static bool mi_abandoned_visited_revisit(void)
// 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;
+ size_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));
@@ -978,7 +982,7 @@ static void mi_abandoned_push(mi_segment_t* segment) {
// 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;
+ size_t n;
do {
n = mi_atomic_load_acquire(&abandoned_readers);
if (n != 0) mi_atomic_yield();
@@ -1326,7 +1330,7 @@ void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block
// 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;
+ size_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;
diff --git a/src/stats.c b/src/stats.c
index c94fbde9..6d486f42 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -133,25 +133,29 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
// 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];
+ char buf[32]; buf[0] = 0;
int len = 32;
- const char* suffix = (unit <= 0 ? " " : "b");
+ 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);
+ if (n!=1 || suffix[0] != 'B') { // skip printing 1 B for the unit column
+ snprintf(buf, len, "%d %-3s", (int)n, (n==0 ? "" : 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"; }
+ 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 < 0 ? -frac1 : frac1), magnitude, suffix);
+ char unitdesc[8];
+ snprintf(unitdesc, 8, "%s%s%s", magnitude, (base==1024 ? "i" : ""), suffix);
+ snprintf(buf, len, "%ld.%ld %-3s", whole, (frac1 < 0 ? -frac1 : frac1), unitdesc);
}
_mi_fprintf(out, arg, (fmt==NULL ? "%11s" : fmt), buf);
}
@@ -221,7 +225,7 @@ static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char*
static void mi_print_header(mi_output_fun* out, void* arg ) {
- _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "current ", "unit ", "count ");
+ _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "current ", "unit ", "count ");
}
#if MI_STAT>1
@@ -323,7 +327,7 @@ static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0)
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_fprintf(out, arg, "%10s: %7zu\n", "numa nodes", _mi_os_numa_node_count());
mi_msecs_t elapsed;
mi_msecs_t user_time;
@@ -412,10 +416,14 @@ mi_msecs_t _mi_clock_now(void) {
}
#else
#include
-#ifdef CLOCK_REALTIME
+#if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC)
mi_msecs_t _mi_clock_now(void) {
struct timespec t;
+ #ifdef CLOCK_MONOTONIC
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ #else
clock_gettime(CLOCK_REALTIME, &t);
+ #endif
return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000);
}
#else
@@ -479,7 +487,7 @@ static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msec
*page_faults = (size_t)info.PageFaultCount;
}
-#elif defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__)
+#elif !defined(__wasi__) && (defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__))
#include
#include
#include
@@ -520,6 +528,7 @@ static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msec
while (get_next_area_info(tid.team, &c, &mem) == B_OK) {
*peak_rss += mem.ram_size;
}
+ *page_faults = 0;
#elif defined(__APPLE__)
*peak_rss = rusage.ru_maxrss; // BSD reports in bytes
struct mach_task_basic_info info;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7986d2da..054d9409 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.0)
project(mimalloc-test C CXX)
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+
# Set default build type
if (NOT CMAKE_BUILD_TYPE)
if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$")
@@ -14,7 +17,7 @@ endif()
# Import mimalloc (if installed)
find_package(mimalloc 1.7 REQUIRED NO_SYSTEM_ENVIRONMENT_PATH)
-message(STATUS "Found mimalloc installed at: ${MIMALLOC_LIBRARY_DIR}")
+message(STATUS "Found mimalloc installed at: ${MIMALLOC_LIBRARY_DIR} (${MIMALLOC_VERSION_DIR})")
# overriding with a dynamic library
add_executable(dynamic-override main-override.c)
@@ -26,7 +29,7 @@ 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_LIBRARY_DIR}/mimalloc.o)
+add_executable(static-override-obj main-override.c ${MIMALLOC_OBJECT_DIR}/mimalloc.o)
target_include_directories(static-override-obj PUBLIC ${MIMALLOC_INCLUDE_DIR})
target_link_libraries(static-override-obj PUBLIC pthread)
diff --git a/test/main-override-static.c b/test/main-override-static.c
index 221db7e8..071e4248 100644
--- a/test/main-override-static.c
+++ b/test/main-override-static.c
@@ -42,7 +42,7 @@ int main() {
free(p1);
free(p2);
free(s);
-
+
/* now test if override worked by allocating/freeing across the api's*/
//p1 = mi_malloc(32);
//free(p1);
diff --git a/test/main-override.c b/test/main-override.c
index 1bec1179..284fdd20 100644
--- a/test/main-override.c
+++ b/test/main-override.c
@@ -3,7 +3,7 @@
#include
#include
-#include
+#include
int main() {
mi_version(); // ensure mimalloc library is linked
@@ -25,6 +25,12 @@ int main() {
//free(p1);
//p2 = malloc(32);
//mi_free(p2);
+ p1 = malloc(24);
+ p2 = reallocarray(p1, 16, 16);
+ free(p2);
+ p1 = malloc(24);
+ assert(reallocarr(&p1, 16, 16) == 0);
+ free(p1);
mi_stats_print(NULL);
return 0;
}
diff --git a/test/main-override.cpp b/test/main-override.cpp
index 5fe3f9a3..f748c75a 100644
--- a/test/main-override.cpp
+++ b/test/main-override.cpp
@@ -26,14 +26,15 @@ static void msleep(unsigned long msecs) { Sleep(msecs); }
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();
-void fail_aslr(); // issue #372
-void tsan_numa_test(); // issue #414
+static void heap_thread_free_large(); // issue #221
+static void heap_no_delete(); // issue #202
+static void heap_late_free(); // issue #204
+static void padding_shrink(); // issue #209
+static void various_tests();
+static void test_mt_shutdown();
+static void fail_aslr(); // issue #372
+static void tsan_numa_test(); // issue #414
+static void strdup_test(); // issue #445
int main() {
mi_stats_reset(); // ignore earlier allocations
@@ -43,8 +44,9 @@ int main() {
padding_shrink();
various_tests();
tsan_numa_test();
+ strdup_test();
- //test_mt_shutdown();
+ test_mt_shutdown();
//fail_aslr();
mi_stats_print(NULL);
return 0;
@@ -66,26 +68,21 @@ public:
};
-void various_tests() {
+static void various_tests() {
atexit(free_p);
void* p1 = malloc(78);
- void* p2 = mi_malloc_aligned(16, 24);
+ void* p2 = mi_malloc_aligned(24, 16);
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);
@@ -109,7 +106,7 @@ public:
static Static s = Static();
-bool test_stl_allocator1() {
+static bool test_stl_allocator1() {
std::vector > vec;
vec.push_back(1);
vec.pop_back();
@@ -118,38 +115,48 @@ bool test_stl_allocator1() {
struct some_struct { int i; int j; double z; };
-bool test_stl_allocator2() {
+static bool test_stl_allocator2() {
std::vector > vec;
vec.push_back(some_struct());
vec.pop_back();
return vec.size() == 0;
}
-
+// issue 445
+static void strdup_test() {
+#ifdef _MSC_VER
+ char* s = _strdup("hello\n");
+ char* buf = NULL;
+ size_t len;
+ _dupenv_s(&buf, &len, "MIMALLOC_VERBOSE");
+ mi_free(buf);
+ mi_free(s);
+#endif
+}
// Issue #202
-void heap_no_delete_worker() {
+static 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() {
+static void heap_no_delete() {
auto t1 = std::thread(heap_no_delete_worker);
t1.join();
}
// Issue #204
-volatile void* global_p;
+static volatile void* global_p;
-void t1main() {
+static void t1main() {
mi_heap_t* heap = mi_heap_new();
global_p = mi_heap_malloc(heap, 1024);
mi_heap_delete(heap);
}
-void heap_late_free() {
+static void heap_late_free() {
auto t1 = std::thread(t1main);
msleep(2000);
@@ -166,7 +173,7 @@ static void alloc0(/* void* arg */)
shared_p = mi_malloc(8);
}
-void padding_shrink(void)
+static void padding_shrink(void)
{
auto t1 = std::thread(alloc0);
t1.join();
@@ -175,11 +182,11 @@ void padding_shrink(void)
// Issue #221
-void heap_thread_free_large_worker() {
+static void heap_thread_free_large_worker() {
mi_free(shared_p);
}
-void heap_thread_free_large() {
+static 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);
@@ -189,7 +196,7 @@ void heap_thread_free_large() {
-void test_mt_shutdown()
+static void test_mt_shutdown()
{
const int threads = 5;
std::vector< std::future< std::vector< char* > > > ts;
@@ -214,7 +221,7 @@ void test_mt_shutdown()
}
// issue #372
-void fail_aslr() {
+static void fail_aslr() {
size_t sz = (4ULL << 40); // 4TiB
void* p = malloc(sz);
printf("pointer p: %p: area up to %p\n", p, (uint8_t*)p + sz);
@@ -222,12 +229,12 @@ void fail_aslr() {
}
// issues #414
-void dummy_worker() {
+static void dummy_worker() {
void* p = mi_malloc(0);
mi_free(p);
}
-void tsan_numa_test() {
+static void tsan_numa_test() {
auto t1 = std::thread(dummy_worker);
dummy_worker();
t1.join();
diff --git a/test/test-api-fill.c b/test/test-api-fill.c
new file mode 100644
index 00000000..0e5a65dc
--- /dev/null
+++ b/test/test-api-fill.c
@@ -0,0 +1,332 @@
+/* ----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------*/
+#include "mimalloc.h"
+#include "mimalloc-types.h"
+
+#include "testhelper.h"
+
+// ---------------------------------------------------------------------------
+// Helper functions
+// ---------------------------------------------------------------------------
+bool check_zero_init(uint8_t* p, size_t size);
+#if MI_DEBUG >= 2
+bool check_debug_fill_uninit(uint8_t* p, size_t size);
+bool check_debug_fill_freed(uint8_t* p, size_t size);
+#endif
+
+// ---------------------------------------------------------------------------
+// Main testing
+// ---------------------------------------------------------------------------
+int main(void) {
+ mi_option_disable(mi_option_verbose);
+
+ // ---------------------------------------------------
+ // Zeroing allocation
+ // ---------------------------------------------------
+ CHECK_BODY("zeroinit-zalloc-small", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+ result = check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-zalloc-large", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+ result = check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-zalloc_small", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_zalloc_small(zalloc_size);
+ result = check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-calloc-small", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+ result = check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-calloc-large", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+ result = check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-rezalloc-small", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+ result = check_zero_init(p, zalloc_size);
+ zalloc_size *= 3;
+ p = (uint8_t*)mi_rezalloc(p, zalloc_size);
+ result &= check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-rezalloc-large", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+ result = check_zero_init(p, zalloc_size);
+ zalloc_size *= 3;
+ p = (uint8_t*)mi_rezalloc(p, zalloc_size);
+ result &= check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-recalloc-small", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+ result = check_zero_init(p, calloc_size);
+ calloc_size *= 3;
+ p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
+ result &= check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-recalloc-large", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+ result = check_zero_init(p, calloc_size);
+ calloc_size *= 3;
+ p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
+ result &= check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+
+ // ---------------------------------------------------
+ // Zeroing in aligned API
+ // ---------------------------------------------------
+ CHECK_BODY("zeroinit-zalloc_aligned-small", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-zalloc_aligned-large", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-calloc_aligned-small", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-calloc_aligned-large", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-rezalloc_aligned-small", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, zalloc_size);
+ zalloc_size *= 3;
+ p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-rezalloc_aligned-large", {
+ size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, zalloc_size);
+ zalloc_size *= 3;
+ p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_zero_init(p, zalloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("zeroinit-recalloc_aligned-small", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, calloc_size);
+ calloc_size *= 3;
+ p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("zeroinit-recalloc_aligned-large", {
+ size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result = check_zero_init(p, calloc_size);
+ calloc_size *= 3;
+ p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_zero_init(p, calloc_size);
+ mi_free(p);
+ });
+
+#if MI_DEBUG >= 2
+ // ---------------------------------------------------
+ // Debug filling
+ // ---------------------------------------------------
+ CHECK_BODY("uninit-malloc-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-malloc-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-malloc_small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc_small(malloc_size);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-realloc-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_realloc(p, malloc_size);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-realloc-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_realloc(p, malloc_size);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-mallocn-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-mallocn-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-reallocn-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-reallocn-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-malloc_aligned-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-malloc_aligned-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+ CHECK_BODY("uninit-realloc_aligned-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+ CHECK_BODY("uninit-realloc_aligned-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result = check_debug_fill_uninit(p, malloc_size);
+ malloc_size *= 3;
+ p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
+ result &= check_debug_fill_uninit(p, malloc_size);
+ mi_free(p);
+ });
+
+
+ CHECK_BODY("fill-freed-small", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ mi_free(p);
+ // First sizeof(void*) bytes will contain housekeeping data, skip these
+ result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
+ });
+ CHECK_BODY("fill-freed-large", {
+ size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+ uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+ mi_free(p);
+ // First sizeof(void*) bytes will contain housekeeping data, skip these
+ result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
+ });
+#endif
+
+ // ---------------------------------------------------
+ // Done
+ // ---------------------------------------------------[]
+ return print_test_summary();
+}
+
+// ---------------------------------------------------------------------------
+// Helper functions
+// ---------------------------------------------------------------------------
+bool check_zero_init(uint8_t* p, size_t size) {
+ if(!p)
+ return false;
+ bool result = true;
+ for (size_t i = 0; i < size; ++i) {
+ result &= p[i] == 0;
+ }
+ return result;
+}
+
+#if MI_DEBUG >= 2
+bool check_debug_fill_uninit(uint8_t* p, size_t size) {
+ if(!p)
+ return false;
+
+ bool result = true;
+ for (size_t i = 0; i < size; ++i) {
+ result &= p[i] == MI_DEBUG_UNINIT;
+ }
+ return result;
+}
+
+bool check_debug_fill_freed(uint8_t* p, size_t size) {
+ if(!p)
+ return false;
+
+ bool result = true;
+ for (size_t i = 0; i < size; ++i) {
+ result &= p[i] == MI_DEBUG_FREED;
+ }
+ return result;
+}
+#endif
diff --git a/test/test-api.c b/test/test-api.c
index d3344928..7ce6f111 100644
--- a/test/test-api.c
+++ b/test/test-api.c
@@ -4,6 +4,9 @@ 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(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
+#endif
/*
Testing allocators is difficult as bugs may only surface after particular
@@ -20,7 +23,6 @@ we therefore test the API over various inputs. Please add more tests :-)
[1] https://github.com/daanx/mimalloc-bench
*/
-#include
#include
#include
#include
@@ -32,47 +34,22 @@ we therefore test the API over various inputs. Please add more tests :-)
#include "mimalloc.h"
// #include "mimalloc-internal.h"
+#include "mimalloc-types.h" // for MI_DEBUG
-// ---------------------------------------------------------------------------
-// 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); })
+#include "testhelper.h"
// ---------------------------------------------------------------------------
// Test functions
// ---------------------------------------------------------------------------
-bool test_heap1();
-bool test_heap2();
-bool test_stl_allocator1();
-bool test_stl_allocator2();
+bool test_heap1(void);
+bool test_heap2(void);
+bool test_stl_allocator1(void);
+bool test_stl_allocator2(void);
// ---------------------------------------------------------------------------
// Main testing
// ---------------------------------------------------------------------------
-int main() {
+int main(void) {
mi_option_disable(mi_option_verbose);
// ---------------------------------------------------
@@ -83,7 +60,7 @@ int main() {
void* p = mi_malloc(0); mi_free(p);
});
CHECK_BODY("malloc-nomem1",{
- result = (mi_malloc(SIZE_MAX/2) == NULL);
+ result = (mi_malloc((size_t)PTRDIFF_MAX + (size_t)1) == NULL);
});
CHECK_BODY("malloc-null",{
mi_free(NULL);
@@ -155,6 +132,28 @@ int main() {
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-aligned6", {
+ bool ok = true;
+ for (size_t align = 1; align <= MI_ALIGNMENT_MAX && ok; align *= 2) {
+ void* ps[8];
+ for (int i = 0; i < 8 && ok; i++) {
+ ps[i] = mi_malloc_aligned(align*13 /*size*/, align);
+ if (ps[i] == NULL || (uintptr_t)(ps[i]) % align != 0) {
+ ok = false;
+ }
+ }
+ for (int i = 0; i < 8 && ok; i++) {
+ mi_free(ps[i]);
+ }
+ }
+ result = ok;
+ });
+ CHECK_BODY("malloc-aligned7", {
+ void* p = mi_malloc_aligned(1024,MI_ALIGNMENT_MAX); mi_free(p);
+ });
+ CHECK_BODY("malloc-aligned8", {
+ void* p = mi_malloc_aligned(1024,2*MI_ALIGNMENT_MAX); 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);
});
@@ -169,8 +168,8 @@ int main() {
ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p);
}
result = ok;
- });
-
+ });
+
// ---------------------------------------------------
// Heaps
// ---------------------------------------------------
@@ -194,10 +193,7 @@ int main() {
// ---------------------------------------------------
// Done
// ---------------------------------------------------[]
- fprintf(stderr,"\n\n---------------------------------------------\n"
- "succeeded: %i\n"
- "failed : %i\n\n", ok, failed);
- return failed;
+ return print_test_summary();
}
// ---------------------------------------------------
diff --git a/test/test-stress.c b/test/test-stress.c
index d45e9899..498b7ec6 100644
--- a/test/test-stress.c
+++ b/test/test-stress.c
@@ -25,7 +25,7 @@ terms of the MIT license.
//
// argument defaults
static int THREADS = 32; // more repeatable if THREADS <= #processors
-static int SCALE = 10; // scaling factor
+static int SCALE = 25; // scaling factor
static int ITER = 50; // N full iterations destructing and re-creating all threads
// static int THREADS = 8; // more repeatable if THREADS <= #processors
diff --git a/test/testhelper.h b/test/testhelper.h
new file mode 100644
index 00000000..46d63a00
--- /dev/null
+++ b/test/testhelper.h
@@ -0,0 +1,49 @@
+/* ----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------*/
+#ifndef TESTHELPER_H_
+#define TESTHELPER_H_
+
+#include
+
+// ---------------------------------------------------------------------------
+// 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); })
+
+// Print summary of test. Return value can be directly use as a return value for main().
+static inline int print_test_summary(void)
+{
+ fprintf(stderr,"\n\n---------------------------------------------\n"
+ "succeeded: %i\n"
+ "failed : %i\n\n", ok, failed);
+ return failed;
+}
+
+#endif // TESTHELPER_H_