merge from dev
This commit is contained in:
commit
8857f0a5ef
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,7 +1,8 @@
|
|||||||
ide/vs2017/*.db
|
ide/vs20??/*.db
|
||||||
ide/vs2017/*.opendb
|
ide/vs20??/*.opendb
|
||||||
ide/vs2017/*.user
|
ide/vs20??/*.user
|
||||||
ide/vs2017/.vs
|
ide/vs20??/*.vcxproj.filters
|
||||||
|
ide/vs20??/.vs
|
||||||
out/
|
out/
|
||||||
docs/
|
docs/
|
||||||
*.zip
|
*.zip
|
||||||
|
@ -4,12 +4,14 @@ include("cmake/mimalloc-config-version.cmake")
|
|||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
option(MI_OVERRIDE "Override the standard malloc interface" ON)
|
option(MI_OVERRIDE "Override the standard malloc interface" ON)
|
||||||
option(MI_INTERPOSE "Use interpose to override standard malloc on macOS" ON)
|
option(MI_INTERPOSE "Use interpose to override standard malloc on macOS" ON)
|
||||||
option(MI_SEE_ASM "Generate assembly files" OFF)
|
option(MI_SEE_ASM "Generate assembly files" OFF)
|
||||||
option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode" OFF)
|
option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode" OFF)
|
||||||
option(MI_USE_CXX "Use the C++ compiler to compile the library" OFF)
|
option(MI_USE_CXX "Use the C++ compiler to compile the library" OFF)
|
||||||
option(MI_SECURE "Use security mitigations (like guard pages and randomization)" OFF)
|
option(MI_SECURE "Use security mitigations (like guard pages and randomization)" OFF)
|
||||||
|
option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF)
|
||||||
|
option(MI_BUILD_TESTS "Build test executables" ON)
|
||||||
|
|
||||||
set(mi_install_dir "lib/mimalloc-${mi_version}")
|
set(mi_install_dir "lib/mimalloc-${mi_version}")
|
||||||
|
|
||||||
@ -87,7 +89,12 @@ endif()
|
|||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
||||||
list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -ftls-model=initial-exec)
|
list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas)
|
||||||
|
if(MI_LOCAL_DYNAMIC_TLS MATCHES "ON")
|
||||||
|
list(APPEND mi_cflags -ftls-model=local-dynamic)
|
||||||
|
else()
|
||||||
|
list(APPEND mi_cflags -ftls-model=initial-exec)
|
||||||
|
endif()
|
||||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||||
list(APPEND mi_cflags -Wno-invalid-memory-model)
|
list(APPEND mi_cflags -Wno-invalid-memory-model)
|
||||||
list(APPEND mi_cflags -fvisibility=hidden)
|
list(APPEND mi_cflags -fvisibility=hidden)
|
||||||
@ -95,7 +102,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo"))
|
if(NOT(CMAKE_BUILD_TYPE MATCHES "Release|release|RelWithDebInfo|relwithdebinfo"))
|
||||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type)
|
string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type)
|
||||||
set(mi_basename "mimalloc-${build_type}")
|
set(mi_basename "mimalloc-${build_type}")
|
||||||
else()
|
else()
|
||||||
@ -113,6 +120,10 @@ if(WIN32)
|
|||||||
list(APPEND mi_libraries psapi shell32 user32)
|
list(APPEND mi_libraries psapi shell32 user32)
|
||||||
else()
|
else()
|
||||||
list(APPEND mi_libraries pthread)
|
list(APPEND mi_libraries pthread)
|
||||||
|
find_library(LIBRT rt)
|
||||||
|
if(LIBRT)
|
||||||
|
list(APPEND mi_libraries ${LIBRT})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -122,7 +133,7 @@ endif()
|
|||||||
|
|
||||||
# shared library
|
# shared library
|
||||||
add_library(mimalloc SHARED ${mi_sources})
|
add_library(mimalloc SHARED ${mi_sources})
|
||||||
set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} NO_SONAME "YES" OUTPUT_NAME ${mi_basename} )
|
set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} OUTPUT_NAME ${mi_basename} )
|
||||||
target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_SHARED_LIB MI_SHARED_LIB_EXPORT)
|
target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_SHARED_LIB MI_SHARED_LIB_EXPORT)
|
||||||
target_compile_options(mimalloc PRIVATE ${mi_cflags})
|
target_compile_options(mimalloc PRIVATE ${mi_cflags})
|
||||||
target_link_libraries(mimalloc PUBLIC ${mi_libraries})
|
target_link_libraries(mimalloc PUBLIC ${mi_libraries})
|
||||||
@ -157,14 +168,22 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# install static and shared library, and the include files
|
# install static and shared library, and the include files
|
||||||
install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY NAMELINK_SKIP)
|
install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY)
|
||||||
install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_dir})
|
install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_dir})
|
||||||
install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include)
|
install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include)
|
||||||
install(FILES include/mimalloc-override.h DESTINATION ${mi_install_dir}/include)
|
install(FILES include/mimalloc-override.h DESTINATION ${mi_install_dir}/include)
|
||||||
|
install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_dir}/include)
|
||||||
install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_dir}/cmake)
|
install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_dir}/cmake)
|
||||||
install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_dir}/cmake)
|
install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_dir}/cmake)
|
||||||
install(EXPORT mimalloc DESTINATION ${mi_install_dir}/cmake)
|
install(EXPORT mimalloc DESTINATION ${mi_install_dir}/cmake)
|
||||||
install(FILES "$<TARGET_FILE:mimalloc>" DESTINATION lib) # duplicate the .so in the lib directory (unversioned)
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
# install a symlink in the /usr/local/lib to the versioned library
|
||||||
|
set(mi_symlink "${CMAKE_SHARED_MODULE_PREFIX}${mi_basename}${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||||
|
set(mi_soname "mimalloc-${mi_version}/${mi_symlink}.${mi_version}")
|
||||||
|
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${mi_soname} ${mi_symlink} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${mi_install_dir}/..)")
|
||||||
|
install(CODE "MESSAGE(\"-- Symbolic link: ${CMAKE_INSTALL_PREFIX}/lib/${mi_symlink} -> ${mi_soname}\")")
|
||||||
|
endif()
|
||||||
|
|
||||||
# single object file for more predictable static overriding
|
# single object file for more predictable static overriding
|
||||||
add_library(mimalloc-obj OBJECT src/static.c)
|
add_library(mimalloc-obj OBJECT src/static.c)
|
||||||
@ -187,21 +206,24 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/mimalloc-obj.dir/src/static
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# API surface testing
|
# API surface testing
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
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)
|
|
||||||
|
|
||||||
add_executable(mimalloc-test-stress test/test-stress.c)
|
if (MI_BUILD_TESTS MATCHES "ON")
|
||||||
target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines})
|
add_executable(mimalloc-test-api test/test-api.c)
|
||||||
target_compile_options(mimalloc-test-stress PRIVATE ${mi_cflags})
|
target_compile_definitions(mimalloc-test-api PRIVATE ${mi_defines})
|
||||||
target_include_directories(mimalloc-test-stress PRIVATE include)
|
target_compile_options(mimalloc-test-api PRIVATE ${mi_cflags})
|
||||||
target_link_libraries(mimalloc-test-stress PRIVATE mimalloc-static)
|
target_include_directories(mimalloc-test-api PRIVATE include)
|
||||||
|
target_link_libraries(mimalloc-test-api PRIVATE mimalloc-static ${mi_libraries})
|
||||||
|
|
||||||
enable_testing()
|
add_executable(mimalloc-test-stress test/test-stress.c)
|
||||||
add_test(test_api, mimalloc-test-api)
|
target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines})
|
||||||
add_test(test_stress, mimalloc-test-stress)
|
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-static ${mi_libraries})
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
add_test(test_api, mimalloc-test-api)
|
||||||
|
add_test(test_stress, mimalloc-test-stress)
|
||||||
|
endif()
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Set override properties
|
# Set override properties
|
||||||
|
Binary file not shown.
Binary file not shown.
BIN
bin/mimalloc-redirect32.dll
Normal file
BIN
bin/mimalloc-redirect32.dll
Normal file
Binary file not shown.
BIN
bin/mimalloc-redirect32.lib
Normal file
BIN
bin/mimalloc-redirect32.lib
Normal file
Binary file not shown.
@ -48,20 +48,23 @@ Notable aspects of the design include:
|
|||||||
- __first-class heaps__: efficiently create and use multiple heaps to allocate across different regions.
|
- __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.
|
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
|
- __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 16.7% waste in allocation sizes),
|
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.
|
and has no internal points of contention using only atomic operations.
|
||||||
- __fast__: In our benchmarks (see [below](#performance)),
|
- __fast__: In our benchmarks (see [below](#performance)),
|
||||||
_mimalloc_ always outperforms all other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc),
|
_mimalloc_ always 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
|
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.
|
is that it does consistently well over a wide range of benchmarks.
|
||||||
|
|
||||||
You can read more on the design of _mimalloc_ in the upcoming technical report
|
You can read more on the design of _mimalloc_ in the
|
||||||
|
[technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action)
|
||||||
which also has detailed benchmark results.
|
which also has detailed benchmark results.
|
||||||
|
|
||||||
|
|
||||||
Further information:
|
Further information:
|
||||||
|
|
||||||
- \ref build
|
- \ref build
|
||||||
- \ref using
|
- \ref using
|
||||||
|
- \ref environment
|
||||||
- \ref overrides
|
- \ref overrides
|
||||||
- \ref bench
|
- \ref bench
|
||||||
- \ref malloc
|
- \ref malloc
|
||||||
@ -293,31 +296,34 @@ size_t mi_good_size(size_t size);
|
|||||||
/// resource usage by calling this every once in a while.
|
/// resource usage by calling this every once in a while.
|
||||||
void mi_collect(bool force);
|
void mi_collect(bool force);
|
||||||
|
|
||||||
/// Print statistics.
|
/// Print the main statistics.
|
||||||
/// @param out Output file. Use \a NULL for \a stderr.
|
/// @param out Output function. Use \a NULL for outputting to \a stderr.
|
||||||
///
|
///
|
||||||
/// Most detailed when using a debug build.
|
/// Most detailed when using a debug build.
|
||||||
void mi_stats_print(FILE* out);
|
void mi_stats_print(mi_output_fun* out);
|
||||||
|
|
||||||
/// Reset statistics.
|
/// Reset statistics.
|
||||||
void mi_stats_reset();
|
void mi_stats_reset(void);
|
||||||
|
|
||||||
|
/// Merge thread local statistics with the main statistics and reset.
|
||||||
|
void mi_stats_merge(void);
|
||||||
|
|
||||||
/// Initialize mimalloc on a thread.
|
/// Initialize mimalloc on a thread.
|
||||||
/// Should not be used as on most systems (pthreads, windows) this is done
|
/// Should not be used as on most systems (pthreads, windows) this is done
|
||||||
/// automatically.
|
/// automatically.
|
||||||
void mi_thread_init();
|
void mi_thread_init(void);
|
||||||
|
|
||||||
/// Uninitialize mimalloc on a thread.
|
/// Uninitialize mimalloc on a thread.
|
||||||
/// Should not be used as on most systems (pthreads, windows) this is done
|
/// Should not be used as on most systems (pthreads, windows) this is done
|
||||||
/// automatically. Ensures that any memory that is not freed yet (but will
|
/// automatically. Ensures that any memory that is not freed yet (but will
|
||||||
/// be freed by other threads in the future) is properly handled.
|
/// be freed by other threads in the future) is properly handled.
|
||||||
void mi_thread_done();
|
void mi_thread_done(void);
|
||||||
|
|
||||||
/// Print out heap statistics for this thread.
|
/// Print out heap statistics for this thread.
|
||||||
/// @param out Output file. Use \a NULL for \a stderr.
|
/// @param out Output function. Use \a NULL for outputting to \a stderr.
|
||||||
///
|
///
|
||||||
/// Most detailed when using a debug build.
|
/// Most detailed when using a debug build.
|
||||||
void mi_thread_stats_print(FILE* out);
|
void mi_thread_stats_print(mi_output_fun* out);
|
||||||
|
|
||||||
/// Type of deferred free functions.
|
/// Type of deferred free functions.
|
||||||
/// @param force If \a true all outstanding items should be freed.
|
/// @param force If \a true all outstanding items should be freed.
|
||||||
@ -342,6 +348,45 @@ typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat);
|
|||||||
/// At most one \a deferred_free function can be active.
|
/// At most one \a deferred_free function can be active.
|
||||||
void mi_register_deferred_free(mi_deferred_free_fun* deferred_free);
|
void mi_register_deferred_free(mi_deferred_free_fun* deferred_free);
|
||||||
|
|
||||||
|
/// Type of output functions.
|
||||||
|
/// @param msg Message to output.
|
||||||
|
///
|
||||||
|
/// @see mi_register_output()
|
||||||
|
typedef void (mi_output_fun)(const char* msg);
|
||||||
|
|
||||||
|
/// Register an output function.
|
||||||
|
/// @param out The output function, use `NULL` to output to stdout.
|
||||||
|
///
|
||||||
|
/// The `out` function is called to output any information from mimalloc,
|
||||||
|
/// like verbose or warning messages.
|
||||||
|
void mi_register_output(mi_output_fun* out) mi_attr_noexcept;
|
||||||
|
|
||||||
|
/// Is a pointer part of our heap?
|
||||||
|
/// @param p The pointer to check.
|
||||||
|
/// @returns \a true if this is a pointer into our heap.
|
||||||
|
/// This function is relatively fast.
|
||||||
|
bool mi_is_in_heap_region(const void* p);
|
||||||
|
|
||||||
|
/// Reserve \a pages of huge OS pages (1GiB) but stops after at most `max_secs` seconds.
|
||||||
|
/// @param pages The number of 1GiB pages to reserve.
|
||||||
|
/// @param max_secs Maximum number of seconds to try reserving.
|
||||||
|
/// @param pages_reserved If not \a NULL, it is set to the actual number of pages that were reserved.
|
||||||
|
/// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out.
|
||||||
|
///
|
||||||
|
/// The reserved memory is used by mimalloc to satisfy allocations.
|
||||||
|
/// May quit before \a max_secs are expired if it estimates it will take more than
|
||||||
|
/// 1.5 times \a max_secs. 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.
|
||||||
|
int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved);
|
||||||
|
|
||||||
|
/// Is the C runtime \a malloc API redirected?
|
||||||
|
/// @returns \a true if all malloc API calls are redirected to mimalloc.
|
||||||
|
///
|
||||||
|
/// Currenty only used on Windows.
|
||||||
|
bool mi_is_redirected();
|
||||||
|
|
||||||
|
|
||||||
/// \}
|
/// \}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@ -443,10 +488,18 @@ mi_heap_t* mi_heap_get_default();
|
|||||||
/// except by exiting the thread.
|
/// except by exiting the thread.
|
||||||
mi_heap_t* mi_heap_get_backing();
|
mi_heap_t* mi_heap_get_backing();
|
||||||
|
|
||||||
|
/// Release outstanding resources in a specific heap.
|
||||||
|
void mi_heap_collect(mi_heap_t* heap, bool force);
|
||||||
|
|
||||||
/// Allocate in a specific heap.
|
/// Allocate in a specific heap.
|
||||||
/// @see mi_malloc()
|
/// @see mi_malloc()
|
||||||
void* mi_heap_malloc(mi_heap_t* heap, size_t size);
|
void* mi_heap_malloc(mi_heap_t* heap, size_t size);
|
||||||
|
|
||||||
|
/// Allocate a small object in a specific heap.
|
||||||
|
/// \a size must be smaller or equal to MI_SMALL_SIZE_MAX().
|
||||||
|
/// @see mi_malloc()
|
||||||
|
void* mi_heap_malloc_small(mi_heap_t* heap, size_t size);
|
||||||
|
|
||||||
/// Allocate zero-initialized in a specific heap.
|
/// Allocate zero-initialized in a specific heap.
|
||||||
/// @see mi_zalloc()
|
/// @see mi_zalloc()
|
||||||
void* mi_heap_zalloc(mi_heap_t* heap, size_t size);
|
void* mi_heap_zalloc(mi_heap_t* heap, size_t size);
|
||||||
@ -486,6 +539,34 @@ void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_
|
|||||||
|
|
||||||
/// \}
|
/// \}
|
||||||
|
|
||||||
|
|
||||||
|
/// \defgroup zeroinit Zero initialized re-allocation
|
||||||
|
///
|
||||||
|
/// The zero-initialized re-allocations are only valid on memory that was
|
||||||
|
/// originally allocated with zero initialization too.
|
||||||
|
/// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
|
||||||
|
/// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
|
||||||
|
///
|
||||||
|
/// \{
|
||||||
|
|
||||||
|
void* mi_rezalloc(void* p, size_t newsize);
|
||||||
|
void* mi_recalloc(void* p, size_t newcount, size_t size) ;
|
||||||
|
|
||||||
|
void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment);
|
||||||
|
void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset);
|
||||||
|
void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment);
|
||||||
|
void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset);
|
||||||
|
|
||||||
|
void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize);
|
||||||
|
void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size);
|
||||||
|
|
||||||
|
void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, 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_heap_recalloc_aligned(mi_heap_t* heap, 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);
|
||||||
|
|
||||||
|
/// \}
|
||||||
|
|
||||||
/// \defgroup typed Typed Macros
|
/// \defgroup typed Typed Macros
|
||||||
///
|
///
|
||||||
/// Typed allocation macros
|
/// Typed allocation macros
|
||||||
@ -532,6 +613,9 @@ void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_
|
|||||||
/// Re-allocate to \a count blocks of type \a tp in a heap \a hp.
|
/// Re-allocate to \a count blocks of type \a tp in a heap \a hp.
|
||||||
#define mi_heap_reallocn_tp(hp,p,tp,count) ((tp*)mi_heap_reallocn(p,count,sizeof(tp)))
|
#define mi_heap_reallocn_tp(hp,p,tp,count) ((tp*)mi_heap_reallocn(p,count,sizeof(tp)))
|
||||||
|
|
||||||
|
/// Re-allocate to \a count zero initialized blocks of type \a tp in a heap \a hp.
|
||||||
|
#define mi_heap_recalloc_tp(hp,p,tp,count) ((tp*)mi_heap_recalloc(p,count,sizeof(tp)))
|
||||||
|
|
||||||
/// \}
|
/// \}
|
||||||
|
|
||||||
/// \defgroup analysis Heap Introspection
|
/// \defgroup analysis Heap Introspection
|
||||||
@ -614,14 +698,17 @@ typedef enum mi_option_e {
|
|||||||
mi_option_show_errors, ///< Print error messages to `stderr`.
|
mi_option_show_errors, ///< Print error messages to `stderr`.
|
||||||
mi_option_verbose, ///< Print verbose messages to `stderr`.
|
mi_option_verbose, ///< Print verbose messages to `stderr`.
|
||||||
// the following options are experimental
|
// the following options are experimental
|
||||||
mi_option_secure, ///< Experimental
|
|
||||||
mi_option_eager_commit, ///< Eagerly commit segments (4MiB) (enabled by default).
|
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_eager_region_commit, ///< Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
|
||||||
mi_option_large_os_pages, ///< Use large OS pages if possible
|
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_page_reset, ///< Reset page memory when it becomes free.
|
mi_option_page_reset, ///< Reset page memory when it becomes free.
|
||||||
mi_option_cache_reset, ///< Reset segment memory when a segment is cached.
|
mi_option_cache_reset, ///< Reset segment memory when a segment is cached.
|
||||||
mi_option_reset_decommits, ///< Experimental
|
mi_option_reset_decommits, ///< Experimental
|
||||||
mi_option_reset_discards, ///< Experimental
|
mi_option_eager_commit_delay, ///< Experimental
|
||||||
|
mi_option_segment_reset, ///< Experimental
|
||||||
|
mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory
|
||||||
_mi_option_last
|
_mi_option_last
|
||||||
} mi_option_t;
|
} mi_option_t;
|
||||||
|
|
||||||
@ -647,6 +734,8 @@ void mi_option_set_default(mi_option_t option, long value);
|
|||||||
void* mi_recalloc(void* p, size_t count, size_t size);
|
void* mi_recalloc(void* p, size_t count, size_t size);
|
||||||
size_t mi_malloc_size(const void* p);
|
size_t mi_malloc_size(const void* p);
|
||||||
size_t mi_malloc_usable_size(const void *p);
|
size_t mi_malloc_usable_size(const void *p);
|
||||||
|
|
||||||
|
/// Just as `free` but also checks if the pointer `p` belongs to our heap.
|
||||||
void mi_cfree(void* p);
|
void mi_cfree(void* p);
|
||||||
|
|
||||||
int mi_posix_memalign(void** p, size_t alignment, size_t size);
|
int mi_posix_memalign(void** p, size_t alignment, size_t size);
|
||||||
@ -804,9 +893,12 @@ completely and redirect all calls to the _mimalloc_ library instead.
|
|||||||
|
|
||||||
See \ref overrides for more info.
|
See \ref overrides for more info.
|
||||||
|
|
||||||
## Environment Options
|
*/
|
||||||
|
|
||||||
You can set further options either programmatically (using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
|
/*! \page environment Environment Options
|
||||||
|
|
||||||
|
You can set further options either programmatically
|
||||||
|
(using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
|
||||||
or via environment variables.
|
or via environment variables.
|
||||||
|
|
||||||
- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
|
- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
|
||||||
@ -869,19 +961,23 @@ Note: unfortunately, at this time, dynamic overriding on macOS seems broken but
|
|||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
On Windows you need to link your program explicitly with the mimalloc
|
On Windows you need to link your program explicitly with the mimalloc
|
||||||
DLL, and use the C-runtime library as a DLL (the `/MD` or `/MDd` switch).
|
DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
|
||||||
To ensure the mimalloc DLL gets loaded it is easiest to insert some
|
Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available
|
||||||
|
in the same folder as the mimalloc DLL at runtime (as it as referred to by the mimalloc DLL).
|
||||||
|
The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc.
|
||||||
|
|
||||||
|
To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some
|
||||||
call to the mimalloc API in the `main` function, like `mi_version()`
|
call to the mimalloc API in the `main` function, like `mi_version()`
|
||||||
(or use the `/INCLUDE:mi_version` switch on the linker)
|
(or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project
|
||||||
|
for an example on how to use this.
|
||||||
|
|
||||||
Due to the way mimalloc intercepts the standard malloc at runtime, it is best
|
The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic
|
||||||
to link to the mimalloc import library first on the command line so it gets
|
overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc successfully redirected.
|
||||||
loaded right after the universal C runtime DLL (`ucrtbase`). See
|
|
||||||
the `mimalloc-override-test` project for an example.
|
|
||||||
|
|
||||||
Note: the current overriding on Windows works for most programs but some programs still have
|
(Note: in principle, it should be possible to patch existing executables
|
||||||
trouble -- the `dev-exp` branch contains a newer way of overriding that is more
|
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the mimalloc DLL into
|
||||||
robust; try this out if you experience troubles.
|
the import table (and putting `mimalloc-redirect.dll` in the same folder)
|
||||||
|
Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)).
|
||||||
|
|
||||||
## Static override
|
## Static override
|
||||||
|
|
||||||
@ -897,8 +993,6 @@ object file. For example:
|
|||||||
gcc -o myprogram mimalloc-override.o myfile1.c ...
|
gcc -o myprogram mimalloc-override.o myfile1.c ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## List of Overrides:
|
## List of Overrides:
|
||||||
|
|
||||||
The specific functions that get redirected to the _mimalloc_ library are:
|
The specific functions that get redirected to the _mimalloc_ library are:
|
||||||
|
@ -121,6 +121,9 @@ Typedefs</h2></td></tr>
|
|||||||
<tr class="memitem:ga22213691c3ce5ab4d91b24aff1023529"><td class="memItemLeft" align="right" valign="top">typedef void() </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat)</td></tr>
|
<tr class="memitem:ga22213691c3ce5ab4d91b24aff1023529"><td class="memItemLeft" align="right" valign="top">typedef void() </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat)</td></tr>
|
||||||
<tr class="memdesc:ga22213691c3ce5ab4d91b24aff1023529"><td class="mdescLeft"> </td><td class="mdescRight">Type of deferred free functions. <a href="#ga22213691c3ce5ab4d91b24aff1023529">More...</a><br /></td></tr>
|
<tr class="memdesc:ga22213691c3ce5ab4d91b24aff1023529"><td class="mdescLeft"> </td><td class="mdescRight">Type of deferred free functions. <a href="#ga22213691c3ce5ab4d91b24aff1023529">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga22213691c3ce5ab4d91b24aff1023529"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga22213691c3ce5ab4d91b24aff1023529"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga2bed6d40b74591a67f81daea4b4a246f"><td class="memItemLeft" align="right" valign="top">typedef void() </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a>(const char *msg)</td></tr>
|
||||||
|
<tr class="memdesc:ga2bed6d40b74591a67f81daea4b4a246f"><td class="mdescLeft"> </td><td class="mdescRight">Type of output functions. <a href="#ga2bed6d40b74591a67f81daea4b4a246f">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga2bed6d40b74591a67f81daea4b4a246f"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
</table><table class="memberdecls">
|
</table><table class="memberdecls">
|
||||||
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
|
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
|
||||||
Functions</h2></td></tr>
|
Functions</h2></td></tr>
|
||||||
@ -139,24 +142,39 @@ Functions</h2></td></tr>
|
|||||||
<tr class="memitem:ga421430e2226d7d468529cec457396756"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a> (bool force)</td></tr>
|
<tr class="memitem:ga421430e2226d7d468529cec457396756"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a> (bool force)</td></tr>
|
||||||
<tr class="memdesc:ga421430e2226d7d468529cec457396756"><td class="mdescLeft"> </td><td class="mdescRight">Eagerly free memory. <a href="#ga421430e2226d7d468529cec457396756">More...</a><br /></td></tr>
|
<tr class="memdesc:ga421430e2226d7d468529cec457396756"><td class="mdescLeft"> </td><td class="mdescRight">Eagerly free memory. <a href="#ga421430e2226d7d468529cec457396756">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga421430e2226d7d468529cec457396756"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga421430e2226d7d468529cec457396756"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga6bb821ca1b664b452112c0e17b15fcf1"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga6bb821ca1b664b452112c0e17b15fcf1">mi_stats_print</a> (FILE *out)</td></tr>
|
<tr class="memitem:ga8ca07ccff283956d71f48272f4fd5c01"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01">mi_stats_print</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out)</td></tr>
|
||||||
<tr class="memdesc:ga6bb821ca1b664b452112c0e17b15fcf1"><td class="mdescLeft"> </td><td class="mdescRight">Print statistics. <a href="#ga6bb821ca1b664b452112c0e17b15fcf1">More...</a><br /></td></tr>
|
<tr class="memdesc:ga8ca07ccff283956d71f48272f4fd5c01"><td class="mdescLeft"> </td><td class="mdescRight">Print the main statistics. <a href="#ga8ca07ccff283956d71f48272f4fd5c01">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga6bb821ca1b664b452112c0e17b15fcf1"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga8ca07ccff283956d71f48272f4fd5c01"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga9883b8a059aed7eb0888a01ec1461161"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga9883b8a059aed7eb0888a01ec1461161">mi_stats_reset</a> ()</td></tr>
|
<tr class="memitem:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a> (void)</td></tr>
|
||||||
<tr class="memdesc:ga9883b8a059aed7eb0888a01ec1461161"><td class="mdescLeft"> </td><td class="mdescRight">Reset statistics. <a href="#ga9883b8a059aed7eb0888a01ec1461161">More...</a><br /></td></tr>
|
<tr class="memdesc:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="mdescLeft"> </td><td class="mdescRight">Reset statistics. <a href="#ga3bb8468b8cfcc6e2a61d98aee85c5f99">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga9883b8a059aed7eb0888a01ec1461161"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga9398517f01a1ec971244aa0db084ea46"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga9398517f01a1ec971244aa0db084ea46">mi_thread_init</a> ()</td></tr>
|
<tr class="memitem:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">mi_stats_merge</a> (void)</td></tr>
|
||||||
<tr class="memdesc:ga9398517f01a1ec971244aa0db084ea46"><td class="mdescLeft"> </td><td class="mdescRight">Initialize mimalloc on a thread. <a href="#ga9398517f01a1ec971244aa0db084ea46">More...</a><br /></td></tr>
|
<tr class="memdesc:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="mdescLeft"> </td><td class="mdescRight">Merge thread local statistics with the main statistics and reset. <a href="#ga854b1de8cb067c7316286c28b2fcd3d1">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga9398517f01a1ec971244aa0db084ea46"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:gac0f4849256aaf677f334690952c6ebbd"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gac0f4849256aaf677f334690952c6ebbd">mi_thread_done</a> ()</td></tr>
|
<tr class="memitem:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">mi_thread_init</a> (void)</td></tr>
|
||||||
<tr class="memdesc:gac0f4849256aaf677f334690952c6ebbd"><td class="mdescLeft"> </td><td class="mdescRight">Uninitialize mimalloc on a thread. <a href="#gac0f4849256aaf677f334690952c6ebbd">More...</a><br /></td></tr>
|
<tr class="memdesc:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="mdescLeft"> </td><td class="mdescRight">Initialize mimalloc on a thread. <a href="#gaf8e73efc2cbca9ebfdfb166983a04c17">More...</a><br /></td></tr>
|
||||||
<tr class="separator:gac0f4849256aaf677f334690952c6ebbd"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga490826cbd7c494acc9fe69be23f018ac"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga490826cbd7c494acc9fe69be23f018ac">mi_thread_stats_print</a> (FILE *out)</td></tr>
|
<tr class="memitem:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a> (void)</td></tr>
|
||||||
<tr class="memdesc:ga490826cbd7c494acc9fe69be23f018ac"><td class="mdescLeft"> </td><td class="mdescRight">Print out heap statistics for this thread. <a href="#ga490826cbd7c494acc9fe69be23f018ac">More...</a><br /></td></tr>
|
<tr class="memdesc:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="mdescLeft"> </td><td class="mdescRight">Uninitialize mimalloc on a thread. <a href="#ga0ae4581e85453456a0d658b2b98bf7bf">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga490826cbd7c494acc9fe69be23f018ac"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga489670a15d1a257ab4639e645ee4612a"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga489670a15d1a257ab4639e645ee4612a">mi_thread_stats_print</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out)</td></tr>
|
||||||
|
<tr class="memdesc:ga489670a15d1a257ab4639e645ee4612a"><td class="mdescLeft"> </td><td class="mdescRight">Print out heap statistics for this thread. <a href="#ga489670a15d1a257ab4639e645ee4612a">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga489670a15d1a257ab4639e645ee4612a"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2">mi_register_deferred_free</a> (<a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a> *deferred_free)</td></tr>
|
<tr class="memitem:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2">mi_register_deferred_free</a> (<a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a> *deferred_free)</td></tr>
|
||||||
<tr class="memdesc:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="mdescLeft"> </td><td class="mdescRight">Register a deferred free function. <a href="#ga24dc9cc6fca8daa2aa30aa8025467ce2">More...</a><br /></td></tr>
|
<tr class="memdesc:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="mdescLeft"> </td><td class="mdescRight">Register a deferred free function. <a href="#ga24dc9cc6fca8daa2aa30aa8025467ce2">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5">mi_register_output</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out) mi_attr_noexcept</td></tr>
|
||||||
|
<tr class="memdesc:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="mdescLeft"> </td><td class="mdescRight">Register an output function. <a href="#ga84a0c8b401e42eb5b1bce156852f44c5">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a> (const void *p)</td></tr>
|
||||||
|
<tr class="memdesc:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="mdescLeft"> </td><td class="mdescRight">Is a pointer part of our heap? <a href="#ga5f071b10d4df1c3658e04e7fd67a94e6">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga2664f36a2dd557741c429cb799f04641"><td class="memItemLeft" align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2664f36a2dd557741c429cb799f04641">mi_reserve_huge_os_pages</a> (size_t pages, double max_secs, size_t *pages_reserved)</td></tr>
|
||||||
|
<tr class="memdesc:ga2664f36a2dd557741c429cb799f04641"><td class="mdescLeft"> </td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) but stops after at most <code>max_secs</code> seconds. <a href="#ga2664f36a2dd557741c429cb799f04641">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga2664f36a2dd557741c429cb799f04641"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:gaad25050b19f30cd79397b227e0157a3f"><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a> ()</td></tr>
|
||||||
|
<tr class="memdesc:gaad25050b19f30cd79397b227e0157a3f"><td class="mdescLeft"> </td><td class="mdescRight">Is the C runtime <em>malloc</em> API redirected? <a href="#gaad25050b19f30cd79397b227e0157a3f">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:gaad25050b19f30cd79397b227e0157a3f"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
</table>
|
</table>
|
||||||
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
|
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
|
||||||
<p>Extended functionality. </p>
|
<p>Extended functionality. </p>
|
||||||
@ -200,6 +218,29 @@ Functions</h2></td></tr>
|
|||||||
</dl>
|
</dl>
|
||||||
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2" title="Register a deferred free function.">mi_register_deferred_free</a> </dd></dl>
|
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2" title="Register a deferred free function.">mi_register_deferred_free</a> </dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga2bed6d40b74591a67f81daea4b4a246f"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga2bed6d40b74591a67f81daea4b4a246f">◆ </a></span>mi_output_fun</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">typedef void() mi_output_fun(const char *msg)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Type of output functions. </p>
|
||||||
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
|
<table class="params">
|
||||||
|
<tr><td class="paramname">msg</td><td>Message to output.</td></tr>
|
||||||
|
</table>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5" title="Register an output function.">mi_register_output()</a> </dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2 class="groupheader">Function Documentation</h2>
|
<h2 class="groupheader">Function Documentation</h2>
|
||||||
@ -257,6 +298,54 @@ Functions</h2></td></tr>
|
|||||||
<p>Generally, <code>mi_usable_size(mi_malloc(size)) == mi_good_size(size)</code>. This can be used to reduce internal wasted space when allocating buffers for example.</p>
|
<p>Generally, <code>mi_usable_size(mi_malloc(size)) == mi_good_size(size)</code>. This can be used to reduce internal wasted space when allocating buffers for example.</p>
|
||||||
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee" title="Return the available bytes in a memory block.">mi_usable_size()</a> </dd></dl>
|
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee" title="Return the available bytes in a memory block.">mi_usable_size()</a> </dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga5f071b10d4df1c3658e04e7fd67a94e6"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga5f071b10d4df1c3658e04e7fd67a94e6">◆ </a></span>mi_is_in_heap_region()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">bool mi_is_in_heap_region </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype">const void * </td>
|
||||||
|
<td class="paramname"><em>p</em></td><td>)</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Is a pointer part of our heap? </p>
|
||||||
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
|
<table class="params">
|
||||||
|
<tr><td class="paramname">p</td><td>The pointer to check. </td></tr>
|
||||||
|
</table>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="section return"><dt>Returns</dt><dd><em>true</em> if this is a pointer into our heap. This function is relatively fast. </dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="gaad25050b19f30cd79397b227e0157a3f"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#gaad25050b19f30cd79397b227e0157a3f">◆ </a></span>mi_is_redirected()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">bool mi_is_redirected </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramname"></td><td>)</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Is the C runtime <em>malloc</em> API redirected? </p>
|
||||||
|
<dl class="section return"><dt>Returns</dt><dd><em>true</em> if all malloc API calls are redirected to mimalloc.</dd></dl>
|
||||||
|
<p>Currenty only used on Windows. </p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga7136c2e55cb22c98ecf95d08d6debb99"></a>
|
<a id="ga7136c2e55cb22c98ecf95d08d6debb99"></a>
|
||||||
@ -313,8 +402,101 @@ Functions</h2></td></tr>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga6bb821ca1b664b452112c0e17b15fcf1"></a>
|
<a id="ga84a0c8b401e42eb5b1bce156852f44c5"></a>
|
||||||
<h2 class="memtitle"><span class="permalink"><a href="#ga6bb821ca1b664b452112c0e17b15fcf1">◆ </a></span>mi_stats_print()</h2>
|
<h2 class="memtitle"><span class="permalink"><a href="#ga84a0c8b401e42eb5b1bce156852f44c5">◆ </a></span>mi_register_output()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">void mi_register_output </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> * </td>
|
||||||
|
<td class="paramname"><em>out</em></td><td>)</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Register an output function. </p>
|
||||||
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
|
<table class="params">
|
||||||
|
<tr><td class="paramname">out</td><td>The output function, use <code>NULL</code> to output to stdout.</td></tr>
|
||||||
|
</table>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<p>The <code>out</code> function is called to output any information from mimalloc, like verbose or warning messages. </p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga2664f36a2dd557741c429cb799f04641"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga2664f36a2dd557741c429cb799f04641">◆ </a></span>mi_reserve_huge_os_pages()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">int mi_reserve_huge_os_pages </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype">size_t </td>
|
||||||
|
<td class="paramname"><em>pages</em>, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype">double </td>
|
||||||
|
<td class="paramname"><em>max_secs</em>, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype">size_t * </td>
|
||||||
|
<td class="paramname"><em>pages_reserved</em> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>)</td>
|
||||||
|
<td></td><td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Reserve <em>pages</em> of huge OS pages (1GiB) but stops after at most <code>max_secs</code> seconds. </p>
|
||||||
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
|
<table class="params">
|
||||||
|
<tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
|
||||||
|
<tr><td class="paramname">max_secs</td><td>Maximum number of seconds to try reserving. </td></tr>
|
||||||
|
<tr><td class="paramname">pages_reserved</td><td>If not <em>NULL</em>, it is set to the actual number of pages that were reserved. </td></tr>
|
||||||
|
</table>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
|
||||||
|
<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>max_secs</em> are expired if it estimates it will take more than 1.5 times <em>max_secs</em>. 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. </p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga854b1de8cb067c7316286c28b2fcd3d1"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga854b1de8cb067c7316286c28b2fcd3d1">◆ </a></span>mi_stats_merge()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">void mi_stats_merge </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype">void </td>
|
||||||
|
<td class="paramname"></td><td>)</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Merge thread local statistics with the main statistics and reset. </p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga8ca07ccff283956d71f48272f4fd5c01"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga8ca07ccff283956d71f48272f4fd5c01">◆ </a></span>mi_stats_print()</h2>
|
||||||
|
|
||||||
<div class="memitem">
|
<div class="memitem">
|
||||||
<div class="memproto">
|
<div class="memproto">
|
||||||
@ -322,17 +504,17 @@ Functions</h2></td></tr>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="memname">void mi_stats_print </td>
|
<td class="memname">void mi_stats_print </td>
|
||||||
<td>(</td>
|
<td>(</td>
|
||||||
<td class="paramtype">FILE * </td>
|
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> * </td>
|
||||||
<td class="paramname"><em>out</em></td><td>)</td>
|
<td class="paramname"><em>out</em></td><td>)</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div><div class="memdoc">
|
</div><div class="memdoc">
|
||||||
|
|
||||||
<p>Print statistics. </p>
|
<p>Print the main statistics. </p>
|
||||||
<dl class="params"><dt>Parameters</dt><dd>
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
<table class="params">
|
<table class="params">
|
||||||
<tr><td class="paramname">out</td><td>Output file. Use <em>NULL</em> for <em>stderr</em>.</td></tr>
|
<tr><td class="paramname">out</td><td>Output function. Use <em>NULL</em> for outputting to <em>stderr</em>.</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -340,8 +522,8 @@ Functions</h2></td></tr>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga9883b8a059aed7eb0888a01ec1461161"></a>
|
<a id="ga3bb8468b8cfcc6e2a61d98aee85c5f99"></a>
|
||||||
<h2 class="memtitle"><span class="permalink"><a href="#ga9883b8a059aed7eb0888a01ec1461161">◆ </a></span>mi_stats_reset()</h2>
|
<h2 class="memtitle"><span class="permalink"><a href="#ga3bb8468b8cfcc6e2a61d98aee85c5f99">◆ </a></span>mi_stats_reset()</h2>
|
||||||
|
|
||||||
<div class="memitem">
|
<div class="memitem">
|
||||||
<div class="memproto">
|
<div class="memproto">
|
||||||
@ -349,6 +531,7 @@ Functions</h2></td></tr>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="memname">void mi_stats_reset </td>
|
<td class="memname">void mi_stats_reset </td>
|
||||||
<td>(</td>
|
<td>(</td>
|
||||||
|
<td class="paramtype">void </td>
|
||||||
<td class="paramname"></td><td>)</td>
|
<td class="paramname"></td><td>)</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -359,8 +542,8 @@ Functions</h2></td></tr>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="gac0f4849256aaf677f334690952c6ebbd"></a>
|
<a id="ga0ae4581e85453456a0d658b2b98bf7bf"></a>
|
||||||
<h2 class="memtitle"><span class="permalink"><a href="#gac0f4849256aaf677f334690952c6ebbd">◆ </a></span>mi_thread_done()</h2>
|
<h2 class="memtitle"><span class="permalink"><a href="#ga0ae4581e85453456a0d658b2b98bf7bf">◆ </a></span>mi_thread_done()</h2>
|
||||||
|
|
||||||
<div class="memitem">
|
<div class="memitem">
|
||||||
<div class="memproto">
|
<div class="memproto">
|
||||||
@ -368,6 +551,7 @@ Functions</h2></td></tr>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="memname">void mi_thread_done </td>
|
<td class="memname">void mi_thread_done </td>
|
||||||
<td>(</td>
|
<td>(</td>
|
||||||
|
<td class="paramtype">void </td>
|
||||||
<td class="paramname"></td><td>)</td>
|
<td class="paramname"></td><td>)</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -379,8 +563,8 @@ Functions</h2></td></tr>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga9398517f01a1ec971244aa0db084ea46"></a>
|
<a id="gaf8e73efc2cbca9ebfdfb166983a04c17"></a>
|
||||||
<h2 class="memtitle"><span class="permalink"><a href="#ga9398517f01a1ec971244aa0db084ea46">◆ </a></span>mi_thread_init()</h2>
|
<h2 class="memtitle"><span class="permalink"><a href="#gaf8e73efc2cbca9ebfdfb166983a04c17">◆ </a></span>mi_thread_init()</h2>
|
||||||
|
|
||||||
<div class="memitem">
|
<div class="memitem">
|
||||||
<div class="memproto">
|
<div class="memproto">
|
||||||
@ -388,6 +572,7 @@ Functions</h2></td></tr>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="memname">void mi_thread_init </td>
|
<td class="memname">void mi_thread_init </td>
|
||||||
<td>(</td>
|
<td>(</td>
|
||||||
|
<td class="paramtype">void </td>
|
||||||
<td class="paramname"></td><td>)</td>
|
<td class="paramname"></td><td>)</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -399,8 +584,8 @@ Functions</h2></td></tr>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga490826cbd7c494acc9fe69be23f018ac"></a>
|
<a id="ga489670a15d1a257ab4639e645ee4612a"></a>
|
||||||
<h2 class="memtitle"><span class="permalink"><a href="#ga490826cbd7c494acc9fe69be23f018ac">◆ </a></span>mi_thread_stats_print()</h2>
|
<h2 class="memtitle"><span class="permalink"><a href="#ga489670a15d1a257ab4639e645ee4612a">◆ </a></span>mi_thread_stats_print()</h2>
|
||||||
|
|
||||||
<div class="memitem">
|
<div class="memitem">
|
||||||
<div class="memproto">
|
<div class="memproto">
|
||||||
@ -408,7 +593,7 @@ Functions</h2></td></tr>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="memname">void mi_thread_stats_print </td>
|
<td class="memname">void mi_thread_stats_print </td>
|
||||||
<td>(</td>
|
<td>(</td>
|
||||||
<td class="paramtype">FILE * </td>
|
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> * </td>
|
||||||
<td class="paramname"><em>out</em></td><td>)</td>
|
<td class="paramname"><em>out</em></td><td>)</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -418,7 +603,7 @@ Functions</h2></td></tr>
|
|||||||
<p>Print out heap statistics for this thread. </p>
|
<p>Print out heap statistics for this thread. </p>
|
||||||
<dl class="params"><dt>Parameters</dt><dd>
|
<dl class="params"><dt>Parameters</dt><dd>
|
||||||
<table class="params">
|
<table class="params">
|
||||||
<tr><td class="paramname">out</td><td>Output file. Use <em>NULL</em> for <em>stderr</em>.</td></tr>
|
<tr><td class="paramname">out</td><td>Output function. Use <em>NULL</em> for outputting to <em>stderr</em>.</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
@ -2,15 +2,21 @@ var group__extended =
|
|||||||
[
|
[
|
||||||
[ "MI_SMALL_SIZE_MAX", "group__extended.html#ga1ea64283508718d9d645c38efc2f4305", null ],
|
[ "MI_SMALL_SIZE_MAX", "group__extended.html#ga1ea64283508718d9d645c38efc2f4305", null ],
|
||||||
[ "mi_deferred_free_fun", "group__extended.html#ga22213691c3ce5ab4d91b24aff1023529", null ],
|
[ "mi_deferred_free_fun", "group__extended.html#ga22213691c3ce5ab4d91b24aff1023529", null ],
|
||||||
|
[ "mi_output_fun", "group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f", null ],
|
||||||
[ "mi_collect", "group__extended.html#ga421430e2226d7d468529cec457396756", null ],
|
[ "mi_collect", "group__extended.html#ga421430e2226d7d468529cec457396756", null ],
|
||||||
[ "mi_good_size", "group__extended.html#gac057927cd06c854b45fe7847e921bd47", null ],
|
[ "mi_good_size", "group__extended.html#gac057927cd06c854b45fe7847e921bd47", null ],
|
||||||
|
[ "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_malloc_small", "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99", null ],
|
||||||
[ "mi_register_deferred_free", "group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2", null ],
|
[ "mi_register_deferred_free", "group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2", null ],
|
||||||
[ "mi_stats_print", "group__extended.html#ga6bb821ca1b664b452112c0e17b15fcf1", null ],
|
[ "mi_register_output", "group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5", null ],
|
||||||
[ "mi_stats_reset", "group__extended.html#ga9883b8a059aed7eb0888a01ec1461161", null ],
|
[ "mi_reserve_huge_os_pages", "group__extended.html#ga2664f36a2dd557741c429cb799f04641", null ],
|
||||||
[ "mi_thread_done", "group__extended.html#gac0f4849256aaf677f334690952c6ebbd", null ],
|
[ "mi_stats_merge", "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1", null ],
|
||||||
[ "mi_thread_init", "group__extended.html#ga9398517f01a1ec971244aa0db084ea46", null ],
|
[ "mi_stats_print", "group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01", null ],
|
||||||
[ "mi_thread_stats_print", "group__extended.html#ga490826cbd7c494acc9fe69be23f018ac", null ],
|
[ "mi_stats_reset", "group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99", null ],
|
||||||
|
[ "mi_thread_done", "group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf", null ],
|
||||||
|
[ "mi_thread_init", "group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17", null ],
|
||||||
|
[ "mi_thread_stats_print", "group__extended.html#ga489670a15d1a257ab4639e645ee4612a", null ],
|
||||||
[ "mi_usable_size", "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee", null ],
|
[ "mi_usable_size", "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee", null ],
|
||||||
[ "mi_zalloc_small", "group__extended.html#ga220f29f40a44404b0061c15bc1c31152", null ]
|
[ "mi_zalloc_small", "group__extended.html#ga220f29f40a44404b0061c15bc1c31152", null ]
|
||||||
];
|
];
|
@ -135,9 +135,15 @@ Functions</h2></td></tr>
|
|||||||
<tr class="memitem:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">mi_heap_get_backing</a> ()</td></tr>
|
<tr class="memitem:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">mi_heap_get_backing</a> ()</td></tr>
|
||||||
<tr class="memdesc:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="mdescLeft"> </td><td class="mdescRight">Get the backing heap. <a href="#ga5d03fbe062ffcf38f0f417fd968357fc">More...</a><br /></td></tr>
|
<tr class="memdesc:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="mdescLeft"> </td><td class="mdescRight">Get the backing heap. <a href="#ga5d03fbe062ffcf38f0f417fd968357fc">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga7922f7495cde30b1984d0e6072419298"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">mi_heap_collect</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, bool force)</td></tr>
|
||||||
|
<tr class="memdesc:ga7922f7495cde30b1984d0e6072419298"><td class="mdescLeft"> </td><td class="mdescRight">Release outstanding resources in a specific heap. <a href="#ga7922f7495cde30b1984d0e6072419298">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga7922f7495cde30b1984d0e6072419298"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga9cbed01e42c0647907295de92c3fa296"><td class="memItemLeft" align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">mi_heap_malloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
|
<tr class="memitem:ga9cbed01e42c0647907295de92c3fa296"><td class="memItemLeft" align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">mi_heap_malloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
|
||||||
<tr class="memdesc:ga9cbed01e42c0647907295de92c3fa296"><td class="mdescLeft"> </td><td class="mdescRight">Allocate in a specific heap. <a href="#ga9cbed01e42c0647907295de92c3fa296">More...</a><br /></td></tr>
|
<tr class="memdesc:ga9cbed01e42c0647907295de92c3fa296"><td class="mdescLeft"> </td><td class="mdescRight">Allocate in a specific heap. <a href="#ga9cbed01e42c0647907295de92c3fa296">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga9cbed01e42c0647907295de92c3fa296"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga9cbed01e42c0647907295de92c3fa296"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="memItemLeft" align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">mi_heap_malloc_small</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
|
||||||
|
<tr class="memdesc:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="mdescLeft"> </td><td class="mdescRight">Allocate a small object in a specific heap. <a href="#gaa1a1c7a1f4da6826b5a25b70ef878368">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga903104592c8ed53417a3762da6241133"><td class="memItemLeft" align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga903104592c8ed53417a3762da6241133">mi_heap_zalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
|
<tr class="memitem:ga903104592c8ed53417a3762da6241133"><td class="memItemLeft" align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga903104592c8ed53417a3762da6241133">mi_heap_zalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
|
||||||
<tr class="memdesc:ga903104592c8ed53417a3762da6241133"><td class="mdescLeft"> </td><td class="mdescRight">Allocate zero-initialized in a specific heap. <a href="#ga903104592c8ed53417a3762da6241133">More...</a><br /></td></tr>
|
<tr class="memdesc:ga903104592c8ed53417a3762da6241133"><td class="mdescLeft"> </td><td class="mdescRight">Allocate zero-initialized in a specific heap. <a href="#ga903104592c8ed53417a3762da6241133">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga903104592c8ed53417a3762da6241133"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga903104592c8ed53417a3762da6241133"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
@ -321,6 +327,36 @@ Functions</h2></td></tr>
|
|||||||
</table>
|
</table>
|
||||||
</div><div class="memdoc">
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga7922f7495cde30b1984d0e6072419298"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga7922f7495cde30b1984d0e6072419298">◆ </a></span>mi_heap_collect()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">void mi_heap_collect </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> * </td>
|
||||||
|
<td class="paramname"><em>heap</em>, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype">bool </td>
|
||||||
|
<td class="paramname"><em>force</em> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>)</td>
|
||||||
|
<td></td><td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Release outstanding resources in a specific heap. </p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga2ab1af8d438819b55319c7ef51d1e409"></a>
|
<a id="ga2ab1af8d438819b55319c7ef51d1e409"></a>
|
||||||
@ -510,6 +546,37 @@ Functions</h2></td></tr>
|
|||||||
</table>
|
</table>
|
||||||
</div><div class="memdoc">
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="gaa1a1c7a1f4da6826b5a25b70ef878368"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#gaa1a1c7a1f4da6826b5a25b70ef878368">◆ </a></span>mi_heap_malloc_small()</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">void* mi_heap_malloc_small </td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> * </td>
|
||||||
|
<td class="paramname"><em>heap</em>, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype">size_t </td>
|
||||||
|
<td class="paramname"><em>size</em> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>)</td>
|
||||||
|
<td></td><td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Allocate a small object in a specific heap. </p>
|
||||||
|
<p><em>size</em> must be smaller or equal to <a class="el" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305" title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX()</a>. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> </dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga851da6c43fe0b71c1376cee8aef90db0"></a>
|
<a id="ga851da6c43fe0b71c1376cee8aef90db0"></a>
|
||||||
|
@ -4,6 +4,7 @@ var group__heap =
|
|||||||
[ "mi_heap_calloc", "group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55", null ],
|
[ "mi_heap_calloc", "group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55", null ],
|
||||||
[ "mi_heap_calloc_aligned", "group__heap.html#ga4af03a6e2b93fae77424d93f889705c3", null ],
|
[ "mi_heap_calloc_aligned", "group__heap.html#ga4af03a6e2b93fae77424d93f889705c3", null ],
|
||||||
[ "mi_heap_calloc_aligned_at", "group__heap.html#ga08ca6419a5c057a4d965868998eef487", null ],
|
[ "mi_heap_calloc_aligned_at", "group__heap.html#ga08ca6419a5c057a4d965868998eef487", null ],
|
||||||
|
[ "mi_heap_collect", "group__heap.html#ga7922f7495cde30b1984d0e6072419298", null ],
|
||||||
[ "mi_heap_delete", "group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409", null ],
|
[ "mi_heap_delete", "group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409", null ],
|
||||||
[ "mi_heap_destroy", "group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d", null ],
|
[ "mi_heap_destroy", "group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d", null ],
|
||||||
[ "mi_heap_get_backing", "group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc", null ],
|
[ "mi_heap_get_backing", "group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc", null ],
|
||||||
@ -11,6 +12,7 @@ var group__heap =
|
|||||||
[ "mi_heap_malloc", "group__heap.html#ga9cbed01e42c0647907295de92c3fa296", null ],
|
[ "mi_heap_malloc", "group__heap.html#ga9cbed01e42c0647907295de92c3fa296", null ],
|
||||||
[ "mi_heap_malloc_aligned", "group__heap.html#gab5b87e1805306f70df38789fcfcf6653", null ],
|
[ "mi_heap_malloc_aligned", "group__heap.html#gab5b87e1805306f70df38789fcfcf6653", null ],
|
||||||
[ "mi_heap_malloc_aligned_at", "group__heap.html#ga23acd7680fb0976dde3783254c6c874b", null ],
|
[ "mi_heap_malloc_aligned_at", "group__heap.html#ga23acd7680fb0976dde3783254c6c874b", null ],
|
||||||
|
[ "mi_heap_malloc_small", "group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368", null ],
|
||||||
[ "mi_heap_mallocn", "group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0", null ],
|
[ "mi_heap_mallocn", "group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0", null ],
|
||||||
[ "mi_heap_new", "group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11", null ],
|
[ "mi_heap_new", "group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11", null ],
|
||||||
[ "mi_heap_realloc", "group__heap.html#gaaef3395f66be48f37bdc8322509c5d81", null ],
|
[ "mi_heap_realloc", "group__heap.html#gaaef3395f66be48f37bdc8322509c5d81", null ],
|
||||||
|
@ -115,16 +115,20 @@ Enumerations</h2></td></tr>
|
|||||||
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">mi_option_show_stats</a>,
|
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">mi_option_show_stats</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">mi_option_show_errors</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">mi_option_show_errors</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">mi_option_verbose</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">mi_option_verbose</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f">mi_option_secure</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">mi_option_eager_commit</a>,
|
||||||
<br />
|
<br />
|
||||||
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">mi_option_eager_commit</a>,
|
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">mi_option_eager_region_commit</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">mi_option_eager_region_commit</a>,
|
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">mi_option_large_os_pages</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">mi_option_large_os_pages</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2">mi_option_reserve_huge_os_pages</a>,
|
||||||
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a>,
|
||||||
<br />
|
<br />
|
||||||
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07">mi_option_cache_reset</a>,
|
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>,
|
||||||
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07">mi_option_cache_reset</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b">mi_option_reset_discards</a>,
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a>,
|
||||||
|
<br />
|
||||||
|
  <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a>,
|
||||||
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a>,
|
||||||
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a>
|
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a>
|
||||||
<br />
|
<br />
|
||||||
}</td></tr>
|
}</td></tr>
|
||||||
@ -169,13 +173,15 @@ Functions</h2></td></tr>
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777"></a>mi_option_verbose </td><td class="fielddoc"><p>Print verbose messages to <code>stderr</code>. </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777"></a>mi_option_verbose </td><td class="fielddoc"><p>Print verbose messages to <code>stderr</code>. </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f"></a>mi_option_secure </td><td class="fielddoc"><p>Experimental. </p>
|
|
||||||
</td></tr>
|
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b"></a>mi_option_eager_commit </td><td class="fielddoc"><p>Eagerly commit segments (4MiB) (enabled by default). </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b"></a>mi_option_eager_commit </td><td class="fielddoc"><p>Eagerly commit segments (4MiB) (enabled by default). </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad"></a>mi_option_eager_region_commit </td><td class="fielddoc"><p>Eagerly commit large (256MiB) memory regions (enabled by default except on Windows) </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad"></a>mi_option_eager_region_commit </td><td class="fielddoc"><p>Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows) </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e"></a>mi_option_large_os_pages </td><td class="fielddoc"><p>Use large OS pages if possible. </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e"></a>mi_option_large_os_pages </td><td class="fielddoc"><p>Use large OS pages (2MiB in size) if possible. </p>
|
||||||
|
</td></tr>
|
||||||
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2"></a>mi_option_reserve_huge_os_pages </td><td class="fielddoc"><p>The number of huge OS pages (1GiB in size) to reserve at the start of the program. </p>
|
||||||
|
</td></tr>
|
||||||
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1"></a>mi_option_segment_cache </td><td class="fielddoc"><p>The number of segments per thread to keep cached. </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"></a>mi_option_page_reset </td><td class="fielddoc"><p>Reset page memory when it becomes free. </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"></a>mi_option_page_reset </td><td class="fielddoc"><p>Reset page memory when it becomes free. </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
@ -183,7 +189,11 @@ Functions</h2></td></tr>
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"></a>mi_option_reset_decommits </td><td class="fielddoc"><p>Experimental. </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"></a>mi_option_reset_decommits </td><td class="fielddoc"><p>Experimental. </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b"></a>mi_option_reset_discards </td><td class="fielddoc"><p>Experimental. </p>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c"></a>mi_option_eager_commit_delay </td><td class="fielddoc"><p>Experimental. </p>
|
||||||
|
</td></tr>
|
||||||
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d"></a>mi_option_segment_reset </td><td class="fielddoc"><p>Experimental. </p>
|
||||||
|
</td></tr>
|
||||||
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf"></a>mi_option_os_tag </td><td class="fielddoc"><p>OS tag to assign to mimalloc'd memory. </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"></a>_mi_option_last </td><td class="fielddoc"></td></tr>
|
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"></a>_mi_option_last </td><td class="fielddoc"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -4,14 +4,17 @@ var group__options =
|
|||||||
[ "mi_option_show_stats", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda", null ],
|
[ "mi_option_show_stats", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda", null ],
|
||||||
[ "mi_option_show_errors", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0", null ],
|
[ "mi_option_show_errors", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0", null ],
|
||||||
[ "mi_option_verbose", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777", null ],
|
[ "mi_option_verbose", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777", null ],
|
||||||
[ "mi_option_secure", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f", null ],
|
|
||||||
[ "mi_option_eager_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b", null ],
|
[ "mi_option_eager_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b", null ],
|
||||||
[ "mi_option_eager_region_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad", null ],
|
[ "mi_option_eager_region_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad", null ],
|
||||||
[ "mi_option_large_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e", null ],
|
[ "mi_option_large_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e", null ],
|
||||||
|
[ "mi_option_reserve_huge_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2", null ],
|
||||||
|
[ "mi_option_segment_cache", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1", null ],
|
||||||
[ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ],
|
[ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ],
|
||||||
[ "mi_option_cache_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07", null ],
|
[ "mi_option_cache_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07", null ],
|
||||||
[ "mi_option_reset_decommits", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536", null ],
|
[ "mi_option_reset_decommits", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536", null ],
|
||||||
[ "mi_option_reset_discards", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b", null ],
|
[ "mi_option_eager_commit_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c", null ],
|
||||||
|
[ "mi_option_segment_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d", null ],
|
||||||
|
[ "mi_option_os_tag", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf", null ],
|
||||||
[ "_mi_option_last", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a", null ]
|
[ "_mi_option_last", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a", null ]
|
||||||
] ],
|
] ],
|
||||||
[ "mi_option_enable", "group__options.html#ga6d45a20a3131f18bc351b69763b38ce4", null ],
|
[ "mi_option_enable", "group__options.html#ga6d45a20a3131f18bc351b69763b38ce4", null ],
|
||||||
|
@ -115,6 +115,7 @@ Functions</h2></td></tr>
|
|||||||
<tr class="memitem:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memItemLeft" align="right" valign="top">size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">mi_malloc_usable_size</a> (const void *p)</td></tr>
|
<tr class="memitem:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memItemLeft" align="right" valign="top">size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">mi_malloc_usable_size</a> (const void *p)</td></tr>
|
||||||
<tr class="separator:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">mi_cfree</a> (void *p)</td></tr>
|
<tr class="memitem:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">mi_cfree</a> (void *p)</td></tr>
|
||||||
|
<tr class="memdesc:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="mdescLeft"> </td><td class="mdescRight">Just as <code>free</code> but also checks if the pointer <code>p</code> belongs to our heap. <a href="#ga705dc7a64bffacfeeb0141501a5c35d7">More...</a><br /></td></tr>
|
||||||
<tr class="separator:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
<tr class="memitem:gacff84f226ba9feb2031b8992e5579447"><td class="memItemLeft" align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">mi_posix_memalign</a> (void **p, size_t alignment, size_t size)</td></tr>
|
<tr class="memitem:gacff84f226ba9feb2031b8992e5579447"><td class="memItemLeft" align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">mi_posix_memalign</a> (void **p, size_t alignment, size_t size)</td></tr>
|
||||||
<tr class="separator:gacff84f226ba9feb2031b8992e5579447"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:gacff84f226ba9feb2031b8992e5579447"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
@ -231,6 +232,8 @@ Functions</h2></td></tr>
|
|||||||
</table>
|
</table>
|
||||||
</div><div class="memdoc">
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Just as <code>free</code> but also checks if the pointer <code>p</code> belongs to our heap. </p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="ga0d28d5cf61e6bfbb18c63092939fe5c9"></a>
|
<a id="ga0d28d5cf61e6bfbb18c63092939fe5c9"></a>
|
||||||
|
@ -140,6 +140,9 @@ Macros</h2></td></tr>
|
|||||||
<tr class="memitem:gaf213d5422ec35e7f6caad827c79bc948"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gaf213d5422ec35e7f6caad827c79bc948">mi_heap_reallocn_tp</a>(hp, p, tp, count)</td></tr>
|
<tr class="memitem:gaf213d5422ec35e7f6caad827c79bc948"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gaf213d5422ec35e7f6caad827c79bc948">mi_heap_reallocn_tp</a>(hp, p, tp, count)</td></tr>
|
||||||
<tr class="memdesc:gaf213d5422ec35e7f6caad827c79bc948"><td class="mdescLeft"> </td><td class="mdescRight">Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. <a href="#gaf213d5422ec35e7f6caad827c79bc948">More...</a><br /></td></tr>
|
<tr class="memdesc:gaf213d5422ec35e7f6caad827c79bc948"><td class="mdescLeft"> </td><td class="mdescRight">Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. <a href="#gaf213d5422ec35e7f6caad827c79bc948">More...</a><br /></td></tr>
|
||||||
<tr class="separator:gaf213d5422ec35e7f6caad827c79bc948"><td class="memSeparator" colspan="2"> </td></tr>
|
<tr class="separator:gaf213d5422ec35e7f6caad827c79bc948"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
|
<tr class="memitem:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e">mi_heap_recalloc_tp</a>(hp, p, tp, count)</td></tr>
|
||||||
|
<tr class="memdesc:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="mdescLeft"> </td><td class="mdescRight">Re-allocate to <em>count</em> zero initialized blocks of type <em>tp</em> in a heap <em>hp</em>. <a href="#ga3e50a1600958fcaf1a7f3560c9174f9e">More...</a><br /></td></tr>
|
||||||
|
<tr class="separator:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="memSeparator" colspan="2"> </td></tr>
|
||||||
</table>
|
</table>
|
||||||
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
|
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
|
||||||
<p>Typed allocation macros. </p>
|
<p>Typed allocation macros. </p>
|
||||||
@ -316,6 +319,48 @@ Macros</h2></td></tr>
|
|||||||
|
|
||||||
<p>Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
|
<p>Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a id="ga3e50a1600958fcaf1a7f3560c9174f9e"></a>
|
||||||
|
<h2 class="memtitle"><span class="permalink"><a href="#ga3e50a1600958fcaf1a7f3560c9174f9e">◆ </a></span>mi_heap_recalloc_tp</h2>
|
||||||
|
|
||||||
|
<div class="memitem">
|
||||||
|
<div class="memproto">
|
||||||
|
<table class="memname">
|
||||||
|
<tr>
|
||||||
|
<td class="memname">#define mi_heap_recalloc_tp</td>
|
||||||
|
<td>(</td>
|
||||||
|
<td class="paramtype"> </td>
|
||||||
|
<td class="paramname">hp, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype"> </td>
|
||||||
|
<td class="paramname">p, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype"> </td>
|
||||||
|
<td class="paramname">tp, </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="paramkey"></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="paramtype"> </td>
|
||||||
|
<td class="paramname">count </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>)</td>
|
||||||
|
<td></td><td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div><div class="memdoc">
|
||||||
|
|
||||||
|
<p>Re-allocate to <em>count</em> zero initialized blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a id="gad6e87e86e994aa14416ae9b5d4c188fe"></a>
|
<a id="gad6e87e86e994aa14416ae9b5d4c188fe"></a>
|
||||||
|
@ -5,6 +5,7 @@ var group__typed =
|
|||||||
[ "mi_heap_malloc_tp", "group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7", null ],
|
[ "mi_heap_malloc_tp", "group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7", null ],
|
||||||
[ "mi_heap_mallocn_tp", "group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83", null ],
|
[ "mi_heap_mallocn_tp", "group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83", null ],
|
||||||
[ "mi_heap_reallocn_tp", "group__typed.html#gaf213d5422ec35e7f6caad827c79bc948", null ],
|
[ "mi_heap_reallocn_tp", "group__typed.html#gaf213d5422ec35e7f6caad827c79bc948", null ],
|
||||||
|
[ "mi_heap_recalloc_tp", "group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e", null ],
|
||||||
[ "mi_heap_zalloc_tp", "group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe", null ],
|
[ "mi_heap_zalloc_tp", "group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe", null ],
|
||||||
[ "mi_malloc_tp", "group__typed.html#ga0619a62c5fd886f1016030abe91f0557", null ],
|
[ "mi_malloc_tp", "group__typed.html#ga0619a62c5fd886f1016030abe91f0557", null ],
|
||||||
[ "mi_mallocn_tp", "group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b", null ],
|
[ "mi_mallocn_tp", "group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b", null ],
|
||||||
|
@ -110,14 +110,15 @@ $(document).ready(function(){initNavTree('index.html','');});
|
|||||||
<li><b>eager page reset</b>: 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.</li>
|
<li><b>eager page reset</b>: 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.</li>
|
||||||
<li><b>secure</b>: <em>mimalloc</em> 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.</li>
|
<li><b>secure</b>: <em>mimalloc</em> 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.</li>
|
||||||
<li><b>first-class heaps</b>: efficiently create and use multiple heaps to allocate across different regions. A heap can be destroyed at once instead of deallocating each object separately.</li>
|
<li><b>first-class heaps</b>: efficiently create and use multiple heaps to allocate across different regions. A heap can be destroyed at once instead of deallocating each object separately.</li>
|
||||||
<li><b>bounded</b>: it does not suffer from <em>blowup</em> [1], has bounded worst-case allocation times (<em>wcat</em>), bounded space overhead (~0.2% meta-data, with at most 16.7% waste in allocation sizes), and has no internal points of contention using only atomic operations.</li>
|
<li><b>bounded</b>: it does not suffer from <em>blowup</em> [1], has bounded worst-case allocation times (<em>wcat</em>), 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.</li>
|
||||||
<li><b>fast</b>: In our benchmarks (see <a href="#performance">below</a>), <em>mimalloc</em> always outperforms all other leading allocators (<em>jemalloc</em>, <em>tcmalloc</em>, <em>Hoard</em>, 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.</li>
|
<li><b>fast</b>: In our benchmarks (see <a href="#performance">below</a>), <em>mimalloc</em> always outperforms all other leading allocators (<em>jemalloc</em>, <em>tcmalloc</em>, <em>Hoard</em>, 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.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>You can read more on the design of <em>mimalloc</em> in the upcoming technical report which also has detailed benchmark results.</p>
|
<p>You can read more on the design of <em>mimalloc</em> in the <a href="https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action">technical report</a> which also has detailed benchmark results.</p>
|
||||||
<p>Further information:</p>
|
<p>Further information:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="el" href="build.html">Building</a></li>
|
<li><a class="el" href="build.html">Building</a></li>
|
||||||
<li><a class="el" href="using.html">Using the library</a></li>
|
<li><a class="el" href="using.html">Using the library</a></li>
|
||||||
|
<li><a class="el" href="environment.html">Environment Options</a></li>
|
||||||
<li><a class="el" href="overrides.html">Overriding Malloc</a></li>
|
<li><a class="el" href="overrides.html">Overriding Malloc</a></li>
|
||||||
<li><a class="el" href="bench.html">Performance</a></li>
|
<li><a class="el" href="bench.html">Performance</a></li>
|
||||||
<li><a class="el" href="group__malloc.html">Basic Allocation</a></li>
|
<li><a class="el" href="group__malloc.html">Basic Allocation</a></li>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -108,10 +108,11 @@ $(document).ready(function(){initNavTree('modules.html','');});
|
|||||||
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__extended.html" target="_self">Extended Functions</a></td><td class="desc">Extended functionality </td></tr>
|
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__extended.html" target="_self">Extended Functions</a></td><td class="desc">Extended functionality </td></tr>
|
||||||
<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__aligned.html" target="_self">Aligned Allocation</a></td><td class="desc">Allocating aligned memory blocks </td></tr>
|
<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__aligned.html" target="_self">Aligned Allocation</a></td><td class="desc">Allocating aligned memory blocks </td></tr>
|
||||||
<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__heap.html" target="_self">Heap Allocation</a></td><td class="desc">First-class heaps that can be destroyed in one go </td></tr>
|
<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__heap.html" target="_self">Heap Allocation</a></td><td class="desc">First-class heaps that can be destroyed in one go </td></tr>
|
||||||
<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__typed.html" target="_self">Typed Macros</a></td><td class="desc">Typed allocation macros </td></tr>
|
<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__zeroinit.html" target="_self">Zero initialized re-allocation</a></td><td class="desc">The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too </td></tr>
|
||||||
<tr id="row_5_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__analysis.html" target="_self">Heap Introspection</a></td><td class="desc">Inspect the heap at runtime </td></tr>
|
<tr id="row_5_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__typed.html" target="_self">Typed Macros</a></td><td class="desc">Typed allocation macros </td></tr>
|
||||||
<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__options.html" target="_self">Runtime Options</a></td><td class="desc">Set runtime behavior </td></tr>
|
<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__analysis.html" target="_self">Heap Introspection</a></td><td class="desc">Inspect the heap at runtime </td></tr>
|
||||||
<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__posix.html" target="_self">Posix</a></td><td class="desc"><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions </td></tr>
|
<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__options.html" target="_self">Runtime Options</a></td><td class="desc">Set runtime behavior </td></tr>
|
||||||
|
<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__posix.html" target="_self">Posix</a></td><td class="desc"><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions </td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div><!-- directory -->
|
</div><!-- directory -->
|
||||||
</div><!-- contents -->
|
</div><!-- contents -->
|
||||||
|
@ -4,6 +4,7 @@ var modules =
|
|||||||
[ "Extended Functions", "group__extended.html", "group__extended" ],
|
[ "Extended Functions", "group__extended.html", "group__extended" ],
|
||||||
[ "Aligned Allocation", "group__aligned.html", "group__aligned" ],
|
[ "Aligned Allocation", "group__aligned.html", "group__aligned" ],
|
||||||
[ "Heap Allocation", "group__heap.html", "group__heap" ],
|
[ "Heap Allocation", "group__heap.html", "group__heap" ],
|
||||||
|
[ "Zero initialized re-allocation", "group__zeroinit.html", "group__zeroinit" ],
|
||||||
[ "Typed Macros", "group__typed.html", "group__typed" ],
|
[ "Typed Macros", "group__typed.html", "group__typed" ],
|
||||||
[ "Heap Introspection", "group__analysis.html", "group__analysis" ],
|
[ "Heap Introspection", "group__analysis.html", "group__analysis" ],
|
||||||
[ "Runtime Options", "group__options.html", "group__options" ],
|
[ "Runtime Options", "group__options.html", "group__options" ],
|
||||||
|
@ -26,6 +26,7 @@ var NAVTREE =
|
|||||||
[ "mi-malloc", "index.html", [
|
[ "mi-malloc", "index.html", [
|
||||||
[ "Building", "build.html", null ],
|
[ "Building", "build.html", null ],
|
||||||
[ "Using the library", "using.html", null ],
|
[ "Using the library", "using.html", null ],
|
||||||
|
[ "Environment Options", "environment.html", null ],
|
||||||
[ "Overriding Malloc", "overrides.html", null ],
|
[ "Overriding Malloc", "overrides.html", null ],
|
||||||
[ "Performance", "bench.html", null ],
|
[ "Performance", "bench.html", null ],
|
||||||
[ "Modules", "modules.html", "modules" ],
|
[ "Modules", "modules.html", "modules" ],
|
||||||
|
@ -1,138 +1,163 @@
|
|||||||
var NAVTREEINDEX0 =
|
var NAVTREEINDEX0 =
|
||||||
{
|
{
|
||||||
"annotated.html":[5,0],
|
"annotated.html":[6,0],
|
||||||
"bench.html":[3],
|
"bench.html":[4],
|
||||||
"build.html":[0],
|
"build.html":[0],
|
||||||
"classes.html":[5,1],
|
"classes.html":[6,1],
|
||||||
"functions.html":[5,2,0],
|
"environment.html":[2],
|
||||||
"functions_vars.html":[5,2,1],
|
"functions.html":[6,2,0],
|
||||||
"group__aligned.html":[4,2],
|
"functions_vars.html":[6,2,1],
|
||||||
"group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3":[4,2,1],
|
"group__aligned.html":[5,2],
|
||||||
"group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819":[4,2,6],
|
"group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3":[5,2,1],
|
||||||
"group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae":[4,2,4],
|
"group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819":[5,2,6],
|
||||||
"group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9":[4,2,0],
|
"group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae":[5,2,4],
|
||||||
"group__aligned.html#ga5850da130c936bd77db039dcfbc8295d":[4,2,3],
|
"group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9":[5,2,0],
|
||||||
"group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8":[4,2,7],
|
"group__aligned.html#ga5850da130c936bd77db039dcfbc8295d":[5,2,3],
|
||||||
"group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56":[4,2,2],
|
"group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8":[5,2,7],
|
||||||
"group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb":[4,2,5],
|
"group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56":[5,2,2],
|
||||||
"group__analysis.html":[4,5],
|
"group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb":[5,2,5],
|
||||||
"group__analysis.html#a332a6c14d736a99699d5453a1cb04b41":[4,5,0,0],
|
"group__analysis.html":[5,6],
|
||||||
"group__analysis.html#ab47526df656d8837ec3e97f11b83f835":[4,5,0,2],
|
"group__analysis.html#a332a6c14d736a99699d5453a1cb04b41":[5,6,0,0],
|
||||||
"group__analysis.html#ab820302c5cd0df133eb8e51650a008b4":[4,5,0,4],
|
"group__analysis.html#ab47526df656d8837ec3e97f11b83f835":[5,6,0,2],
|
||||||
"group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8":[4,5,0,1],
|
"group__analysis.html#ab820302c5cd0df133eb8e51650a008b4":[5,6,0,4],
|
||||||
"group__analysis.html#ae848a3e6840414891035423948ca0383":[4,5,0,3],
|
"group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8":[5,6,0,1],
|
||||||
"group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377":[4,5,3],
|
"group__analysis.html#ae848a3e6840414891035423948ca0383":[5,6,0,3],
|
||||||
"group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5":[4,5,2],
|
"group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377":[5,6,3],
|
||||||
"group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed":[4,5,5],
|
"group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5":[5,6,2],
|
||||||
"group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af":[4,5,4],
|
"group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed":[5,6,5],
|
||||||
"group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65":[4,5,1],
|
"group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af":[5,6,4],
|
||||||
"group__analysis.html#structmi__heap__area__t":[4,5,0],
|
"group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65":[5,6,1],
|
||||||
"group__extended.html":[4,1],
|
"group__analysis.html#structmi__heap__area__t":[5,6,0],
|
||||||
"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[4,1,11],
|
"group__extended.html":[5,1],
|
||||||
"group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[4,1,0],
|
"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,17],
|
||||||
"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[4,1,12],
|
"group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,14],
|
||||||
"group__extended.html#ga22213691c3ce5ab4d91b24aff1023529":[4,1,1],
|
"group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[5,1,0],
|
||||||
"group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2":[4,1,5],
|
"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,18],
|
||||||
"group__extended.html#ga421430e2226d7d468529cec457396756":[4,1,2],
|
"group__extended.html#ga22213691c3ce5ab4d91b24aff1023529":[5,1,1],
|
||||||
"group__extended.html#ga490826cbd7c494acc9fe69be23f018ac":[4,1,10],
|
"group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2":[5,1,8],
|
||||||
"group__extended.html#ga6bb821ca1b664b452112c0e17b15fcf1":[4,1,6],
|
"group__extended.html#ga2664f36a2dd557741c429cb799f04641":[5,1,10],
|
||||||
"group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[4,1,4],
|
"group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f":[5,1,2],
|
||||||
"group__extended.html#ga9398517f01a1ec971244aa0db084ea46":[4,1,9],
|
"group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,13],
|
||||||
"group__extended.html#ga9883b8a059aed7eb0888a01ec1461161":[4,1,7],
|
"group__extended.html#ga421430e2226d7d468529cec457396756":[5,1,3],
|
||||||
"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[4,1,3],
|
"group__extended.html#ga489670a15d1a257ab4639e645ee4612a":[5,1,16],
|
||||||
"group__extended.html#gac0f4849256aaf677f334690952c6ebbd":[4,1,8],
|
"group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6":[5,1,5],
|
||||||
"group__heap.html":[4,3],
|
"group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[5,1,7],
|
||||||
"group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[4,3,18],
|
"group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5":[5,1,9],
|
||||||
"group__heap.html#ga08ca6419a5c057a4d965868998eef487":[4,3,3],
|
"group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,11],
|
||||||
"group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5":[4,3,20],
|
"group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01":[5,1,12],
|
||||||
"group__heap.html#ga23acd7680fb0976dde3783254c6c874b":[4,3,10],
|
"group__extended.html#gaad25050b19f30cd79397b227e0157a3f":[5,1,6],
|
||||||
"group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409":[4,3,4],
|
"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[5,1,4],
|
||||||
"group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2":[4,3,0],
|
"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,15],
|
||||||
"group__heap.html#ga45fb43a62776fbebbdf1edd99b527954":[4,3,24],
|
"group__heap.html":[5,3],
|
||||||
"group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527":[4,3,16],
|
"group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[5,3,20],
|
||||||
"group__heap.html#ga4af03a6e2b93fae77424d93f889705c3":[4,3,2],
|
"group__heap.html#ga08ca6419a5c057a4d965868998eef487":[5,3,3],
|
||||||
"group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc":[4,3,6],
|
"group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5":[5,3,22],
|
||||||
"group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11":[4,3,12],
|
"group__heap.html#ga23acd7680fb0976dde3783254c6c874b":[5,3,11],
|
||||||
"group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0":[4,3,11],
|
"group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409":[5,3,5],
|
||||||
"group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05":[4,3,7],
|
"group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2":[5,3,0],
|
||||||
"group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a":[4,3,21],
|
"group__heap.html#ga45fb43a62776fbebbdf1edd99b527954":[5,3,26],
|
||||||
"group__heap.html#ga903104592c8ed53417a3762da6241133":[4,3,22],
|
"group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527":[5,3,18],
|
||||||
"group__heap.html#ga9cbed01e42c0647907295de92c3fa296":[4,3,8],
|
"group__heap.html#ga4af03a6e2b93fae77424d93f889705c3":[5,3,2],
|
||||||
"group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d":[4,3,5],
|
"group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc":[5,3,7],
|
||||||
"group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0":[4,3,23],
|
"group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11":[5,3,14],
|
||||||
"group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55":[4,3,1],
|
"group__heap.html#ga7922f7495cde30b1984d0e6072419298":[5,3,4],
|
||||||
"group__heap.html#gaaef3395f66be48f37bdc8322509c5d81":[4,3,13],
|
"group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0":[5,3,13],
|
||||||
"group__heap.html#gab5b87e1805306f70df38789fcfcf6653":[4,3,9],
|
"group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05":[5,3,8],
|
||||||
"group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422":[4,3,19],
|
"group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a":[5,3,23],
|
||||||
"group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8":[4,3,17],
|
"group__heap.html#ga903104592c8ed53417a3762da6241133":[5,3,24],
|
||||||
"group__heap.html#gaf96c788a1bf553fe2d371de9365e047c":[4,3,15],
|
"group__heap.html#ga9cbed01e42c0647907295de92c3fa296":[5,3,9],
|
||||||
"group__heap.html#gafc603b696bd14cae6da28658f950d98c":[4,3,14],
|
"group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d":[5,3,6],
|
||||||
"group__malloc.html":[4,0],
|
"group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368":[5,3,12],
|
||||||
"group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe":[4,0,8],
|
"group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0":[5,3,25],
|
||||||
"group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6":[4,0,4],
|
"group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55":[5,3,1],
|
||||||
"group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc":[4,0,9],
|
"group__heap.html#gaaef3395f66be48f37bdc8322509c5d81":[5,3,15],
|
||||||
"group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a":[4,0,3],
|
"group__heap.html#gab5b87e1805306f70df38789fcfcf6653":[5,3,10],
|
||||||
"group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853":[4,0,7],
|
"group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422":[5,3,21],
|
||||||
"group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d":[4,0,0],
|
"group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8":[5,3,19],
|
||||||
"group__malloc.html#gaaabf971c2571891433477e2d21a35266":[4,0,11],
|
"group__heap.html#gaf96c788a1bf553fe2d371de9365e047c":[5,3,17],
|
||||||
"group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4":[4,0,1],
|
"group__heap.html#gafc603b696bd14cae6da28658f950d98c":[5,3,16],
|
||||||
"group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2":[4,0,10],
|
"group__malloc.html":[5,0],
|
||||||
"group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6":[4,0,5],
|
"group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe":[5,0,8],
|
||||||
"group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95":[4,0,2],
|
"group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6":[5,0,4],
|
||||||
"group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000":[4,0,12],
|
"group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc":[5,0,9],
|
||||||
"group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0":[4,0,6],
|
"group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a":[5,0,3],
|
||||||
"group__options.html":[4,6],
|
"group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853":[5,0,7],
|
||||||
"group__options.html#ga37988264b915a7db92530cc02d5494cb":[4,6,2],
|
"group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d":[5,0,0],
|
||||||
"group__options.html#ga6d45a20a3131f18bc351b69763b38ce4":[4,6,1],
|
"group__malloc.html#gaaabf971c2571891433477e2d21a35266":[5,0,11],
|
||||||
"group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a":[4,6,4],
|
"group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4":[5,0,1],
|
||||||
"group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90":[4,6,6],
|
"group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2":[5,0,10],
|
||||||
"group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30":[4,6,3],
|
"group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6":[5,0,5],
|
||||||
"group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[4,6,5],
|
"group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95":[5,0,2],
|
||||||
"group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[4,6,0],
|
"group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000":[5,0,12],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f":[4,6,0,3],
|
"group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0":[5,0,6],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[4,6,0,0],
|
"group__options.html":[5,7],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[4,6,0,4],
|
"group__options.html#ga37988264b915a7db92530cc02d5494cb":[5,7,2],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[4,6,0,5],
|
"group__options.html#ga6d45a20a3131f18bc351b69763b38ce4":[5,7,1],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[4,6,0,6],
|
"group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a":[5,7,4],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[4,6,0,11],
|
"group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90":[5,7,6],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[4,6,0,2],
|
"group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30":[5,7,3],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b":[4,6,0,10],
|
"group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[5,7,5],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07":[4,6,0,8],
|
"group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[5,7,0],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[4,6,0,9],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[5,7,0,0],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[4,6,0,7],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,11],
|
||||||
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[4,6,0,1],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[5,7,0,3],
|
||||||
"group__posix.html":[4,7],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,7],
|
||||||
"group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[4,7,7],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[5,7,0,4],
|
||||||
"group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[4,7,3],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[5,7,0,5],
|
||||||
"group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[4,7,1],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,13],
|
||||||
"group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[4,7,6],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,14],
|
||||||
"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[4,7,15],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[5,7,0,2],
|
||||||
"group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[4,7,2],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07":[5,7,0,9],
|
||||||
"group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[4,7,5],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,10],
|
||||||
"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[4,7,16],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2":[5,7,0,6],
|
||||||
"group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[4,7,8],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,8],
|
||||||
"group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545":[4,7,9],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,12],
|
||||||
"group__posix.html#gab5e29558926d934c3f1cae8c815f942c":[4,7,11],
|
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[5,7,0,1],
|
||||||
"group__posix.html#gacff84f226ba9feb2031b8992e5579447":[4,7,13],
|
"group__posix.html":[5,8],
|
||||||
"group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[4,7,0],
|
"group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[5,8,7],
|
||||||
"group__posix.html#gae01389eedab8d67341ff52e2aad80ebb":[4,7,4],
|
"group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[5,8,3],
|
||||||
"group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a":[4,7,12],
|
"group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[5,8,1],
|
||||||
"group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e":[4,7,14],
|
"group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[5,8,6],
|
||||||
"group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3":[4,7,10],
|
"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,15],
|
||||||
"group__typed.html":[4,4],
|
"group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[5,8,2],
|
||||||
"group__typed.html#ga0619a62c5fd886f1016030abe91f0557":[4,4,6],
|
"group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[5,8,5],
|
||||||
"group__typed.html#ga1158b49a55dfa81f58a4426a7578f523":[4,4,8],
|
"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,16],
|
||||||
"group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74":[4,4,1],
|
"group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[5,8,8],
|
||||||
"group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7":[4,4,2],
|
"group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545":[5,8,9],
|
||||||
"group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83":[4,4,3],
|
"group__posix.html#gab5e29558926d934c3f1cae8c815f942c":[5,8,11],
|
||||||
"group__typed.html#gac77a61bdaf680a803785fe307820b48c":[4,4,9],
|
"group__posix.html#gacff84f226ba9feb2031b8992e5579447":[5,8,13],
|
||||||
"group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe":[4,4,5],
|
"group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[5,8,0],
|
||||||
"group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b":[4,4,7],
|
"group__posix.html#gae01389eedab8d67341ff52e2aad80ebb":[5,8,4],
|
||||||
"group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07":[4,4,0],
|
"group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a":[5,8,12],
|
||||||
"group__typed.html#gaf213d5422ec35e7f6caad827c79bc948":[4,4,4],
|
"group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e":[5,8,14],
|
||||||
|
"group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3":[5,8,10],
|
||||||
|
"group__typed.html":[5,5],
|
||||||
|
"group__typed.html#ga0619a62c5fd886f1016030abe91f0557":[5,5,7],
|
||||||
|
"group__typed.html#ga1158b49a55dfa81f58a4426a7578f523":[5,5,9],
|
||||||
|
"group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e":[5,5,5],
|
||||||
|
"group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74":[5,5,1],
|
||||||
|
"group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7":[5,5,2],
|
||||||
|
"group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83":[5,5,3],
|
||||||
|
"group__typed.html#gac77a61bdaf680a803785fe307820b48c":[5,5,10],
|
||||||
|
"group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe":[5,5,6],
|
||||||
|
"group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b":[5,5,8],
|
||||||
|
"group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07":[5,5,0],
|
||||||
|
"group__typed.html#gaf213d5422ec35e7f6caad827c79bc948":[5,5,4],
|
||||||
|
"group__zeroinit.html":[5,4],
|
||||||
|
"group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664":[5,4,4],
|
||||||
|
"group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f":[5,4,6],
|
||||||
|
"group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7":[5,4,2],
|
||||||
|
"group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9":[5,4,7],
|
||||||
|
"group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd":[5,4,0],
|
||||||
|
"group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6":[5,4,8],
|
||||||
|
"group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3":[5,4,1],
|
||||||
|
"group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb":[5,4,5],
|
||||||
|
"group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0":[5,4,9],
|
||||||
|
"group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76":[5,4,3],
|
||||||
|
"group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1":[5,4,10],
|
||||||
"index.html":[],
|
"index.html":[],
|
||||||
"modules.html":[4],
|
"modules.html":[5],
|
||||||
"overrides.html":[2],
|
"overrides.html":[3],
|
||||||
"pages.html":[],
|
"pages.html":[],
|
||||||
"using.html":[1]
|
"using.html":[1]
|
||||||
};
|
};
|
||||||
|
@ -118,9 +118,10 @@ $(document).ready(function(){initNavTree('overrides.html','');});
|
|||||||
<p>Note that certain security restrictions may apply when doing this from the <a href="https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash">shell</a>.</p>
|
<p>Note that certain security restrictions may apply when doing this from the <a href="https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash">shell</a>.</p>
|
||||||
<p>Note: unfortunately, at this time, dynamic overriding on macOS seems broken but it is actively worked on to fix this (see issue <a href="https://github.com/microsoft/mimalloc/issues/50"><code>#50</code></a>).</p>
|
<p>Note: unfortunately, at this time, dynamic overriding on macOS seems broken but it is actively worked on to fix this (see issue <a href="https://github.com/microsoft/mimalloc/issues/50"><code>#50</code></a>).</p>
|
||||||
<h3>Windows</h3>
|
<h3>Windows</h3>
|
||||||
<p>On Windows you need to link your program explicitly with the mimalloc DLL, and use the C-runtime library as a DLL (the <code>/MD</code> or <code>/MDd</code> switch). To ensure the mimalloc DLL gets loaded it is easiest to insert some call to the mimalloc API in the <code>main</code> function, like <code>mi_version()</code> (or use the <code>/INCLUDE:mi_version</code> switch on the linker)</p>
|
<p>On Windows you need to link your program explicitly with the mimalloc DLL and use the C-runtime library as a DLL (using the <code>/MD</code> or <code>/MDd</code> switch). Moreover, you need to ensure the <code>mimalloc-redirect.dll</code> (or <code>mimalloc-redirect32.dll</code>) is available in the same folder as the mimalloc DLL at runtime (as it as referred to by the mimalloc DLL). The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc.</p>
|
||||||
<p>Due to the way mimalloc intercepts the standard malloc at runtime, it is best to link to the mimalloc import library first on the command line so it gets loaded right after the universal C runtime DLL (<code>ucrtbase</code>). See the <code>mimalloc-override-test</code> project for an example.</p>
|
<p>To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some call to the mimalloc API in the <code>main</code> function, like <code>mi_version()</code> (or use the <code>/INCLUDE:mi_version</code> switch on the linker). See the <code>mimalloc-override-test</code> project for an example on how to use this.</p>
|
||||||
<p>Note: the current overriding on Windows works for most programs but some programs still have trouble – the <code>dev-exp</code> branch contains a newer way of overriding that is more robust; try this out if you experience troubles.</p>
|
<p>The environment variable <code>MIMALLOC_DISABLE_REDIRECT=1</code> can be used to disable dynamic overriding at run-time. Use <code>MIMALLOC_VERBOSE=1</code> to check if mimalloc successfully redirected.</p>
|
||||||
|
<p>(Note: in principle, it should be possible to patch existing executables that are linked with the dynamic C runtime (<code>ucrtbase.dll</code>) by just putting the mimalloc DLL into the import table (and putting <code>mimalloc-redirect.dll</code> in the same folder) Such patching can be done for example with <a href="https://ntcore.com/?page_id=388">CFF Explorer</a>).</p>
|
||||||
<h2>Static override</h2>
|
<h2>Static override</h2>
|
||||||
<p>On Unix systems, you can also statically link with <em>mimalloc</em> to override the standard malloc interface. The recommended way is to link the final program with the <em>mimalloc</em> single object file (<code>mimalloc-override.o</code>). 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 <em>mimalloc</em> library, link it as the first object file. For example:</p>
|
<p>On Unix systems, you can also statically link with <em>mimalloc</em> to override the standard malloc interface. The recommended way is to link the final program with the <em>mimalloc</em> single object file (<code>mimalloc-override.o</code>). 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 <em>mimalloc</em> library, link it as the first object file. For example:</p>
|
||||||
<div class="fragment"><div class="line">gcc -o myprogram mimalloc-<span class="keyword">override</span>.o myfile1.c ...</div></div><!-- fragment --><h2>List of Overrides:</h2>
|
<div class="fragment"><div class="line">gcc -o myprogram mimalloc-<span class="keyword">override</span>.o myfile1.c ...</div></div><!-- fragment --><h2>List of Overrides:</h2>
|
||||||
|
@ -106,8 +106,9 @@ $(document).ready(function(){initNavTree('pages.html','');});
|
|||||||
<table class="directory">
|
<table class="directory">
|
||||||
<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="build.html" target="_self">Building</a></td><td class="desc"></td></tr>
|
<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="build.html" target="_self">Building</a></td><td class="desc"></td></tr>
|
||||||
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="using.html" target="_self">Using the library</a></td><td class="desc"></td></tr>
|
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="using.html" target="_self">Using the library</a></td><td class="desc"></td></tr>
|
||||||
<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="overrides.html" target="_self">Overriding Malloc</a></td><td class="desc"></td></tr>
|
<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="environment.html" target="_self">Environment Options</a></td><td class="desc"></td></tr>
|
||||||
<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="bench.html" target="_self">Performance</a></td><td class="desc"></td></tr>
|
<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="overrides.html" target="_self">Overriding Malloc</a></td><td class="desc"></td></tr>
|
||||||
|
<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="bench.html" target="_self">Performance</a></td><td class="desc"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div><!-- directory -->
|
</div><!-- directory -->
|
||||||
</div><!-- contents -->
|
</div><!-- contents -->
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
var searchData=
|
var searchData=
|
||||||
[
|
[
|
||||||
|
['environment_20options',['Environment Options',['../environment.html',1,'']]],
|
||||||
['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]]
|
['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]]
|
||||||
];
|
];
|
||||||
|
@ -23,6 +23,7 @@ var searchData=
|
|||||||
['mi_5fheap_5fcalloc_5faligned_5fat',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',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_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_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_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_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_5fdestroy',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
|
||||||
@ -31,6 +32,7 @@ var searchData=
|
|||||||
['mi_5fheap_5fmalloc',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',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',['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_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_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',['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_5fmallocn_5ftp',['mi_heap_mallocn_tp',['../group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83',1,'mimalloc-doc.h']]],
|
||||||
@ -42,6 +44,13 @@ var searchData=
|
|||||||
['mi_5fheap_5freallocn',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',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_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_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_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_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_5fstrndup',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
|
||||||
@ -51,6 +60,8 @@ var searchData=
|
|||||||
['mi_5fheap_5fzalloc_5faligned',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',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_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_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',['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',['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_5faligned_5fat',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
|
||||||
@ -67,22 +78,26 @@ var searchData=
|
|||||||
['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
|
['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',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_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#ga6d45a20a3131f18bc351b69763b38ce4',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fenable',['mi_option_enable',['../group__options.html#ga6d45a20a3131f18bc351b69763b38ce4',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fenable_5fdefault',['mi_option_enable_default',['../group__options.html#ga37988264b915a7db92530cc02d5494cb',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fenable_5fdefault',['mi_option_enable_default',['../group__options.html#ga37988264b915a7db92530cc02d5494cb',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fenabled',['mi_option_enabled',['../group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fenabled',['mi_option_enabled',['../group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fget',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fget',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5flarge_5fos_5fpages',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',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_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_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5freset_5fdiscards',['mi_option_reset_discards',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fsecure',['mi_option_secure',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f',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',['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_5fdefault',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',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_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_5ft',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',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#ga2bed6d40b74591a67f81daea4b4a246f',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
|
['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fpvalloc',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',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',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
|
||||||
@ -94,15 +109,23 @@ var searchData=
|
|||||||
['mi_5freallocn_5ftp',['mi_reallocn_tp',['../group__typed.html#ga1158b49a55dfa81f58a4426a7578f523',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_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',['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#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]],
|
['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]],
|
||||||
|
['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5',1,'mimalloc-doc.h']]],
|
||||||
|
['mi_5freserve_5fhuge_5fos_5fpages',['mi_reserve_huge_os_pages',['../group__extended.html#ga2664f36a2dd557741c429cb799f04641',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_5fsmall_5fsize_5fmax',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga6bb821ca1b664b452112c0e17b15fcf1',1,'mimalloc-doc.h']]],
|
['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga9883b8a059aed7eb0888a01ec1461161',1,'mimalloc-doc.h']]],
|
['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01',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_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',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#gac0f4849256aaf677f334690952c6ebbd',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#ga9398517f01a1ec971244aa0db084ea46',1,'mimalloc-doc.h']]],
|
['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga490826cbd7c494acc9fe69be23f018ac',1,'mimalloc-doc.h']]],
|
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga489670a15d1a257ab4639e645ee4612a',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',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_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',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
|
||||||
|
@ -2,12 +2,15 @@ var searchData=
|
|||||||
[
|
[
|
||||||
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',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_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_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_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_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5freset_5fdiscards',['mi_option_reset_discards',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cab3a837b5ceee250e14e051dbee2a441b',1,'mimalloc-doc.h']]],
|
['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fsecure',['mi_option_secure',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca083ee20765063fc6d727e11d33cf378f',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_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_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
|
||||||
['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
|
['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
|
||||||
|
@ -18,6 +18,7 @@ var searchData=
|
|||||||
['mi_5fheap_5fcalloc_5faligned',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',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_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_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_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_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_5fdestroy',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
|
||||||
@ -26,6 +27,7 @@ var searchData=
|
|||||||
['mi_5fheap_5fmalloc',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',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',['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_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_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_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',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
|
||||||
@ -34,6 +36,12 @@ var searchData=
|
|||||||
['mi_5fheap_5freallocf',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',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',['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_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_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_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_5fstrndup',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
|
||||||
@ -41,6 +49,8 @@ var searchData=
|
|||||||
['mi_5fheap_5fzalloc',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',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',['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_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',['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',['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_5faligned_5fat',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
|
||||||
@ -69,14 +79,22 @@ var searchData=
|
|||||||
['mi_5freallocn',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',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_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',['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#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]],
|
['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga6bb821ca1b664b452112c0e17b15fcf1',1,'mimalloc-doc.h']]],
|
['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga9883b8a059aed7eb0888a01ec1461161',1,'mimalloc-doc.h']]],
|
['mi_5freserve_5fhuge_5fos_5fpages',['mi_reserve_huge_os_pages',['../group__extended.html#ga2664f36a2dd557741c429cb799f04641',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#ga8ca07ccff283956d71f48272f4fd5c01',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_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',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#gac0f4849256aaf677f334690952c6ebbd',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#ga9398517f01a1ec971244aa0db084ea46',1,'mimalloc-doc.h']]],
|
['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga490826cbd7c494acc9fe69be23f018ac',1,'mimalloc-doc.h']]],
|
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga489670a15d1a257ab4639e645ee4612a',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',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_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',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
var searchData=
|
var searchData=
|
||||||
[
|
[
|
||||||
['overriding_20malloc',['Overriding Malloc',['../overrides.html',1,'']]]
|
['environment_20options',['Environment Options',['../environment.html',1,'']]]
|
||||||
];
|
];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
var searchData=
|
var searchData=
|
||||||
[
|
[
|
||||||
['performance',['Performance',['../bench.html',1,'']]]
|
['overriding_20malloc',['Overriding Malloc',['../overrides.html',1,'']]]
|
||||||
];
|
];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
var searchData=
|
var searchData=
|
||||||
[
|
[
|
||||||
['using_20the_20library',['Using the library',['../using.html',1,'']]]
|
['performance',['Performance',['../bench.html',1,'']]]
|
||||||
];
|
];
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
var indexSectionsWithContent =
|
var indexSectionsWithContent =
|
||||||
{
|
{
|
||||||
0: "_abcehmoprtu",
|
0: "_abcehmoprtuz",
|
||||||
1: "m",
|
1: "m",
|
||||||
2: "m",
|
2: "m",
|
||||||
3: "bcru",
|
3: "bcru",
|
||||||
4: "m",
|
4: "m",
|
||||||
5: "m",
|
5: "m",
|
||||||
6: "_m",
|
6: "_m",
|
||||||
7: "abehprt",
|
7: "abehprtz",
|
||||||
8: "bopu"
|
8: "beopu"
|
||||||
};
|
};
|
||||||
|
|
||||||
var indexSectionNames =
|
var indexSectionNames =
|
||||||
|
@ -2,5 +2,6 @@ var searchData=
|
|||||||
[
|
[
|
||||||
['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
|
['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#ga22213691c3ce5ab4d91b24aff1023529',1,'mimalloc-doc.h']]],
|
['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga22213691c3ce5ab4d91b24aff1023529',1,'mimalloc-doc.h']]],
|
||||||
['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',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#ga2bed6d40b74591a67f81daea4b4a246f',1,'mimalloc-doc.h']]]
|
||||||
];
|
];
|
||||||
|
@ -104,16 +104,7 @@ $(document).ready(function(){initNavTree('using.html','');});
|
|||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div class="textblock"><p>The preferred usage is including <code><mimalloc.h></code>, linking with the shared- or static library, and using the <code>mi_malloc</code> API exclusively for allocation. For example, </p><div class="fragment"><div class="line">gcc -o myprogram -lmimalloc myfile.c</div></div><!-- fragment --><p>mimalloc uses only safe OS calls (<code>mmap</code> and <code>VirtualAlloc</code>) and can co-exist with other allocators linked to the same program. If you use <code>cmake</code>, you can simply use: </p><div class="fragment"><div class="line">find_package(mimalloc 1.0 REQUIRED)</div></div><!-- fragment --><p> in your <code>CMakeLists.txt</code> to find a locally installed mimalloc. Then use either: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc)</div></div><!-- fragment --><p> to link with the shared (dynamic) library, or: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc-<span class="keyword">static</span>)</div></div><!-- fragment --><p> to link with the static library. See <code>test\CMakeLists.txt</code> for an example.</p>
|
<div class="textblock"><p>The preferred usage is including <code><mimalloc.h></code>, linking with the shared- or static library, and using the <code>mi_malloc</code> API exclusively for allocation. For example, </p><div class="fragment"><div class="line">gcc -o myprogram -lmimalloc myfile.c</div></div><!-- fragment --><p>mimalloc uses only safe OS calls (<code>mmap</code> and <code>VirtualAlloc</code>) and can co-exist with other allocators linked to the same program. If you use <code>cmake</code>, you can simply use: </p><div class="fragment"><div class="line">find_package(mimalloc 1.0 REQUIRED)</div></div><!-- fragment --><p> in your <code>CMakeLists.txt</code> to find a locally installed mimalloc. Then use either: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc)</div></div><!-- fragment --><p> to link with the shared (dynamic) library, or: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc-<span class="keyword">static</span>)</div></div><!-- fragment --><p> to link with the static library. See <code>test\CMakeLists.txt</code> for an example.</p>
|
||||||
<p>You can pass environment variables to print verbose messages (<code>MIMALLOC_VERBOSE=1</code>) and statistics (<code>MIMALLOC_SHOW_STATS=1</code>) (in the debug version): </p><div class="fragment"><div class="line">> env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363</div><div class="line"></div><div class="line">175451865205073170563711388363 = 374456281610909315237213 * 468551</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line">normal 2: 16.4 kb 17.5 mb 17.5 mb 16 b ok</div><div class="line">normal 3: 16.3 kb 15.2 mb 15.2 mb 24 b ok</div><div class="line">normal 4: 64 b 4.6 kb 4.6 kb 32 b ok</div><div class="line">normal 5: 80 b 118.4 kb 118.4 kb 40 b ok</div><div class="line">normal 6: 48 b 48 b 48 b 48 b ok</div><div class="line">normal 17: 960 b 960 b 960 b 320 b ok</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line"> normal: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line"> huge: 0 b 0 b 0 b 1 b ok</div><div class="line"> total: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line">malloc requested: 32.8 mb</div><div class="line"></div><div class="line"> committed: 58.2 kb 58.2 kb 58.2 kb 1 b ok</div><div class="line"> reserved: 2.0 mb 2.0 mb 2.0 mb 1 b ok</div><div class="line"> reset: 0 b 0 b 0 b 1 b ok</div><div class="line"> segments: 1 1 1</div><div class="line">-abandoned: 0</div><div class="line"> pages: 6 6 6</div><div class="line">-abandoned: 0</div><div class="line"> mmaps: 3</div><div class="line"> mmap fast: 0</div><div class="line"> mmap slow: 1</div><div class="line"> threads: 0</div><div class="line"> elapsed: 2.022s</div><div class="line"> process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb</div></div><!-- fragment --><p>The above model of using the <code>mi_</code> 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 <em>mimalloc</em> library instead.</p>
|
<p>You can pass environment variables to print verbose messages (<code>MIMALLOC_VERBOSE=1</code>) and statistics (<code>MIMALLOC_SHOW_STATS=1</code>) (in the debug version): </p><div class="fragment"><div class="line">> env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363</div><div class="line"></div><div class="line">175451865205073170563711388363 = 374456281610909315237213 * 468551</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line">normal 2: 16.4 kb 17.5 mb 17.5 mb 16 b ok</div><div class="line">normal 3: 16.3 kb 15.2 mb 15.2 mb 24 b ok</div><div class="line">normal 4: 64 b 4.6 kb 4.6 kb 32 b ok</div><div class="line">normal 5: 80 b 118.4 kb 118.4 kb 40 b ok</div><div class="line">normal 6: 48 b 48 b 48 b 48 b ok</div><div class="line">normal 17: 960 b 960 b 960 b 320 b ok</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line"> normal: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line"> huge: 0 b 0 b 0 b 1 b ok</div><div class="line"> total: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line">malloc requested: 32.8 mb</div><div class="line"></div><div class="line"> committed: 58.2 kb 58.2 kb 58.2 kb 1 b ok</div><div class="line"> reserved: 2.0 mb 2.0 mb 2.0 mb 1 b ok</div><div class="line"> reset: 0 b 0 b 0 b 1 b ok</div><div class="line"> segments: 1 1 1</div><div class="line">-abandoned: 0</div><div class="line"> pages: 6 6 6</div><div class="line">-abandoned: 0</div><div class="line"> mmaps: 3</div><div class="line"> mmap fast: 0</div><div class="line"> mmap slow: 1</div><div class="line"> threads: 0</div><div class="line"> elapsed: 2.022s</div><div class="line"> process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb</div></div><!-- fragment --><p>The above model of using the <code>mi_</code> 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 <em>mimalloc</em> library instead.</p>
|
||||||
<p>See <a class="el" href="overrides.html">Overriding Malloc</a> for more info.</p>
|
<p>See <a class="el" href="overrides.html">Overriding Malloc</a> for more info. </p>
|
||||||
<h2>Environment Options</h2>
|
|
||||||
<p>You can set further options either programmatically (using <a href="https://microsoft.github.io/mimalloc/group__options.html"><code>mi_option_set</code></a>), or via environment variables.</p>
|
|
||||||
<ul>
|
|
||||||
<li><code>MIMALLOC_SHOW_STATS=1</code>: show statistics when the program terminates.</li>
|
|
||||||
<li><code>MIMALLOC_VERBOSE=1</code>: show verbose messages.</li>
|
|
||||||
<li><code>MIMALLOC_SHOW_ERRORS=1</code>: show error and warning messages.</li>
|
|
||||||
<li><code>MIMALLOC_LARGE_OS_PAGES=1</code>: use large OS pages when available; for some workloads this can significantly improve performance. Use <code>MIMALLOC_VERBOSE</code> to check if the large OS pages are enabled – usually one needs to explicitly allow large OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>).</li>
|
|
||||||
<li><code>MIMALLOC_EAGER_REGION_COMMIT=1</code>: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions show in the working set even though usually just a small part is committed to physical memory. This is why it turned off by default on Windows as it looks not good in the task manager. However, in reality it is always better to turn it on as it improves performance and has no other drawbacks. </li>
|
|
||||||
</ul>
|
|
||||||
</div></div><!-- PageDoc -->
|
</div></div><!-- PageDoc -->
|
||||||
</div><!-- contents -->
|
</div><!-- contents -->
|
||||||
</div><!-- doc-content -->
|
</div><!-- doc-content -->
|
||||||
|
@ -100,7 +100,8 @@
|
|||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent />
|
<PostBuildEvent />
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
<Command>
|
||||||
|
</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -123,7 +124,8 @@
|
|||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent />
|
<PostBuildEvent />
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
<Command>
|
||||||
|
</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -145,7 +147,8 @@
|
|||||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
<Command>
|
||||||
|
</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -169,7 +172,8 @@
|
|||||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
<Command>
|
||||||
|
</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -101,15 +101,20 @@
|
|||||||
<CompileAs>Default</CompileAs>
|
<CompileAs>Default</CompileAs>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy mimalloc-redirect32.dll to the output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -124,17 +129,16 @@
|
|||||||
<CompileAs>Default</CompileAs>
|
<CompileAs>Default</CompileAs>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
||||||
@ -159,13 +163,18 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy mimalloc-redirect32.dll to the output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -186,15 +195,14 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>COPY /Y $(SolutionDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
||||||
@ -204,6 +212,7 @@
|
|||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-atomic.h" />
|
<ClInclude Include="..\..\include\mimalloc-atomic.h" />
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-override.h" />
|
<ClInclude Include="..\..\include\mimalloc-override.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-types.h" />
|
<ClInclude Include="..\..\include\mimalloc-types.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -214,7 +223,6 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\alloc-override-win.c" />
|
|
||||||
<ClCompile Include="..\..\src\alloc-override.c">
|
<ClCompile Include="..\..\src\alloc-override.c">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
<ClInclude Include="..\..\include\mimalloc-override.h">
|
<ClInclude Include="..\..\include\mimalloc-override.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\alloc.c">
|
<ClCompile Include="..\..\src\alloc.c">
|
||||||
@ -67,8 +70,5 @@
|
|||||||
<ClCompile Include="..\..\src\alloc-posix.c">
|
<ClCompile Include="..\..\src\alloc-posix.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\alloc-override-win.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -149,8 +149,8 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="mimalloc.vcxproj">
|
<ProjectReference Include="mimalloc-override.vcxproj">
|
||||||
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
|
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -238,6 +238,7 @@
|
|||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-atomic.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-atomic.h" />
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h" />
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h" />
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -70,5 +70,8 @@
|
|||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h">
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -90,10 +90,19 @@
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent />
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -103,14 +112,21 @@
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EntryPointSymbol>
|
<EntryPointSymbol>
|
||||||
</EntryPointSymbol>
|
</EntryPointSymbol>
|
||||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent />
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -128,7 +144,12 @@
|
|||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -150,15 +171,19 @@
|
|||||||
</EntryPointSymbol>
|
</EntryPointSymbol>
|
||||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\test\main-override.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="mimalloc-override.vcxproj">
|
<ProjectReference Include="mimalloc-override.vcxproj">
|
||||||
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
|
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\test\main-override.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@ -46,7 +45,6 @@
|
|||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
@ -70,21 +68,25 @@
|
|||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.dll</TargetExt>
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<TargetName>mimalloc-override</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.dll</TargetExt>
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<TargetName>mimalloc-override</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.dll</TargetExt>
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<TargetName>mimalloc-override</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.dll</TargetExt>
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<TargetName>mimalloc-override</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -93,26 +95,26 @@
|
|||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;_MBCS;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>
|
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>
|
|
||||||
</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<Link>
|
<Link>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy mimalloc-redirect32.dll to the output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -121,26 +123,26 @@
|
|||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;_MBCS;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>
|
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>
|
|
||||||
</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<Link>
|
<Link>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -148,30 +150,30 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;_MBCS;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
||||||
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect32.dll $(OutputPath)</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Message>
|
<Message>Copy mimalloc-redirect32.dll to the output directory</Message>
|
||||||
</Message>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -180,36 +182,38 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;_MBCS;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
||||||
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<EntryPointSymbol>DllEntry</EntryPointSymbol>
|
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<ModuleDefinitionFile>
|
<ModuleDefinitionFile>
|
||||||
</ModuleDefinitionFile>
|
</ModuleDefinitionFile>
|
||||||
|
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>
|
<Command>COPY /Y $(ProjectDir)..\..\bin\mimalloc-redirect.dll $(OutputPath)</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Message>
|
<Message>copy mimalloc-redirect.dll to the output directory</Message>
|
||||||
</Message>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-atomic.h" />
|
<ClInclude Include="..\..\include\mimalloc-atomic.h" />
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h" />
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-override.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-types.h" />
|
<ClInclude Include="..\..\include\mimalloc-types.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -219,7 +223,12 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\alloc-override-win.c" />
|
<ClCompile Include="..\..\src\alloc-override.c">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\alloc-posix.c" />
|
<ClCompile Include="..\..\src\alloc-posix.c" />
|
||||||
<ClCompile Include="..\..\src\alloc.c" />
|
<ClCompile Include="..\..\src\alloc.c" />
|
||||||
<ClCompile Include="..\..\src\heap.c" />
|
<ClCompile Include="..\..\src\heap.c" />
|
||||||
|
@ -67,19 +67,19 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
@ -149,8 +149,8 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="mimalloc.vcxproj">
|
<ProjectReference Include="mimalloc-override.vcxproj">
|
||||||
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
|
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -67,19 +67,19 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</OutDir>
|
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
@ -144,19 +144,14 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\test\test-api.c">
|
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AssemblyAndSourceCode</AssemblerOutput>
|
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AssemblyAndSourceCode</AssemblerOutput>
|
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AssemblyAndSourceCode</AssemblerOutput>
|
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AssemblyAndSourceCode</AssemblerOutput>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="mimalloc.vcxproj">
|
<ProjectReference Include="mimalloc.vcxproj">
|
||||||
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
|
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\test\main-override-static.c" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@ -70,21 +70,25 @@
|
|||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.lib</TargetExt>
|
<TargetExt>.lib</TargetExt>
|
||||||
|
<TargetName>mimalloc-static</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.lib</TargetExt>
|
<TargetExt>.lib</TargetExt>
|
||||||
|
<TargetName>mimalloc-static</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.lib</TargetExt>
|
<TargetExt>.lib</TargetExt>
|
||||||
|
<TargetName>mimalloc-static</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
<TargetExt>.lib</TargetExt>
|
<TargetExt>.lib</TargetExt>
|
||||||
|
<TargetName>mimalloc-static</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -94,8 +98,9 @@
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
||||||
<CompileAs>Default</CompileAs>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>
|
||||||
@ -112,8 +117,9 @@
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
||||||
<CompileAs>Default</CompileAs>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>
|
<Command>
|
||||||
@ -135,8 +141,6 @@
|
|||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
||||||
@ -144,11 +148,9 @@
|
|||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<OmitFramePointers>false</OmitFramePointers>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
|
||||||
<CompileAs>Default</CompileAs>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
@ -166,8 +168,6 @@
|
|||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
||||||
@ -175,11 +175,9 @@
|
|||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<OmitFramePointers>false</OmitFramePointers>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
|
||||||
<CompileAs>Default</CompileAs>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
@ -211,12 +209,6 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\alloc-override-win.c">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\src\alloc-override.c">
|
<ClCompile Include="..\..\src\alloc-override.c">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
@ -243,8 +235,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h" />
|
||||||
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-atomic.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-atomic.h" />
|
||||||
<ClInclude Include="..\..\include\mimalloc-types.h" />
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h" />
|
||||||
|
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h" />
|
||||||
|
<ClInclude Include="..\..\include\mimalloc-new-delete.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -10,7 +10,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
|
|
||||||
#include "mimalloc-types.h"
|
#include "mimalloc-types.h"
|
||||||
|
|
||||||
#if defined(MI_MALLOC_OVERRIDE) && defined(__APPLE__)
|
#if defined(MI_MALLOC_OVERRIDE) && (defined(__APPLE__) || defined(__OpenBSD__))
|
||||||
#define MI_TLS_RECURSE_GUARD
|
#define MI_TLS_RECURSE_GUARD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -20,9 +20,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
#define mi_trace_message(...)
|
#define mi_trace_message(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// "options.c"
|
// "options.c"
|
||||||
void _mi_fprintf(FILE* out, const char* fmt, ...);
|
void _mi_fputs(mi_output_fun* out, const char* prefix, const char* message);
|
||||||
|
void _mi_fprintf(mi_output_fun* out, const char* fmt, ...);
|
||||||
void _mi_error_message(const char* fmt, ...);
|
void _mi_error_message(const char* fmt, ...);
|
||||||
void _mi_warning_message(const char* fmt, ...);
|
void _mi_warning_message(const char* fmt, ...);
|
||||||
void _mi_verbose_message(const char* fmt, ...);
|
void _mi_verbose_message(const char* fmt, ...);
|
||||||
@ -43,15 +43,15 @@ size_t _mi_os_page_size(void);
|
|||||||
void _mi_os_init(void); // called from process init
|
void _mi_os_init(void); // called from process init
|
||||||
void* _mi_os_alloc(size_t size, mi_stats_t* stats); // to allocate thread local data
|
void* _mi_os_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
|
void _mi_os_free(void* p, size_t size, mi_stats_t* stats); // to free thread local data
|
||||||
|
size_t _mi_os_good_alloc_size(size_t size);
|
||||||
|
|
||||||
// memory.c
|
// memory.c
|
||||||
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool commit, size_t* id, mi_os_tld_t* tld);
|
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld);
|
||||||
void* _mi_mem_alloc(size_t size, bool commit, size_t* id, mi_os_tld_t* tld);
|
|
||||||
void _mi_mem_free(void* p, size_t size, size_t id, mi_stats_t* stats);
|
void _mi_mem_free(void* p, size_t size, size_t id, mi_stats_t* stats);
|
||||||
|
|
||||||
bool _mi_mem_reset(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_mem_reset(void* p, size_t size, mi_stats_t* stats);
|
||||||
bool _mi_mem_unreset(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
|
||||||
bool _mi_mem_commit(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
|
||||||
bool _mi_mem_protect(void* addr, size_t size);
|
bool _mi_mem_protect(void* addr, size_t size);
|
||||||
bool _mi_mem_unprotect(void* addr, size_t size);
|
bool _mi_mem_unprotect(void* addr, size_t size);
|
||||||
|
|
||||||
@ -101,6 +101,7 @@ void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero);
|
|||||||
void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero);
|
void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero);
|
||||||
mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p);
|
mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p);
|
||||||
bool _mi_free_delayed_block(mi_block_t* block);
|
bool _mi_free_delayed_block(mi_block_t* block);
|
||||||
|
void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size);
|
||||||
|
|
||||||
#if MI_DEBUG>1
|
#if MI_DEBUG>1
|
||||||
bool _mi_page_is_valid(mi_page_t* page);
|
bool _mi_page_is_valid(mi_page_t* page);
|
||||||
@ -167,10 +168,12 @@ static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align upwards
|
// Is `x` a power of two? (0 is considered a power of two)
|
||||||
static inline uintptr_t _mi_is_power_of_two(uintptr_t x) {
|
static inline bool _mi_is_power_of_two(uintptr_t x) {
|
||||||
return ((x & (x - 1)) == 0);
|
return ((x & (x - 1)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Align upwards
|
||||||
static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
|
static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
|
||||||
uintptr_t mask = alignment - 1;
|
uintptr_t mask = alignment - 1;
|
||||||
if ((alignment & mask) == 0) { // power of two?
|
if ((alignment & mask) == 0) { // power of two?
|
||||||
@ -181,6 +184,14 @@ static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is memory zero initialized?
|
||||||
|
static inline bool mi_mem_is_zero(void* p, size_t size) {
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if (((uint8_t*)p)[i] != 0) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Align a byte size to a size in _machine words_,
|
// Align a byte size to a size in _machine words_,
|
||||||
// i.e. byte size == `wsize*sizeof(void*)`.
|
// i.e. byte size == `wsize*sizeof(void*)`.
|
||||||
static inline size_t _mi_wsize_from_size(size_t size) {
|
static inline size_t _mi_wsize_from_size(size_t size) {
|
||||||
@ -188,6 +199,11 @@ static inline size_t _mi_wsize_from_size(size_t size) {
|
|||||||
return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
|
return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------
|
||||||
|
The thread local default heap
|
||||||
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap
|
extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap
|
||||||
extern mi_heap_t _mi_heap_main; // statically allocated main backing heap
|
extern mi_heap_t _mi_heap_main; // statically allocated main backing heap
|
||||||
extern bool _mi_process_is_initialized;
|
extern bool _mi_process_is_initialized;
|
||||||
@ -219,6 +235,10 @@ static inline bool mi_heap_is_initialized(mi_heap_t* heap) {
|
|||||||
return (heap != &_mi_heap_empty);
|
return (heap != &_mi_heap_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------
|
||||||
|
Pages
|
||||||
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) {
|
static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) {
|
||||||
mi_assert_internal(size <= MI_SMALL_SIZE_MAX);
|
mi_assert_internal(size <= MI_SMALL_SIZE_MAX);
|
||||||
return heap->pages_free_direct[_mi_wsize_from_size(size)];
|
return heap->pages_free_direct[_mi_wsize_from_size(size)];
|
||||||
@ -229,7 +249,6 @@ static inline mi_page_t* _mi_get_free_small_page(size_t size) {
|
|||||||
return _mi_heap_get_free_small_page(mi_get_default_heap(), size);
|
return _mi_heap_get_free_small_page(mi_get_default_heap(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Segment that contains the pointer
|
// Segment that contains the pointer
|
||||||
static inline mi_segment_t* _mi_ptr_segment(const void* p) {
|
static inline mi_segment_t* _mi_ptr_segment(const void* p) {
|
||||||
// mi_assert_internal(p != NULL);
|
// mi_assert_internal(p != NULL);
|
||||||
|
52
include/mimalloc-new-delete.h
Normal file
52
include/mimalloc-new-delete.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2018,2019 Microsoft Research, Daan Leijen
|
||||||
|
This is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the MIT license. A copy of the license can be found in the file
|
||||||
|
"LICENSE" at the root of this distribution.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef MIMALLOC_NEW_DELETE_H
|
||||||
|
#define MIMALLOC_NEW_DELETE_H
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This header provides convenient overrides for the new and
|
||||||
|
// delete operations in C++.
|
||||||
|
//
|
||||||
|
// This header should be included in only one source file!
|
||||||
|
//
|
||||||
|
// On Windows, or when linking dynamically with mimalloc, these
|
||||||
|
// can be more performant than the standard new-delete operations.
|
||||||
|
// See <https://en.cppreference.com/w/cpp/memory/new/operator_new>
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#include <new>
|
||||||
|
#include <mimalloc.h>
|
||||||
|
|
||||||
|
void operator delete(void* p) noexcept { mi_free(p); };
|
||||||
|
void operator delete[](void* p) noexcept { mi_free(p); };
|
||||||
|
|
||||||
|
void* operator new(std::size_t n) noexcept(false) { return mi_new(n); }
|
||||||
|
void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); }
|
||||||
|
|
||||||
|
void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); }
|
||||||
|
void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); }
|
||||||
|
|
||||||
|
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||||
|
void operator delete (void* p, std::size_t n) { mi_free_size(p,n); };
|
||||||
|
void operator delete[](void* p, std::size_t n) { mi_free_size(p,n); };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||||
|
void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
|
||||||
|
void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
|
||||||
|
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
|
||||||
|
void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
|
||||||
|
|
||||||
|
void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
|
||||||
|
void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
|
||||||
|
void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
|
||||||
|
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MIMALLOC_NEW_DELETE_H
|
@ -13,14 +13,9 @@ This header can be used to statically redirect malloc/free and new/delete
|
|||||||
to the mimalloc variants. This can be useful if one can include this file on
|
to the mimalloc variants. This can be useful if one can include this file on
|
||||||
each source file in a project (but be careful when using external code to
|
each source file in a project (but be careful when using external code to
|
||||||
not accidentally mix pointers from different allocators).
|
not accidentally mix pointers from different allocators).
|
||||||
|
|
||||||
On windows it can still be good to always try to include this header even
|
|
||||||
when dynamically overriding since this will give better performance especially
|
|
||||||
for new/delete. On Unix dynamic overriding already includes all variants so
|
|
||||||
including this header is not necessary.
|
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "mimalloc.h"
|
#include <mimalloc.h>
|
||||||
|
|
||||||
// Standard C allocation
|
// Standard C allocation
|
||||||
#define malloc(n) mi_malloc(n)
|
#define malloc(n) mi_malloc(n)
|
||||||
@ -68,43 +63,4 @@ including this header is not necessary.
|
|||||||
#define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o)
|
#define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o)
|
||||||
#define _aligned_offset_recalloc(p,s,n,a,o) mi_recalloc_aligned_at(p,s,n,a,o)
|
#define _aligned_offset_recalloc(p,s,n,a,o) mi_recalloc_aligned_at(p,s,n,a,o)
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
// With a C++ compiler we can override all the new/delete operators
|
|
||||||
// by defining 'MIMALLOC_DEFINE_NEW_DELETE' in some source file and
|
|
||||||
// then including this header file. This is not needed when linking
|
|
||||||
// statically with the mimalloc library, but it can be more performant
|
|
||||||
// on Windows when using dynamic overiding as well.
|
|
||||||
// see <https://en.cppreference.com/w/cpp/memory/new/operator_new>
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
#if defined(__cplusplus) && defined(MIMALLOC_DEFINE_NEW_DELETE)
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
void operator delete(void* p) noexcept { mi_free(p); };
|
|
||||||
void operator delete[](void* p) noexcept { mi_free(p); };
|
|
||||||
|
|
||||||
void* operator new(std::size_t n) noexcept(false) { return mi_new(n); }
|
|
||||||
void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); }
|
|
||||||
|
|
||||||
void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); }
|
|
||||||
void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); }
|
|
||||||
|
|
||||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
|
||||||
void operator delete (void* p, std::size_t n) { mi_free_size(p,n); };
|
|
||||||
void operator delete[](void* p, std::size_t n) { mi_free_size(p,n); };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
|
||||||
void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
|
|
||||||
void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
|
|
||||||
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
|
|
||||||
void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
|
|
||||||
|
|
||||||
void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
|
|
||||||
void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
|
|
||||||
void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
|
|
||||||
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // MIMALLOC_OVERRIDE_H
|
#endif // MIMALLOC_OVERRIDE_H
|
||||||
|
@ -68,6 +68,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
|
|
||||||
#define MI_INTPTR_SIZE (1<<MI_INTPTR_SHIFT)
|
#define MI_INTPTR_SIZE (1<<MI_INTPTR_SHIFT)
|
||||||
|
|
||||||
|
#define KiB ((size_t)1024)
|
||||||
|
#define MiB (KiB*KiB)
|
||||||
|
#define GiB (MiB*KiB)
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Main internal data-structures
|
// Main internal data-structures
|
||||||
@ -131,9 +134,11 @@ typedef enum mi_delayed_e {
|
|||||||
// test if both are false (`value == 0`) in the `mi_free` routine.
|
// test if both are false (`value == 0`) in the `mi_free` routine.
|
||||||
typedef union mi_page_flags_u {
|
typedef union mi_page_flags_u {
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
|
uint8_t full_aligned;
|
||||||
struct {
|
struct {
|
||||||
bool in_full;
|
bool in_full:1;
|
||||||
bool has_aligned;
|
bool has_aligned:1;
|
||||||
|
bool is_zero; // `true` if the blocks in the free list are zero initialized
|
||||||
};
|
};
|
||||||
} mi_page_flags_t;
|
} mi_page_flags_t;
|
||||||
|
|
||||||
@ -165,9 +170,10 @@ typedef struct mi_page_s {
|
|||||||
bool segment_in_use:1; // `true` if the segment allocated this page
|
bool segment_in_use:1; // `true` if the segment allocated this page
|
||||||
bool is_reset:1; // `true` if the page memory was reset
|
bool is_reset:1; // `true` if the page memory was reset
|
||||||
bool is_committed:1; // `true` if the page virtual memory is committed
|
bool is_committed:1; // `true` if the page virtual memory is committed
|
||||||
|
bool is_zero_init:1; // `true` if the page was zero initialized
|
||||||
|
|
||||||
// layout like this to optimize access in `mi_malloc` and `mi_free`
|
// layout like this to optimize access in `mi_malloc` and `mi_free`
|
||||||
uint16_t capacity; // number of blocks committed
|
uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear`
|
||||||
uint16_t reserved; // number of blocks reserved in memory
|
uint16_t reserved; // number of blocks reserved in memory
|
||||||
mi_page_flags_t flags; // `in_full` and `has_aligned` flags (16 bits)
|
mi_page_flags_t flags; // `in_full` and `has_aligned` flags (16 bits)
|
||||||
|
|
||||||
@ -207,7 +213,13 @@ typedef enum mi_page_kind_e {
|
|||||||
// the OS. Inside segments we allocated fixed size _pages_ that
|
// the OS. Inside segments we allocated fixed size _pages_ that
|
||||||
// contain blocks.
|
// contain blocks.
|
||||||
typedef struct mi_segment_s {
|
typedef struct mi_segment_s {
|
||||||
struct mi_segment_s* next;
|
// memory fields
|
||||||
|
size_t memid; // id for the os-level memory manager
|
||||||
|
bool mem_is_fixed; // `true` if we cannot decommit/reset/protect in this memory (i.e. when allocated using large OS pages)
|
||||||
|
bool mem_is_committed; // `true` if the whole segment is eagerly committed
|
||||||
|
|
||||||
|
// segment fields
|
||||||
|
struct mi_segment_s* next; // must be the first segment field -- see `segment.c:segment_alloc`
|
||||||
struct mi_segment_s* prev;
|
struct mi_segment_s* prev;
|
||||||
volatile _Atomic(struct mi_segment_s*) abandoned_next;
|
volatile _Atomic(struct mi_segment_s*) abandoned_next;
|
||||||
size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
|
size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
|
||||||
@ -216,7 +228,6 @@ typedef struct mi_segment_s {
|
|||||||
size_t segment_size;// for huge pages this may be different from `MI_SEGMENT_SIZE`
|
size_t segment_size;// for huge pages this may be different from `MI_SEGMENT_SIZE`
|
||||||
size_t segment_info_size; // space we are using from the first page for segment meta-data and possible guard pages.
|
size_t segment_info_size; // space we are using from the first page for segment meta-data and possible guard pages.
|
||||||
uintptr_t cookie; // verify addresses in debug mode: `mi_ptr_cookie(segment) == segment->cookie`
|
uintptr_t cookie; // verify addresses in debug mode: `mi_ptr_cookie(segment) == segment->cookie`
|
||||||
size_t memid; // id for the os-level memory manager
|
|
||||||
|
|
||||||
// layout like this to optimize access in `mi_free`
|
// 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`).
|
size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`).
|
||||||
@ -397,6 +408,7 @@ typedef struct mi_os_tld_s {
|
|||||||
// Thread local data
|
// Thread local data
|
||||||
struct mi_tld_s {
|
struct mi_tld_s {
|
||||||
unsigned long long heartbeat; // monotonic heartbeat count
|
unsigned long long heartbeat; // monotonic heartbeat count
|
||||||
|
bool recurse; // true if deferred was called; used to prevent infinite recursion.
|
||||||
mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted)
|
mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted)
|
||||||
mi_segments_tld_t segments; // segment tld
|
mi_segments_tld_t segments; // segment tld
|
||||||
mi_os_tld_t os; // os tld
|
mi_os_tld_t os; // os tld
|
||||||
|
@ -69,8 +69,8 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
// Includes
|
// Includes
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stddef.h> // size_t
|
||||||
#include <stdbool.h> // bool
|
#include <stdbool.h> // bool
|
||||||
#include <stdio.h> // FILE
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -100,29 +100,37 @@ mi_decl_export mi_decl_allocator void* mi_malloc_small(size_t size) mi_attr_no
|
|||||||
mi_decl_export mi_decl_allocator void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
mi_decl_export mi_decl_allocator void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
||||||
mi_decl_export mi_decl_allocator void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
mi_decl_export mi_decl_allocator void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
||||||
|
|
||||||
mi_decl_export mi_decl_allocator void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept;
|
mi_decl_export mi_decl_allocator void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
|
||||||
mi_decl_export mi_decl_allocator void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept;
|
mi_decl_export mi_decl_allocator void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
||||||
mi_decl_export mi_decl_allocator void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
mi_decl_export mi_decl_allocator void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
|
|
||||||
|
|
||||||
mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
|
mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
|
||||||
mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
|
mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
|
||||||
|
|
||||||
|
typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat);
|
||||||
|
mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free) mi_attr_noexcept;
|
||||||
|
|
||||||
|
typedef void (mi_output_fun)(const char* msg);
|
||||||
|
mi_decl_export void mi_register_output(mi_output_fun* out) mi_attr_noexcept;
|
||||||
|
|
||||||
mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
|
mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
|
||||||
mi_decl_export void mi_stats_print(FILE* out) mi_attr_noexcept;
|
|
||||||
mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
|
|
||||||
mi_decl_export int mi_version(void) mi_attr_noexcept;
|
mi_decl_export int mi_version(void) mi_attr_noexcept;
|
||||||
|
mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
|
||||||
|
mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
|
||||||
|
mi_decl_export void mi_stats_print(mi_output_fun* out) mi_attr_noexcept;
|
||||||
|
|
||||||
mi_decl_export void mi_process_init(void) mi_attr_noexcept;
|
mi_decl_export void mi_process_init(void) mi_attr_noexcept;
|
||||||
mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
|
mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
|
||||||
mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
|
mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
|
||||||
mi_decl_export void mi_thread_stats_print(FILE* out) mi_attr_noexcept;
|
mi_decl_export void mi_thread_stats_print(mi_output_fun* out) mi_attr_noexcept;
|
||||||
|
|
||||||
typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat);
|
|
||||||
mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free) mi_attr_noexcept;
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
// Aligned allocation
|
// Aligned allocation
|
||||||
// ------------------------------------------------------
|
// Note that `alignment` always follows `size` for consistency with unaligned
|
||||||
|
// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
|
||||||
|
// -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
mi_decl_export mi_decl_allocator void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
mi_decl_export mi_decl_allocator void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
||||||
mi_decl_export mi_decl_allocator void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
mi_decl_export mi_decl_allocator 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);
|
||||||
@ -172,6 +180,30 @@ mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned(mi_heap_t* heap,
|
|||||||
mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
|
mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------
|
||||||
|
// Zero initialized re-allocation.
|
||||||
|
// Only valid on memory that was originally allocated with zero initialization too.
|
||||||
|
// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
|
||||||
|
// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
|
||||||
|
// --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
||||||
|
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
||||||
|
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4);
|
||||||
|
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4);
|
||||||
|
mi_decl_export mi_decl_allocator void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4);
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Analysis
|
// Analysis
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@ -194,8 +226,10 @@ typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_
|
|||||||
|
|
||||||
mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
|
mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
|
||||||
|
|
||||||
|
// Experimental
|
||||||
mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
|
mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
|
||||||
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
||||||
|
mi_decl_export bool mi_is_redirected() mi_attr_noexcept;
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Convenience
|
// Convenience
|
||||||
@ -206,12 +240,14 @@ mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size
|
|||||||
#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
|
#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
|
||||||
#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
|
#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
|
||||||
#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
|
#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
|
||||||
|
#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
|
||||||
|
|
||||||
#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
|
#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
|
||||||
#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
|
#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
|
||||||
#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
|
#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
|
||||||
#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
|
#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
|
||||||
#define mi_heap_reallocn_tp(hp,tp,n) ((tp*)mi_heap_reallocn(hp,n,sizeof(tp)))
|
#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
|
||||||
|
#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@ -224,7 +260,6 @@ typedef enum mi_option_e {
|
|||||||
mi_option_show_stats,
|
mi_option_show_stats,
|
||||||
mi_option_verbose,
|
mi_option_verbose,
|
||||||
// the following options are experimental
|
// the following options are experimental
|
||||||
mi_option_secure,
|
|
||||||
mi_option_eager_commit,
|
mi_option_eager_commit,
|
||||||
mi_option_eager_region_commit,
|
mi_option_eager_region_commit,
|
||||||
mi_option_large_os_pages, // implies eager commit
|
mi_option_large_os_pages, // implies eager commit
|
||||||
@ -233,6 +268,9 @@ typedef enum mi_option_e {
|
|||||||
mi_option_page_reset,
|
mi_option_page_reset,
|
||||||
mi_option_cache_reset,
|
mi_option_cache_reset,
|
||||||
mi_option_reset_decommits,
|
mi_option_reset_decommits,
|
||||||
|
mi_option_eager_commit_delay,
|
||||||
|
mi_option_segment_reset,
|
||||||
|
mi_option_os_tag,
|
||||||
_mi_option_last
|
_mi_option_last
|
||||||
} mi_option_t;
|
} mi_option_t;
|
||||||
|
|
||||||
@ -258,18 +296,16 @@ mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
|
|||||||
mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
|
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_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
|
||||||
|
|
||||||
mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
|
mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
|
||||||
mi_decl_export int mi__posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
|
mi_decl_export void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
mi_decl_export mi_decl_allocator void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
mi_decl_export void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
||||||
mi_decl_export mi_decl_allocator void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
|
||||||
|
|
||||||
mi_decl_export mi_decl_allocator void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
mi_decl_export void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
|
||||||
mi_decl_export mi_decl_allocator void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
mi_decl_export void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
|
||||||
mi_decl_export mi_decl_allocator void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
|
||||||
|
|
||||||
mi_decl_export void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept;
|
mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
|
||||||
mi_decl_export void* mi_aligned_recalloc(void* p, size_t size, size_t newcount, size_t alignment) mi_attr_noexcept;
|
mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
|
||||||
mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t size, size_t newcount, size_t alignment, size_t offset) mi_attr_noexcept;
|
|
||||||
|
|
||||||
mi_decl_export unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept;
|
mi_decl_export unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept;
|
||||||
mi_decl_export unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept;
|
mi_decl_export unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept;
|
||||||
|
58
readme.md
58
readme.md
@ -13,7 +13,7 @@ Initially developed by Daan Leijen for the run-time systems of the
|
|||||||
[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages.
|
[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages.
|
||||||
|
|
||||||
It is a drop-in replacement for `malloc` and can be used in other programs
|
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:
|
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/bin/libmimalloc.so myprogram
|
||||||
```
|
```
|
||||||
@ -57,6 +57,7 @@ Enjoy!
|
|||||||
### Releases
|
### Releases
|
||||||
|
|
||||||
* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements.
|
* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements.
|
||||||
|
* 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support.
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ Notes:
|
|||||||
The preferred usage is including `<mimalloc.h>`, linking with
|
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,
|
the shared- or static library, and using the `mi_malloc` API exclusively for allocation. For example,
|
||||||
```
|
```
|
||||||
gcc -o myprogram -lmimalloc myfile.c
|
> gcc -o myprogram -lmimalloc myfile.c
|
||||||
```
|
```
|
||||||
|
|
||||||
mimalloc uses only safe OS calls (`mmap` and `VirtualAlloc`) and can co-exist
|
mimalloc uses only safe OS calls (`mmap` and `VirtualAlloc`) and can co-exist
|
||||||
@ -188,11 +189,17 @@ or via environment variables.
|
|||||||
- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages.
|
- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages.
|
||||||
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages when available; for some workloads this can significantly
|
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages 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
|
improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs
|
||||||
to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]).
|
to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes
|
||||||
|
the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that
|
||||||
|
can have fragmented memory.
|
||||||
- `MIMALLOC_EAGER_REGION_COMMIT=1`: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions
|
- `MIMALLOC_EAGER_REGION_COMMIT=1`: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions
|
||||||
show in the working set even though usually just a small part is committed to physical memory. This is why it
|
show in the working set even though usually just a small part is committed to physical memory. This is why it
|
||||||
turned off by default on Windows as it looks not good in the task manager. However, in reality it is always better
|
turned off by default on Windows as it looks not good in the task manager. However, in reality it is always better
|
||||||
to turn it on as it improves performance and has no other drawbacks.
|
to turn it on as it improves performance and has no other drawbacks.
|
||||||
|
- `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB huge OS pages. This reserves the huge pages at
|
||||||
|
startup and can give quite a performance improvement on long running 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. Still experimental.
|
||||||
|
|
||||||
[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5
|
[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5
|
||||||
[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017
|
[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017
|
||||||
@ -207,20 +214,21 @@ This is the recommended way to override the standard malloc interface.
|
|||||||
|
|
||||||
### Linux, BSD
|
### Linux, BSD
|
||||||
|
|
||||||
On these systems we preload the mimalloc shared
|
On these ELF-based systems we preload the mimalloc shared
|
||||||
library so all calls to the standard `malloc` interface are
|
library so all calls to the standard `malloc` interface are
|
||||||
resolved to the _mimalloc_ library.
|
resolved to the _mimalloc_ library.
|
||||||
|
```
|
||||||
- `env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram`
|
> env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram
|
||||||
|
```
|
||||||
|
|
||||||
You can set extra environment variables to check that mimalloc is running,
|
You can set extra environment variables to check that mimalloc is running,
|
||||||
like:
|
like:
|
||||||
```
|
```
|
||||||
env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram
|
> env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram
|
||||||
```
|
```
|
||||||
or run with the debug version to get detailed statistics:
|
or run with the debug version to get detailed statistics:
|
||||||
```
|
```
|
||||||
env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram
|
> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram
|
||||||
```
|
```
|
||||||
|
|
||||||
### MacOS
|
### MacOS
|
||||||
@ -228,8 +236,9 @@ env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram
|
|||||||
On macOS we can also preload the mimalloc shared
|
On macOS we can also preload the mimalloc shared
|
||||||
library so all calls to the standard `malloc` interface are
|
library so all calls to the standard `malloc` interface are
|
||||||
resolved to the _mimalloc_ library.
|
resolved to the _mimalloc_ library.
|
||||||
|
```
|
||||||
- `env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram`
|
> env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram
|
||||||
|
```
|
||||||
|
|
||||||
Note that certain security restrictions may apply when doing this from
|
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).
|
the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash).
|
||||||
@ -240,33 +249,36 @@ Note: unfortunately, at this time, dynamic overriding on macOS seems broken but
|
|||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
On Windows you need to link your program explicitly with the mimalloc
|
On Windows you need to link your program explicitly with the mimalloc
|
||||||
DLL, and use the C-runtime library as a DLL (the `/MD` or `/MDd` switch).
|
DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
|
||||||
To ensure the mimalloc DLL gets loaded it is easiest to insert some
|
Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available
|
||||||
|
in the same folder as the mimalloc DLL at runtime (as it as referred to by the mimalloc DLL).
|
||||||
|
The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc.
|
||||||
|
|
||||||
|
To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some
|
||||||
call to the mimalloc API in the `main` function, like `mi_version()`
|
call to the mimalloc API in the `main` function, like `mi_version()`
|
||||||
(or use the `/INCLUDE:mi_version` switch on the linker)
|
(or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project
|
||||||
|
for an example on how to use this.
|
||||||
|
|
||||||
Due to the way mimalloc intercepts the standard malloc at runtime, it is best
|
The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic
|
||||||
to link to the mimalloc import library first on the command line so it gets
|
overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc successfully redirected.
|
||||||
loaded right after the universal C runtime DLL (`ucrtbase`). See
|
|
||||||
the `mimalloc-override-test` project for an example.
|
|
||||||
|
|
||||||
Note: the current overriding on Windows works for most programs but some programs still have
|
(Note: in principle, it should be possible to patch existing executables
|
||||||
trouble -- the `dev-exp` branch contains a newer way of overriding that is more
|
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the mimalloc DLL into
|
||||||
robust; try this out if you experience troubles.
|
the import table (and putting `mimalloc-redirect.dll` in the same folder)
|
||||||
|
Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)).
|
||||||
|
|
||||||
|
|
||||||
## Static override
|
## Static override
|
||||||
|
|
||||||
On Unix systems, you can also statically link with _mimalloc_ to override the standard
|
On Unix-like systems, you can also statically link with _mimalloc_ to override the standard
|
||||||
malloc interface. The recommended way is to link the final program with the
|
malloc interface. The recommended way is to link the final program with the
|
||||||
_mimalloc_ single object file (`mimalloc-override.o`). We use
|
_mimalloc_ single object file (`mimalloc-override.o`). We use
|
||||||
an object file instead of a library file as linkers give preference to
|
an object file instead of a library file as linkers give preference to
|
||||||
that over archives to resolve symbols. To ensure that the standard
|
that over archives to resolve symbols. To ensure that the standard
|
||||||
malloc interface resolves to the _mimalloc_ library, link it as the first
|
malloc interface resolves to the _mimalloc_ library, link it as the first
|
||||||
object file. For example:
|
object file. For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
gcc -o myprogram mimalloc-override.o myfile1.c ...
|
> gcc -o myprogram mimalloc-override.o myfile1.c ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,39 +14,47 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
// Aligned Allocation
|
// Aligned Allocation
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset, bool zero) mi_attr_noexcept {
|
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
|
// note: we don't require `size > offset`, we just guarantee that
|
||||||
// the address at offset is aligned regardless of the allocated size.
|
// the address at offset is aligned regardless of the allocated size.
|
||||||
mi_assert(alignment > 0 && alignment % sizeof(uintptr_t) == 0);
|
mi_assert(alignment > 0 && alignment % sizeof(void*) == 0);
|
||||||
if (alignment <= sizeof(uintptr_t)) return _mi_heap_malloc_zero(heap,size,zero);
|
if (mi_unlikely(size > PTRDIFF_MAX)) return NULL; // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)
|
||||||
if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
|
if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>)
|
||||||
|
const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)`
|
||||||
// try if there is a current small block with just the right alignment
|
|
||||||
if (size <= MI_SMALL_SIZE_MAX) {
|
// try if there is a small block available with just the right alignment
|
||||||
|
if (mi_likely(size <= MI_SMALL_SIZE_MAX)) {
|
||||||
mi_page_t* page = _mi_heap_get_free_small_page(heap,size);
|
mi_page_t* page = _mi_heap_get_free_small_page(heap,size);
|
||||||
if (page->free != NULL &&
|
const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0;
|
||||||
(((uintptr_t)page->free + offset) % alignment) == 0)
|
if (mi_likely(page->free != NULL && is_aligned))
|
||||||
{
|
{
|
||||||
#if MI_STAT>1
|
#if MI_STAT>1
|
||||||
mi_heap_stat_increase( heap, malloc, size);
|
mi_heap_stat_increase( heap, malloc, size);
|
||||||
#endif
|
#endif
|
||||||
void* p = _mi_page_malloc(heap,page,size);
|
void* p = _mi_page_malloc(heap,page,size); // TODO: inline _mi_page_malloc
|
||||||
mi_assert_internal(p != NULL);
|
mi_assert_internal(p != NULL);
|
||||||
mi_assert_internal(((uintptr_t)p + offset) % alignment == 0);
|
mi_assert_internal(((uintptr_t)p + offset) % alignment == 0);
|
||||||
if (zero) memset(p,0,size);
|
if (zero) _mi_block_zero_init(page,p,size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use regular allocation if it is guaranteed to fit the alignment constraints
|
||||||
|
if (offset==0 && alignment<=size && size<=MI_MEDIUM_OBJ_SIZE_MAX && (size&align_mask)==0) {
|
||||||
|
void* p = _mi_heap_malloc_zero(heap, size, zero);
|
||||||
|
mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise over-allocate
|
// otherwise over-allocate
|
||||||
void* p = _mi_heap_malloc_zero(heap, size + alignment - 1, zero);
|
void* p = _mi_heap_malloc_zero(heap, size + alignment - 1, zero);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
|
|
||||||
// .. and align within the allocation
|
// .. and align within the allocation
|
||||||
mi_page_set_has_aligned( _mi_ptr_page(p), true );
|
uintptr_t adjust = alignment - (((uintptr_t)p + offset) & align_mask);
|
||||||
uintptr_t adjust = alignment - (((uintptr_t)p + offset) % alignment);
|
|
||||||
mi_assert_internal(adjust % sizeof(uintptr_t) == 0);
|
mi_assert_internal(adjust % sizeof(uintptr_t) == 0);
|
||||||
void* aligned_p = (adjust == alignment ? p : (void*)((uintptr_t)p + adjust));
|
void* aligned_p = (adjust == alignment ? p : (void*)((uintptr_t)p + adjust));
|
||||||
|
if (aligned_p != p) mi_page_set_has_aligned(_mi_ptr_page(p), true);
|
||||||
mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0);
|
mi_assert_internal(((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;
|
return aligned_p;
|
||||||
@ -117,9 +125,16 @@ static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t ne
|
|||||||
void* newp = mi_heap_malloc_aligned_at(heap,newsize,alignment,offset);
|
void* newp = mi_heap_malloc_aligned_at(heap,newsize,alignment,offset);
|
||||||
if (newp != NULL) {
|
if (newp != NULL) {
|
||||||
if (zero && newsize > size) {
|
if (zero && newsize > size) {
|
||||||
// also set last word in the previous allocation to zero to ensure any padding is zero-initialized
|
const mi_page_t* page = _mi_ptr_page(newp);
|
||||||
size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0);
|
if (page->flags.is_zero) {
|
||||||
memset((uint8_t*)newp + start, 0, newsize - start);
|
// already zero initialized
|
||||||
|
mi_assert_expensive(mi_mem_is_zero(newp,newsize));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// also set last word in the previous allocation to zero to ensure any padding is zero-initialized
|
||||||
|
size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0);
|
||||||
|
memset((uint8_t*)newp + start, 0, newsize - start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy(newp, p, (newsize > size ? size : newsize));
|
memcpy(newp, p, (newsize > size ? size : newsize));
|
||||||
mi_free(p); // only free if successful
|
mi_free(p); // only free if successful
|
||||||
@ -143,6 +158,26 @@ void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t a
|
|||||||
return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false);
|
return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||||
|
return mi_heap_realloc_zero_aligned_at(heap, p, newsize, alignment, offset, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept {
|
||||||
|
return mi_heap_realloc_zero_aligned(heap, p, newsize, alignment, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||||
|
size_t total;
|
||||||
|
if (mi_mul_overflow(newcount, size, &total)) return NULL;
|
||||||
|
return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept {
|
||||||
|
size_t total;
|
||||||
|
if (mi_mul_overflow(newcount, size, &total)) return NULL;
|
||||||
|
return mi_heap_rezalloc_aligned(heap, p, total, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept {
|
void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||||
return mi_heap_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset);
|
return mi_heap_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset);
|
||||||
}
|
}
|
||||||
@ -151,13 +186,19 @@ void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noex
|
|||||||
return mi_heap_realloc_aligned(mi_get_default_heap(), p, newsize, alignment);
|
return mi_heap_realloc_aligned(mi_get_default_heap(), p, newsize, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mi_aligned_offset_recalloc(void* p, size_t size, size_t newcount, size_t alignment, size_t offset) mi_attr_noexcept {
|
void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||||
size_t newsize;
|
return mi_heap_rezalloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset);
|
||||||
if (mi_mul_overflow(size,newcount,&newsize)) return NULL;
|
|
||||||
return mi_heap_realloc_zero_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset, true );
|
|
||||||
}
|
}
|
||||||
void* mi_aligned_recalloc(void* p, size_t size, size_t newcount, size_t alignment) mi_attr_noexcept {
|
|
||||||
size_t newsize;
|
void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept {
|
||||||
if (mi_mul_overflow(size, newcount, &newsize)) return NULL;
|
return mi_heap_rezalloc_aligned(mi_get_default_heap(), p, newsize, alignment);
|
||||||
return mi_heap_realloc_zero_aligned(mi_get_default_heap(), p, newsize, alignment, true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||||
|
return mi_heap_recalloc_aligned_at(mi_get_default_heap(), p, newcount, size, alignment, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept {
|
||||||
|
return mi_heap_recalloc_aligned(mi_get_default_heap(), p, newcount, size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
|
|
||||||
#include <stdlib.h> // getenv
|
#include <stdlib.h> // getenv
|
||||||
|
#include <stdio.h> // _setmaxstdio
|
||||||
#include <string.h> // strstr
|
#include <string.h> // strstr
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MI_MALLOC_OVERRIDE) && defined(_WIN32) && !(defined(MI_SHARED_LIB) && defined(_DLL))
|
#if defined(MI_MALLOC_OVERRIDE) && defined(_WIN32) && !(defined(MI_SHARED_LIB) && defined(_DLL))
|
||||||
#error "It is only possible to override "malloc" on Windows when building as a 64-bit DLL (and linking the C runtime as a DLL)"
|
#error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MI_MALLOC_OVERRIDE) && !defined(_WIN32)
|
#if defined(MI_MALLOC_OVERRIDE) && !defined(_WIN32)
|
||||||
|
@ -48,17 +48,13 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept
|
|||||||
// <http://man7.org/linux/man-pages/man3/posix_memalign.3.html>
|
// <http://man7.org/linux/man-pages/man3/posix_memalign.3.html>
|
||||||
if (p == NULL) return EINVAL;
|
if (p == NULL) return EINVAL;
|
||||||
if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment
|
if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment
|
||||||
if ((alignment & (alignment - 1)) != 0) return EINVAL; // not a power of 2
|
if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2
|
||||||
void* q = mi_malloc_aligned(size, alignment);
|
void* q = mi_malloc_aligned(size, alignment);
|
||||||
if (q==NULL && size != 0) return ENOMEM;
|
if (q==NULL && size != 0) return ENOMEM;
|
||||||
*p = q;
|
*p = q;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mi__posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept {
|
|
||||||
return mi_posix_memalign(p, alignment, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept {
|
void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept {
|
||||||
return mi_malloc_aligned(size, alignment);
|
return mi_malloc_aligned(size, alignment);
|
||||||
}
|
}
|
||||||
@ -75,6 +71,8 @@ void* mi_pvalloc(size_t size) mi_attr_noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept {
|
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 <https://en.cppreference.com/w/c/memory/aligned_alloc>
|
||||||
return mi_malloc_aligned(size, alignment);
|
return mi_malloc_aligned(size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,12 +88,6 @@ void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { // Microsoft
|
|
||||||
size_t total;
|
|
||||||
if (mi_mul_overflow(count, size, &total)) return NULL;
|
|
||||||
return _mi_heap_realloc_zero(mi_get_default_heap(), p, total, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
|
unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
|
||||||
if (s==NULL) return NULL;
|
if (s==NULL) return NULL;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -149,3 +141,11 @@ int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft
|
||||||
|
return mi_recalloc_aligned_at(p, newcount, size, alignment, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft
|
||||||
|
return mi_recalloc_aligned(p, newcount, size, alignment);
|
||||||
|
}
|
||||||
|
48
src/alloc.c
48
src/alloc.c
@ -33,7 +33,7 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
|
|||||||
page->used++;
|
page->used++;
|
||||||
mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page);
|
mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page);
|
||||||
#if (MI_DEBUG)
|
#if (MI_DEBUG)
|
||||||
memset(block, MI_DEBUG_UNINIT, size);
|
if (!page->flags.is_zero) { memset(block, MI_DEBUG_UNINIT, size); }
|
||||||
#elif (MI_SECURE)
|
#elif (MI_SECURE)
|
||||||
block->next = 0;
|
block->next = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -89,9 +89,29 @@ extern inline void* mi_malloc(size_t size) mi_attr_noexcept {
|
|||||||
return mi_heap_malloc(mi_get_default_heap(), size);
|
return mi_heap_malloc(mi_get_default_heap(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size) {
|
||||||
|
// note: we need to initialize the whole block to zero, not just size
|
||||||
|
// or the recalloc/rezalloc functions cannot safely expand in place (see issue #63)
|
||||||
|
UNUSED(size);
|
||||||
|
mi_assert_internal(p != NULL);
|
||||||
|
mi_assert_internal(size > 0 && page->block_size >= size);
|
||||||
|
mi_assert_internal(_mi_ptr_page(p)==page);
|
||||||
|
if (page->flags.is_zero) {
|
||||||
|
// already zero initialized memory?
|
||||||
|
((mi_block_t*)p)->next = 0; // clear the free list pointer
|
||||||
|
mi_assert_expensive(mi_mem_is_zero(p,page->block_size));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// otherwise memset
|
||||||
|
memset(p, 0, page->block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) {
|
void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) {
|
||||||
void* p = mi_heap_malloc(heap,size);
|
void* p = mi_heap_malloc(heap,size);
|
||||||
if (zero && p != NULL) memset(p,0,size);
|
if (zero && p != NULL) {
|
||||||
|
_mi_block_zero_init(_mi_ptr_page(p),p,size); // todo: can we avoid getting the page again?
|
||||||
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +147,7 @@ static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* bloc
|
|||||||
mi_block_set_next(page, block, page->free);
|
mi_block_set_next(page, block, page->free);
|
||||||
page->free = block;
|
page->free = block;
|
||||||
page->used--;
|
page->used--;
|
||||||
|
page->flags.is_zero = false;
|
||||||
_mi_segment_page_free(page,true,&heap->tld->segments);
|
_mi_segment_page_free(page,true,&heap->tld->segments);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -254,7 +275,7 @@ void mi_free(void* p) mi_attr_noexcept
|
|||||||
// huge page stat is accounted for in `_mi_page_retire`
|
// huge page stat is accounted for in `_mi_page_retire`
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mi_likely(tid == segment->thread_id && page->flags.value == 0)) { // the thread id matches and it is not a full page, nor has aligned blocks
|
if (mi_likely(tid == segment->thread_id && page->flags.full_aligned == 0)) { // the thread id matches and it is not a full page, nor has aligned blocks
|
||||||
// local, and not full or aligned
|
// local, and not full or aligned
|
||||||
mi_block_t* block = (mi_block_t*)p;
|
mi_block_t* block = (mi_block_t*)p;
|
||||||
mi_block_set_next(page, block, page->local_free);
|
mi_block_set_next(page, block, page->local_free);
|
||||||
@ -405,6 +426,17 @@ void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcep
|
|||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept {
|
||||||
|
return _mi_heap_realloc_zero(heap, p, newsize, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept {
|
||||||
|
size_t total;
|
||||||
|
if (mi_mul_overflow(count, size, &total)) return NULL;
|
||||||
|
return mi_heap_rezalloc(heap, p, total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept {
|
void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept {
|
||||||
return mi_heap_realloc(mi_get_default_heap(),p,newsize);
|
return mi_heap_realloc(mi_get_default_heap(),p,newsize);
|
||||||
}
|
}
|
||||||
@ -418,6 +450,16 @@ void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept {
|
|||||||
return mi_heap_reallocf(mi_get_default_heap(),p,newsize);
|
return mi_heap_reallocf(mi_get_default_heap(),p,newsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept {
|
||||||
|
return mi_heap_rezalloc(mi_get_default_heap(), p, newsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept {
|
||||||
|
return mi_heap_recalloc(mi_get_default_heap(), p, count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// strdup, strndup, and realpath
|
// strdup, strndup, and realpath
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
@ -108,10 +108,9 @@ static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq
|
|||||||
|
|
||||||
static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
|
static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
|
||||||
{
|
{
|
||||||
_mi_deferred_free(heap,collect > NORMAL);
|
|
||||||
if (!mi_heap_is_initialized(heap)) return;
|
if (!mi_heap_is_initialized(heap)) return;
|
||||||
|
_mi_deferred_free(heap, collect > NORMAL);
|
||||||
|
|
||||||
// collect (some) abandoned pages
|
// collect (some) abandoned pages
|
||||||
if (collect >= NORMAL && !heap->no_reclaim) {
|
if (collect >= NORMAL && !heap->no_reclaim) {
|
||||||
if (collect == NORMAL) {
|
if (collect == NORMAL) {
|
||||||
|
46
src/init.c
46
src/init.c
@ -12,7 +12,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
|
|
||||||
// Empty page used to initialize the small free pages array
|
// Empty page used to initialize the small free pages array
|
||||||
const mi_page_t _mi_page_empty = {
|
const mi_page_t _mi_page_empty = {
|
||||||
0, false, false, false, 0, 0,
|
0, false, false, false, false, 0, 0,
|
||||||
{ 0 },
|
{ 0 },
|
||||||
NULL, // free
|
NULL, // free
|
||||||
#if MI_SECURE
|
#if MI_SECURE
|
||||||
@ -96,7 +96,7 @@ mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty;
|
|||||||
#define tld_main_stats ((mi_stats_t*)((uint8_t*)&tld_main + offsetof(mi_tld_t,stats)))
|
#define tld_main_stats ((mi_stats_t*)((uint8_t*)&tld_main + offsetof(mi_tld_t,stats)))
|
||||||
|
|
||||||
static mi_tld_t tld_main = {
|
static mi_tld_t tld_main = {
|
||||||
0,
|
0, false,
|
||||||
&_mi_heap_main,
|
&_mi_heap_main,
|
||||||
{ { NULL, NULL }, {NULL ,NULL}, 0, 0, 0, 0, 0, 0, NULL, tld_main_stats }, // segments
|
{ { NULL, NULL }, {NULL ,NULL}, 0, 0, 0, 0, 0, 0, NULL, tld_main_stats }, // segments
|
||||||
{ 0, tld_main_stats }, // os
|
{ 0, tld_main_stats }, // os
|
||||||
@ -352,9 +352,7 @@ void mi_thread_init(void) mi_attr_noexcept
|
|||||||
pthread_setspecific(mi_pthread_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_pthread_done` is called
|
pthread_setspecific(mi_pthread_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_pthread_done` is called
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (MI_DEBUG>0) && !defined(NDEBUG) // not in release mode as that leads to crashes on Windows dynamic override
|
//_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
||||||
_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mi_thread_done(void) mi_attr_noexcept {
|
void mi_thread_done(void) mi_attr_noexcept {
|
||||||
@ -367,11 +365,9 @@ void mi_thread_done(void) mi_attr_noexcept {
|
|||||||
// abandon the thread local heap
|
// abandon the thread local heap
|
||||||
if (_mi_heap_done()) return; // returns true if already ran
|
if (_mi_heap_done()) return; // returns true if already ran
|
||||||
|
|
||||||
#if (MI_DEBUG>0)
|
//if (!_mi_is_main_thread()) {
|
||||||
if (!_mi_is_main_thread()) {
|
// _mi_verbose_message("thread done: 0x%zx\n", _mi_thread_id());
|
||||||
_mi_verbose_message("thread done: 0x%zx\n", _mi_thread_id());
|
//}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -388,14 +384,26 @@ bool _mi_preloading() {
|
|||||||
return os_preloading;
|
return os_preloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mi_is_redirected() mi_attr_noexcept {
|
||||||
|
return mi_redirected;
|
||||||
|
}
|
||||||
|
|
||||||
// Communicate with the redirection module on Windows
|
// Communicate with the redirection module on Windows
|
||||||
#if 0
|
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
mi_decl_export void _mi_redirect_init() {
|
mi_decl_export void _mi_redirect_entry(DWORD reason) {
|
||||||
// called on redirection
|
// called on redirection; careful as this may be called before DllMain
|
||||||
mi_redirected = true;
|
if (reason == DLL_PROCESS_ATTACH) {
|
||||||
|
mi_redirected = true;
|
||||||
|
}
|
||||||
|
else if (reason == DLL_PROCESS_DETACH) {
|
||||||
|
mi_redirected = false;
|
||||||
|
}
|
||||||
|
else if (reason == DLL_THREAD_DETACH) {
|
||||||
|
mi_thread_done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__declspec(dllimport) bool mi_allocator_init(const char** message);
|
__declspec(dllimport) bool mi_allocator_init(const char** message);
|
||||||
__declspec(dllimport) void mi_allocator_done();
|
__declspec(dllimport) void mi_allocator_done();
|
||||||
@ -424,7 +432,9 @@ static void mi_process_load(void) {
|
|||||||
// show message from the redirector (if present)
|
// show message from the redirector (if present)
|
||||||
const char* msg = NULL;
|
const char* msg = NULL;
|
||||||
mi_allocator_init(&msg);
|
mi_allocator_init(&msg);
|
||||||
if (msg != NULL) _mi_verbose_message(msg);
|
if (msg != NULL && (mi_option_is_enabled(mi_option_verbose) || mi_option_is_enabled(mi_option_show_errors))) {
|
||||||
|
_mi_fputs(NULL,NULL,msg);
|
||||||
|
}
|
||||||
|
|
||||||
if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) {
|
if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) {
|
||||||
size_t pages = mi_option_get(mi_option_reserve_huge_os_pages);
|
size_t pages = mi_option_get(mi_option_reserve_huge_os_pages);
|
||||||
@ -483,9 +493,7 @@ static void mi_process_done(void) {
|
|||||||
|
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
||||||
// Windows DLL: easy to hook into process_init and thread_done
|
// Windows DLL: easy to hook into process_init and thread_done
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||||
UNUSED(reserved);
|
UNUSED(reserved);
|
||||||
UNUSED(inst);
|
UNUSED(inst);
|
||||||
@ -493,7 +501,7 @@ static void mi_process_done(void) {
|
|||||||
mi_process_load();
|
mi_process_load();
|
||||||
}
|
}
|
||||||
else if (reason==DLL_THREAD_DETACH) {
|
else if (reason==DLL_THREAD_DETACH) {
|
||||||
mi_thread_done();
|
if (!mi_is_redirected()) mi_thread_done();
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
206
src/memory.c
206
src/memory.c
@ -17,7 +17,7 @@ We need this memory layer between the raw OS calls because of:
|
|||||||
to reuse memory effectively.
|
to reuse memory effectively.
|
||||||
2. It turns out that for large objects, between 1MiB and 32MiB (?), the cost of
|
2. It turns out that for large objects, between 1MiB and 32MiB (?), the cost of
|
||||||
an OS allocation/free is still (much) too expensive relative to the accesses in that
|
an OS allocation/free is still (much) too expensive relative to the accesses in that
|
||||||
object :-( (`mallloc-large` tests this). This means we need a cheaper way to
|
object :-( (`malloc-large` tests this). This means we need a cheaper way to
|
||||||
reuse memory.
|
reuse memory.
|
||||||
3. This layer can help with a NUMA aware allocation in the future.
|
3. This layer can help with a NUMA aware allocation in the future.
|
||||||
|
|
||||||
@ -39,14 +39,16 @@ Possible issues:
|
|||||||
|
|
||||||
// Internal raw OS interface
|
// Internal raw OS interface
|
||||||
size_t _mi_os_large_page_size();
|
size_t _mi_os_large_page_size();
|
||||||
bool _mi_os_protect(void* addr, size_t size);
|
bool _mi_os_protect(void* addr, size_t size);
|
||||||
bool _mi_os_unprotect(void* addr, size_t size);
|
bool _mi_os_unprotect(void* addr, size_t size);
|
||||||
bool _mi_os_commit(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
|
||||||
bool _mi_os_decommit(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_os_decommit(void* p, size_t size, mi_stats_t* stats);
|
||||||
bool _mi_os_reset(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_os_reset(void* p, size_t size, mi_stats_t* stats);
|
||||||
bool _mi_os_unreset(void* p, size_t size, mi_stats_t* stats);
|
bool _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
|
||||||
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, mi_os_tld_t* tld);
|
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld);
|
||||||
|
void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats);
|
||||||
|
void* _mi_os_try_alloc_from_huge_reserved(size_t size, size_t try_alignment);
|
||||||
|
bool _mi_os_is_huge_reserved(void* p);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
#if (MI_INTPTR_SIZE==8)
|
#if (MI_INTPTR_SIZE==8)
|
||||||
@ -66,11 +68,25 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, mi_os_tld
|
|||||||
#define MI_REGION_MAP_FULL UINTPTR_MAX
|
#define MI_REGION_MAP_FULL UINTPTR_MAX
|
||||||
|
|
||||||
|
|
||||||
|
typedef uintptr_t mi_region_info_t;
|
||||||
|
|
||||||
|
static inline mi_region_info_t mi_region_info_create(void* start, bool is_large, bool is_committed) {
|
||||||
|
return ((uintptr_t)start | ((is_large?1:0) << 1) | (is_committed?1:0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void* mi_region_info_read(mi_region_info_t info, bool* is_large, bool* is_committed) {
|
||||||
|
if (is_large) *is_large = ((info&0x02) != 0);
|
||||||
|
if (is_committed) *is_committed = ((info&0x01) != 0);
|
||||||
|
return (void*)(info & ~0x03);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// A region owns a chunk of REGION_SIZE (256MiB) (virtual) memory with
|
// A region owns a chunk of REGION_SIZE (256MiB) (virtual) memory with
|
||||||
// a bit map with one bit per MI_SEGMENT_SIZE (4MiB) block.
|
// a bit map with one bit per MI_SEGMENT_SIZE (4MiB) block.
|
||||||
typedef struct mem_region_s {
|
typedef struct mem_region_s {
|
||||||
volatile _Atomic(uintptr_t) map; // in-use bit per MI_SEGMENT_SIZE block
|
volatile _Atomic(uintptr_t) map; // in-use bit per MI_SEGMENT_SIZE block
|
||||||
volatile _Atomic(void*) start; // start of virtual memory area
|
volatile _Atomic(mi_region_info_t) info; // start of virtual memory area, and flags
|
||||||
|
volatile _Atomic(uintptr_t) dirty_mask; // bit per block if the contents are not zero'd
|
||||||
} mem_region_t;
|
} mem_region_t;
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +124,7 @@ bool mi_is_in_heap_region(const void* p) mi_attr_noexcept {
|
|||||||
if (p==NULL) return false;
|
if (p==NULL) return false;
|
||||||
size_t count = mi_atomic_read_relaxed(®ions_count);
|
size_t count = mi_atomic_read_relaxed(®ions_count);
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
uint8_t* start = (uint8_t*)mi_atomic_read_ptr_relaxed(®ions[i].start);
|
uint8_t* start = (uint8_t*)mi_region_info_read( mi_atomic_read_relaxed(®ions[i].info), NULL, NULL);
|
||||||
if (start != NULL && (uint8_t*)p >= start && (uint8_t*)p < start + MI_REGION_SIZE) return true;
|
if (start != NULL && (uint8_t*)p >= start && (uint8_t*)p < start + MI_REGION_SIZE) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -123,7 +139,8 @@ Commit from a region
|
|||||||
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
||||||
// if the blocks were successfully claimed so ensure they are initialized to NULL/SIZE_MAX before the call.
|
// if the blocks were successfully claimed so ensure they are initialized to NULL/SIZE_MAX before the call.
|
||||||
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
||||||
static bool mi_region_commit_blocks(mem_region_t* region, size_t idx, size_t bitidx, size_t blocks, size_t size, bool commit, void** p, size_t* id, mi_os_tld_t* tld)
|
static bool mi_region_commit_blocks(mem_region_t* region, size_t idx, size_t bitidx, size_t blocks,
|
||||||
|
size_t size, bool* commit, bool* allow_large, bool* is_zero, void** p, size_t* id, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
size_t mask = mi_region_block_mask(blocks,bitidx);
|
size_t mask = mi_region_block_mask(blocks,bitidx);
|
||||||
mi_assert_internal(mask != 0);
|
mi_assert_internal(mask != 0);
|
||||||
@ -131,10 +148,21 @@ static bool mi_region_commit_blocks(mem_region_t* region, size_t idx, size_t bit
|
|||||||
mi_assert_internal(®ions[idx] == region);
|
mi_assert_internal(®ions[idx] == region);
|
||||||
|
|
||||||
// ensure the region is reserved
|
// ensure the region is reserved
|
||||||
void* start = mi_atomic_read_ptr(®ion->start);
|
mi_region_info_t info = mi_atomic_read(®ion->info);
|
||||||
if (start == NULL)
|
if (info == 0)
|
||||||
{
|
{
|
||||||
start = _mi_os_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, mi_option_is_enabled(mi_option_eager_region_commit), tld);
|
bool region_commit = mi_option_is_enabled(mi_option_eager_region_commit);
|
||||||
|
bool region_large = *allow_large;
|
||||||
|
void* start = NULL;
|
||||||
|
if (region_large) {
|
||||||
|
start = _mi_os_try_alloc_from_huge_reserved(MI_REGION_SIZE, MI_SEGMENT_ALIGN);
|
||||||
|
if (start != NULL) { region_commit = true; }
|
||||||
|
}
|
||||||
|
if (start == NULL) {
|
||||||
|
start = _mi_os_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, region_commit, ®ion_large, tld);
|
||||||
|
}
|
||||||
|
mi_assert_internal(!(region_large && !*allow_large));
|
||||||
|
|
||||||
if (start == NULL) {
|
if (start == NULL) {
|
||||||
// failure to allocate from the OS! unclaim the blocks and fail
|
// failure to allocate from the OS! unclaim the blocks and fail
|
||||||
size_t map;
|
size_t map;
|
||||||
@ -145,7 +173,8 @@ static bool mi_region_commit_blocks(mem_region_t* region, size_t idx, size_t bit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the newly allocated region
|
// set the newly allocated region
|
||||||
if (mi_atomic_cas_ptr_strong(®ion->start, start, NULL)) {
|
info = mi_region_info_create(start,region_large,region_commit);
|
||||||
|
if (mi_atomic_cas_strong(®ion->info, info, 0)) {
|
||||||
// update the region count
|
// update the region count
|
||||||
mi_atomic_increment(®ions_count);
|
mi_atomic_increment(®ions_count);
|
||||||
}
|
}
|
||||||
@ -153,30 +182,52 @@ static bool mi_region_commit_blocks(mem_region_t* region, size_t idx, size_t bit
|
|||||||
// failed, another thread allocated just before us!
|
// failed, another thread allocated just before us!
|
||||||
// we assign it to a later slot instead (up to 4 tries).
|
// we assign it to a later slot instead (up to 4 tries).
|
||||||
for(size_t i = 1; i <= 4 && idx + i < MI_REGION_MAX; i++) {
|
for(size_t i = 1; i <= 4 && idx + i < MI_REGION_MAX; i++) {
|
||||||
if (mi_atomic_cas_ptr_strong(®ions[idx+i].start, start, NULL)) {
|
if (mi_atomic_cas_strong(®ions[idx+i].info, info, 0)) {
|
||||||
mi_atomic_increment(®ions_count);
|
mi_atomic_increment(®ions_count);
|
||||||
start = NULL;
|
start = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start != NULL) {
|
if (start != NULL) {
|
||||||
// free it if we didn't succeed to save it to some other region
|
// free it if we didn't succeed to save it to some other region
|
||||||
_mi_os_free(start, MI_REGION_SIZE, tld->stats);
|
_mi_os_free_ex(start, MI_REGION_SIZE, region_commit, tld->stats);
|
||||||
}
|
}
|
||||||
// and continue with the memory at our index
|
// and continue with the memory at our index
|
||||||
start = mi_atomic_read_ptr(®ion->start);
|
info = mi_atomic_read(®ion->info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mi_assert_internal(start == mi_atomic_read_ptr(®ion->start));
|
mi_assert_internal(info == mi_atomic_read(®ion->info));
|
||||||
mi_assert_internal(start != NULL);
|
mi_assert_internal(info != 0);
|
||||||
|
|
||||||
// Commit the blocks to memory
|
// Commit the blocks to memory
|
||||||
|
bool region_is_committed = false;
|
||||||
|
bool region_is_large = false;
|
||||||
|
void* start = mi_region_info_read(info,®ion_is_large,®ion_is_committed);
|
||||||
|
mi_assert_internal(!(region_is_large && !*allow_large));
|
||||||
|
mi_assert_internal(start!=NULL);
|
||||||
|
|
||||||
|
// set dirty bits
|
||||||
|
uintptr_t m;
|
||||||
|
do {
|
||||||
|
m = mi_atomic_read(®ion->dirty_mask);
|
||||||
|
} while (!mi_atomic_cas_weak(®ion->dirty_mask, m | mask, m));
|
||||||
|
*is_zero = ((m & mask) == 0); // no dirty bit set in our claimed range?
|
||||||
|
|
||||||
void* blocks_start = (uint8_t*)start + (bitidx * MI_SEGMENT_SIZE);
|
void* blocks_start = (uint8_t*)start + (bitidx * MI_SEGMENT_SIZE);
|
||||||
if (commit && !mi_option_is_enabled(mi_option_eager_region_commit)) {
|
if (*commit && !region_is_committed) {
|
||||||
_mi_os_commit(blocks_start, mi_good_commit_size(size), tld->stats); // only commit needed size (unless using large OS pages)
|
// ensure commit
|
||||||
|
bool commit_zero = false;
|
||||||
|
_mi_os_commit(blocks_start, mi_good_commit_size(size), &commit_zero, tld->stats); // only commit needed size (unless using large OS pages)
|
||||||
|
if (commit_zero) *is_zero = true;
|
||||||
|
}
|
||||||
|
else if (!*commit && region_is_committed) {
|
||||||
|
// but even when no commit is requested, we might have committed anyway (in a huge OS page for example)
|
||||||
|
*commit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and return the allocation
|
// and return the allocation
|
||||||
|
mi_assert_internal(blocks_start != NULL);
|
||||||
|
*allow_large = region_is_large;
|
||||||
*p = blocks_start;
|
*p = blocks_start;
|
||||||
*id = (idx*MI_REGION_MAP_BITS) + bitidx;
|
*id = (idx*MI_REGION_MAP_BITS) + bitidx;
|
||||||
return true;
|
return true;
|
||||||
@ -220,7 +271,8 @@ static inline size_t mi_bsr(uintptr_t x) {
|
|||||||
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
||||||
// if the blocks were successfully claimed so ensure they are initialized to NULL/SIZE_MAX before the call.
|
// if the blocks were successfully claimed so ensure they are initialized to NULL/SIZE_MAX before the call.
|
||||||
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
||||||
static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t blocks, size_t size, bool commit, void** p, size_t* id, mi_os_tld_t* tld)
|
static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t blocks, size_t size,
|
||||||
|
bool* commit, bool* allow_large, bool* is_zero, void** p, size_t* id, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
mi_assert_internal(p != NULL && id != NULL);
|
mi_assert_internal(p != NULL && id != NULL);
|
||||||
mi_assert_internal(blocks < MI_REGION_MAP_BITS);
|
mi_assert_internal(blocks < MI_REGION_MAP_BITS);
|
||||||
@ -228,6 +280,7 @@ static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t bloc
|
|||||||
const uintptr_t mask = mi_region_block_mask(blocks, 0);
|
const uintptr_t mask = mi_region_block_mask(blocks, 0);
|
||||||
const size_t bitidx_max = MI_REGION_MAP_BITS - blocks;
|
const size_t bitidx_max = MI_REGION_MAP_BITS - blocks;
|
||||||
uintptr_t map = mi_atomic_read(®ion->map);
|
uintptr_t map = mi_atomic_read(®ion->map);
|
||||||
|
if (map==MI_REGION_MAP_FULL) return true;
|
||||||
|
|
||||||
#ifdef MI_HAVE_BITSCAN
|
#ifdef MI_HAVE_BITSCAN
|
||||||
size_t bitidx = mi_bsf(~map); // quickly find the first zero bit if possible
|
size_t bitidx = mi_bsf(~map); // quickly find the first zero bit if possible
|
||||||
@ -242,7 +295,7 @@ static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t bloc
|
|||||||
mi_assert_internal((m >> bitidx) == mask); // no overflow?
|
mi_assert_internal((m >> bitidx) == mask); // no overflow?
|
||||||
uintptr_t newmap = map | m;
|
uintptr_t newmap = map | m;
|
||||||
mi_assert_internal((newmap^map) >> bitidx == mask);
|
mi_assert_internal((newmap^map) >> bitidx == mask);
|
||||||
if (!mi_atomic_cas_weak(®ion->map, newmap, map)) {
|
if (!mi_atomic_cas_weak(®ion->map, newmap, map)) { // TODO: use strong cas here?
|
||||||
// no success, another thread claimed concurrently.. keep going
|
// no success, another thread claimed concurrently.. keep going
|
||||||
map = mi_atomic_read(®ion->map);
|
map = mi_atomic_read(®ion->map);
|
||||||
continue;
|
continue;
|
||||||
@ -250,7 +303,8 @@ static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t bloc
|
|||||||
else {
|
else {
|
||||||
// success, we claimed the bits
|
// success, we claimed the bits
|
||||||
// now commit the block memory -- this can still fail
|
// now commit the block memory -- this can still fail
|
||||||
return mi_region_commit_blocks(region, idx, bitidx, blocks, size, commit, p, id, tld);
|
return mi_region_commit_blocks(region, idx, bitidx, blocks,
|
||||||
|
size, commit, allow_large, is_zero, p, id, tld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -273,18 +327,32 @@ static bool mi_region_alloc_blocks(mem_region_t* region, size_t idx, size_t bloc
|
|||||||
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
// Returns `false` on an error (OOM); `true` otherwise. `p` and `id` are only written
|
||||||
// if the blocks were successfully claimed so ensure they are initialized to NULL/0 before the call.
|
// if the blocks were successfully claimed so ensure they are initialized to NULL/0 before the call.
|
||||||
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
// (not being able to claim is not considered an error so check for `p != NULL` afterwards).
|
||||||
static bool mi_region_try_alloc_blocks(size_t idx, size_t blocks, size_t size, bool commit, void** p, size_t* id, mi_os_tld_t* tld)
|
static bool mi_region_try_alloc_blocks(size_t idx, size_t blocks, size_t size,
|
||||||
|
bool* commit, bool* allow_large, bool* is_zero,
|
||||||
|
void** p, size_t* id, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
// check if there are available blocks in the region..
|
// check if there are available blocks in the region..
|
||||||
mi_assert_internal(idx < MI_REGION_MAX);
|
mi_assert_internal(idx < MI_REGION_MAX);
|
||||||
mem_region_t* region = ®ions[idx];
|
mem_region_t* region = ®ions[idx];
|
||||||
uintptr_t m = mi_atomic_read_relaxed(®ion->map);
|
uintptr_t m = mi_atomic_read_relaxed(®ion->map);
|
||||||
if (m != MI_REGION_MAP_FULL) { // some bits are zero
|
if (m != MI_REGION_MAP_FULL) { // some bits are zero
|
||||||
return mi_region_alloc_blocks(region, idx, blocks, size, commit, p, id, tld);
|
bool ok = (*commit || *allow_large); // committing or allow-large is always ok
|
||||||
}
|
if (!ok) {
|
||||||
else {
|
// otherwise skip incompatible regions if possible.
|
||||||
return true; // no error, but no success either
|
// this is not guaranteed due to multiple threads allocating at the same time but
|
||||||
|
// that's ok. In secure mode, large is never allowed for any thread, so that works out;
|
||||||
|
// otherwise we might just not be able to reset/decommit individual pages sometimes.
|
||||||
|
mi_region_info_t info = mi_atomic_read_relaxed(®ion->info);
|
||||||
|
bool is_large;
|
||||||
|
bool is_committed;
|
||||||
|
void* start = mi_region_info_read(info,&is_large,&is_committed);
|
||||||
|
ok = (start == NULL || (*commit || !is_committed) || (*allow_large || !is_large)); // Todo: test with one bitmap operation?
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
return mi_region_alloc_blocks(region, idx, blocks, size, commit, allow_large, is_zero, p, id, tld);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true; // no error, but no success either
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
@ -293,15 +361,20 @@ static bool mi_region_try_alloc_blocks(size_t idx, size_t blocks, size_t size, b
|
|||||||
|
|
||||||
// Allocate `size` memory aligned at `alignment`. Return non NULL on success, with a given memory `id`.
|
// Allocate `size` memory aligned at `alignment`. Return non NULL on success, with a given memory `id`.
|
||||||
// (`id` is abstract, but `id = idx*MI_REGION_MAP_BITS + bitidx`)
|
// (`id` is abstract, but `id = idx*MI_REGION_MAP_BITS + bitidx`)
|
||||||
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool commit, size_t* id, mi_os_tld_t* tld)
|
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero,
|
||||||
|
size_t* id, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
mi_assert_internal(id != NULL && tld != NULL);
|
mi_assert_internal(id != NULL && tld != NULL);
|
||||||
mi_assert_internal(size > 0);
|
mi_assert_internal(size > 0);
|
||||||
*id = SIZE_MAX;
|
*id = SIZE_MAX;
|
||||||
|
*is_zero = false;
|
||||||
|
bool default_large = false;
|
||||||
|
if (large==NULL) large = &default_large; // ensure `large != NULL`
|
||||||
|
|
||||||
// use direct OS allocation for huge blocks or alignment (with `id = SIZE_MAX`)
|
// use direct OS allocation for huge blocks or alignment (with `id = SIZE_MAX`)
|
||||||
if (size > MI_REGION_MAX_ALLOC_SIZE || alignment > MI_SEGMENT_ALIGN) {
|
if (size > MI_REGION_MAX_ALLOC_SIZE || alignment > MI_SEGMENT_ALIGN) {
|
||||||
return _mi_os_alloc_aligned(mi_good_commit_size(size), alignment, true, tld); // round up size
|
*is_zero = true;
|
||||||
|
return _mi_os_alloc_aligned(mi_good_commit_size(size), alignment, *commit, large, tld); // round up size
|
||||||
}
|
}
|
||||||
|
|
||||||
// always round size to OS page size multiple (so commit/decommit go over the entire range)
|
// always round size to OS page size multiple (so commit/decommit go over the entire range)
|
||||||
@ -315,27 +388,29 @@ void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool commit, size_t*
|
|||||||
// find a range of free blocks
|
// find a range of free blocks
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
size_t count = mi_atomic_read(®ions_count);
|
size_t count = mi_atomic_read(®ions_count);
|
||||||
size_t idx = tld->region_idx; // start index is per-thread to reduce contention
|
size_t idx = tld->region_idx; // start at 0 to reuse low addresses? Or, use tld->region_idx to reduce contention?
|
||||||
for (size_t visited = 0; visited < count; visited++, idx++) {
|
for (size_t visited = 0; visited < count; visited++, idx++) {
|
||||||
if (idx >= count) idx = 0; // wrap around
|
if (idx >= count) idx = 0; // wrap around
|
||||||
if (!mi_region_try_alloc_blocks(idx, blocks, size, commit, &p, id, tld)) return NULL; // error
|
if (!mi_region_try_alloc_blocks(idx, blocks, size, commit, large, is_zero, &p, id, tld)) return NULL; // error
|
||||||
if (p != NULL) break;
|
if (p != NULL) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
// no free range in existing regions -- try to extend beyond the count.. but at most 4 regions
|
// no free range in existing regions -- try to extend beyond the count.. but at most 8 regions
|
||||||
for (idx = count; idx < count + 4 && idx < MI_REGION_MAX; idx++) {
|
for (idx = count; idx < mi_atomic_read_relaxed(®ions_count) + 8 && idx < MI_REGION_MAX; idx++) {
|
||||||
if (!mi_region_try_alloc_blocks(idx, blocks, size, commit, &p, id, tld)) return NULL; // error
|
if (!mi_region_try_alloc_blocks(idx, blocks, size, commit, large, is_zero, &p, id, tld)) return NULL; // error
|
||||||
if (p != NULL) break;
|
if (p != NULL) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
// we could not find a place to allocate, fall back to the os directly
|
// we could not find a place to allocate, fall back to the os directly
|
||||||
p = _mi_os_alloc_aligned(size, alignment, commit, tld);
|
_mi_warning_message("unable to allocate from region: size %zu\n", size);
|
||||||
|
*is_zero = true;
|
||||||
|
p = _mi_os_alloc_aligned(size, alignment, commit, large, tld);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tld->region_idx = idx; // next start of search
|
tld->region_idx = idx; // next start of search? currently not used as we use first-fit
|
||||||
}
|
}
|
||||||
|
|
||||||
mi_assert_internal( p == NULL || (uintptr_t)p % alignment == 0);
|
mi_assert_internal( p == NULL || (uintptr_t)p % alignment == 0);
|
||||||
@ -343,10 +418,6 @@ void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool commit, size_t*
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Allocate `size` memory. Return non NULL on success, with a given memory `id`.
|
|
||||||
void* _mi_mem_alloc(size_t size, bool commit, size_t* id, mi_os_tld_t* tld) {
|
|
||||||
return _mi_mem_alloc_aligned(size,0,commit,id,tld);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
Free
|
Free
|
||||||
@ -374,7 +445,10 @@ void _mi_mem_free(void* p, size_t size, size_t id, mi_stats_t* stats) {
|
|||||||
mi_assert_internal(idx < MI_REGION_MAX); if (idx >= MI_REGION_MAX) return; // or `abort`?
|
mi_assert_internal(idx < MI_REGION_MAX); if (idx >= MI_REGION_MAX) return; // or `abort`?
|
||||||
mem_region_t* region = ®ions[idx];
|
mem_region_t* region = ®ions[idx];
|
||||||
mi_assert_internal((mi_atomic_read_relaxed(®ion->map) & mask) == mask ); // claimed?
|
mi_assert_internal((mi_atomic_read_relaxed(®ion->map) & mask) == mask ); // claimed?
|
||||||
void* start = mi_atomic_read_ptr(®ion->start);
|
mi_region_info_t info = mi_atomic_read(®ion->info);
|
||||||
|
bool is_large;
|
||||||
|
bool is_eager_committed;
|
||||||
|
void* start = mi_region_info_read(info,&is_large,&is_eager_committed);
|
||||||
mi_assert_internal(start != NULL);
|
mi_assert_internal(start != NULL);
|
||||||
void* blocks_start = (uint8_t*)start + (bitidx * MI_SEGMENT_SIZE);
|
void* blocks_start = (uint8_t*)start + (bitidx * MI_SEGMENT_SIZE);
|
||||||
mi_assert_internal(blocks_start == p); // not a pointer in our area?
|
mi_assert_internal(blocks_start == p); // not a pointer in our area?
|
||||||
@ -385,18 +459,20 @@ void _mi_mem_free(void* p, size_t size, size_t id, mi_stats_t* stats) {
|
|||||||
// TODO: implement delayed decommit/reset as these calls are too expensive
|
// TODO: implement delayed decommit/reset as these calls are too expensive
|
||||||
// if the memory is reused soon.
|
// if the memory is reused soon.
|
||||||
// reset: 10x slowdown on malloc-large, decommit: 17x slowdown on malloc-large
|
// reset: 10x slowdown on malloc-large, decommit: 17x slowdown on malloc-large
|
||||||
if (!mi_option_is_enabled(mi_option_large_os_pages)) {
|
if (!is_large) {
|
||||||
if (mi_option_is_enabled(mi_option_eager_region_commit)) {
|
if (mi_option_is_enabled(mi_option_segment_reset)) {
|
||||||
//_mi_os_reset(p, size, stats);
|
_mi_os_reset(p, size, stats); //
|
||||||
}
|
// _mi_os_decommit(p,size,stats); // if !is_eager_committed (and clear dirty bits)
|
||||||
else {
|
|
||||||
//_mi_os_decommit(p, size, stats);
|
|
||||||
}
|
}
|
||||||
|
// else { _mi_os_reset(p,size,stats); }
|
||||||
|
}
|
||||||
|
if (!is_eager_committed) {
|
||||||
|
// adjust commit statistics as we commit again when re-using the same slot
|
||||||
|
_mi_stat_decrease(&stats->committed, mi_good_commit_size(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should we free empty regions? currently only done _mi_mem_collect.
|
// TODO: should we free empty regions? currently only done _mi_mem_collect.
|
||||||
// this frees up virtual address space which
|
// this frees up virtual address space which might be useful on 32-bit systems?
|
||||||
// might be useful on 32-bit systems?
|
|
||||||
|
|
||||||
// and unclaim
|
// and unclaim
|
||||||
uintptr_t map;
|
uintptr_t map;
|
||||||
@ -416,17 +492,21 @@ void _mi_mem_collect(mi_stats_t* stats) {
|
|||||||
// free every region that has no segments in use.
|
// free every region that has no segments in use.
|
||||||
for (size_t i = 0; i < regions_count; i++) {
|
for (size_t i = 0; i < regions_count; i++) {
|
||||||
mem_region_t* region = ®ions[i];
|
mem_region_t* region = ®ions[i];
|
||||||
if (mi_atomic_read_relaxed(®ion->map) == 0 && region->start != NULL) {
|
if (mi_atomic_read_relaxed(®ion->map) == 0) {
|
||||||
// if no segments used, try to claim the whole region
|
// if no segments used, try to claim the whole region
|
||||||
uintptr_t m;
|
uintptr_t m;
|
||||||
do {
|
do {
|
||||||
m = mi_atomic_read_relaxed(®ion->map);
|
m = mi_atomic_read_relaxed(®ion->map);
|
||||||
} while(m == 0 && !mi_atomic_cas_weak(®ion->map, ~((uintptr_t)0), 0 ));
|
} while(m == 0 && !mi_atomic_cas_weak(®ion->map, ~((uintptr_t)0), 0 ));
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
// on success, free the whole region
|
// on success, free the whole region (unless it was huge reserved)
|
||||||
if (region->start != NULL) _mi_os_free((void*)region->start, MI_REGION_SIZE, stats);
|
bool is_eager_committed;
|
||||||
|
void* start = mi_region_info_read(mi_atomic_read(®ion->info), NULL, &is_eager_committed);
|
||||||
|
if (start != NULL && !_mi_os_is_huge_reserved(start)) {
|
||||||
|
_mi_os_free_ex(start, MI_REGION_SIZE, is_eager_committed, stats);
|
||||||
|
}
|
||||||
// and release
|
// and release
|
||||||
mi_atomic_write_ptr(®ion->start,NULL);
|
mi_atomic_write(®ion->info,0);
|
||||||
mi_atomic_write(®ion->map,0);
|
mi_atomic_write(®ion->map,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,8 +517,8 @@ void _mi_mem_collect(mi_stats_t* stats) {
|
|||||||
Other
|
Other
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool _mi_mem_commit(void* p, size_t size, mi_stats_t* stats) {
|
bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats) {
|
||||||
return _mi_os_commit(p, size, stats);
|
return _mi_os_commit(p, size, is_zero, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_mem_decommit(void* p, size_t size, mi_stats_t* stats) {
|
bool _mi_mem_decommit(void* p, size_t size, mi_stats_t* stats) {
|
||||||
@ -449,8 +529,8 @@ bool _mi_mem_reset(void* p, size_t size, mi_stats_t* stats) {
|
|||||||
return _mi_os_reset(p, size, stats);
|
return _mi_os_reset(p, size, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_mem_unreset(void* p, size_t size, mi_stats_t* stats) {
|
bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats) {
|
||||||
return _mi_os_unreset(p, size, stats);
|
return _mi_os_unreset(p, size, is_zero, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_mem_protect(void* p, size_t size) {
|
bool _mi_mem_protect(void* p, size_t size) {
|
||||||
|
105
src/options.c
105
src/options.c
@ -51,16 +51,10 @@ static mi_option_desc_t options[_mi_option_last] =
|
|||||||
{ 0, UNINIT, MI_OPTION(show_stats) },
|
{ 0, UNINIT, MI_OPTION(show_stats) },
|
||||||
{ 0, UNINIT, MI_OPTION(verbose) },
|
{ 0, UNINIT, MI_OPTION(verbose) },
|
||||||
|
|
||||||
#if MI_SECURE
|
|
||||||
{ MI_SECURE, INITIALIZED, MI_OPTION(secure) }, // in a secure build the environment setting is ignored
|
|
||||||
#else
|
|
||||||
{ 0, UNINIT, MI_OPTION(secure) },
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// the following options are experimental and not all combinations make sense.
|
// the following options are experimental and not all combinations make sense.
|
||||||
{ 1, UNINIT, MI_OPTION(eager_commit) }, // note: if eager_region_commit is on, this should be on too.
|
{ 1, UNINIT, MI_OPTION(eager_commit) }, // note: needs to be on when eager_region_commit is enabled
|
||||||
#ifdef _WIN32 // and BSD?
|
#ifdef _WIN32 // and BSD?
|
||||||
{ 1, UNINIT, MI_OPTION(eager_region_commit) }, // don't commit too eagerly on windows (just for looks...)
|
{ 0, UNINIT, MI_OPTION(eager_region_commit) }, // don't commit too eagerly on windows (just for looks...)
|
||||||
#else
|
#else
|
||||||
{ 1, UNINIT, MI_OPTION(eager_region_commit) },
|
{ 1, UNINIT, MI_OPTION(eager_region_commit) },
|
||||||
#endif
|
#endif
|
||||||
@ -69,7 +63,10 @@ static mi_option_desc_t options[_mi_option_last] =
|
|||||||
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
|
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
|
||||||
{ 0, UNINIT, MI_OPTION(page_reset) },
|
{ 0, UNINIT, MI_OPTION(page_reset) },
|
||||||
{ 0, UNINIT, MI_OPTION(cache_reset) },
|
{ 0, UNINIT, MI_OPTION(cache_reset) },
|
||||||
{ 0, UNINIT, MI_OPTION(reset_decommits) } // note: cannot enable this if secure is on
|
{ 0, UNINIT, MI_OPTION(reset_decommits) }, // note: cannot enable this if secure is on
|
||||||
|
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
||||||
|
{ 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free
|
||||||
|
{ 100, UNINIT, MI_OPTION(os_tag) } // only apple specific for now but might serve more or less related purpose
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mi_option_init(mi_option_desc_t* desc);
|
static void mi_option_init(mi_option_desc_t* desc);
|
||||||
@ -77,7 +74,12 @@ static void mi_option_init(mi_option_desc_t* desc);
|
|||||||
void _mi_options_init(void) {
|
void _mi_options_init(void) {
|
||||||
// called on process load
|
// called on process load
|
||||||
for(int i = 0; i < _mi_option_last; i++ ) {
|
for(int i = 0; i < _mi_option_last; i++ ) {
|
||||||
mi_option_get((mi_option_t)i); // initialize
|
mi_option_t option = (mi_option_t)i;
|
||||||
|
mi_option_get(option); // initialize
|
||||||
|
if (option != mi_option_verbose) {
|
||||||
|
mi_option_desc_t* desc = &options[option];
|
||||||
|
_mi_verbose_message("option '%s': %ld\n", desc->name, desc->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,10 +88,7 @@ long mi_option_get(mi_option_t option) {
|
|||||||
mi_option_desc_t* desc = &options[option];
|
mi_option_desc_t* desc = &options[option];
|
||||||
mi_assert(desc->option == option); // index should match the option
|
mi_assert(desc->option == option); // index should match the option
|
||||||
if (mi_unlikely(desc->init == UNINIT)) {
|
if (mi_unlikely(desc->init == UNINIT)) {
|
||||||
mi_option_init(desc);
|
mi_option_init(desc);
|
||||||
if (option != mi_option_verbose) {
|
|
||||||
_mi_verbose_message("option '%s': %ld\n", desc->name, desc->value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return desc->value;
|
return desc->value;
|
||||||
}
|
}
|
||||||
@ -131,6 +130,35 @@ void mi_option_disable(mi_option_t option) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void mi_out_stderr(const char* msg) {
|
||||||
|
#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.
|
||||||
|
_cputs(msg);
|
||||||
|
#else
|
||||||
|
fputs(msg, stderr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Default output handler
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t.
|
||||||
|
// For now, don't register output from multiple threads.
|
||||||
|
#pragma warning(suppress:4180)
|
||||||
|
static mi_output_fun* volatile mi_out_default; // = NULL
|
||||||
|
|
||||||
|
static mi_output_fun* mi_out_get_default(void) {
|
||||||
|
mi_output_fun* out = mi_out_default;
|
||||||
|
return (out == NULL ? &mi_out_stderr : out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mi_register_output(mi_output_fun* out) mi_attr_noexcept {
|
||||||
|
mi_out_default = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Messages
|
// Messages
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
@ -141,33 +169,30 @@ static volatile _Atomic(uintptr_t) error_count; // = 0; // when MAX_ERROR_COUNT
|
|||||||
// inside the C runtime causes another message.
|
// inside the C runtime causes another message.
|
||||||
static mi_decl_thread bool recurse = false;
|
static mi_decl_thread bool recurse = false;
|
||||||
|
|
||||||
// Define our own limited `fprintf` that avoids memory allocation.
|
void _mi_fputs(mi_output_fun* out, const char* prefix, const char* message) {
|
||||||
// We do this using `snprintf` with a limited buffer.
|
|
||||||
static void mi_vfprintf( FILE* out, const char* prefix, const char* fmt, va_list args ) {
|
|
||||||
char buf[256];
|
|
||||||
if (fmt==NULL) return;
|
|
||||||
if (_mi_preloading() || recurse) return;
|
if (_mi_preloading() || recurse) return;
|
||||||
|
if (out==NULL || (FILE*)out==stdout || (FILE*)out==stderr) out = mi_out_get_default();
|
||||||
recurse = true;
|
recurse = true;
|
||||||
if (out==NULL) out = stdout;
|
if (prefix != NULL) out(prefix);
|
||||||
vsnprintf(buf,sizeof(buf)-1,fmt,args);
|
out(message);
|
||||||
#ifdef _WIN32
|
|
||||||
// on windows with redirection, the C runtime cannot handle locale dependent output
|
|
||||||
// after the main thread closes so use direct console output.
|
|
||||||
if (out==stderr) {
|
|
||||||
if (prefix != NULL) _cputs(prefix);
|
|
||||||
_cputs(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (prefix != NULL) fputs(prefix,out);
|
|
||||||
fputs(buf,out);
|
|
||||||
}
|
|
||||||
recurse = false;
|
recurse = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _mi_fprintf( FILE* out, const char* fmt, ... ) {
|
// Define our own limited `fprintf` that avoids memory allocation.
|
||||||
|
// We do this using `snprintf` with a limited buffer.
|
||||||
|
static void mi_vfprintf( mi_output_fun* out, const char* prefix, const char* fmt, va_list args ) {
|
||||||
|
char buf[512];
|
||||||
|
if (fmt==NULL) return;
|
||||||
|
if (_mi_preloading() || recurse) return;
|
||||||
|
recurse = true;
|
||||||
|
vsnprintf(buf,sizeof(buf)-1,fmt,args);
|
||||||
|
recurse = false;
|
||||||
|
_mi_fputs(out,prefix,buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _mi_fprintf( mi_output_fun* out, const char* fmt, ... ) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args,fmt);
|
||||||
mi_vfprintf(out,NULL,fmt,args);
|
mi_vfprintf(out,NULL,fmt,args);
|
||||||
@ -178,7 +203,7 @@ void _mi_trace_message(const char* fmt, ...) {
|
|||||||
if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher
|
if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
mi_vfprintf(stderr, "mimalloc: ", fmt, args);
|
mi_vfprintf(NULL, "mimalloc: ", fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +211,7 @@ void _mi_verbose_message(const char* fmt, ...) {
|
|||||||
if (!mi_option_is_enabled(mi_option_verbose)) return;
|
if (!mi_option_is_enabled(mi_option_verbose)) return;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args,fmt);
|
||||||
mi_vfprintf(stderr, "mimalloc: ", fmt, args);
|
mi_vfprintf(NULL, "mimalloc: ", fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +220,7 @@ void _mi_error_message(const char* fmt, ...) {
|
|||||||
if (mi_atomic_increment(&error_count) > MAX_ERROR_COUNT) return;
|
if (mi_atomic_increment(&error_count) > MAX_ERROR_COUNT) return;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args,fmt);
|
||||||
mi_vfprintf(stderr, "mimalloc: error: ", fmt, args);
|
mi_vfprintf(NULL, "mimalloc: error: ", fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
mi_assert(false);
|
mi_assert(false);
|
||||||
}
|
}
|
||||||
@ -205,14 +230,14 @@ void _mi_warning_message(const char* fmt, ...) {
|
|||||||
if (mi_atomic_increment(&error_count) > MAX_ERROR_COUNT) return;
|
if (mi_atomic_increment(&error_count) > MAX_ERROR_COUNT) return;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args,fmt);
|
||||||
mi_vfprintf(stderr, "mimalloc: warning: ", fmt, args);
|
mi_vfprintf(NULL, "mimalloc: warning: ", fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if MI_DEBUG
|
#if MI_DEBUG
|
||||||
void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) {
|
void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) {
|
||||||
_mi_fprintf(stderr,"mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion);
|
_mi_fprintf(NULL,"mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
366
src/os.c
366
src/os.c
@ -35,10 +35,9 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
On windows initializes support for aligned allocation and
|
On windows initializes support for aligned allocation and
|
||||||
large OS pages (if MIMALLOC_LARGE_OS_PAGES is true).
|
large OS pages (if MIMALLOC_LARGE_OS_PAGES is true).
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
|
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
|
||||||
|
bool _mi_os_is_huge_reserved(void* p);
|
||||||
static bool mi_os_is_huge_reserved(void* p);
|
void* _mi_os_try_alloc_from_huge_reserved(size_t size, size_t try_alignment);
|
||||||
static void* mi_os_alloc_from_huge_reserved(size_t size, size_t try_alignment, bool commit);
|
|
||||||
|
|
||||||
static void* mi_align_up_ptr(void* p, size_t alignment) {
|
static void* mi_align_up_ptr(void* p, size_t alignment) {
|
||||||
return (void*)_mi_align_up((uintptr_t)p, alignment);
|
return (void*)_mi_align_up((uintptr_t)p, alignment);
|
||||||
@ -77,11 +76,16 @@ static bool use_large_os_page(size_t size, size_t alignment) {
|
|||||||
return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0);
|
return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// round to a good allocation size
|
// round to a good OS allocation size (bounded by max 12.5% waste)
|
||||||
static size_t mi_os_good_alloc_size(size_t size, size_t alignment) {
|
size_t _mi_os_good_alloc_size(size_t size) {
|
||||||
UNUSED(alignment);
|
size_t align_size;
|
||||||
if (size >= (SIZE_MAX - os_alloc_granularity)) return size; // possible overflow?
|
if (size < 512*KiB) align_size = _mi_os_page_size();
|
||||||
return _mi_align_up(size, os_alloc_granularity);
|
else if (size < 2*MiB) align_size = 64*KiB;
|
||||||
|
else if (size < 8*MiB) align_size = 256*KiB;
|
||||||
|
else if (size < 32*MiB) align_size = 1*MiB;
|
||||||
|
else align_size = 4*MiB;
|
||||||
|
if (size >= (SIZE_MAX - align_size)) return size; // possible overflow?
|
||||||
|
return _mi_align_up(size, align_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -95,6 +99,41 @@ typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*
|
|||||||
static PVirtualAlloc2 pVirtualAlloc2 = NULL;
|
static PVirtualAlloc2 pVirtualAlloc2 = NULL;
|
||||||
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
|
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
|
||||||
|
|
||||||
|
static bool mi_win_enable_large_os_pages()
|
||||||
|
{
|
||||||
|
if (large_os_page_size > 0) return true;
|
||||||
|
|
||||||
|
// Try to see if large OS pages are supported
|
||||||
|
// To use large pages on Windows, we first need access permission
|
||||||
|
// Set "Lock pages in memory" permission in the group policy editor
|
||||||
|
// <https://devblogs.microsoft.com/oldnewthing/20110128-00/?p=11643>
|
||||||
|
unsigned long err = 0;
|
||||||
|
HANDLE token = NULL;
|
||||||
|
BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token);
|
||||||
|
if (ok) {
|
||||||
|
TOKEN_PRIVILEGES tp;
|
||||||
|
ok = LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid);
|
||||||
|
if (ok) {
|
||||||
|
tp.PrivilegeCount = 1;
|
||||||
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
ok = AdjustTokenPrivileges(token, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
|
||||||
|
if (ok) {
|
||||||
|
err = GetLastError();
|
||||||
|
ok = (err == ERROR_SUCCESS);
|
||||||
|
if (ok) {
|
||||||
|
large_os_page_size = GetLargePageMinimum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(token);
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
if (err == 0) err = GetLastError();
|
||||||
|
_mi_warning_message("cannot enable large OS page support, error %lu\n", err);
|
||||||
|
}
|
||||||
|
return (ok!=0);
|
||||||
|
}
|
||||||
|
|
||||||
void _mi_os_init(void) {
|
void _mi_os_init(void) {
|
||||||
// get the page size
|
// get the page size
|
||||||
SYSTEM_INFO si;
|
SYSTEM_INFO si;
|
||||||
@ -111,40 +150,12 @@ void _mi_os_init(void) {
|
|||||||
FreeLibrary(hDll);
|
FreeLibrary(hDll);
|
||||||
}
|
}
|
||||||
hDll = LoadLibrary(TEXT("ntdll.dll"));
|
hDll = LoadLibrary(TEXT("ntdll.dll"));
|
||||||
if (hDll != NULL) {
|
if (hDll != NULL) {
|
||||||
pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)GetProcAddress(hDll, "NtAllocateVirtualMemoryEx");
|
pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)GetProcAddress(hDll, "NtAllocateVirtualMemoryEx");
|
||||||
FreeLibrary(hDll);
|
FreeLibrary(hDll);
|
||||||
}
|
}
|
||||||
// Try to see if large OS pages are supported
|
if (mi_option_is_enabled(mi_option_large_os_pages) || mi_option_is_enabled(mi_option_reserve_huge_os_pages)) {
|
||||||
unsigned long err = 0;
|
mi_win_enable_large_os_pages();
|
||||||
bool ok = mi_option_is_enabled(mi_option_large_os_pages) || mi_option_is_enabled(mi_option_reserve_huge_os_pages);
|
|
||||||
if (ok) {
|
|
||||||
// To use large pages on Windows, we first need access permission
|
|
||||||
// Set "Lock pages in memory" permission in the group policy editor
|
|
||||||
// <https://devblogs.microsoft.com/oldnewthing/20110128-00/?p=11643>
|
|
||||||
HANDLE token = NULL;
|
|
||||||
ok = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != 0;
|
|
||||||
if (ok) {
|
|
||||||
TOKEN_PRIVILEGES tp;
|
|
||||||
ok = LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid) != 0;
|
|
||||||
if (ok) {
|
|
||||||
tp.PrivilegeCount = 1;
|
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
ok = AdjustTokenPrivileges(token, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0) != 0;
|
|
||||||
if (ok) {
|
|
||||||
err = GetLastError();
|
|
||||||
ok = (err == ERROR_SUCCESS);
|
|
||||||
if (ok) {
|
|
||||||
large_os_page_size = GetLargePageMinimum();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(token);
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
if (err == 0) err = GetLastError();
|
|
||||||
_mi_warning_message("cannot enable large OS page support, error %lu\n", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(__wasi__)
|
#elif defined(__wasi__)
|
||||||
@ -171,9 +182,9 @@ void _mi_os_init() {
|
|||||||
Raw allocation on Windows (VirtualAlloc) and Unix's (mmap).
|
Raw allocation on Windows (VirtualAlloc) and Unix's (mmap).
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
static bool mi_os_mem_free(void* addr, size_t size, mi_stats_t* stats)
|
static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats)
|
||||||
{
|
{
|
||||||
if (addr == NULL || size == 0 || mi_os_is_huge_reserved(addr)) return true;
|
if (addr == NULL || size == 0 || _mi_os_is_huge_reserved(addr)) return true;
|
||||||
bool err = false;
|
bool err = false;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
|
err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
|
||||||
@ -182,7 +193,7 @@ static bool mi_os_mem_free(void* addr, size_t size, mi_stats_t* stats)
|
|||||||
#else
|
#else
|
||||||
err = (munmap(addr, size) == -1);
|
err = (munmap(addr, size) == -1);
|
||||||
#endif
|
#endif
|
||||||
_mi_stat_decrease(&stats->committed, size); // TODO: what if never committed?
|
if (was_committed) _mi_stat_decrease(&stats->committed, size);
|
||||||
_mi_stat_decrease(&stats->reserved, size);
|
_mi_stat_decrease(&stats->reserved, size);
|
||||||
if (err) {
|
if (err) {
|
||||||
#pragma warning(suppress:4996)
|
#pragma warning(suppress:4996)
|
||||||
@ -194,12 +205,14 @@ static bool mi_os_mem_free(void* addr, size_t size, mi_stats_t* stats)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) {
|
static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) {
|
||||||
#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
|
#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
|
||||||
// on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages
|
// on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages
|
||||||
if ((size % ((uintptr_t)1 << 30)) == 0 /* 1GiB multiple */
|
if ((size % ((uintptr_t)1 << 30)) == 0 /* 1GiB multiple */
|
||||||
&& (flags & MEM_LARGE_PAGES) != 0 && (flags & MEM_COMMIT) != 0
|
&& (flags & MEM_LARGE_PAGES) != 0 && (flags & MEM_COMMIT) != 0 && (flags & MEM_RESERVE) != 0
|
||||||
&& (addr != NULL || try_alignment == 0 || try_alignment % _mi_os_page_size() == 0)
|
&& (addr != NULL || try_alignment == 0 || try_alignment % _mi_os_page_size() == 0)
|
||||||
&& pNtAllocateVirtualMemoryEx != NULL)
|
&& pNtAllocateVirtualMemoryEx != NULL)
|
||||||
{
|
{
|
||||||
@ -211,7 +224,7 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
|
|||||||
param.ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE;
|
param.ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE;
|
||||||
SIZE_T psize = size;
|
SIZE_T psize = size;
|
||||||
void* base = addr;
|
void* base = addr;
|
||||||
NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags | MEM_RESERVE, PAGE_READWRITE, ¶m, 1);
|
NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, ¶m, 1);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
@ -221,19 +234,14 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if (MI_INTPTR_SIZE >= 8)
|
#if (MI_INTPTR_SIZE >= 8)
|
||||||
// on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations
|
// on 64-bit systems, try to use the virtual address area after 4TiB for 4MiB aligned allocations
|
||||||
static volatile _Atomic(intptr_t) aligned_base = ATOMIC_VAR_INIT((intptr_t)4 << 40); // starting at 4TiB
|
void* hint;
|
||||||
if (addr == NULL && try_alignment > 0 &&
|
if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment,size)) != NULL) {
|
||||||
try_alignment <= MI_SEGMENT_SIZE && (size%MI_SEGMENT_SIZE) == 0)
|
return VirtualAlloc(hint, size, flags, PAGE_READWRITE);
|
||||||
{
|
|
||||||
intptr_t hint = mi_atomic_add(&aligned_base, size);
|
|
||||||
if (hint%try_alignment == 0) {
|
|
||||||
return VirtualAlloc((void*)hint, size, flags, PAGE_READWRITE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
|
#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
|
||||||
// on modern Windows try use VirtualAlloc2 for aligned allocation
|
// 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 > 0 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) {
|
||||||
MEM_ADDRESS_REQUIREMENTS reqs = { 0 };
|
MEM_ADDRESS_REQUIREMENTS reqs = { 0 };
|
||||||
@ -247,10 +255,12 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
|
|||||||
return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
|
return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DWORD flags, bool large_only) {
|
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 volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
|
static volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
if (large_only || use_large_os_page(size, try_alignment)) {
|
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_read(&large_page_try_ok);
|
uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
|
||||||
if (!large_only && try_ok > 0) {
|
if (!large_only && try_ok > 0) {
|
||||||
// if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive.
|
// if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive.
|
||||||
@ -259,7 +269,8 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// large OS pages must always reserve and commit.
|
// large OS pages must always reserve and commit.
|
||||||
p = mi_win_virtual_allocx(addr, size, try_alignment, MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE | flags);
|
*is_large = true;
|
||||||
|
p = mi_win_virtual_allocx(addr, size, try_alignment, flags | MEM_LARGE_PAGES);
|
||||||
if (large_only) return p;
|
if (large_only) return p;
|
||||||
// fall back to non-large page allocation on error (`p == NULL`).
|
// fall back to non-large page allocation on error (`p == NULL`).
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@ -268,6 +279,7 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
*is_large = ((flags&MEM_LARGE_PAGES) != 0);
|
||||||
p = mi_win_virtual_allocx(addr, size, try_alignment, flags);
|
p = mi_win_virtual_allocx(addr, size, try_alignment, flags);
|
||||||
}
|
}
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@ -295,14 +307,13 @@ static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int pr
|
|||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
#if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
|
#if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
|
||||||
// on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations
|
// on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations
|
||||||
static volatile _Atomic(intptr_t) aligned_base = ATOMIC_VAR_INIT((intptr_t)1 << 42); // starting at 4TiB
|
void* hint;
|
||||||
if (addr==NULL && try_alignment <= MI_SEGMENT_SIZE && (size%MI_SEGMENT_SIZE)==0) {
|
if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment, size)) != NULL) {
|
||||||
intptr_t hint = mi_atomic_add(&aligned_base,size);
|
p = mmap(hint,size,protect_flags,flags,fd,0);
|
||||||
if (hint%try_alignment == 0) {
|
if (p==MAP_FAILED) p = NULL; // fall back to regular mmap
|
||||||
p = mmap((void*)hint,size,protect_flags,flags,fd,0);
|
|
||||||
if (p==MAP_FAILED) p = NULL; // fall back to regular mmap
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
UNUSED(try_alignment);
|
||||||
#endif
|
#endif
|
||||||
if (p==NULL) {
|
if (p==NULL) {
|
||||||
p = mmap(addr,size,protect_flags,flags,fd,0);
|
p = mmap(addr,size,protect_flags,flags,fd,0);
|
||||||
@ -311,7 +322,7 @@ static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int pr
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only) {
|
static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) {
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
#if !defined(MAP_ANONYMOUS)
|
#if !defined(MAP_ANONYMOUS)
|
||||||
#define MAP_ANONYMOUS MAP_ANON
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
@ -331,9 +342,11 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
|||||||
#endif
|
#endif
|
||||||
#if defined(VM_MAKE_TAG)
|
#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)
|
// macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99)
|
||||||
fd = VM_MAKE_TAG(100);
|
int os_tag = (int)mi_option_get(mi_option_os_tag);
|
||||||
|
if (os_tag < 100 || os_tag > 255) os_tag = 100;
|
||||||
|
fd = VM_MAKE_TAG(os_tag);
|
||||||
#endif
|
#endif
|
||||||
if (large_only || use_large_os_page(size, try_alignment)) {
|
if ((large_only || use_large_os_page(size, try_alignment)) && allow_large) {
|
||||||
static volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
|
static volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
|
||||||
uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
|
uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
|
||||||
if (!large_only && try_ok > 0) {
|
if (!large_only && try_ok > 0) {
|
||||||
@ -368,6 +381,7 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
|||||||
#endif
|
#endif
|
||||||
if (large_only || lflags != flags) {
|
if (large_only || lflags != flags) {
|
||||||
// try large OS page allocation
|
// try large OS page allocation
|
||||||
|
*is_large = true;
|
||||||
p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd);
|
p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd);
|
||||||
#ifdef MAP_HUGE_1GB
|
#ifdef MAP_HUGE_1GB
|
||||||
if (p == NULL && (lflags & MAP_HUGE_1GB) != 0) {
|
if (p == NULL && (lflags & MAP_HUGE_1GB) != 0) {
|
||||||
@ -384,7 +398,8 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, flags, fd);
|
*is_large = false;
|
||||||
|
p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, flags, fd);
|
||||||
#if defined(MADV_HUGEPAGE)
|
#if defined(MADV_HUGEPAGE)
|
||||||
// Many Linux systems don't allow MAP_HUGETLB but they support instead
|
// Many Linux systems don't allow MAP_HUGETLB but they support instead
|
||||||
// transparent huge pages (TPH). It is not required to call `madvise` with MADV_HUGE
|
// transparent huge pages (TPH). It is not required to call `madvise` with MADV_HUGE
|
||||||
@ -392,8 +407,10 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
|||||||
// in that case -- in particular for our large regions (in `memory.c`).
|
// in that case -- in particular for our large regions (in `memory.c`).
|
||||||
// However, some systems only allow TPH if called with explicit `madvise`, so
|
// However, some systems only allow TPH if called with explicit `madvise`, so
|
||||||
// when large OS pages are enabled for mimalloc, we call `madvice` anyways.
|
// when large OS pages are enabled for mimalloc, we call `madvice` anyways.
|
||||||
if (use_large_os_page(size, try_alignment)) {
|
if (allow_large && use_large_os_page(size, try_alignment)) {
|
||||||
madvise(p, size, MADV_HUGEPAGE);
|
if (madvise(p, size, MADV_HUGEPAGE) == 0) {
|
||||||
|
*is_large = true; // possibly
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -401,29 +418,67 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On 64-bit systems, we can do efficient aligned allocation by using
|
||||||
|
// the 4TiB to 30TiB area to allocate them.
|
||||||
|
#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED)))
|
||||||
|
static volatile _Atomic(intptr_t) aligned_base;
|
||||||
|
|
||||||
|
// Return a 4MiB aligned address that is probably available
|
||||||
|
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
|
||||||
|
if (try_alignment == 0 || try_alignment > MI_SEGMENT_SIZE) return NULL;
|
||||||
|
if ((size%MI_SEGMENT_SIZE) != 0) return NULL;
|
||||||
|
intptr_t hint = mi_atomic_add(&aligned_base, size);
|
||||||
|
if (hint == 0 || hint > ((intptr_t)30<<40)) { // try to wrap around after 30TiB (area after 32TiB is used for huge OS pages)
|
||||||
|
intptr_t init = ((intptr_t)4 << 40); // start at 4TiB area
|
||||||
|
#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode
|
||||||
|
uintptr_t r = _mi_random_init((uintptr_t)&mi_os_get_aligned_hint ^ hint);
|
||||||
|
init = init + (MI_SEGMENT_SIZE * ((r>>17) & 0xFFFF)); // (randomly 0-64k)*4MiB == 0 to 256GiB
|
||||||
|
#endif
|
||||||
|
mi_atomic_cas_strong(mi_atomic_cast(uintptr_t, &aligned_base), init, hint + size);
|
||||||
|
hint = mi_atomic_add(&aligned_base, size); // this may still give 0 or > 30TiB but that is ok, it is a hint after all
|
||||||
|
}
|
||||||
|
if (hint%try_alignment != 0) return NULL;
|
||||||
|
return (void*)hint;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
|
||||||
|
UNUSED(try_alignment); UNUSED(size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Primitive allocation from the OS.
|
// Primitive allocation from the OS.
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// 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, mi_stats_t* stats) {
|
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);
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
||||||
if (size == 0) return NULL;
|
if (size == 0) return NULL;
|
||||||
|
if (!commit) allow_large = false;
|
||||||
|
|
||||||
void* p = mi_os_alloc_from_huge_reserved(size, try_alignment, commit);
|
void* p = NULL;
|
||||||
if (p != NULL) return p;
|
if (commit && allow_large) {
|
||||||
|
p = _mi_os_try_alloc_from_huge_reserved(size, try_alignment);
|
||||||
|
if (p != NULL) {
|
||||||
|
*is_large = true;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int flags = MEM_RESERVE;
|
int flags = MEM_RESERVE;
|
||||||
if (commit) flags |= MEM_COMMIT;
|
if (commit) flags |= MEM_COMMIT;
|
||||||
p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false);
|
p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large);
|
||||||
#elif defined(__wasi__)
|
#elif defined(__wasi__)
|
||||||
|
*is_large = false;
|
||||||
p = mi_wasm_heap_grow(size, try_alignment);
|
p = mi_wasm_heap_grow(size, try_alignment);
|
||||||
#else
|
#else
|
||||||
int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
|
int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
|
||||||
p = mi_unix_mmap(NULL, size, try_alignment, protect_flags, false);
|
p = mi_unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large);
|
||||||
#endif
|
#endif
|
||||||
_mi_stat_increase(&stats->mmap_calls, 1);
|
_mi_stat_increase(&stats->mmap_calls, 1);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
_mi_stat_increase(&stats->reserved, size);
|
_mi_stat_increase(&stats->reserved, size);
|
||||||
if (commit) _mi_stat_increase(&stats->committed, size);
|
if (commit) { _mi_stat_increase(&stats->committed, size); }
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -431,19 +486,20 @@ static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, mi_
|
|||||||
|
|
||||||
// Primitive aligned allocation from the OS.
|
// Primitive aligned allocation from the OS.
|
||||||
// This function guarantees the allocated memory is aligned.
|
// This function guarantees the allocated memory is aligned.
|
||||||
static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, mi_stats_t* stats) {
|
static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) {
|
||||||
mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
|
mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
|
||||||
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
||||||
|
if (!commit) allow_large = false;
|
||||||
if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
|
if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
|
||||||
size = _mi_align_up(size, _mi_os_page_size());
|
size = _mi_align_up(size, _mi_os_page_size());
|
||||||
|
|
||||||
// try first with a hint (this will be aligned directly on Win 10+ or BSD)
|
// try first with a hint (this will be aligned directly on Win 10+ or BSD)
|
||||||
void* p = mi_os_mem_alloc(size, alignment, commit, stats);
|
void* p = mi_os_mem_alloc(size, alignment, commit, allow_large, is_large, stats);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
|
|
||||||
// if not aligned, free it, overallocate, and unmap around it
|
// if not aligned, free it, overallocate, and unmap around it
|
||||||
if (((uintptr_t)p % alignment != 0)) {
|
if (((uintptr_t)p % alignment != 0)) {
|
||||||
mi_os_mem_free(p, size, stats);
|
mi_os_mem_free(p, size, commit, stats);
|
||||||
if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
|
if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
|
||||||
size_t over_size = size + alignment;
|
size_t over_size = size + alignment;
|
||||||
|
|
||||||
@ -457,7 +513,7 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
|
|||||||
if (commit) flags |= MEM_COMMIT;
|
if (commit) flags |= MEM_COMMIT;
|
||||||
for (int tries = 0; tries < 3; tries++) {
|
for (int tries = 0; tries < 3; tries++) {
|
||||||
// over-allocate to determine a virtual memory range
|
// over-allocate to determine a virtual memory range
|
||||||
p = mi_os_mem_alloc(over_size, alignment, commit, stats);
|
p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats);
|
||||||
if (p == NULL) return NULL; // error
|
if (p == NULL) return NULL; // error
|
||||||
if (((uintptr_t)p % alignment) == 0) {
|
if (((uintptr_t)p % alignment) == 0) {
|
||||||
// if p happens to be aligned, just decommit the left-over area
|
// if p happens to be aligned, just decommit the left-over area
|
||||||
@ -466,19 +522,19 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// otherwise free and allocate at an aligned address in there
|
// otherwise free and allocate at an aligned address in there
|
||||||
mi_os_mem_free(p, over_size, stats);
|
mi_os_mem_free(p, over_size, commit, stats);
|
||||||
void* aligned_p = mi_align_up_ptr(p, alignment);
|
void* aligned_p = mi_align_up_ptr(p, alignment);
|
||||||
p = mi_win_virtual_alloc(aligned_p, size, alignment, flags, false);
|
p = mi_win_virtual_alloc(aligned_p, size, alignment, flags, false, allow_large, is_large);
|
||||||
if (p == aligned_p) break; // success!
|
if (p == aligned_p) break; // success!
|
||||||
if (p != NULL) { // should not happen?
|
if (p != NULL) { // should not happen?
|
||||||
mi_os_mem_free(p, size, stats);
|
mi_os_mem_free(p, size, commit, stats);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// overallocate...
|
// overallocate...
|
||||||
p = mi_os_mem_alloc(over_size, alignment, commit, stats);
|
p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
// and selectively unmap parts around the over-allocated area.
|
// and selectively unmap parts around the over-allocated area.
|
||||||
void* aligned_p = mi_align_up_ptr(p, alignment);
|
void* aligned_p = mi_align_up_ptr(p, alignment);
|
||||||
@ -486,8 +542,8 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
|
|||||||
size_t mid_size = _mi_align_up(size, _mi_os_page_size());
|
size_t mid_size = _mi_align_up(size, _mi_os_page_size());
|
||||||
size_t post_size = over_size - pre_size - mid_size;
|
size_t post_size = over_size - pre_size - mid_size;
|
||||||
mi_assert_internal(pre_size < over_size && post_size < over_size && mid_size >= size);
|
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, stats);
|
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, 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` systems
|
||||||
p = aligned_p;
|
p = aligned_p;
|
||||||
#endif
|
#endif
|
||||||
@ -503,22 +559,32 @@ 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* stats) {
|
void* _mi_os_alloc(size_t size, mi_stats_t* stats) {
|
||||||
if (size == 0) return NULL;
|
if (size == 0) return NULL;
|
||||||
size = mi_os_good_alloc_size(size, 0);
|
size = _mi_os_good_alloc_size(size);
|
||||||
return mi_os_mem_alloc(size, 0, true, stats);
|
bool is_large = false;
|
||||||
|
return mi_os_mem_alloc(size, 0, true, false, &is_large, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats) {
|
||||||
|
if (size == 0 || p == NULL) return;
|
||||||
|
size = _mi_os_good_alloc_size(size);
|
||||||
|
mi_os_mem_free(p, size, was_committed, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _mi_os_free(void* p, size_t size, mi_stats_t* stats) {
|
void _mi_os_free(void* p, size_t size, mi_stats_t* stats) {
|
||||||
if (size == 0 || p == NULL) return;
|
_mi_os_free_ex(p, size, true, stats);
|
||||||
size = mi_os_good_alloc_size(size, 0);
|
|
||||||
mi_os_mem_free(p, size, stats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, mi_os_tld_t* tld)
|
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
if (size == 0) return NULL;
|
if (size == 0) return NULL;
|
||||||
size = mi_os_good_alloc_size(size, alignment);
|
size = _mi_os_good_alloc_size(size);
|
||||||
alignment = _mi_align_up(alignment, _mi_os_page_size());
|
alignment = _mi_align_up(alignment, _mi_os_page_size());
|
||||||
return mi_os_mem_alloc_aligned(size, alignment, commit, tld->stats);
|
bool allow_large = false;
|
||||||
|
if (large != NULL) {
|
||||||
|
allow_large = *large;
|
||||||
|
*large = false;
|
||||||
|
}
|
||||||
|
return mi_os_mem_alloc_aligned(size, alignment, commit, allow_large, (large!=NULL?large:&allow_large), tld->stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -555,11 +621,12 @@ static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t*
|
|||||||
// Commit/Decommit memory.
|
// Commit/Decommit memory.
|
||||||
// Usuelly commit is aligned liberal, while decommit is aligned conservative.
|
// Usuelly commit is aligned liberal, while decommit is aligned conservative.
|
||||||
// (but not for the reset version where we want commit to be conservative as well)
|
// (but not for the reset version where we want commit to be conservative as well)
|
||||||
static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservative, mi_stats_t* stats) {
|
static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservative, bool* is_zero, mi_stats_t* stats) {
|
||||||
// page align in the range, commit liberally, decommit conservative
|
// page align in the range, commit liberally, decommit conservative
|
||||||
|
*is_zero = false;
|
||||||
size_t csize;
|
size_t csize;
|
||||||
void* start = mi_os_page_align_areax(conservative, addr, size, &csize);
|
void* start = mi_os_page_align_areax(conservative, addr, size, &csize);
|
||||||
if (csize == 0 || mi_os_is_huge_reserved(addr)) return true;
|
if (csize == 0 || _mi_os_is_huge_reserved(addr)) return true;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if (commit) {
|
if (commit) {
|
||||||
_mi_stat_increase(&stats->committed, csize);
|
_mi_stat_increase(&stats->committed, csize);
|
||||||
@ -571,6 +638,8 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (commit) {
|
if (commit) {
|
||||||
|
// if the memory was already committed, the call succeeds but it is not zero'd
|
||||||
|
// *is_zero = true;
|
||||||
void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE);
|
void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE);
|
||||||
err = (p == start ? 0 : GetLastError());
|
err = (p == start ? 0 : GetLastError());
|
||||||
}
|
}
|
||||||
@ -582,6 +651,7 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
|
|||||||
// WebAssembly guests can't control memory protection
|
// WebAssembly guests can't control memory protection
|
||||||
#else
|
#else
|
||||||
err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE));
|
err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE));
|
||||||
|
if (err != 0) { err = errno; }
|
||||||
#endif
|
#endif
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("commit/decommit error: start: 0x%p, csize: 0x%x, err: %i\n", start, csize, err);
|
_mi_warning_message("commit/decommit error: start: 0x%p, csize: 0x%x, err: %i\n", start, csize, err);
|
||||||
@ -590,16 +660,17 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
|
|||||||
return (err == 0);
|
return (err == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_os_commit(void* addr, size_t size, mi_stats_t* stats) {
|
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
|
||||||
return mi_os_commitx(addr, size, true, false /* conservative? */, stats);
|
return mi_os_commitx(addr, size, true, false /* conservative? */, is_zero, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats) {
|
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats) {
|
||||||
return mi_os_commitx(addr, size, false, true /* conservative? */, stats);
|
bool is_zero;
|
||||||
|
return mi_os_commitx(addr, size, false, true /* conservative? */, &is_zero, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_os_commit_unreset(void* addr, size_t size, mi_stats_t* stats) {
|
bool _mi_os_commit_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
|
||||||
return mi_os_commitx(addr, size, true, true /* conservative? */, stats);
|
return mi_os_commitx(addr, size, true, true /* conservative? */, is_zero, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -611,13 +682,13 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
|
|||||||
// page align conservatively within the range
|
// page align conservatively within the range
|
||||||
size_t csize;
|
size_t csize;
|
||||||
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
||||||
if (csize == 0 || mi_os_is_huge_reserved(addr)) return true;
|
if (csize == 0 || _mi_os_is_huge_reserved(addr)) return true;
|
||||||
if (reset) _mi_stat_increase(&stats->reset, csize);
|
if (reset) _mi_stat_increase(&stats->reset, csize);
|
||||||
else _mi_stat_decrease(&stats->reset, csize);
|
else _mi_stat_decrease(&stats->reset, csize);
|
||||||
if (!reset) return true; // nothing to do on unreset!
|
if (!reset) return true; // nothing to do on unreset!
|
||||||
|
|
||||||
#if (MI_DEBUG>1)
|
#if (MI_DEBUG>1)
|
||||||
if (!mi_option_is_enabled(mi_option_secure)) {
|
if (MI_SECURE==0) {
|
||||||
memset(start, 0, csize); // pretend it is eagerly reset
|
memset(start, 0, csize); // pretend it is eagerly reset
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -626,6 +697,11 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
|
|||||||
// Testing shows that for us (on `malloc-large`) MEM_RESET is 2x faster than DiscardVirtualMemory
|
// Testing shows that for us (on `malloc-large`) MEM_RESET is 2x faster than DiscardVirtualMemory
|
||||||
void* p = VirtualAlloc(start, csize, MEM_RESET, PAGE_READWRITE);
|
void* p = VirtualAlloc(start, csize, MEM_RESET, PAGE_READWRITE);
|
||||||
mi_assert_internal(p == start);
|
mi_assert_internal(p == start);
|
||||||
|
#if 1
|
||||||
|
if (p == start) {
|
||||||
|
VirtualUnlock(start,csize); // VirtualUnlock after MEM_RESET removes the memory from the working set
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (p != start) return false;
|
if (p != start) return false;
|
||||||
#else
|
#else
|
||||||
#if defined(MADV_FREE)
|
#if defined(MADV_FREE)
|
||||||
@ -663,11 +739,12 @@ bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_os_unreset(void* addr, size_t size, mi_stats_t* stats) {
|
bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
|
||||||
if (mi_option_is_enabled(mi_option_reset_decommits)) {
|
if (mi_option_is_enabled(mi_option_reset_decommits)) {
|
||||||
return _mi_os_commit_unreset(addr, size, stats); // re-commit it (conservatively!)
|
return _mi_os_commit_unreset(addr, size, is_zero, stats); // re-commit it (conservatively!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
*is_zero = false;
|
||||||
return mi_os_resetx(addr, size, false, stats);
|
return mi_os_resetx(addr, size, false, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,8 +756,8 @@ static bool mi_os_protectx(void* addr, size_t size, bool protect) {
|
|||||||
size_t csize = 0;
|
size_t csize = 0;
|
||||||
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
||||||
if (csize == 0) return false;
|
if (csize == 0) return false;
|
||||||
if (mi_os_is_huge_reserved(addr)) {
|
if (_mi_os_is_huge_reserved(addr)) {
|
||||||
_mi_warning_message("cannot mprotect memory allocated in huge OS pages\n");
|
_mi_warning_message("cannot mprotect memory allocated in huge OS pages\n");
|
||||||
}
|
}
|
||||||
int err = 0;
|
int err = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -691,6 +768,7 @@ static bool mi_os_protectx(void* addr, size_t size, bool protect) {
|
|||||||
err = 0;
|
err = 0;
|
||||||
#else
|
#else
|
||||||
err = mprotect(start, csize, protect ? PROT_NONE : (PROT_READ | PROT_WRITE));
|
err = mprotect(start, csize, protect ? PROT_NONE : (PROT_READ | PROT_WRITE));
|
||||||
|
if (err != 0) { err = errno; }
|
||||||
#endif
|
#endif
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("mprotect error: start: 0x%p, csize: 0x%x, err: %i\n", start, csize, err);
|
_mi_warning_message("mprotect error: start: 0x%p, csize: 0x%x, err: %i\n", start, csize, err);
|
||||||
@ -724,43 +802,44 @@ bool _mi_os_shrink(void* p, size_t oldsize, size_t newsize, mi_stats_t* stats) {
|
|||||||
// we cannot shrink on windows, but we can decommit
|
// we cannot shrink on windows, but we can decommit
|
||||||
return _mi_os_decommit(start, size, stats);
|
return _mi_os_decommit(start, size, stats);
|
||||||
#else
|
#else
|
||||||
return mi_os_mem_free(start, size, stats);
|
return mi_os_mem_free(start, size, true, stats);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
Support for huge OS pages (1Gib) that are reserved up-front and never
|
||||||
|
released. Only regions are allocated in here (see `memory.c`) so the memory
|
||||||
|
will be reused.
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
#define MI_HUGE_OS_PAGE_SIZE ((size_t)1 << 30) // 1GiB
|
#define MI_HUGE_OS_PAGE_SIZE ((size_t)1 << 30) // 1GiB
|
||||||
|
|
||||||
typedef struct mi_huge_info_s {
|
typedef struct mi_huge_info_s {
|
||||||
volatile _Atomic(void*) start;
|
volatile _Atomic(void*) start; // start of huge page area (32TiB)
|
||||||
volatile _Atomic(size_t) reserved;
|
volatile _Atomic(size_t) reserved; // total reserved size
|
||||||
volatile _Atomic(size_t) used;
|
volatile _Atomic(size_t) used; // currently allocated
|
||||||
} mi_huge_info_t;
|
} mi_huge_info_t;
|
||||||
|
|
||||||
static mi_huge_info_t os_huge_reserved = { NULL, 0, ATOMIC_VAR_INIT(0) };
|
static mi_huge_info_t os_huge_reserved = { NULL, 0, ATOMIC_VAR_INIT(0) };
|
||||||
|
|
||||||
static bool mi_os_is_huge_reserved(void* p) {
|
bool _mi_os_is_huge_reserved(void* p) {
|
||||||
return (mi_atomic_read_ptr(&os_huge_reserved.start) != NULL &&
|
return (mi_atomic_read_ptr(&os_huge_reserved.start) != NULL &&
|
||||||
p >= mi_atomic_read_ptr(&os_huge_reserved.start) &&
|
p >= mi_atomic_read_ptr(&os_huge_reserved.start) &&
|
||||||
(uint8_t*)p < (uint8_t*)mi_atomic_read_ptr(&os_huge_reserved.start) + mi_atomic_read(&os_huge_reserved.reserved));
|
(uint8_t*)p < (uint8_t*)mi_atomic_read_ptr(&os_huge_reserved.start) + mi_atomic_read(&os_huge_reserved.reserved));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* mi_os_alloc_from_huge_reserved(size_t size, size_t try_alignment, bool commit)
|
void* _mi_os_try_alloc_from_huge_reserved(size_t size, size_t try_alignment)
|
||||||
{
|
{
|
||||||
// only allow large aligned allocations
|
// only allow large aligned allocations (e.g. regions)
|
||||||
if (size < MI_SEGMENT_SIZE || (size % MI_SEGMENT_SIZE) != 0) return NULL;
|
if (size < MI_SEGMENT_SIZE || (size % MI_SEGMENT_SIZE) != 0) return NULL;
|
||||||
if (try_alignment > MI_SEGMENT_SIZE) return NULL;
|
if (try_alignment > MI_SEGMENT_SIZE) return NULL;
|
||||||
if (!commit) return NULL;
|
|
||||||
if (mi_atomic_read_ptr(&os_huge_reserved.start)==NULL) return NULL;
|
if (mi_atomic_read_ptr(&os_huge_reserved.start)==NULL) return NULL;
|
||||||
if (mi_atomic_read(&os_huge_reserved.used) >= mi_atomic_read(&os_huge_reserved.reserved)) return NULL; // already full
|
if (mi_atomic_read(&os_huge_reserved.used) >= mi_atomic_read(&os_huge_reserved.reserved)) return NULL; // already full
|
||||||
|
|
||||||
// always aligned
|
// always aligned
|
||||||
mi_assert_internal(mi_atomic_read(&os_huge_reserved.used) % MI_SEGMENT_SIZE == 0 );
|
mi_assert_internal(mi_atomic_read(&os_huge_reserved.used) % MI_SEGMENT_SIZE == 0 );
|
||||||
mi_assert_internal( (uintptr_t)mi_atomic_read_ptr(&os_huge_reserved.start) % MI_SEGMENT_SIZE == 0 );
|
mi_assert_internal( (uintptr_t)mi_atomic_read_ptr(&os_huge_reserved.start) % MI_SEGMENT_SIZE == 0 );
|
||||||
|
|
||||||
// try to reserve space
|
// try to reserve space
|
||||||
size_t base = mi_atomic_addu( &os_huge_reserved.used, size );
|
size_t base = mi_atomic_addu( &os_huge_reserved.used, size );
|
||||||
if ((base + size) > os_huge_reserved.reserved) {
|
if ((base + size) > os_huge_reserved.reserved) {
|
||||||
@ -791,37 +870,45 @@ static void mi_os_free_huge_reserved() {
|
|||||||
int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept {
|
int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept {
|
||||||
UNUSED(pages); UNUSED(max_secs);
|
UNUSED(pages); UNUSED(max_secs);
|
||||||
if (pages_reserved != NULL) *pages_reserved = 0;
|
if (pages_reserved != NULL) *pages_reserved = 0;
|
||||||
return ENOMEM; // cannot allocate
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int mi_reserve_huge_os_pages( size_t pages, double max_secs, size_t* pages_reserved ) mi_attr_noexcept
|
int mi_reserve_huge_os_pages( size_t pages, double max_secs, size_t* pages_reserved ) mi_attr_noexcept
|
||||||
{
|
{
|
||||||
if (pages_reserved != NULL) *pages_reserved = 0;
|
if (pages_reserved != NULL) *pages_reserved = 0;
|
||||||
if (max_secs==0) return ETIMEDOUT; // timeout
|
if (max_secs==0) return ETIMEDOUT; // timeout
|
||||||
if (pages==0) return 0; // ok
|
if (pages==0) return 0; // ok
|
||||||
if (!mi_atomic_cas_ptr_strong(&os_huge_reserved.start,(void*)1,NULL)) return -2; // already reserved
|
if (!mi_atomic_cas_ptr_strong(&os_huge_reserved.start,(void*)1,NULL)) return ETIMEDOUT; // already reserved
|
||||||
|
|
||||||
|
// Set the start address after the 32TiB area
|
||||||
|
uint8_t* start = (uint8_t*)((uintptr_t)32 << 40); // 32TiB virtual start address
|
||||||
|
#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode
|
||||||
|
uintptr_t r = _mi_random_init((uintptr_t)&mi_reserve_huge_os_pages);
|
||||||
|
start = start + ((uintptr_t)MI_SEGMENT_SIZE * ((r>>17) & 0xFFFF)); // (randomly 0-64k)*4MiB == 0 to 256GiB
|
||||||
|
#endif
|
||||||
|
|
||||||
// Allocate one page at the time but try to place them contiguously
|
// Allocate one page at the time but try to place them contiguously
|
||||||
// We allocate one page at the time to be able to abort if it takes too long
|
// We allocate one page at the time to be able to abort if it takes too long
|
||||||
double start_t = _mi_clock_start();
|
double start_t = _mi_clock_start();
|
||||||
uint8_t* start = (uint8_t*)((uintptr_t)16 << 40); // 16TiB virtual start address
|
|
||||||
uint8_t* addr = start; // current top of the allocations
|
uint8_t* addr = start; // current top of the allocations
|
||||||
for (size_t page = 0; page < pages; page++, addr += MI_HUGE_OS_PAGE_SIZE ) {
|
for (size_t page = 0; page < pages; page++, addr += MI_HUGE_OS_PAGE_SIZE ) {
|
||||||
// allocate a page
|
// allocate a page
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
|
bool is_large = true;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
p = mi_win_virtual_alloc(addr, MI_HUGE_OS_PAGE_SIZE, 0, MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE, true);
|
if (page==0) { mi_win_enable_large_os_pages(); }
|
||||||
|
p = mi_win_virtual_alloc(addr, MI_HUGE_OS_PAGE_SIZE, 0, MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE, true, true, &is_large);
|
||||||
#elif defined(MI_OS_USE_MMAP)
|
#elif defined(MI_OS_USE_MMAP)
|
||||||
p = mi_unix_mmap(addr, MI_HUGE_OS_PAGE_SIZE, 0, PROT_READ | PROT_WRITE, true);
|
p = mi_unix_mmap(addr, MI_HUGE_OS_PAGE_SIZE, 0, PROT_READ | PROT_WRITE, true, true, &is_large);
|
||||||
#else
|
#else
|
||||||
// always fail
|
// always fail
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Did we succeed at a contiguous address?
|
// Did we succeed at a contiguous address?
|
||||||
if (p != addr) {
|
if (p != addr) {
|
||||||
// no success, issue a warning and return with an error
|
// no success, issue a warning and return with an error
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
_mi_warning_message("could not allocate contiguous huge page %zu at 0x%p\n", page, addr);
|
_mi_warning_message("could not allocate contiguous huge page %zu at 0x%p\n", page, addr);
|
||||||
_mi_os_free(p, MI_HUGE_OS_PAGE_SIZE, &_mi_stats_main );
|
_mi_os_free(p, MI_HUGE_OS_PAGE_SIZE, &_mi_stats_main );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -832,30 +919,29 @@ int mi_reserve_huge_os_pages( size_t pages, double max_secs, size_t* pages_reser
|
|||||||
#endif
|
#endif
|
||||||
_mi_warning_message("could not allocate huge page %zu at 0x%p, error: %i\n", page, addr, err);
|
_mi_warning_message("could not allocate huge page %zu at 0x%p, error: %i\n", page, addr, err);
|
||||||
}
|
}
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
// success, record it
|
// success, record it
|
||||||
if (page==0) {
|
if (page==0) {
|
||||||
mi_atomic_write_ptr(&os_huge_reserved.start, addr);
|
mi_atomic_write_ptr(&os_huge_reserved.start, addr); // don't switch the order of these writes
|
||||||
mi_atomic_write(&os_huge_reserved.reserved, MI_HUGE_OS_PAGE_SIZE);
|
mi_atomic_write(&os_huge_reserved.reserved, MI_HUGE_OS_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mi_atomic_addu(&os_huge_reserved.reserved,MI_HUGE_OS_PAGE_SIZE);
|
mi_atomic_addu(&os_huge_reserved.reserved,MI_HUGE_OS_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
_mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE);
|
_mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE);
|
||||||
_mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE);
|
_mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE);
|
||||||
if (pages_reserved != NULL) { *pages_reserved = page + 1; };
|
if (pages_reserved != NULL) { *pages_reserved = page + 1; }
|
||||||
|
|
||||||
// check for timeout
|
// check for timeout
|
||||||
double elapsed = _mi_clock_end(start_t);
|
double elapsed = _mi_clock_end(start_t);
|
||||||
if (elapsed > max_secs) return (-1); // timeout
|
if (elapsed > max_secs) return ETIMEDOUT;
|
||||||
if (page >= 1) {
|
if (page >= 1) {
|
||||||
double estimate = ((elapsed / (double)(page+1)) * (double)pages);
|
double estimate = ((elapsed / (double)(page+1)) * (double)pages);
|
||||||
if (estimate > 1.5*max_secs) return (-1); // seems like we are going to timeout
|
if (estimate > 1.5*max_secs) return ETIMEDOUT; // seems like we are going to timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_mi_verbose_message("reserved %zu huge pages\n", pages);
|
_mi_verbose_message("reserved %zu huge pages\n", pages);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
49
src/page.c
49
src/page.c
@ -81,6 +81,14 @@ static bool mi_page_is_valid_init(mi_page_t* page) {
|
|||||||
mi_assert_internal(mi_page_list_is_valid(page,page->free));
|
mi_assert_internal(mi_page_list_is_valid(page,page->free));
|
||||||
mi_assert_internal(mi_page_list_is_valid(page,page->local_free));
|
mi_assert_internal(mi_page_list_is_valid(page,page->local_free));
|
||||||
|
|
||||||
|
#if MI_DEBUG>3 // generally too expensive to check this
|
||||||
|
if (page->flags.is_zero) {
|
||||||
|
for(mi_block_t* block = page->free; block != NULL; mi_block_next(page,block)) {
|
||||||
|
mi_assert_expensive(mi_mem_is_zero(block + 1, page->block_size - sizeof(mi_block_t)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mi_block_t* tfree = mi_tf_block(page->thread_free);
|
mi_block_t* tfree = mi_tf_block(page->thread_free);
|
||||||
mi_assert_internal(mi_page_list_is_valid(page, tfree));
|
mi_assert_internal(mi_page_list_is_valid(page, tfree));
|
||||||
size_t tfree_count = mi_page_list_count(page, tfree);
|
size_t tfree_count = mi_page_list_count(page, tfree);
|
||||||
@ -180,10 +188,11 @@ void _mi_page_free_collect(mi_page_t* page, bool force) {
|
|||||||
|
|
||||||
// and the local free list
|
// and the local free list
|
||||||
if (page->local_free != NULL) {
|
if (page->local_free != NULL) {
|
||||||
if (mi_unlikely(page->free == NULL)) {
|
if (mi_likely(page->free == NULL)) {
|
||||||
// usual case
|
// usual case
|
||||||
page->free = page->local_free;
|
page->free = page->local_free;
|
||||||
page->local_free = NULL;
|
page->local_free = NULL;
|
||||||
|
page->flags.is_zero = false;
|
||||||
}
|
}
|
||||||
else if (force) {
|
else if (force) {
|
||||||
// append -- only on shutdown (force) as this is a linear operation
|
// append -- only on shutdown (force) as this is a linear operation
|
||||||
@ -195,7 +204,8 @@ void _mi_page_free_collect(mi_page_t* page, bool force) {
|
|||||||
mi_block_set_next(page, tail, page->free);
|
mi_block_set_next(page, tail, page->free);
|
||||||
page->free = page->local_free;
|
page->free = page->local_free;
|
||||||
page->local_free = NULL;
|
page->local_free = NULL;
|
||||||
}
|
page->flags.is_zero = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mi_assert_internal(!force || page->local_free == NULL);
|
mi_assert_internal(!force || page->local_free == NULL);
|
||||||
@ -400,7 +410,7 @@ void _mi_page_retire(mi_page_t* page) {
|
|||||||
// if its neighbours are almost fully used.
|
// if its neighbours are almost fully used.
|
||||||
if (mi_likely(page->block_size <= (MI_SMALL_SIZE_MAX/4))) {
|
if (mi_likely(page->block_size <= (MI_SMALL_SIZE_MAX/4))) {
|
||||||
if (mi_page_mostly_used(page->prev) && mi_page_mostly_used(page->next)) {
|
if (mi_page_mostly_used(page->prev) && mi_page_mostly_used(page->next)) {
|
||||||
_mi_stat_counter_increase(&_mi_stats_main.page_no_retire,1);
|
mi_stat_counter_increase(_mi_stats_main.page_no_retire,1);
|
||||||
return; // dont't retire after all
|
return; // dont't retire after all
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,7 +482,7 @@ static void mi_page_free_list_extend_secure(mi_heap_t* heap, mi_page_t* page, si
|
|||||||
heap->random = _mi_random_shuffle(rnd);
|
heap->random = _mi_random_shuffle(rnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_page_free_list_extend( mi_page_t* page, size_t extend, mi_stats_t* stats)
|
static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* page, size_t extend, mi_stats_t* stats)
|
||||||
{
|
{
|
||||||
UNUSED(stats);
|
UNUSED(stats);
|
||||||
mi_assert_internal(page->free == NULL);
|
mi_assert_internal(page->free == NULL);
|
||||||
@ -481,15 +491,15 @@ static void mi_page_free_list_extend( mi_page_t* page, size_t extend, mi_stats_t
|
|||||||
void* page_area = _mi_page_start(_mi_page_segment(page), page, NULL );
|
void* page_area = _mi_page_start(_mi_page_segment(page), page, NULL );
|
||||||
size_t bsize = page->block_size;
|
size_t bsize = page->block_size;
|
||||||
mi_block_t* start = mi_page_block_at(page, page_area, page->capacity);
|
mi_block_t* start = mi_page_block_at(page, page_area, page->capacity);
|
||||||
|
|
||||||
// initialize a sequential free list
|
// initialize a sequential free list
|
||||||
mi_block_t* last = mi_page_block_at(page, page_area, page->capacity + extend - 1);
|
mi_block_t* last = mi_page_block_at(page, page_area, page->capacity + extend - 1);
|
||||||
mi_block_t* block = start;
|
mi_block_t* block = start;
|
||||||
while(block <= last) {
|
while(block <= last) {
|
||||||
mi_block_t* next = (mi_block_t*)((uint8_t*)block + bsize);
|
mi_block_t* next = (mi_block_t*)((uint8_t*)block + bsize);
|
||||||
mi_block_set_next(page,block,next);
|
mi_block_set_next(page,block,next);
|
||||||
block = next;
|
block = next;
|
||||||
}
|
}
|
||||||
mi_block_set_next(page, last, NULL);
|
mi_block_set_next(page, last, NULL);
|
||||||
page->free = start;
|
page->free = start;
|
||||||
}
|
}
|
||||||
@ -520,11 +530,11 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_stats_t* st
|
|||||||
|
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
_mi_page_start(_mi_page_segment(page), page, &page_size);
|
_mi_page_start(_mi_page_segment(page), page, &page_size);
|
||||||
_mi_stat_increase(&stats->pages_extended, 1);
|
mi_stat_increase(stats->pages_extended, 1);
|
||||||
|
|
||||||
// calculate the extend count
|
// calculate the extend count
|
||||||
size_t extend = page->reserved - page->capacity;
|
size_t extend = page->reserved - page->capacity;
|
||||||
size_t max_extend = MI_MAX_EXTEND_SIZE/page->block_size;
|
size_t max_extend = (page->block_size >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)page->block_size);
|
||||||
if (max_extend < MI_MIN_EXTEND) max_extend = MI_MIN_EXTEND;
|
if (max_extend < MI_MIN_EXTEND) max_extend = MI_MIN_EXTEND;
|
||||||
|
|
||||||
if (extend > max_extend) {
|
if (extend > max_extend) {
|
||||||
@ -537,7 +547,7 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_stats_t* st
|
|||||||
mi_assert_internal(extend < (1UL<<16));
|
mi_assert_internal(extend < (1UL<<16));
|
||||||
|
|
||||||
// and append the extend the free list
|
// and append the extend the free list
|
||||||
if (extend < MI_MIN_SLICES || !mi_option_is_enabled(mi_option_secure)) {
|
if (extend < MI_MIN_SLICES || MI_SECURE==0) { //!mi_option_is_enabled(mi_option_secure)) {
|
||||||
mi_page_free_list_extend(page, extend, stats );
|
mi_page_free_list_extend(page, extend, stats );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -545,8 +555,12 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_stats_t* st
|
|||||||
}
|
}
|
||||||
// enable the new free list
|
// enable the new free list
|
||||||
page->capacity += (uint16_t)extend;
|
page->capacity += (uint16_t)extend;
|
||||||
_mi_stat_increase(&stats->page_committed, extend * page->block_size);
|
mi_stat_increase(stats->page_committed, extend * page->block_size);
|
||||||
|
|
||||||
|
// extension into zero initialized memory preserves the zero'd free list
|
||||||
|
if (!page->is_zero_init) {
|
||||||
|
page->flags.is_zero = false;
|
||||||
|
}
|
||||||
mi_assert_expensive(mi_page_is_valid_init(page));
|
mi_assert_expensive(mi_page_is_valid_init(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,6 +579,7 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
|
|||||||
#if MI_SECURE
|
#if MI_SECURE
|
||||||
page->cookie = _mi_heap_random(heap) | 1;
|
page->cookie = _mi_heap_random(heap) | 1;
|
||||||
#endif
|
#endif
|
||||||
|
page->flags.is_zero = page->is_zero_init;
|
||||||
|
|
||||||
mi_assert_internal(page->capacity == 0);
|
mi_assert_internal(page->capacity == 0);
|
||||||
mi_assert_internal(page->free == NULL);
|
mi_assert_internal(page->free == NULL);
|
||||||
@ -638,7 +653,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p
|
|||||||
page = next;
|
page = next;
|
||||||
} // for each page
|
} // for each page
|
||||||
|
|
||||||
_mi_stat_counter_increase(&heap->tld->stats.searches,count);
|
mi_stat_counter_increase(heap->tld->stats.searches,count);
|
||||||
|
|
||||||
if (page == NULL) {
|
if (page == NULL) {
|
||||||
page = rpage;
|
page = rpage;
|
||||||
@ -664,7 +679,7 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) {
|
|||||||
mi_page_queue_t* pq = mi_page_queue(heap,size);
|
mi_page_queue_t* pq = mi_page_queue(heap,size);
|
||||||
mi_page_t* page = pq->first;
|
mi_page_t* page = pq->first;
|
||||||
if (page != NULL) {
|
if (page != NULL) {
|
||||||
if (mi_option_get(mi_option_secure) >= 3 && page->capacity < page->reserved && ((_mi_heap_random(heap) & 1) == 1)) {
|
if ((MI_SECURE >= 3) && page->capacity < page->reserved && ((_mi_heap_random(heap) & 1) == 1)) {
|
||||||
// in secure mode, we extend half the time to increase randomness
|
// in secure mode, we extend half the time to increase randomness
|
||||||
mi_page_extend_free(heap, page, &heap->tld->stats);
|
mi_page_extend_free(heap, page, &heap->tld->stats);
|
||||||
mi_assert_internal(mi_page_immediate_available(page));
|
mi_assert_internal(mi_page_immediate_available(page));
|
||||||
@ -687,12 +702,14 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) {
|
|||||||
a certain number of allocations.
|
a certain number of allocations.
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
static mi_deferred_free_fun* deferred_free = NULL;
|
static mi_deferred_free_fun* volatile deferred_free = NULL;
|
||||||
|
|
||||||
void _mi_deferred_free(mi_heap_t* heap, bool force) {
|
void _mi_deferred_free(mi_heap_t* heap, bool force) {
|
||||||
heap->tld->heartbeat++;
|
heap->tld->heartbeat++;
|
||||||
if (deferred_free != NULL) {
|
if (deferred_free != NULL && !heap->tld->recurse) {
|
||||||
|
heap->tld->recurse = true;
|
||||||
deferred_free(force, heap->tld->heartbeat);
|
deferred_free(force, heap->tld->heartbeat);
|
||||||
|
heap->tld->recurse = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +727,7 @@ void mi_register_deferred_free(mi_deferred_free_fun* fn) mi_attr_noexcept {
|
|||||||
// just that page, we always treat them as abandoned and any thread
|
// just that page, we always treat them as abandoned and any thread
|
||||||
// that frees the block can free the whole page and segment directly.
|
// 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) {
|
static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) {
|
||||||
size_t block_size = _mi_wsize_from_size(size) * sizeof(uintptr_t);
|
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);
|
mi_page_t* page = mi_page_fresh_alloc(heap,NULL,block_size);
|
||||||
if (page != NULL) {
|
if (page != NULL) {
|
||||||
|
123
src/segment.c
123
src/segment.c
@ -151,22 +151,22 @@ uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* pa
|
|||||||
size_t psize = (segment->page_kind == MI_PAGE_HUGE ? segment->segment_size : (size_t)1 << segment->page_shift);
|
size_t psize = (segment->page_kind == MI_PAGE_HUGE ? segment->segment_size : (size_t)1 << segment->page_shift);
|
||||||
uint8_t* p = (uint8_t*)segment + page->segment_idx*psize;
|
uint8_t* p = (uint8_t*)segment + page->segment_idx*psize;
|
||||||
|
|
||||||
if (page->segment_idx == 0) {
|
if (page->segment_idx == 0) {
|
||||||
// the first page starts after the segment info (and possible guard page)
|
// the first page starts after the segment info (and possible guard page)
|
||||||
p += segment->segment_info_size;
|
p += segment->segment_info_size;
|
||||||
psize -= segment->segment_info_size;
|
psize -= segment->segment_info_size;
|
||||||
// for small and medium objects, ensure the page start is aligned with the block size (PR#66 by kickunderscore)
|
// for small and medium objects, ensure the page start is aligned with the block size (PR#66 by kickunderscore)
|
||||||
if (block_size > 0 && segment->page_kind <= MI_PAGE_MEDIUM) {
|
if (block_size > 0 && segment->page_kind <= MI_PAGE_MEDIUM) {
|
||||||
size_t adjust = block_size - ((uintptr_t)p % block_size);
|
size_t adjust = block_size - ((uintptr_t)p % block_size);
|
||||||
if (adjust < block_size) {
|
if (adjust < block_size) {
|
||||||
p += adjust;
|
p += adjust;
|
||||||
psize -= adjust;
|
psize -= adjust;
|
||||||
}
|
}
|
||||||
mi_assert_internal((uintptr_t)p % block_size == 0);
|
mi_assert_internal((uintptr_t)p % block_size == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long secure = mi_option_get(mi_option_secure);
|
|
||||||
if (secure > 1 || (secure == 1 && page->segment_idx == segment->capacity - 1)) {
|
if (MI_SECURE > 1 || (MI_SECURE == 1 && page->segment_idx == segment->capacity - 1)) {
|
||||||
// secure == 1: the last page has an os guard page at the end
|
// secure == 1: the last page has an os guard page at the end
|
||||||
// secure > 1: every page has an os guard page
|
// secure > 1: every page has an os guard page
|
||||||
psize -= _mi_os_page_size();
|
psize -= _mi_os_page_size();
|
||||||
@ -186,18 +186,18 @@ static size_t mi_segment_size(size_t capacity, size_t required, size_t* pre_size
|
|||||||
capacity = MI_SMALL_PAGES_PER_SEGMENT;
|
capacity = MI_SMALL_PAGES_PER_SEGMENT;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */;
|
const size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */;
|
||||||
size_t guardsize = 0;
|
size_t guardsize = 0;
|
||||||
size_t isize = 0;
|
size_t isize = 0;
|
||||||
|
|
||||||
if (!mi_option_is_enabled(mi_option_secure)) {
|
if (MI_SECURE == 0) {
|
||||||
// normally no guard pages
|
// normally no guard pages
|
||||||
isize = _mi_align_up(minsize, (16 > MI_MAX_ALIGN_SIZE ? 16 : MI_MAX_ALIGN_SIZE));
|
isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// in secure mode, we set up a protected page in between the segment info
|
// in secure mode, we set up a protected page in between the segment info
|
||||||
// and the page data (and one at the end of the segment)
|
// and the page data (and one at the end of the segment)
|
||||||
size_t page_size = _mi_os_page_size();
|
const size_t page_size = _mi_os_page_size();
|
||||||
isize = _mi_align_up(minsize, page_size);
|
isize = _mi_align_up(minsize, page_size);
|
||||||
guardsize = page_size;
|
guardsize = page_size;
|
||||||
required = _mi_align_up(required, page_size);
|
required = _mi_align_up(required, page_size);
|
||||||
@ -228,7 +228,8 @@ static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) {
|
|||||||
static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_segments_tld_t* tld) {
|
static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_segments_tld_t* tld) {
|
||||||
segment->thread_id = 0;
|
segment->thread_id = 0;
|
||||||
mi_segments_track_size(-((long)segment_size),tld);
|
mi_segments_track_size(-((long)segment_size),tld);
|
||||||
if (mi_option_is_enabled(mi_option_secure)) {
|
if (MI_SECURE != 0) {
|
||||||
|
mi_assert_internal(!segment->mem_is_fixed);
|
||||||
_mi_mem_unprotect(segment, segment->segment_size); // ensure no more guard pages are set
|
_mi_mem_unprotect(segment, segment->segment_size); // ensure no more guard pages are set
|
||||||
}
|
}
|
||||||
_mi_mem_free(segment, segment_size, segment->memid, tld->stats);
|
_mi_mem_free(segment, segment_size, segment->memid, tld->stats);
|
||||||
@ -277,7 +278,7 @@ static bool mi_segment_cache_push(mi_segment_t* segment, mi_segments_tld_t* tld)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE);
|
mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE);
|
||||||
if (mi_option_is_enabled(mi_option_cache_reset)) {
|
if (!segment->mem_is_fixed && mi_option_is_enabled(mi_option_cache_reset)) {
|
||||||
_mi_mem_reset((uint8_t*)segment + segment->segment_info_size, segment->segment_size - segment->segment_info_size, tld->stats);
|
_mi_mem_reset((uint8_t*)segment + segment->segment_info_size, segment->segment_size - segment->segment_info_size, tld->stats);
|
||||||
}
|
}
|
||||||
segment->next = tld->cache;
|
segment->next = tld->cache;
|
||||||
@ -325,11 +326,15 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
|
|||||||
size_t page_size = (page_kind == MI_PAGE_HUGE ? segment_size : (size_t)1 << page_shift);
|
size_t page_size = (page_kind == MI_PAGE_HUGE ? segment_size : (size_t)1 << page_shift);
|
||||||
|
|
||||||
// Try to get it from our thread local cache first
|
// Try to get it from our thread local cache first
|
||||||
bool commit = mi_option_is_enabled(mi_option_eager_commit) || (page_kind > MI_PAGE_MEDIUM);
|
bool eager_delay = (tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay));
|
||||||
|
bool eager = !eager_delay && mi_option_is_enabled(mi_option_eager_commit);
|
||||||
|
bool commit = eager || (page_kind > MI_PAGE_MEDIUM);
|
||||||
bool protection_still_good = false;
|
bool protection_still_good = false;
|
||||||
|
bool is_zero = false;
|
||||||
mi_segment_t* segment = mi_segment_cache_pop(segment_size, tld);
|
mi_segment_t* segment = mi_segment_cache_pop(segment_size, tld);
|
||||||
if (segment != NULL) {
|
if (segment != NULL) {
|
||||||
if (mi_option_is_enabled(mi_option_secure)) {
|
if (MI_SECURE!=0) {
|
||||||
|
mi_assert_internal(!segment->mem_is_fixed);
|
||||||
if (segment->page_kind != page_kind) {
|
if (segment->page_kind != page_kind) {
|
||||||
_mi_mem_unprotect(segment, segment->segment_size); // reset protection if the page kind differs
|
_mi_mem_unprotect(segment, segment->segment_size); // reset protection if the page kind differs
|
||||||
}
|
}
|
||||||
@ -337,44 +342,49 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
|
|||||||
protection_still_good = true; // otherwise, the guard pages are still in place
|
protection_still_good = true; // otherwise, the guard pages are still in place
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mi_option_is_enabled(mi_option_eager_commit)) {
|
if (!segment->mem_is_committed && page_kind > MI_PAGE_MEDIUM) {
|
||||||
if (page_kind > MI_PAGE_MEDIUM) {
|
mi_assert_internal(!segment->mem_is_fixed);
|
||||||
_mi_mem_commit(segment, segment->segment_size, tld->stats);
|
_mi_mem_commit(segment, segment->segment_size, &is_zero, tld->stats);
|
||||||
}
|
segment->mem_is_committed = true;
|
||||||
else {
|
|
||||||
// ok, commit (and unreset) on demand again
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (mi_option_is_enabled(mi_option_cache_reset) || mi_option_is_enabled(mi_option_page_reset)) {
|
if (!segment->mem_is_fixed &&
|
||||||
_mi_mem_unreset(segment, segment->segment_size, tld->stats);
|
(mi_option_is_enabled(mi_option_cache_reset) || mi_option_is_enabled(mi_option_page_reset))) {
|
||||||
|
bool reset_zero = false;
|
||||||
|
_mi_mem_unreset(segment, segment->segment_size, &reset_zero, tld->stats);
|
||||||
|
if (reset_zero) is_zero = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Allocate the segment from the OS
|
// Allocate the segment from the OS
|
||||||
size_t memid;
|
size_t memid;
|
||||||
segment = (mi_segment_t*)_mi_mem_alloc_aligned(segment_size, MI_SEGMENT_SIZE, commit, &memid, os_tld);
|
bool mem_large = (!eager_delay && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy
|
||||||
|
segment = (mi_segment_t*)_mi_mem_alloc_aligned(segment_size, MI_SEGMENT_SIZE, &commit, &mem_large, &is_zero, &memid, os_tld);
|
||||||
if (segment == NULL) return NULL; // failed to allocate
|
if (segment == NULL) return NULL; // failed to allocate
|
||||||
if (!commit) {
|
if (!commit) {
|
||||||
_mi_mem_commit(segment, info_size, tld->stats);
|
// ensure the initial info is committed
|
||||||
|
bool commit_zero = false;
|
||||||
|
_mi_mem_commit(segment, info_size, &commit_zero, tld->stats);
|
||||||
|
if (commit_zero) is_zero = true;
|
||||||
}
|
}
|
||||||
segment->memid = memid;
|
segment->memid = memid;
|
||||||
|
segment->mem_is_fixed = mem_large;
|
||||||
|
segment->mem_is_committed = commit;
|
||||||
mi_segments_track_size((long)segment_size, tld);
|
mi_segments_track_size((long)segment_size, tld);
|
||||||
}
|
}
|
||||||
mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0);
|
mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0);
|
||||||
|
|
||||||
// zero the segment info
|
// zero the segment info (but not the `mem` fields)
|
||||||
{ size_t memid = segment->memid;
|
ptrdiff_t ofs = offsetof(mi_segment_t,next);
|
||||||
memset(segment, 0, info_size);
|
memset((uint8_t*)segment + ofs, 0, info_size - ofs);
|
||||||
segment->memid = memid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mi_option_is_enabled(mi_option_secure) && !protection_still_good) {
|
// guard pages
|
||||||
|
if ((MI_SECURE != 0) && !protection_still_good) {
|
||||||
// in secure mode, we set up a protected page in between the segment info
|
// in secure mode, we set up a protected page in between the segment info
|
||||||
// and the page data
|
// and the page data
|
||||||
mi_assert_internal( info_size == pre_size - _mi_os_page_size() && info_size % _mi_os_page_size() == 0);
|
mi_assert_internal( info_size == pre_size - _mi_os_page_size() && info_size % _mi_os_page_size() == 0);
|
||||||
_mi_mem_protect( (uint8_t*)segment + info_size, (pre_size - info_size) );
|
_mi_mem_protect( (uint8_t*)segment + info_size, (pre_size - info_size) );
|
||||||
size_t os_page_size = _mi_os_page_size();
|
size_t os_page_size = _mi_os_page_size();
|
||||||
if (mi_option_get(mi_option_secure) <= 1) {
|
if (MI_SECURE <= 1) {
|
||||||
// and protect the last page too
|
// and protect the last page too
|
||||||
_mi_mem_protect( (uint8_t*)segment + segment_size - os_page_size, os_page_size );
|
_mi_mem_protect( (uint8_t*)segment + segment_size - os_page_size, os_page_size );
|
||||||
}
|
}
|
||||||
@ -386,6 +396,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize
|
||||||
segment->page_kind = page_kind;
|
segment->page_kind = page_kind;
|
||||||
segment->capacity = capacity;
|
segment->capacity = capacity;
|
||||||
segment->page_shift = page_shift;
|
segment->page_shift = page_shift;
|
||||||
@ -397,6 +408,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
|
|||||||
segment->pages[i].segment_idx = i;
|
segment->pages[i].segment_idx = i;
|
||||||
segment->pages[i].is_reset = false;
|
segment->pages[i].is_reset = false;
|
||||||
segment->pages[i].is_committed = commit;
|
segment->pages[i].is_committed = commit;
|
||||||
|
segment->pages[i].is_zero_init = is_zero;
|
||||||
}
|
}
|
||||||
_mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size);
|
_mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size);
|
||||||
//fprintf(stderr,"mimalloc: alloc segment at %p\n", (void*)segment);
|
//fprintf(stderr,"mimalloc: alloc segment at %p\n", (void*)segment);
|
||||||
@ -453,15 +465,20 @@ static mi_page_t* mi_segment_find_free(mi_segment_t* segment, mi_stats_t* stats)
|
|||||||
if (!page->segment_in_use) {
|
if (!page->segment_in_use) {
|
||||||
if (page->is_reset || !page->is_committed) {
|
if (page->is_reset || !page->is_committed) {
|
||||||
size_t psize;
|
size_t psize;
|
||||||
uint8_t* start = _mi_page_start(segment, page, &psize);
|
uint8_t* start = _mi_page_start(segment, page, &psize);
|
||||||
mi_assert_internal(!(page->is_reset && !page->is_committed));
|
|
||||||
if (!page->is_committed) {
|
if (!page->is_committed) {
|
||||||
|
mi_assert_internal(!segment->mem_is_fixed);
|
||||||
page->is_committed = true;
|
page->is_committed = true;
|
||||||
_mi_mem_commit(start,psize,stats);
|
bool is_zero = false;
|
||||||
|
_mi_mem_commit(start,psize,&is_zero,stats);
|
||||||
|
if (is_zero) page->is_zero_init = true;
|
||||||
}
|
}
|
||||||
if (page->is_reset) {
|
if (page->is_reset) {
|
||||||
|
mi_assert_internal(!segment->mem_is_fixed);
|
||||||
page->is_reset = false;
|
page->is_reset = false;
|
||||||
_mi_mem_unreset(start, psize, stats);
|
bool is_zero = false;
|
||||||
|
_mi_mem_unreset(start, psize, &is_zero, stats);
|
||||||
|
if (is_zero) page->is_zero_init = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
@ -486,24 +503,20 @@ static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, mi_sta
|
|||||||
size_t inuse = page->capacity * page->block_size;
|
size_t inuse = page->capacity * page->block_size;
|
||||||
_mi_stat_decrease(&stats->page_committed, inuse);
|
_mi_stat_decrease(&stats->page_committed, inuse);
|
||||||
_mi_stat_decrease(&stats->pages, 1);
|
_mi_stat_decrease(&stats->pages, 1);
|
||||||
|
|
||||||
// reset the page memory to reduce memory pressure?
|
// reset the page memory to reduce memory pressure?
|
||||||
if (!page->is_reset && mi_option_is_enabled(mi_option_page_reset)) {
|
if (!segment->mem_is_fixed && !page->is_reset && mi_option_is_enabled(mi_option_page_reset)) {
|
||||||
size_t psize;
|
size_t psize;
|
||||||
uint8_t* start = _mi_page_start(segment, page, &psize);
|
uint8_t* start = _mi_page_start(segment, page, &psize);
|
||||||
page->is_reset = true;
|
page->is_reset = true;
|
||||||
_mi_mem_reset(start, psize, stats);
|
_mi_mem_reset(start, psize, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero the page data
|
// zero the page data, but not the segment fields
|
||||||
uint8_t idx = page->segment_idx; // don't clear the index
|
page->is_zero_init = false;
|
||||||
bool is_reset = page->is_reset; // don't clear the reset flag
|
ptrdiff_t ofs = offsetof(mi_page_t,capacity);
|
||||||
bool is_committed = page->is_committed; // don't clear the commit flag
|
memset((uint8_t*)page + ofs, 0, sizeof(*page) - ofs);
|
||||||
memset(page, 0, sizeof(*page));
|
|
||||||
page->segment_idx = idx;
|
|
||||||
page->segment_in_use = false;
|
page->segment_in_use = false;
|
||||||
page->is_reset = is_reset;
|
|
||||||
page->is_committed = is_committed;
|
|
||||||
segment->used--;
|
segment->used--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
src/stats.c
61
src/stats.c
@ -8,22 +8,10 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||||||
#include "mimalloc-internal.h"
|
#include "mimalloc-internal.h"
|
||||||
#include "mimalloc-atomic.h"
|
#include "mimalloc-atomic.h"
|
||||||
|
|
||||||
|
#include <stdio.h> // fputs, stderr
|
||||||
#include <string.h> // memset
|
#include <string.h> // memset
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
|
||||||
Merge thread statistics with the main one.
|
|
||||||
----------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src);
|
|
||||||
|
|
||||||
void _mi_stats_done(mi_stats_t* stats) {
|
|
||||||
if (stats == &_mi_stats_main) return;
|
|
||||||
mi_stats_add(&_mi_stats_main, stats);
|
|
||||||
memset(stats,0,sizeof(*stats));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
Statistics operations
|
Statistics operations
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
@ -85,6 +73,7 @@ static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64
|
|||||||
mi_atomic_add64( &stat->allocated, src->allocated * unit);
|
mi_atomic_add64( &stat->allocated, src->allocated * unit);
|
||||||
mi_atomic_add64( &stat->current, src->current * unit);
|
mi_atomic_add64( &stat->current, src->current * unit);
|
||||||
mi_atomic_add64( &stat->freed, src->freed * unit);
|
mi_atomic_add64( &stat->freed, src->freed * unit);
|
||||||
|
// peak scores do not work across threads..
|
||||||
mi_atomic_add64( &stat->peak, src->peak * unit);
|
mi_atomic_add64( &stat->peak, src->peak * unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +121,7 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
|
|||||||
Display statistics
|
Display statistics
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
static void mi_printf_amount(int64_t n, int64_t unit, FILE* out, const char* fmt) {
|
static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, const char* fmt) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
int len = 32;
|
int len = 32;
|
||||||
const char* suffix = (unit <= 0 ? " " : "b");
|
const char* suffix = (unit <= 0 ? " " : "b");
|
||||||
@ -153,16 +142,16 @@ static void mi_printf_amount(int64_t n, int64_t unit, FILE* out, const char* fmt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mi_print_amount(int64_t n, int64_t unit, FILE* out) {
|
static void mi_print_amount(int64_t n, int64_t unit, mi_output_fun* out) {
|
||||||
mi_printf_amount(n,unit,out,NULL);
|
mi_printf_amount(n,unit,out,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_print_count(int64_t n, int64_t unit, FILE* out) {
|
static void mi_print_count(int64_t n, int64_t unit, mi_output_fun* out) {
|
||||||
if (unit==1) _mi_fprintf(out,"%11s"," ");
|
if (unit==1) _mi_fprintf(out,"%11s"," ");
|
||||||
else mi_print_amount(n,0,out);
|
else mi_print_amount(n,0,out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, FILE* out ) {
|
static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out ) {
|
||||||
_mi_fprintf(out,"%10s:", msg);
|
_mi_fprintf(out,"%10s:", msg);
|
||||||
if (unit>0) {
|
if (unit>0) {
|
||||||
mi_print_amount(stat->peak, unit, out);
|
mi_print_amount(stat->peak, unit, out);
|
||||||
@ -191,24 +180,24 @@ static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, FILE* out ) {
|
static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out ) {
|
||||||
_mi_fprintf(out, "%10s:", msg);
|
_mi_fprintf(out, "%10s:", msg);
|
||||||
mi_print_amount(stat->total, -1, out);
|
mi_print_amount(stat->total, -1, out);
|
||||||
_mi_fprintf(out, "\n");
|
_mi_fprintf(out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, FILE* out) {
|
static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out) {
|
||||||
double avg = (stat->count == 0 ? 0.0 : (double)stat->total / (double)stat->count);
|
double avg = (stat->count == 0 ? 0.0 : (double)stat->total / (double)stat->count);
|
||||||
_mi_fprintf(out, "%10s: %7.1f avg\n", msg, avg);
|
_mi_fprintf(out, "%10s: %7.1f avg\n", msg, avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mi_print_header( FILE* out ) {
|
static void mi_print_header(mi_output_fun* out ) {
|
||||||
_mi_fprintf(out,"%10s: %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "unit ", "count ");
|
_mi_fprintf(out,"%10s: %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "unit ", "count ");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MI_STAT>1
|
#if MI_STAT>1
|
||||||
static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bins, size_t max, const char* fmt, FILE* out) {
|
static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
for (size_t i = 0; i <= max; i++) {
|
for (size_t i = 0; i <= max; i++) {
|
||||||
@ -232,8 +221,7 @@ static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bin
|
|||||||
|
|
||||||
static void mi_process_info(double* utime, double* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit);
|
static void mi_process_info(double* utime, double* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit);
|
||||||
|
|
||||||
static void _mi_stats_print(mi_stats_t* stats, double secs, FILE* out) mi_attr_noexcept {
|
static void _mi_stats_print(mi_stats_t* stats, double secs, mi_output_fun* out) mi_attr_noexcept {
|
||||||
if (out == NULL) out = stderr;
|
|
||||||
mi_print_header(out);
|
mi_print_header(out);
|
||||||
#if MI_STAT>1
|
#if MI_STAT>1
|
||||||
mi_stat_count_t normal = { 0,0,0,0 };
|
mi_stat_count_t normal = { 0,0,0,0 };
|
||||||
@ -293,6 +281,13 @@ static mi_stats_t* mi_stats_get_default(void) {
|
|||||||
return &heap->tld->stats;
|
return &heap->tld->stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mi_stats_merge_from(mi_stats_t* stats) {
|
||||||
|
if (stats != &_mi_stats_main) {
|
||||||
|
mi_stats_add(&_mi_stats_main, stats);
|
||||||
|
memset(stats, 0, sizeof(mi_stats_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mi_stats_reset(void) mi_attr_noexcept {
|
void mi_stats_reset(void) mi_attr_noexcept {
|
||||||
mi_stats_t* stats = mi_stats_get_default();
|
mi_stats_t* stats = mi_stats_get_default();
|
||||||
if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); }
|
if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); }
|
||||||
@ -300,19 +295,25 @@ void mi_stats_reset(void) mi_attr_noexcept {
|
|||||||
mi_time_start = _mi_clock_start();
|
mi_time_start = _mi_clock_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_stats_print_ex(mi_stats_t* stats, double secs, FILE* out) {
|
void mi_stats_merge(void) mi_attr_noexcept {
|
||||||
if (stats != &_mi_stats_main) {
|
mi_stats_merge_from( mi_stats_get_default() );
|
||||||
mi_stats_add(&_mi_stats_main,stats);
|
}
|
||||||
memset(stats,0,sizeof(mi_stats_t));
|
|
||||||
}
|
void _mi_stats_done(mi_stats_t* stats) { // called from `mi_thread_done`
|
||||||
|
mi_stats_merge_from(stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void mi_stats_print_ex(mi_stats_t* stats, double secs, mi_output_fun* out) {
|
||||||
|
mi_stats_merge_from(stats);
|
||||||
_mi_stats_print(&_mi_stats_main, secs, out);
|
_mi_stats_print(&_mi_stats_main, secs, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mi_stats_print(FILE* out) mi_attr_noexcept {
|
void mi_stats_print(mi_output_fun* out) mi_attr_noexcept {
|
||||||
mi_stats_print_ex(mi_stats_get_default(),_mi_clock_end(mi_time_start),out);
|
mi_stats_print_ex(mi_stats_get_default(),_mi_clock_end(mi_time_start),out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mi_thread_stats_print(FILE* out) mi_attr_noexcept {
|
void mi_thread_stats_print(mi_output_fun* out) mi_attr_noexcept {
|
||||||
_mi_stats_print(mi_stats_get_default(), _mi_clock_end(mi_time_start), out);
|
_mi_stats_print(mi_stats_get_default(), _mi_clock_end(mi_time_start), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,23 +23,31 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
mi_stats_reset(); // ignore earlier allocations
|
//mi_stats_reset(); // ignore earlier allocations
|
||||||
atexit(free_p);
|
atexit(free_p);
|
||||||
void* p1 = malloc(78);
|
void* p1 = malloc(78);
|
||||||
void* p2 = mi_malloc_aligned(16,24);
|
void* p2 = mi_malloc_aligned(16,24);
|
||||||
free(p1);
|
free(p1);
|
||||||
p1 = malloc(8);
|
p1 = malloc(8);
|
||||||
char* s = mi_strdup("hello\n");
|
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);
|
mi_free(p2);
|
||||||
p2 = malloc(16);
|
p2 = malloc(16);
|
||||||
p1 = realloc(p1, 32);
|
p1 = realloc(p1, 32);
|
||||||
free(p1);
|
free(p1);
|
||||||
free(p2);
|
mi_free(p2);
|
||||||
mi_free(s);
|
mi_free(s);
|
||||||
Test* t = new Test(42);
|
Test* t = new Test(42);
|
||||||
delete t;
|
delete t;
|
||||||
t = new (std::nothrow) Test(42);
|
t = new (std::nothrow) Test(42);
|
||||||
delete t;
|
delete t;
|
||||||
|
mi_stats_print(NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,16 +121,16 @@ int main() {
|
|||||||
// Aligned API
|
// Aligned API
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
CHECK_BODY("malloc-aligned1", {
|
CHECK_BODY("malloc-aligned1", {
|
||||||
void* p = mi_malloc_aligned(32,24); result = (p != NULL && (uintptr_t)(p) % 24 == 0); mi_free(p);
|
void* p = mi_malloc_aligned(32,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p);
|
||||||
});
|
});
|
||||||
CHECK_BODY("malloc-aligned2", {
|
CHECK_BODY("malloc-aligned2", {
|
||||||
void* p = mi_malloc_aligned(8,24); result = (p != NULL && (uintptr_t)(p) % 24 == 0); mi_free(p);
|
void* p = mi_malloc_aligned(48,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p);
|
||||||
});
|
});
|
||||||
CHECK_BODY("malloc-aligned-at1", {
|
CHECK_BODY("malloc-aligned-at1", {
|
||||||
void* p = mi_malloc_aligned_at(8,24,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 24 == 0); mi_free(p);
|
void* p = mi_malloc_aligned_at(48,32,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 32 == 0); mi_free(p);
|
||||||
});
|
});
|
||||||
CHECK_BODY("malloc-aligned-at2", {
|
CHECK_BODY("malloc-aligned-at2", {
|
||||||
void* p = mi_malloc_aligned_at(5,24,8); result = (p != NULL && ((uintptr_t)(p) + 8) % 24 == 0); mi_free(p);
|
void* p = mi_malloc_aligned_at(50,32,8); result = (p != NULL && ((uintptr_t)(p) + 8) % 32 == 0); mi_free(p);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
|
@ -18,7 +18,7 @@ terms of the MIT license.
|
|||||||
|
|
||||||
// argument defaults
|
// argument defaults
|
||||||
static int THREADS = 32; // more repeatable if THREADS <= #processors
|
static int THREADS = 32; // more repeatable if THREADS <= #processors
|
||||||
static int N = 10; // scaling factor
|
static int N = 20; // scaling factor
|
||||||
|
|
||||||
// static int THREADS = 8; // more repeatable if THREADS <= #processors
|
// static int THREADS = 8; // more repeatable if THREADS <= #processors
|
||||||
// static int N = 100; // scaling factor
|
// static int N = 100; // scaling factor
|
||||||
@ -163,8 +163,10 @@ int main(int argc, char** argv) {
|
|||||||
for (int i = 0; i < TRANSFERS; i++) {
|
for (int i = 0; i < TRANSFERS; i++) {
|
||||||
free_items((void*)transfer[i]);
|
free_items((void*)transfer[i]);
|
||||||
}
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
mi_collect(false);
|
mi_collect(false);
|
||||||
mi_collect(true);
|
mi_collect(true);
|
||||||
|
#endif
|
||||||
mi_stats_print(NULL);
|
mi_stats_print(NULL);
|
||||||
//bench_end_program();
|
//bench_end_program();
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user