From 469ade882dbff3226be92e71e2d75d04d84029b1 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 7 Dec 2024 14:03:16 -0800 Subject: [PATCH 01/16] Add MI_ARCHOPT option to enable architecture specific optimizations --- CMakeLists.txt | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fc1808e..6b89da08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ option(MI_TRACK_VALGRIND "Compile with Valgrind support (adds a small overhea option(MI_TRACK_ASAN "Compile with address sanitizer support (adds a small overhead)" OFF) option(MI_TRACK_ETW "Compile with Windows event tracing (ETW) support (adds a small overhead)" OFF) option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) +option(MI_ARCHOPT "Only for optimized builds: turn on architecture specific optimizations (for x64: '-march=haswell -mavx2' (2013), for arm64: '-march=armv8.1-a' (2016))" ON) option(MI_SEE_ASM "Generate assembly files" OFF) option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON) option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" ON) @@ -112,6 +113,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel") set(MI_USE_CXX "ON") endif() +if(NOT CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo") + set(MI_ARCHOPT OFF) +endif() + if(MI_OVERRIDE) message(STATUS "Override standard malloc (MI_OVERRIDE=ON)") if(APPLE) @@ -319,16 +324,31 @@ if(MI_WIN_USE_FLS) list(APPEND mi_defines MI_WIN_USE_FLS=1) endif() +# Check architecture +set(MI_ARCH "unknown") +if(APPLE) + list(FIND CMAKE_OSX_ARCHITECTURES "x86_64" x64_index) + list(FIND CMAKE_OSX_ARCHITECTURES "arm64" arm64_index) + if(x64_index GREATER_EQUAL 0) + set(MI_ARCH "x64") + elseif(arm64_index GREATER_EQUAL 0) + set(MI_ARCH "arm64") + endif() +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") + set(MI_ARCH "x64") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + set(MI_ARCH "arm64") +endif() - # Check /proc/cpuinfo for an SV39 MMU and limit the virtual address bits. - # (this will skip the aligned hinting in that case. Issue #939, #949) - if (EXISTS /proc/cpuinfo) - file(STRINGS /proc/cpuinfo mi_sv39_mmu REGEX "^mmu[ \t]+:[ \t]+sv39$") - if (mi_sv39_mmu) - MESSAGE( STATUS "Set virtual address bits to 39 (SV39 MMU detected)" ) - list(APPEND mi_defines MI_DEFAULT_VIRTUAL_ADDRESS_BITS=39) - endif() - endif() +# Check /proc/cpuinfo for an SV39 MMU and limit the virtual address bits. +# (this will skip the aligned hinting in that case. Issue #939, #949) +if (EXISTS /proc/cpuinfo) + file(STRINGS /proc/cpuinfo mi_sv39_mmu REGEX "^mmu[ \t]+:[ \t]+sv39$") + if (mi_sv39_mmu) + MESSAGE( STATUS "Set virtual address bits to 39 (SV39 MMU detected)" ) + list(APPEND mi_defines MI_DEFAULT_VIRTUAL_ADDRESS_BITS=39) + endif() +endif() # On Haiku use `-DCMAKE_INSTALL_PREFIX` instead, issue #788 # if(CMAKE_SYSTEM_NAME MATCHES "Haiku") @@ -367,6 +387,18 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM if(MI_OVERRIDE) list(APPEND mi_cflags -fno-builtin-malloc) endif() + if(MI_ARCHOPT) + set(mi_arch_opt "") + if(MI_ARCH STREQUAL "x64") + set(mi_arch_opt "-march=haswell;-mavx2") # fast bit scan, ~ 2013 + elseif(MI_ARCH STREQUAL "arm64") + set(mi_arch_opt "-march=armv8.1-a") # fast atomics, ~ 2016 + endif() + if(mi_arch_opt) + list(APPEND mi_cflags ${mi_arch_opt}) + message(STATUS "Architecture specific optimization is enabled (with ${mi_arch_opt}) (since MI_ARCHOPT=ON)") + endif() + endif() endif() if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) From 60a8da75ff426d0684f5fc065526f22c32b8f744 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 7 Dec 2024 14:16:39 -0800 Subject: [PATCH 02/16] Add MI_ARCHOPT support for msvc --- CMakeLists.txt | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b89da08..16d153aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel") set(MI_USE_CXX "ON") endif() -if(NOT CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo") +if(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo") + if (NOT MI_ARCHOPT) + message(STATUS "Architecture specific optimizations are disabled (MI_ARCHOPT=OFF)") + endif() +else() set(MI_ARCHOPT OFF) endif() @@ -325,6 +329,7 @@ if(MI_WIN_USE_FLS) endif() # Check architecture +set(MI_ARCHOPT_FLAGS "") set(MI_ARCH "unknown") if(APPLE) list(FIND CMAKE_OSX_ARCHITECTURES "x86_64" x64_index) @@ -388,27 +393,34 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM list(APPEND mi_cflags -fno-builtin-malloc) endif() if(MI_ARCHOPT) - set(mi_arch_opt "") if(MI_ARCH STREQUAL "x64") - set(mi_arch_opt "-march=haswell;-mavx2") # fast bit scan, ~ 2013 + set(MI_ARCH_OPT_FLAGS "-march=haswell;-mavx2") # fast bit scan, ~ 2013 elseif(MI_ARCH STREQUAL "arm64") - set(mi_arch_opt "-march=armv8.1-a") # fast atomics, ~ 2016 - endif() - if(mi_arch_opt) - list(APPEND mi_cflags ${mi_arch_opt}) - message(STATUS "Architecture specific optimization is enabled (with ${mi_arch_opt}) (since MI_ARCHOPT=ON)") + set(MI_ARCH_OPT_FLAGS "-march=armv8.1-a") # fast atomics, ~ 2016 endif() endif() endif() if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) list(APPEND mi_cflags /Zc:__cplusplus) + if(MI_ARCHOPT) + if(MI_ARCH STREQUAL "x64") + set(MI_ARCHOPT_FLAGS "/arch:AVX2") # fast bit scan, ~ 2013 + elseif(MI_ARCH STREQUAL "arm64") + set(MI_ARCHOPT_FLAGS "/arch:armv8.1") # fast atomics, ~ 2016 + endif() + endif() endif() if(MINGW) add_definitions(-D_WIN32_WINNT=0x600) endif() +if(MI_ARCH_OPT_FLAGS) + list(APPEND mi_cflags ${MI_ARCH_OPT_FLAGS}) + message(STATUS "Architecture specific optimization is enabled (with ${MI_ARCH_OPT_FLAGS}) (MI_ARCHOPT=ON)") +endif() + # extra needed libraries # we prefer -l test over `find_library` as sometimes core libraries From 7c2b09fc3e9d1eec62dc240610e8193cf1eec3fe Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 8 Dec 2024 09:02:16 -0800 Subject: [PATCH 03/16] only enable architecture specific optimization for armv8.1 --- CMakeLists.txt | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16d153aa..892a51fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ option(MI_TRACK_VALGRIND "Compile with Valgrind support (adds a small overhea option(MI_TRACK_ASAN "Compile with address sanitizer support (adds a small overhead)" OFF) option(MI_TRACK_ETW "Compile with Windows event tracing (ETW) support (adds a small overhead)" OFF) option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) -option(MI_ARCHOPT "Only for optimized builds: turn on architecture specific optimizations (for x64: '-march=haswell -mavx2' (2013), for arm64: '-march=armv8.1-a' (2016))" ON) +option(MI_OPT_ARCH "Only for optimized builds: turn on architecture specific optimizations (for arm64: '-march=armv8.1-a' (2016))" ON) option(MI_SEE_ASM "Generate assembly files" OFF) option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON) option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" ON) @@ -114,11 +114,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel") endif() if(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo") - if (NOT MI_ARCHOPT) - message(STATUS "Architecture specific optimizations are disabled (MI_ARCHOPT=OFF)") + if (NOT MI_OPT_ARCH) + message(STATUS "Architecture specific optimizations are disabled (MI_OPT_ARCH=OFF)") endif() else() - set(MI_ARCHOPT OFF) + set(MI_OPT_ARCH OFF) endif() if(MI_OVERRIDE) @@ -328,8 +328,8 @@ if(MI_WIN_USE_FLS) list(APPEND mi_defines MI_WIN_USE_FLS=1) endif() -# Check architecture -set(MI_ARCHOPT_FLAGS "") +# Determine architecture +set(MI_OPT_ARCH_FLAGS "") set(MI_ARCH "unknown") if(APPLE) list(FIND CMAKE_OSX_ARCHITECTURES "x86_64" x64_index) @@ -392,22 +392,18 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM if(MI_OVERRIDE) list(APPEND mi_cflags -fno-builtin-malloc) endif() - if(MI_ARCHOPT) - if(MI_ARCH STREQUAL "x64") - set(MI_ARCH_OPT_FLAGS "-march=haswell;-mavx2") # fast bit scan, ~ 2013 - elseif(MI_ARCH STREQUAL "arm64") - set(MI_ARCH_OPT_FLAGS "-march=armv8.1-a") # fast atomics, ~ 2016 + if(MI_OPT_ARCH) + if(MI_ARCH STREQUAL "arm64") + set(MI_ARCH_OPT_FLAGS "-march=armv8.1-a") # fast atomics, since ~ 2016 endif() endif() endif() if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) list(APPEND mi_cflags /Zc:__cplusplus) - if(MI_ARCHOPT) - if(MI_ARCH STREQUAL "x64") - set(MI_ARCHOPT_FLAGS "/arch:AVX2") # fast bit scan, ~ 2013 - elseif(MI_ARCH STREQUAL "arm64") - set(MI_ARCHOPT_FLAGS "/arch:armv8.1") # fast atomics, ~ 2016 + if(MI_OPT_ARCH) + if(MI_ARCH STREQUAL "arm64") + set(MI_OPT_ARCH_FLAGS "/arch:armv8.1") # fast atomics, since ~ 2016 endif() endif() endif() @@ -418,7 +414,7 @@ endif() if(MI_ARCH_OPT_FLAGS) list(APPEND mi_cflags ${MI_ARCH_OPT_FLAGS}) - message(STATUS "Architecture specific optimization is enabled (with ${MI_ARCH_OPT_FLAGS}) (MI_ARCHOPT=ON)") + message(STATUS "Architecture specific optimization is enabled (with ${MI_ARCH_OPT_FLAGS}) (MI_OPT_ARCH=ON)") endif() # extra needed libraries From 68bd8744b7722d918a9a2403eeb4248ee30afb84 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 8 Dec 2024 09:13:48 -0800 Subject: [PATCH 04/16] fix spelling --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 892a51fa..17f2071a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,7 +394,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM endif() if(MI_OPT_ARCH) if(MI_ARCH STREQUAL "arm64") - set(MI_ARCH_OPT_FLAGS "-march=armv8.1-a") # fast atomics, since ~ 2016 + set(MI_OPT_ARCH_FLAGS "-march=armv8.1-a") # fast atomics endif() endif() endif() @@ -403,7 +403,7 @@ if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) list(APPEND mi_cflags /Zc:__cplusplus) if(MI_OPT_ARCH) if(MI_ARCH STREQUAL "arm64") - set(MI_OPT_ARCH_FLAGS "/arch:armv8.1") # fast atomics, since ~ 2016 + set(MI_OPT_ARCH_FLAGS "/arch:armv8.1") # fast atomics endif() endif() endif() @@ -412,9 +412,9 @@ if(MINGW) add_definitions(-D_WIN32_WINNT=0x600) endif() -if(MI_ARCH_OPT_FLAGS) - list(APPEND mi_cflags ${MI_ARCH_OPT_FLAGS}) - message(STATUS "Architecture specific optimization is enabled (with ${MI_ARCH_OPT_FLAGS}) (MI_OPT_ARCH=ON)") +if(MI_OPT_ARCH_FLAGS) + list(APPEND mi_cflags ${MI_OPT_ARCH_FLAGS}) + message(STATUS "Architecture specific optimization is enabled (with ${MI_OPT_ARCH_FLAGS}) (MI_OPT_ARCH=ON)") endif() # extra needed libraries From d9a2f76ff759f04c591d0d7e2595417ccf7f4655 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 8 Dec 2024 17:23:09 -0800 Subject: [PATCH 05/16] fix write to empty heap in mi_guarded build --- src/alloc-aligned.c | 5 +-- test/main-override-static.c | 70 +++++++++++++++++++++++++++---------- test/test-stress.c | 4 +-- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index b4da4ded..6b0a33c1 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -39,9 +39,10 @@ static mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, si static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero) { const size_t rate = heap->guarded_sample_rate; - heap->guarded_sample_rate = 0; + // only write if `rate!=0` so we don't write to the constant `_mi_heap_empty` + if (rate != 0) { heap->guarded_sample_rate = 0; } void* p = _mi_heap_malloc_zero(heap, size, zero); - heap->guarded_sample_rate = rate; + if (rate != 0) { heap->guarded_sample_rate = rate; } return p; } #else diff --git a/test/main-override-static.c b/test/main-override-static.c index 4ad76d6a..34860717 100644 --- a/test/main-override-static.c +++ b/test/main-override-static.c @@ -7,6 +7,8 @@ #include #include // redefines malloc etc. +static void mi_bins(void); + static void double_free1(); static void double_free2(); static void corrupt_free(); @@ -41,6 +43,9 @@ int main() { // test_heap_walk(); // alloc_huge(); + // mi_bins(); + + void* p1 = malloc(78); void* p2 = malloc(24); free(p1); @@ -290,11 +295,11 @@ static void test_large_pages(void) { static inline uint8_t mi_bsr32(uint32_t x); #if defined(_MSC_VER) -#include +//#include #include static inline uint8_t mi_bsr32(uint32_t x) { uint32_t idx; - _BitScanReverse((DWORD*)&idx, x); + _BitScanReverse(&idx, x); return idx; } #elif defined(__GNUC__) || defined(__clang__) @@ -318,7 +323,7 @@ static inline uint8_t mi_bsr32(uint32_t x) { } #endif -/* + // Bit scan reverse: return the index of the highest bit. uint8_t _mi_bsr(uintptr_t x) { if (x == 0) return 0; @@ -331,7 +336,7 @@ uint8_t _mi_bsr(uintptr_t x) { # error "define bsr for non-32 or 64-bit platforms" #endif } -*/ + static inline size_t _mi_wsize_from_size(size_t size) { @@ -408,11 +413,20 @@ static inline uint8_t _mi_bin4(size_t size) { return bin; } -static size_t _mi_binx4(size_t bsize) { - if (bsize==0) return 0; - uint8_t b = mi_bsr32((uint32_t)bsize); - if (b <= 1) return bsize; - size_t bin = ((b << 1) | (bsize >> (b - 1))&0x01); +static size_t _mi_binx4(size_t wsize) { + size_t bin; + if (wsize <= 1) { + bin = 1; + } + else if (wsize <= 8) { + // bin = (wsize+1)&~1; // round to double word sizes + bin = (uint8_t)wsize; + } + else { + uint8_t b = mi_bsr32((uint32_t)wsize); + if (b <= 1) return wsize; + bin = ((b << 1) | (wsize >> (b - 1))&0x01) + 3; + } return bin; } @@ -424,22 +438,40 @@ static size_t _mi_binx8(size_t bsize) { return bin; } + +static inline size_t mi_bin(size_t wsize) { + uint8_t bin; + if (wsize <= 1) { + bin = 1; + } + else if (wsize <= 8) { + // bin = (wsize+1)&~1; // round to double word sizes + bin = (uint8_t)wsize; + } + else { + wsize--; + // find the highest bit + uint8_t b = (uint8_t)mi_bsr32((uint32_t)wsize); // note: wsize != 0 + // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). + // - adjust with 3 because we use do not round the first 8 sizes + // which each get an exact bin + bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; + } + return bin; +} + + static void mi_bins(void) { //printf(" QNULL(1), /* 0 */ \\\n "); size_t last_bin = 0; - size_t min_bsize = 0; - size_t last_bsize = 0; - for (size_t bsize = 1; bsize < 2*1024; bsize++) { - size_t size = bsize * 64 * 1024; - size_t bin = _mi_binx8(bsize); + for (size_t wsize = 1; wsize <= (4*1024*1024) / 8 + 1024; wsize++) { + size_t bin = mi_bin(wsize); if (bin != last_bin) { - printf("min bsize: %6zd, max bsize: %6zd, bin: %6zd\n", min_bsize, last_bsize, last_bin); - //printf("QNULL(%6zd), ", wsize); - //if (last_bin%8 == 0) printf("/* %i */ \\\n ", last_bin); + //printf("min bsize: %6zd, max bsize: %6zd, bin: %6zd\n", min_wsize, last_wsize, last_bin); + printf("QNULL(%6zd), ", wsize-1); + if (last_bin%8 == 0) printf("/* %zu */ \\\n ", last_bin); last_bin = bin; - min_bsize = bsize; } - last_bsize = bsize; } } #endif diff --git a/test/test-stress.c b/test/test-stress.c index 1e70e699..8ede5db2 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -42,7 +42,7 @@ static int SCALE = 10; static int ITER = 10; #else static int THREADS = 32; // more repeatable if THREADS <= #processors -static int SCALE = 25; // scaling factor +static int SCALE = 50; // scaling factor static int ITER = 50; // N full iterations destructing and re-creating all threads #endif @@ -50,7 +50,7 @@ static int ITER = 50; // N full iterations destructing and re-creating a #define STRESS // undefine for leak test -static bool allow_large_objects = true; // allow very large objects? (set to `true` if SCALE>100) +static bool allow_large_objects = false; // allow very large objects? (set to `true` if SCALE>100) static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`? static bool main_participates = false; // main thread participates as a worker too From c8607a8d012665782b9e2dc7cc6a35449ac803f5 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 8 Dec 2024 17:56:13 -0800 Subject: [PATCH 06/16] remove os_tld and stats parameters to os interface --- include/mimalloc/internal.h | 223 ++++++++++++++++++------------------ include/mimalloc/types.h | 8 -- src/arena.c | 92 +++++++-------- src/bitmap.c | 12 +- src/bitmap.h | 2 +- src/heap.c | 2 +- src/init.c | 17 ++- src/os.c | 130 ++++++++++----------- src/page.c | 2 +- src/segment-map.c | 4 +- src/segment.c | 70 +++++------ test/test-stress.c | 2 +- 12 files changed, 270 insertions(+), 294 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 716386d2..703c44b9 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -53,89 +53,100 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_decl_externc #endif +// "libc.c" +#include +void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args); +void _mi_snprintf(char* buf, size_t buflen, const char* fmt, ...); +char _mi_toupper(char c); +int _mi_strnicmp(const char* s, const char* t, size_t n); +void _mi_strlcpy(char* dest, const char* src, size_t dest_size); +void _mi_strlcat(char* dest, const char* src, size_t dest_size); +size_t _mi_strlen(const char* s); +size_t _mi_strnlen(const char* s, size_t max_len); +bool _mi_getenv(const char* name, char* result, size_t result_size); // "options.c" -void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message); -void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...); -void _mi_warning_message(const char* fmt, ...); -void _mi_verbose_message(const char* fmt, ...); -void _mi_trace_message(const char* fmt, ...); -void _mi_options_init(void); -long _mi_option_get_fast(mi_option_t option); -void _mi_error_message(int err, const char* fmt, ...); +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message); +void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...); +void _mi_warning_message(const char* fmt, ...); +void _mi_verbose_message(const char* fmt, ...); +void _mi_trace_message(const char* fmt, ...); +void _mi_options_init(void); +long _mi_option_get_fast(mi_option_t option); +void _mi_error_message(int err, const char* fmt, ...); // random.c -void _mi_random_init(mi_random_ctx_t* ctx); -void _mi_random_init_weak(mi_random_ctx_t* ctx); -void _mi_random_reinit_if_weak(mi_random_ctx_t * ctx); -void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx); -uintptr_t _mi_random_next(mi_random_ctx_t* ctx); -uintptr_t _mi_heap_random_next(mi_heap_t* heap); -uintptr_t _mi_os_random_weak(uintptr_t extra_seed); +void _mi_random_init(mi_random_ctx_t* ctx); +void _mi_random_init_weak(mi_random_ctx_t* ctx); +void _mi_random_reinit_if_weak(mi_random_ctx_t * ctx); +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx); +uintptr_t _mi_random_next(mi_random_ctx_t* ctx); +uintptr_t _mi_heap_random_next(mi_heap_t* heap); +uintptr_t _mi_os_random_weak(uintptr_t extra_seed); static inline uintptr_t _mi_random_shuffle(uintptr_t x); // init.c extern mi_decl_cache_align mi_stats_t _mi_stats_main; extern mi_decl_cache_align const mi_page_t _mi_page_empty; -void _mi_process_load(void); +void _mi_process_load(void); void mi_cdecl _mi_process_done(void); -bool _mi_is_redirected(void); -bool _mi_allocator_init(const char** message); -void _mi_allocator_done(void); -bool _mi_is_main_thread(void); -size_t _mi_current_thread_count(void); -bool _mi_preloading(void); // true while the C runtime is not initialized yet -void _mi_thread_done(mi_heap_t* heap); -void _mi_thread_data_collect(void); -void _mi_tld_init(mi_tld_t* tld, mi_heap_t* bheap); +bool _mi_is_redirected(void); +bool _mi_allocator_init(const char** message); +void _mi_allocator_done(void); +bool _mi_is_main_thread(void); +size_t _mi_current_thread_count(void); +bool _mi_preloading(void); // true while the C runtime is not initialized yet +void _mi_thread_done(mi_heap_t* heap); +void _mi_thread_data_collect(void); +void _mi_tld_init(mi_tld_t* tld, mi_heap_t* bheap); mi_threadid_t _mi_thread_id(void) mi_attr_noexcept; mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing heap mi_subproc_t* _mi_subproc_from_id(mi_subproc_id_t subproc_id); -void _mi_heap_guarded_init(mi_heap_t* heap); +void _mi_heap_guarded_init(mi_heap_t* heap); // os.c -void _mi_os_init(void); // called from process init -void* _mi_os_alloc(size_t size, mi_memid_t* memid, mi_stats_t* stats); -void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* stats); -void _mi_os_free_ex(void* p, size_t size, bool still_committed, mi_memid_t memid, mi_stats_t* stats); +void _mi_os_init(void); // called from process init +void* _mi_os_alloc(size_t size, mi_memid_t* memid); +void _mi_os_free(void* p, size_t size, mi_memid_t memid); +void _mi_os_free_ex(void* p, size_t size, bool still_committed, mi_memid_t memid); -size_t _mi_os_page_size(void); -size_t _mi_os_good_alloc_size(size_t size); -bool _mi_os_has_overcommit(void); -bool _mi_os_has_virtual_reserve(void); +size_t _mi_os_page_size(void); +size_t _mi_os_good_alloc_size(size_t size); +bool _mi_os_has_overcommit(void); +bool _mi_os_has_virtual_reserve(void); -bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats); -bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); -bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); -bool _mi_os_protect(void* addr, size_t size); -bool _mi_os_unprotect(void* addr, size_t size); -bool _mi_os_purge(void* p, size_t size, mi_stats_t* stats); -bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats); +bool _mi_os_reset(void* addr, size_t size); +bool _mi_os_commit(void* p, size_t size, bool* is_zero); +bool _mi_os_decommit(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_purge(void* p, size_t size); +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset); -void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* stats); -void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* tld_stats); +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid); +void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_memid_t* memid); -void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size); -bool _mi_os_use_large_page(size_t size, size_t alignment); -size_t _mi_os_large_page_size(void); +void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size); +bool _mi_os_use_large_page(size_t size, size_t alignment); +size_t _mi_os_large_page_size(void); -void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize, mi_memid_t* memid); +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize, mi_memid_t* memid); // arena.c mi_arena_id_t _mi_arena_id_none(void); -void _mi_arena_free(void* p, size_t size, size_t still_committed_size, mi_memid_t memid, mi_stats_t* stats); -void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld); -void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld); -bool _mi_arena_memid_is_suitable(mi_memid_t memid, mi_arena_id_t request_arena_id); -bool _mi_arena_contains(const void* p); -void _mi_arenas_collect(bool force_purge, mi_stats_t* stats); -void _mi_arena_unsafe_destroy_all(mi_stats_t* stats); +void _mi_arena_free(void* p, size_t size, size_t still_committed_size, mi_memid_t memid); +void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid); +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid); +bool _mi_arena_memid_is_suitable(mi_memid_t memid, mi_arena_id_t request_arena_id); +bool _mi_arena_contains(const void* p); +void _mi_arenas_collect(bool force_purge); +void _mi_arena_unsafe_destroy_all(void); -bool _mi_arena_segment_clear_abandoned(mi_segment_t* segment); -void _mi_arena_segment_mark_abandoned(mi_segment_t* segment); +bool _mi_arena_segment_clear_abandoned(mi_segment_t* segment); +void _mi_arena_segment_mark_abandoned(mi_segment_t* segment); -void* _mi_arena_meta_zalloc(size_t size, mi_memid_t* memid); -void _mi_arena_meta_free(void* p, mi_memid_t memid, size_t size); +void* _mi_arena_meta_zalloc(size_t size, mi_memid_t* memid); +void _mi_arena_meta_free(void* p, mi_memid_t memid, size_t size); typedef struct mi_arena_field_cursor_s { // abstract struct size_t os_list_count; // max entries to visit in the OS abandoned list @@ -151,63 +162,63 @@ mi_segment_t* _mi_arena_segment_clear_abandoned_next(mi_arena_field_cursor_t* pr void _mi_arena_field_cursor_done(mi_arena_field_cursor_t* current); // "segment-map.c" -void _mi_segment_map_allocated_at(const mi_segment_t* segment); -void _mi_segment_map_freed_at(const mi_segment_t* segment); +void _mi_segment_map_allocated_at(const mi_segment_t* segment); +void _mi_segment_map_freed_at(const mi_segment_t* segment); // "segment.c" -mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld, mi_os_tld_t* os_tld); -void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); -void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); -uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld); +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); #if MI_HUGE_PAGE_ABANDON -void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); #else -void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); +void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); #endif -void _mi_segments_collect(bool force, mi_segments_tld_t* tld); -void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld); -bool _mi_segment_attempt_reclaim(mi_heap_t* heap, mi_segment_t* segment); -bool _mi_segment_visit_blocks(mi_segment_t* segment, int heap_tag, bool visit_blocks, mi_block_visit_fun* visitor, void* arg); +void _mi_segments_collect(bool force, mi_segments_tld_t* tld); +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld); +bool _mi_segment_attempt_reclaim(mi_heap_t* heap, mi_segment_t* segment); +bool _mi_segment_visit_blocks(mi_segment_t* segment, int heap_tag, bool visit_blocks, mi_block_visit_fun* visitor, void* arg); // "page.c" -void* _mi_malloc_generic(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept mi_attr_malloc; +void* _mi_malloc_generic(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept mi_attr_malloc; -void _mi_page_retire(mi_page_t* page) mi_attr_noexcept; // free the page if there are no other pages with many free blocks -void _mi_page_unfull(mi_page_t* page); -void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page -void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... -void _mi_page_force_abandon(mi_page_t* page); +void _mi_page_retire(mi_page_t* page) mi_attr_noexcept; // free the page if there are no other pages with many free blocks +void _mi_page_unfull(mi_page_t* page); +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... +void _mi_page_force_abandon(mi_page_t* page); -void _mi_heap_delayed_free_all(mi_heap_t* heap); -bool _mi_heap_delayed_free_partial(mi_heap_t* heap); -void _mi_heap_collect_retired(mi_heap_t* heap, bool force); +void _mi_heap_delayed_free_all(mi_heap_t* heap); +bool _mi_heap_delayed_free_partial(mi_heap_t* heap); +void _mi_heap_collect_retired(mi_heap_t* heap, bool force); -void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); -bool _mi_page_try_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); -size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); -void _mi_deferred_free(mi_heap_t* heap, bool force); +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +bool _mi_page_try_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); +void _mi_deferred_free(mi_heap_t* heap, bool force); -void _mi_page_free_collect(mi_page_t* page,bool force); -void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments +void _mi_page_free_collect(mi_page_t* page,bool force); +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments -size_t _mi_bin_size(uint8_t bin); // for stats -uint8_t _mi_bin(size_t size); // for stats +size_t _mi_bin_size(uint8_t bin); // for stats +uint8_t _mi_bin(size_t size); // for stats // "heap.c" -void _mi_heap_init(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool noreclaim, uint8_t tag); -void _mi_heap_destroy_pages(mi_heap_t* heap); -void _mi_heap_collect_abandon(mi_heap_t* heap); -void _mi_heap_set_default_direct(mi_heap_t* heap); -bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid); -void _mi_heap_unsafe_destroy_all(void); -mi_heap_t* _mi_heap_by_tag(mi_heap_t* heap, uint8_t tag); -void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page); -bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg); +void _mi_heap_init(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool noreclaim, uint8_t tag); +void _mi_heap_destroy_pages(mi_heap_t* heap); +void _mi_heap_collect_abandon(mi_heap_t* heap); +void _mi_heap_set_default_direct(mi_heap_t* heap); +bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid); +void _mi_heap_unsafe_destroy_all(void); +mi_heap_t* _mi_heap_by_tag(mi_heap_t* heap, uint8_t tag); +void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page); +bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg); // "stats.c" -void _mi_stats_done(mi_stats_t* stats); +void _mi_stats_done(mi_stats_t* stats); mi_msecs_t _mi_clock_now(void); mi_msecs_t _mi_clock_end(mi_msecs_t start); mi_msecs_t _mi_clock_start(void); @@ -224,18 +235,6 @@ bool _mi_free_delayed_block(mi_block_t* block); void _mi_free_generic(mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept; // for runtime integration void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size); -// "libc.c" -#include -void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args); -void _mi_snprintf(char* buf, size_t buflen, const char* fmt, ...); -char _mi_toupper(char c); -int _mi_strnicmp(const char* s, const char* t, size_t n); -void _mi_strlcpy(char* dest, const char* src, size_t dest_size); -void _mi_strlcat(char* dest, const char* src, size_t dest_size); -size_t _mi_strlen(const char* s); -size_t _mi_strnlen(const char* s, size_t max_len); -bool _mi_getenv(const char* name, char* result, size_t result_size); - #if MI_DEBUG>1 bool _mi_page_is_valid(mi_page_t* page); #endif @@ -806,13 +805,13 @@ static inline uintptr_t _mi_random_shuffle(uintptr_t x) { // Optimize numa node access for the common case (= one node) // ------------------------------------------------------------------- -int _mi_os_numa_node_get(mi_os_tld_t* tld); +int _mi_os_numa_node_get(void); size_t _mi_os_numa_node_count_get(void); extern _Atomic(size_t) _mi_numa_node_count; -static inline int _mi_os_numa_node(mi_os_tld_t* tld) { +static inline int _mi_os_numa_node(void) { if mi_likely(mi_atomic_load_relaxed(&_mi_numa_node_count) == 1) { return 0; } - else return _mi_os_numa_node_get(tld); + else return _mi_os_numa_node_get(); } static inline size_t _mi_os_numa_node_count(void) { const size_t count = mi_atomic_load_relaxed(&_mi_numa_node_count); diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 44074450..3d8014c3 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -656,12 +656,6 @@ typedef struct mi_segment_queue_s { mi_segment_t* last; } mi_segment_queue_t; -// OS thread local data -typedef struct mi_os_tld_s { - size_t region_idx; // start point for next allocation - mi_stats_t* stats; // points to tld stats -} mi_os_tld_t; - // Segments thread local data typedef struct mi_segments_tld_s { mi_segment_queue_t small_free; // queue of segments with free small pages @@ -674,7 +668,6 @@ typedef struct mi_segments_tld_s { size_t reclaim_count;// number of reclaimed (abandoned) segments mi_subproc_t* subproc; // sub-process this thread belongs to. mi_stats_t* stats; // points to tld stats - mi_os_tld_t* os; // points to os tld } mi_segments_tld_t; // Thread local data @@ -684,7 +677,6 @@ struct mi_tld_s { mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) mi_heap_t* heaps; // list of heaps in this thread (so we can abandon all when the thread terminates) mi_segments_tld_t segments; // segment tld - mi_os_tld_t os; // os tld mi_stats_t stats; // statistics }; diff --git a/src/arena.c b/src/arena.c index 8ca5aaf3..164f3116 100644 --- a/src/arena.c +++ b/src/arena.c @@ -186,7 +186,7 @@ void* _mi_arena_meta_zalloc(size_t size, mi_memid_t* memid) { if (p != NULL) return p; // or fall back to the OS - p = _mi_os_alloc(size, memid, &_mi_stats_main); + p = _mi_os_alloc(size, memid); if (p == NULL) return NULL; // zero the OS memory if needed @@ -199,7 +199,7 @@ void* _mi_arena_meta_zalloc(size_t size, mi_memid_t* memid) { void _mi_arena_meta_free(void* p, mi_memid_t memid, size_t size) { if (mi_memkind_is_os(memid.memkind)) { - _mi_os_free(p, size, memid, &_mi_stats_main); + _mi_os_free(p, size, memid); } else { mi_assert(memid.memkind == MI_MEM_STATIC); @@ -216,10 +216,10 @@ void* mi_arena_block_start(mi_arena_t* arena, mi_bitmap_index_t bindex) { ----------------------------------------------------------- */ // claim the `blocks_inuse` bits -static bool mi_arena_try_claim(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx, mi_stats_t* stats) +static bool mi_arena_try_claim(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx) { size_t idx = 0; // mi_atomic_load_relaxed(&arena->search_idx); // start from last search; ok to be relaxed as the exact start does not matter - if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx, stats)) { + if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx)) { mi_atomic_store_relaxed(&arena->search_idx, mi_bitmap_index_field(*bitmap_idx)); // start search from found location next time around return true; }; @@ -232,13 +232,13 @@ static bool mi_arena_try_claim(mi_arena_t* arena, size_t blocks, mi_bitmap_index ----------------------------------------------------------- */ static mi_decl_noinline void* mi_arena_try_alloc_at(mi_arena_t* arena, size_t arena_index, size_t needed_bcount, - bool commit, mi_memid_t* memid, mi_os_tld_t* tld) + bool commit, mi_memid_t* memid) { MI_UNUSED(arena_index); mi_assert_internal(mi_arena_id_index(arena->id) == arena_index); mi_bitmap_index_t bitmap_index; - if (!mi_arena_try_claim(arena, needed_bcount, &bitmap_index, tld->stats)) return NULL; + if (!mi_arena_try_claim(arena, needed_bcount, &bitmap_index)) return NULL; // claimed it! void* p = mi_arena_block_start(arena, bitmap_index); @@ -268,7 +268,7 @@ static mi_decl_noinline void* mi_arena_try_alloc_at(mi_arena_t* arena, size_t ar _mi_bitmap_claim_across(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted); if (any_uncommitted) { bool commit_zero = false; - if (!_mi_os_commit(p, mi_arena_block_size(needed_bcount), &commit_zero, tld->stats)) { + if (!_mi_os_commit(p, mi_arena_block_size(needed_bcount), &commit_zero)) { memid->initially_committed = false; } else { @@ -286,7 +286,7 @@ static mi_decl_noinline void* mi_arena_try_alloc_at(mi_arena_t* arena, size_t ar // allocate in a speficic arena static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_node, int numa_node, size_t size, size_t alignment, - bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld ) + bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid ) { MI_UNUSED_RELEASE(alignment); mi_assert(alignment <= MI_SEGMENT_ALIGN); @@ -307,7 +307,7 @@ static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_no } // try to allocate - void* p = mi_arena_try_alloc_at(arena, arena_index, bcount, commit, memid, tld); + void* p = mi_arena_try_alloc_at(arena, arena_index, bcount, commit, memid); mi_assert_internal(p == NULL || _mi_is_aligned(p, alignment)); return p; } @@ -316,7 +316,7 @@ static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_no // allocate from an arena with fallback to the OS static mi_decl_noinline void* mi_arena_try_alloc(int numa_node, size_t size, size_t alignment, bool commit, bool allow_large, - mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld ) + mi_arena_id_t req_arena_id, mi_memid_t* memid ) { MI_UNUSED(alignment); mi_assert_internal(alignment <= MI_SEGMENT_ALIGN); @@ -326,21 +326,21 @@ static mi_decl_noinline void* mi_arena_try_alloc(int numa_node, size_t size, siz if (req_arena_id != _mi_arena_id_none()) { // try a specific arena if requested if (mi_arena_id_index(req_arena_id) < max_arena) { - void* p = mi_arena_try_alloc_at_id(req_arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + void* p = mi_arena_try_alloc_at_id(req_arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid); if (p != NULL) return p; } } else { // try numa affine allocation for (size_t i = 0; i < max_arena; i++) { - void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid); if (p != NULL) return p; } // try from another numa node instead.. if (numa_node >= 0) { // if numa_node was < 0 (no specific affinity requested), all arena's have been tried already for (size_t i = 0; i < max_arena; i++) { - void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), false /* only proceed if not numa local */, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), false /* only proceed if not numa local */, numa_node, size, alignment, commit, allow_large, req_arena_id, memid); if (p != NULL) return p; } } @@ -385,18 +385,18 @@ static bool mi_arena_reserve(size_t req_size, bool allow_large, mi_arena_id_t re void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, - mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld) + mi_arena_id_t req_arena_id, mi_memid_t* memid) { - mi_assert_internal(memid != NULL && tld != NULL); + mi_assert_internal(memid != NULL); mi_assert_internal(size > 0); *memid = _mi_memid_none(); - const int numa_node = _mi_os_numa_node(tld); // current numa node + const int numa_node = _mi_os_numa_node(); // current numa node // try to allocate in an arena if the alignment is small enough and the object is not too small (as for heap meta data) if (!mi_option_is_enabled(mi_option_disallow_arena_alloc) || req_arena_id != _mi_arena_id_none()) { // is arena allocation allowed? if (size >= MI_ARENA_MIN_OBJ_SIZE && alignment <= MI_SEGMENT_ALIGN && align_offset == 0) { - void* p = mi_arena_try_alloc(numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + void* p = mi_arena_try_alloc(numa_node, size, alignment, commit, allow_large, req_arena_id, memid); if (p != NULL) return p; // otherwise, try to first eagerly reserve a new arena @@ -405,7 +405,7 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset if (mi_arena_reserve(size, allow_large, req_arena_id, &arena_id)) { // and try allocate in there mi_assert_internal(req_arena_id == _mi_arena_id_none()); - p = mi_arena_try_alloc_at_id(arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + p = mi_arena_try_alloc_at_id(arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid); if (p != NULL) return p; } } @@ -420,16 +420,16 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset // finally, fall back to the OS if (align_offset > 0) { - return _mi_os_alloc_aligned_at_offset(size, alignment, align_offset, commit, allow_large, memid, tld->stats); + return _mi_os_alloc_aligned_at_offset(size, alignment, align_offset, commit, allow_large, memid); } else { - return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid, tld->stats); + return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid); } } -void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld) +void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid) { - return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, 0, commit, allow_large, req_arena_id, memid, tld); + return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, 0, commit, allow_large, req_arena_id, memid); } @@ -455,7 +455,7 @@ static long mi_arena_purge_delay(void) { // reset or decommit in an arena and update the committed/decommit bitmaps // assumes we own the area (i.e. blocks_in_use is claimed by us) -static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, mi_stats_t* stats) { +static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks) { mi_assert_internal(arena->blocks_committed != NULL); mi_assert_internal(arena->blocks_purge != NULL); mi_assert_internal(!arena->memid.is_pinned); @@ -464,7 +464,7 @@ static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, bool needs_recommit; if (_mi_bitmap_is_claimed_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx)) { // all blocks are committed, we can purge freely - needs_recommit = _mi_os_purge(p, size, stats); + needs_recommit = _mi_os_purge(p, size); } else { // some blocks are not committed -- this can happen when a partially committed block is freed @@ -472,7 +472,7 @@ static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, // we need to ensure we do not try to reset (as that may be invalid for uncommitted memory), // and also undo the decommit stats (as it was already adjusted) mi_assert_internal(mi_option_is_enabled(mi_option_purge_decommits)); - needs_recommit = _mi_os_purge_ex(p, size, false /* allow reset? */, stats); + needs_recommit = _mi_os_purge_ex(p, size, false /* allow reset? */); if (needs_recommit) { _mi_stat_increase(&_mi_stats_main.committed, size); } } @@ -486,14 +486,14 @@ static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, // Schedule a purge. This is usually delayed to avoid repeated decommit/commit calls. // Note: assumes we (still) own the area as we may purge immediately -static void mi_arena_schedule_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, mi_stats_t* stats) { +static void mi_arena_schedule_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks) { mi_assert_internal(arena->blocks_purge != NULL); const long delay = mi_arena_purge_delay(); if (delay < 0) return; // is purging allowed at all? if (_mi_preloading() || delay == 0) { // decommit directly - mi_arena_purge(arena, bitmap_idx, blocks, stats); + mi_arena_purge(arena, bitmap_idx, blocks); } else { // schedule decommit @@ -511,7 +511,7 @@ static void mi_arena_schedule_purge(mi_arena_t* arena, size_t bitmap_idx, size_t // purge a range of blocks // return true if the full range was purged. // assumes we own the area (i.e. blocks_in_use is claimed by us) -static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx, size_t bitlen, size_t purge, mi_stats_t* stats) { +static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx, size_t bitlen, size_t purge) { const size_t endidx = startidx + bitlen; size_t bitidx = startidx; bool all_purged = false; @@ -524,7 +524,7 @@ static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx, if (count > 0) { // found range to be purged const mi_bitmap_index_t range_idx = mi_bitmap_index_create(idx, bitidx); - mi_arena_purge(arena, range_idx, count, stats); + mi_arena_purge(arena, range_idx, count); if (count == bitlen) { all_purged = true; } @@ -535,7 +535,7 @@ static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx, } // returns true if anything was purged -static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force, mi_stats_t* stats) +static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force) { if (arena->memid.is_pinned || arena->blocks_purge == NULL) return false; mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire); @@ -571,7 +571,7 @@ static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force, mi if (bitlen > 0) { // read purge again now that we have the in_use bits purge = mi_atomic_load_acquire(&arena->blocks_purge[i]); - if (!mi_arena_purge_range(arena, i, bitidx, bitlen, purge, stats)) { + if (!mi_arena_purge_range(arena, i, bitidx, bitlen, purge)) { full_purge = false; } any_purged = true; @@ -591,7 +591,7 @@ static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force, mi return any_purged; } -static void mi_arenas_try_purge( bool force, bool visit_all, mi_stats_t* stats ) { +static void mi_arenas_try_purge( bool force, bool visit_all ) { if (_mi_preloading() || mi_arena_purge_delay() <= 0) return; // nothing will be scheduled const size_t max_arena = mi_atomic_load_acquire(&mi_arena_count); @@ -606,7 +606,7 @@ static void mi_arenas_try_purge( bool force, bool visit_all, mi_stats_t* stats ) for (size_t i = 0; i < max_arena; i++) { mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]); if (arena != NULL) { - if (mi_arena_try_purge(arena, now, force, stats)) { + if (mi_arena_try_purge(arena, now, force)) { if (max_purge_count <= 1) break; max_purge_count--; } @@ -620,8 +620,8 @@ static void mi_arenas_try_purge( bool force, bool visit_all, mi_stats_t* stats ) Arena free ----------------------------------------------------------- */ -void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memid, mi_stats_t* stats) { - mi_assert_internal(size > 0 && stats != NULL); +void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memid) { + mi_assert_internal(size > 0); mi_assert_internal(committed_size <= size); if (p==NULL) return; if (size==0) return; @@ -636,7 +636,7 @@ void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memi // if partially committed, adjust the committed stats (as `_mi_os_free` will increase decommit by the full size) _mi_stat_decrease(&_mi_stats_main.committed, committed_size); } - _mi_os_free(p, size, memid, stats); + _mi_os_free(p, size, memid); } else if (memid.memkind == MI_MEM_ARENA) { // allocated in an arena @@ -681,7 +681,7 @@ void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memi // works (as we should never reset decommitted parts). } // (delay) purge the entire range - mi_arena_schedule_purge(arena, bitmap_idx, blocks, stats); + mi_arena_schedule_purge(arena, bitmap_idx, blocks); } // and make it available to others again @@ -697,7 +697,7 @@ void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memi } // purge expired decommits - mi_arenas_try_purge(false, false, stats); + mi_arenas_try_purge(false, false); } // destroy owned arenas; this is unsafe and should only be done using `mi_option_destroy_on_exit` @@ -711,7 +711,7 @@ static void mi_arenas_unsafe_destroy(void) { mi_lock_done(&arena->abandoned_visit_lock); if (arena->start != NULL && mi_memkind_is_os(arena->memid.memkind)) { mi_atomic_store_ptr_release(mi_arena_t, &mi_arenas[i], NULL); - _mi_os_free(arena->start, mi_arena_size(arena), arena->memid, &_mi_stats_main); + _mi_os_free(arena->start, mi_arena_size(arena), arena->memid); } else { new_max_arena = i; @@ -726,15 +726,15 @@ static void mi_arenas_unsafe_destroy(void) { } // Purge the arenas; if `force_purge` is true, amenable parts are purged even if not yet expired -void _mi_arenas_collect(bool force_purge, mi_stats_t* stats) { - mi_arenas_try_purge(force_purge, force_purge /* visit all? */, stats); +void _mi_arenas_collect(bool force_purge) { + mi_arenas_try_purge(force_purge, force_purge /* visit all? */); } // destroy owned arenas; this is unsafe and should only be done using `mi_option_destroy_on_exit` // for dynamic libraries that are unloaded and need to release all their allocated memory. -void _mi_arena_unsafe_destroy_all(mi_stats_t* stats) { +void _mi_arena_unsafe_destroy_all(void) { mi_arenas_unsafe_destroy(); - _mi_arenas_collect(true /* force purge */, stats); // purge non-owned arenas + _mi_arenas_collect(true /* force purge */); // purge non-owned arenas } // Is a pointer inside any of our arenas? @@ -838,11 +838,11 @@ int mi_reserve_os_memory_ex(size_t size, bool commit, bool allow_large, bool exc if (arena_id != NULL) *arena_id = _mi_arena_id_none(); size = _mi_align_up(size, MI_ARENA_BLOCK_SIZE); // at least one block mi_memid_t memid; - void* start = _mi_os_alloc_aligned(size, MI_SEGMENT_ALIGN, commit, allow_large, &memid, &_mi_stats_main); + void* start = _mi_os_alloc_aligned(size, MI_SEGMENT_ALIGN, commit, allow_large, &memid); if (start == NULL) return ENOMEM; const bool is_large = memid.is_pinned; // todo: use separate is_large field? if (!mi_manage_os_memory_ex2(start, size, is_large, -1 /* numa node */, exclusive, memid, arena_id)) { - _mi_os_free_ex(start, size, commit, memid, &_mi_stats_main); + _mi_os_free_ex(start, size, commit, memid); _mi_verbose_message("failed to reserve %zu KiB memory\n", _mi_divide_up(size, 1024)); return ENOMEM; } @@ -938,7 +938,7 @@ int mi_reserve_huge_os_pages_at_ex(size_t pages, int numa_node, size_t timeout_m _mi_verbose_message("numa node %i: reserved %zu GiB huge pages (of the %zu GiB requested)\n", numa_node, pages_reserved, pages); if (!mi_manage_os_memory_ex2(p, hsize, true, numa_node, exclusive, memid, arena_id)) { - _mi_os_free(p, hsize, memid, &_mi_stats_main); + _mi_os_free(p, hsize, memid); return ENOMEM; } return 0; diff --git a/src/bitmap.c b/src/bitmap.c index 976ba72c..98f6ab7b 100644 --- a/src/bitmap.c +++ b/src/bitmap.c @@ -182,7 +182,7 @@ bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t // Try to atomically claim a sequence of `count` bits starting from the field // at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success. // Only needs to consider crossing into the next fields (see `mi_bitmap_try_find_from_claim_across`) -static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx, mi_stats_t* stats) +static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx) { mi_assert_internal(bitmap_idx != NULL); @@ -242,7 +242,7 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)); // claimed! - mi_stat_counter_increase(stats->arena_crossover_count,1); + mi_stat_counter_increase(_mi_stats_main.arena_crossover_count,1); *bitmap_idx = mi_bitmap_index_create(idx, initial_idx); return true; @@ -262,10 +262,10 @@ rollback: newmap = (map & ~initial_mask); } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)); } - mi_stat_counter_increase(stats->arena_rollback_count,1); + mi_stat_counter_increase(_mi_stats_main.arena_rollback_count,1); // retry? (we make a recursive call instead of goto to be able to use const declarations) if (retries <= 2) { - return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx, stats); + return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx); } else { return false; @@ -275,7 +275,7 @@ rollback: // Find `count` bits of zeros and set them to 1 atomically; returns `true` on success. // Starts at idx, and wraps around to search in all `bitmap_fields` fields. -bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx, mi_stats_t* stats) { +bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) { mi_assert_internal(count > 0); if (count <= 2) { // we don't bother with crossover fields for small counts @@ -295,7 +295,7 @@ bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitm } */ // if that fails, then try to claim across fields - if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx, stats)) { + if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) { return true; } } diff --git a/src/bitmap.h b/src/bitmap.h index f8898935..d60668cb 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -94,7 +94,7 @@ bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t // Find `count` bits of zeros and set them to 1 atomically; returns `true` on success. // Starts at idx, and wraps around to search in all `bitmap_fields` fields. -bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx, mi_stats_t* stats); +bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx); // Set `count` bits at `bitmap_idx` to 0 atomically // Returns `true` if all `count` bits were 1 previously. diff --git a/src/heap.c b/src/heap.c index 581b3f71..4459ff77 100644 --- a/src/heap.c +++ b/src/heap.c @@ -166,7 +166,7 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) } // collect arenas (this is program wide so don't force purges on abandonment of threads) - _mi_arenas_collect(collect == MI_FORCE /* force purge? */, &heap->tld->stats); + _mi_arenas_collect(collect == MI_FORCE /* force purge? */); } void _mi_heap_collect_abandon(mi_heap_t* heap) { diff --git a/src/init.c b/src/init.c index a90818a4..3e4da831 100644 --- a/src/init.c +++ b/src/init.c @@ -136,9 +136,8 @@ static mi_decl_cache_align mi_tld_t tld_main = { &_mi_heap_main, &_mi_heap_main, { { NULL, NULL }, {NULL ,NULL}, {NULL ,NULL, 0}, 0, 0, 0, 0, 0, &mi_subproc_default, - &tld_main.stats, &tld_main.os + &tld_main.stats }, // segments - { 0, &tld_main.stats }, // os { MI_STATS_NULL } // stats }; @@ -320,10 +319,10 @@ static mi_thread_data_t* mi_thread_data_zalloc(void) { // if that fails, allocate as meta data if (td == NULL) { mi_memid_t memid; - td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid, &_mi_stats_main); + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid); if (td == NULL) { // if this fails, try once more. (issue #257) - td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid, &_mi_stats_main); + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid); if (td == NULL) { // really out of memory _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t)); @@ -353,7 +352,7 @@ static void mi_thread_data_free( mi_thread_data_t* tdfree ) { } } // if that fails, just free it directly - _mi_os_free(tdfree, sizeof(mi_thread_data_t), tdfree->memid, &_mi_stats_main); + _mi_os_free(tdfree, sizeof(mi_thread_data_t), tdfree->memid); } void _mi_thread_data_collect(void) { @@ -363,7 +362,7 @@ void _mi_thread_data_collect(void) { if (td != NULL) { td = mi_atomic_exchange_ptr_acq_rel(mi_thread_data_t, &td_cache[i], NULL); if (td != NULL) { - _mi_os_free(td, sizeof(mi_thread_data_t), td->memid, &_mi_stats_main); + _mi_os_free(td, sizeof(mi_thread_data_t), td->memid); } } } @@ -399,9 +398,7 @@ void _mi_tld_init(mi_tld_t* tld, mi_heap_t* bheap) { tld->heap_backing = bheap; tld->heaps = NULL; tld->segments.subproc = &mi_subproc_default; - tld->segments.stats = &tld->stats; - tld->segments.os = &tld->os; - tld->os.stats = &tld->stats; + tld->segments.stats = &tld->stats; } // Free the thread local default heap (called from `mi_thread_done`) @@ -685,7 +682,7 @@ void mi_cdecl _mi_process_done(void) { if (mi_option_is_enabled(mi_option_destroy_on_exit)) { mi_collect(true /* force */); _mi_heap_unsafe_destroy_all(); // forcefully release all memory held by all heaps (of this thread only!) - _mi_arena_unsafe_destroy_all(& _mi_heap_main_get()->tld->stats); + _mi_arena_unsafe_destroy_all(); } if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { diff --git a/src/os.c b/src/os.c index a7130b90..81dda8a1 100644 --- a/src/os.c +++ b/src/os.c @@ -9,6 +9,7 @@ terms of the MIT license. A copy of the license can be found in the file #include "mimalloc/atomic.h" #include "mimalloc/prim.h" +#define os_stats (&_mi_stats_main) /* ----------------------------------------------------------- Initialization. @@ -85,8 +86,8 @@ void _mi_os_init(void) { /* ----------------------------------------------------------- Util -------------------------------------------------------------- */ -bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); -bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats); +bool _mi_os_decommit(void* addr, size_t size); +bool _mi_os_commit(void* addr, size_t size, bool* is_zero); static inline uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) { mi_assert_internal(alignment != 0); @@ -161,23 +162,20 @@ void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) { Free memory -------------------------------------------------------------- */ -static void mi_os_free_huge_os_pages(void* p, size_t size, mi_stats_t* stats); +static void mi_os_free_huge_os_pages(void* p, size_t size); -static void mi_os_prim_free(void* addr, size_t size, bool still_committed, mi_stats_t* tld_stats) { - MI_UNUSED(tld_stats); - mi_stats_t* stats = &_mi_stats_main; +static void mi_os_prim_free(void* addr, size_t size, bool still_committed) { mi_assert_internal((size % _mi_os_page_size()) == 0); if (addr == NULL || size == 0) return; // || _mi_os_is_huge_reserved(addr) int err = _mi_prim_free(addr, size); if (err != 0) { _mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr); } - if (still_committed) { _mi_stat_decrease(&stats->committed, size); } - _mi_stat_decrease(&stats->reserved, size); + if (still_committed) { _mi_stat_decrease(&os_stats->committed, size); } + _mi_stat_decrease(&os_stats->reserved, size); } -void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid, mi_stats_t* stats) { - if (stats == NULL) stats = &_mi_stats_main; +void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid) { if (mi_memkind_is_os(memid.memkind)) { size_t csize = _mi_os_good_alloc_size(size); void* base = addr; @@ -191,10 +189,10 @@ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t me // free it if (memid.memkind == MI_MEM_OS_HUGE) { mi_assert(memid.is_pinned); - mi_os_free_huge_os_pages(base, csize, stats); + mi_os_free_huge_os_pages(base, csize); } else { - mi_os_prim_free(base, csize, still_committed, stats); + mi_os_prim_free(base, csize, still_committed); } } else { @@ -203,9 +201,8 @@ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t me } } -void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* stats) { - if (stats == NULL) stats = &_mi_stats_main; - _mi_os_free_ex(p, size, true, memid, stats); +void _mi_os_free(void* p, size_t size, mi_memid_t memid) { + _mi_os_free_ex(p, size, true, memid); } @@ -215,7 +212,7 @@ void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* stats) { // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. // Also `hint_addr` is a hint and may be ignored. -static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* tld_stats) { +static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero) { mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); mi_assert_internal(is_zero != NULL); mi_assert_internal(is_large != NULL); @@ -229,13 +226,13 @@ static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignm _mi_warning_message("unable to allocate OS memory (error: %d (0x%x), addr: %p, size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, hint_addr, size, try_alignment, commit, allow_large); } - MI_UNUSED(tld_stats); - mi_stats_t* stats = &_mi_stats_main; - mi_stat_counter_increase(stats->mmap_calls, 1); + + + mi_stat_counter_increase(os_stats->mmap_calls, 1); if (p != NULL) { - _mi_stat_increase(&stats->reserved, size); + _mi_stat_increase(&os_stats->reserved, size); if (commit) { - _mi_stat_increase(&stats->committed, size); + _mi_stat_increase(&os_stats->committed, size); // seems needed for asan (or `mimalloc-test-api` fails) #ifdef MI_TRACK_ASAN if (*is_zero) { mi_track_mem_defined(p,size); } @@ -246,14 +243,14 @@ static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignm return p; } -static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* tld_stats) { - return mi_os_prim_alloc_at(NULL, size, try_alignment, commit, allow_large, is_large, is_zero, tld_stats); +static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero) { + return mi_os_prim_alloc_at(NULL, size, try_alignment, commit, allow_large, is_large, is_zero); } // Primitive aligned allocation from the OS. // This function guarantees the allocated memory is aligned. -static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** base, mi_stats_t* stats) { +static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** base) { 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(is_large != NULL); @@ -264,7 +261,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit size = _mi_align_up(size, _mi_os_page_size()); // try first with a requested alignment hint (this will usually be aligned directly on Win 10+ or BSD) - void* p = mi_os_prim_alloc(size, alignment, commit, allow_large, is_large, is_zero, stats); + void* p = mi_os_prim_alloc(size, alignment, commit, allow_large, is_large, is_zero); if (p == NULL) return NULL; // aligned already? @@ -276,13 +273,13 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit #if !MI_TRACK_ASAN _mi_warning_message("unable to allocate aligned OS memory directly, fall back to over-allocation (size: 0x%zx bytes, address: %p, alignment: 0x%zx, commit: %d)\n", size, p, alignment, commit); #endif - mi_os_prim_free(p, size, commit, stats); + mi_os_prim_free(p, size, commit); if (size >= (SIZE_MAX - alignment)) return NULL; // overflow const size_t over_size = size + alignment; if (!mi_os_mem_config.has_partial_free) { // win32 virtualAlloc cannot free parts of an allocated block // over-allocate uncommitted (virtual) memory - p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero, stats); + p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero); if (p == NULL) return NULL; // set p to the aligned part in the full region @@ -293,12 +290,12 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit // explicitly commit only the aligned part if (commit) { - _mi_os_commit(p, size, NULL, stats); + _mi_os_commit(p, size, NULL); } } else { // mmap can free inside an allocation // overallocate... - p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero, stats); + p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero); if (p == NULL) return NULL; // and selectively unmap parts around the over-allocated area. @@ -307,8 +304,8 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit size_t mid_size = _mi_align_up(size, _mi_os_page_size()); size_t post_size = over_size - pre_size - mid_size; mi_assert_internal(pre_size < over_size&& post_size < over_size&& mid_size >= size); - if (pre_size > 0) { mi_os_prim_free(p, pre_size, commit, stats); } - if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); } + if (pre_size > 0) { mi_os_prim_free(p, pre_size, commit); } + if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit); } // we can return the aligned pointer on `mmap` systems p = aligned_p; *base = aligned_p; // since we freed the pre part, `*base == p`. @@ -324,33 +321,31 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit OS API: alloc and alloc_aligned ----------------------------------------------------------- */ -void* _mi_os_alloc(size_t size, mi_memid_t* memid, mi_stats_t* stats) { +void* _mi_os_alloc(size_t size, mi_memid_t* memid) { *memid = _mi_memid_none(); if (size == 0) return NULL; - if (stats == NULL) stats = &_mi_stats_main; size = _mi_os_good_alloc_size(size); bool os_is_large = false; bool os_is_zero = false; - void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero, stats); + void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero); if (p != NULL) { *memid = _mi_memid_create_os(true, os_is_zero, os_is_large); } return p; } -void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* stats) +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid) { MI_UNUSED(&_mi_os_get_aligned_hint); // suppress unused warnings *memid = _mi_memid_none(); if (size == 0) return NULL; - if (stats == NULL) stats = &_mi_stats_main; size = _mi_os_good_alloc_size(size); alignment = _mi_align_up(alignment, _mi_os_page_size()); bool os_is_large = false; bool os_is_zero = false; void* os_base = NULL; - void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, &os_is_large, &os_is_zero, &os_base, stats ); + void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, &os_is_large, &os_is_zero, &os_base ); if (p != NULL) { *memid = _mi_memid_create_os(commit, os_is_zero, os_is_large); memid->mem.os.base = os_base; @@ -367,29 +362,28 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allo to use the actual start of the memory region. ----------------------------------------------------------- */ -void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offset, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* stats) { +void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offset, bool commit, bool allow_large, mi_memid_t* memid) { mi_assert(offset <= MI_SEGMENT_SIZE); mi_assert(offset <= size); mi_assert((alignment % _mi_os_page_size()) == 0); *memid = _mi_memid_none(); - if (stats == NULL) stats = &_mi_stats_main; if (offset > MI_SEGMENT_SIZE) return NULL; if (offset == 0) { // regular aligned allocation - return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid, stats); + return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid); } else { // overallocate to align at an offset const size_t extra = _mi_align_up(offset, alignment) - offset; const size_t oversize = size + extra; - void* const start = _mi_os_alloc_aligned(oversize, alignment, commit, allow_large, memid, stats); + void* const start = _mi_os_alloc_aligned(oversize, alignment, commit, allow_large, memid); if (start == NULL) return NULL; void* const p = (uint8_t*)start + extra; mi_assert(_mi_is_aligned((uint8_t*)p + offset, alignment)); // decommit the overallocation at the start if (commit && extra > _mi_os_page_size()) { - _mi_os_decommit(start, extra, stats); + _mi_os_decommit(start, extra); } return p; } @@ -423,12 +417,10 @@ static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t* return mi_os_page_align_areax(true, addr, size, newsize); } -bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { - MI_UNUSED(tld_stats); - mi_stats_t* stats = &_mi_stats_main; +bool _mi_os_commit(void* addr, size_t size, bool* is_zero) { if (is_zero != NULL) { *is_zero = false; } - _mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit - _mi_stat_counter_increase(&stats->commit_calls, 1); + _mi_stat_increase(&os_stats->committed, size); // use size for precise commit vs. decommit + _mi_stat_counter_increase(&os_stats->commit_calls, 1); // page align range size_t csize; @@ -454,11 +446,8 @@ bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats return true; } -static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, mi_stats_t* tld_stats) { - MI_UNUSED(tld_stats); - mi_stats_t* stats = &_mi_stats_main; - mi_assert_internal(needs_recommit!=NULL); - _mi_stat_decrease(&stats->committed, size); +static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit) { mi_assert_internal(needs_recommit!=NULL); + _mi_stat_decrease(&os_stats->committed, size); // page align size_t csize; @@ -475,9 +464,9 @@ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, mi_ return (err == 0); } -bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) { +bool _mi_os_decommit(void* addr, size_t size) { bool needs_recommit; - return mi_os_decommit_ex(addr, size, &needs_recommit, tld_stats); + return mi_os_decommit_ex(addr, size, &needs_recommit); } @@ -485,13 +474,13 @@ bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) { // but may be used later again. This will release physical memory // pages and reduce swapping while keeping the memory committed. // We page align to a conservative area inside the range to reset. -bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) { +bool _mi_os_reset(void* addr, size_t size) { // page align conservatively within the range size_t csize; void* start = mi_os_page_align_area_conservative(addr, size, &csize); if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr) - _mi_stat_increase(&stats->reset, csize); - _mi_stat_counter_increase(&stats->reset_calls, 1); + _mi_stat_increase(&os_stats->reset, csize); + _mi_stat_counter_increase(&os_stats->reset_calls, 1); #if (MI_DEBUG>1) && !MI_SECURE && !MI_TRACK_ENABLED // && !MI_TSAN memset(start, 0, csize); // pretend it is eagerly reset @@ -507,22 +496,22 @@ bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) { // either resets or decommits memory, returns true if the memory needs // to be recommitted if it is to be re-used later on. -bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats) +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset) { if (mi_option_get(mi_option_purge_delay) < 0) return false; // is purging allowed? - _mi_stat_counter_increase(&stats->purge_calls, 1); - _mi_stat_increase(&stats->purged, size); + _mi_stat_counter_increase(&os_stats->purge_calls, 1); + _mi_stat_increase(&os_stats->purged, size); if (mi_option_is_enabled(mi_option_purge_decommits) && // should decommit? !_mi_preloading()) // don't decommit during preloading (unsafe) { bool needs_recommit = true; - mi_os_decommit_ex(p, size, &needs_recommit, stats); + mi_os_decommit_ex(p, size, &needs_recommit); return needs_recommit; } else { if (allow_reset) { // this can sometimes be not allowed if the range is not fully committed - _mi_os_reset(p, size, stats); + _mi_os_reset(p, size); } return false; // needs no recommit } @@ -530,8 +519,8 @@ bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats) // either resets or decommits memory, returns true if the memory needs // to be recommitted if it is to be re-used later on. -bool _mi_os_purge(void* p, size_t size, mi_stats_t * stats) { - return _mi_os_purge_ex(p, size, true, stats); +bool _mi_os_purge(void* p, size_t size) { + return _mi_os_purge_ex(p, size, true); } @@ -639,15 +628,15 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse // no success, issue a warning and break if (p != NULL) { _mi_warning_message("could not allocate contiguous huge OS page %zu at %p\n", page, addr); - mi_os_prim_free(p, MI_HUGE_OS_PAGE_SIZE, true, &_mi_stats_main); + mi_os_prim_free(p, MI_HUGE_OS_PAGE_SIZE, true); } break; } // success, record it page++; // increase before timeout check (see issue #711) - _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(&os_stats->committed, MI_HUGE_OS_PAGE_SIZE); + _mi_stat_increase(&os_stats->reserved, MI_HUGE_OS_PAGE_SIZE); // check for timeout if (max_msecs > 0) { @@ -681,11 +670,11 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse // free every huge page in a range individually (as we allocated per page) // note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems. -static void mi_os_free_huge_os_pages(void* p, size_t size, mi_stats_t* stats) { +static void mi_os_free_huge_os_pages(void* p, size_t size) { if (p==NULL || size==0) return; uint8_t* base = (uint8_t*)p; while (size >= MI_HUGE_OS_PAGE_SIZE) { - mi_os_prim_free(base, MI_HUGE_OS_PAGE_SIZE, true, stats); + mi_os_prim_free(base, MI_HUGE_OS_PAGE_SIZE, true); size -= MI_HUGE_OS_PAGE_SIZE; base += MI_HUGE_OS_PAGE_SIZE; } @@ -714,8 +703,7 @@ size_t _mi_os_numa_node_count_get(void) { return count; } -int _mi_os_numa_node_get(mi_os_tld_t* tld) { - MI_UNUSED(tld); +int _mi_os_numa_node_get() { size_t numa_count = _mi_os_numa_node_count(); if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0 // never more than the node count and >= 0 diff --git a/src/page.c b/src/page.c index c681d6d0..85e831d2 100644 --- a/src/page.c +++ b/src/page.c @@ -276,7 +276,7 @@ static mi_page_t* mi_page_fresh_alloc(mi_heap_t* heap, mi_page_queue_t* pq, size mi_assert_internal(mi_heap_contains_queue(heap, pq)); mi_assert_internal(page_alignment > 0 || block_size > MI_LARGE_OBJ_SIZE_MAX || block_size == pq->block_size); #endif - mi_page_t* page = _mi_segment_page_alloc(heap, block_size, page_alignment, &heap->tld->segments, &heap->tld->os); + mi_page_t* page = _mi_segment_page_alloc(heap, block_size, page_alignment, &heap->tld->segments); if (page == NULL) { // this may be out-of-memory, or an abandoned page was reclaimed (and in our queue) return NULL; diff --git a/src/segment-map.c b/src/segment-map.c index 2c3964fe..399f221c 100644 --- a/src/segment-map.c +++ b/src/segment-map.c @@ -55,11 +55,11 @@ static mi_segmap_part_t* mi_segment_map_index_of(const mi_segment_t* segment, bo if (part == NULL) { if (!create_on_demand) return NULL; mi_memid_t memid; - part = (mi_segmap_part_t*)_mi_os_alloc(sizeof(mi_segmap_part_t), &memid, NULL); + part = (mi_segmap_part_t*)_mi_os_alloc(sizeof(mi_segmap_part_t), &memid); if (part == NULL) return NULL; mi_segmap_part_t* expected = NULL; if (!mi_atomic_cas_ptr_strong_release(mi_segmap_part_t, &mi_segment_map[segindex], &expected, part)) { - _mi_os_free(part, sizeof(mi_segmap_part_t), memid, NULL); + _mi_os_free(part, sizeof(mi_segmap_part_t), memid); part = expected; if (part == NULL) return NULL; } diff --git a/src/segment.c b/src/segment.c index 74abcdbc..660351a7 100644 --- a/src/segment.c +++ b/src/segment.c @@ -189,7 +189,7 @@ static void mi_segment_protect_range(void* p, size_t size, bool protect) { } } -static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t* tld) { +static void mi_segment_protect(mi_segment_t* segment, bool protect) { // add/remove guard pages if (MI_SECURE != 0) { // in secure mode, we set up a protected page in between the segment info and the page data @@ -207,7 +207,7 @@ static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t* if (protect && !segment->memid.initially_committed) { if (protect) { // ensure secure page is committed - if (_mi_os_commit(start, os_psize, NULL, tld->stats)) { // if this fails that is ok (as it is an unaccessible page) + if (_mi_os_commit(start, os_psize, NULL)) { // if this fails that is ok (as it is an unaccessible page) mi_segment_protect_range(start, os_psize, protect); } } @@ -241,23 +241,23 @@ static void mi_page_purge(mi_segment_t* segment, mi_page_t* page, mi_segments_tl if (!segment->allow_purge) return; mi_assert_internal(page->used == 0); mi_assert_internal(page->free == NULL); - mi_assert_expensive(!mi_pages_purge_contains(page, tld)); + mi_assert_expensive(!mi_pages_purge_contains(page, tld)); MI_UNUSED(tld); size_t psize; void* start = mi_segment_raw_page_start(segment, page, &psize); - const bool needs_recommit = _mi_os_purge(start, psize, tld->stats); + const bool needs_recommit = _mi_os_purge(start, psize); if (needs_recommit) { page->is_committed = false; } } static bool mi_page_ensure_committed(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { if (page->is_committed) return true; mi_assert_internal(segment->allow_decommit); - mi_assert_expensive(!mi_pages_purge_contains(page, tld)); + mi_assert_expensive(!mi_pages_purge_contains(page, tld)); MI_UNUSED(tld); size_t psize; uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); bool is_zero = false; const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0); - bool ok = _mi_os_commit(start, psize + gsize, &is_zero, tld->stats); + bool ok = _mi_os_commit(start, psize + gsize, &is_zero); if (!ok) return false; // failed to commit! page->is_committed = true; page->used = 0; @@ -502,7 +502,7 @@ static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_se if (MI_SECURE != 0) { mi_assert_internal(!segment->memid.is_pinned); - mi_segment_protect(segment, false, tld->os); // ensure no more guard pages are set + mi_segment_protect(segment, false); // ensure no more guard pages are set } bool fully_committed = true; @@ -516,7 +516,7 @@ static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_se MI_UNUSED(fully_committed); mi_assert_internal((fully_committed && committed_size == segment_size) || (!fully_committed && committed_size < segment_size)); - _mi_arena_free(segment, segment_size, committed_size, segment->memid, tld->stats); + _mi_arena_free(segment, segment_size, committed_size, segment->memid); } // called from `heap_collect`. @@ -537,7 +537,7 @@ void _mi_segments_collect(bool force, mi_segments_tld_t* tld) { static mi_segment_t* mi_segment_os_alloc(bool eager_delayed, size_t page_alignment, mi_arena_id_t req_arena_id, size_t pre_size, size_t info_size, bool commit, size_t segment_size, - mi_segments_tld_t* tld, mi_os_tld_t* tld_os) + mi_segments_tld_t* tld) { mi_memid_t memid; bool allow_large = (!eager_delayed && (MI_SECURE == 0)); // only allow large OS pages once we are no longer lazy @@ -549,7 +549,7 @@ static mi_segment_t* mi_segment_os_alloc(bool eager_delayed, size_t page_alignme segment_size = segment_size + (align_offset - pre_size); // adjust the segment size } - mi_segment_t* segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, alignment, align_offset, commit, allow_large, req_arena_id, &memid, tld_os); + mi_segment_t* segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, alignment, align_offset, commit, allow_large, req_arena_id, &memid); if (segment == NULL) { return NULL; // failed to allocate } @@ -557,10 +557,10 @@ static mi_segment_t* mi_segment_os_alloc(bool eager_delayed, size_t page_alignme if (!memid.initially_committed) { // ensure the initial info is committed mi_assert_internal(!memid.is_pinned); - bool ok = _mi_os_commit(segment, pre_size, NULL, tld_os->stats); + bool ok = _mi_os_commit(segment, pre_size, NULL); if (!ok) { // commit failed; we cannot touch the memory: free the segment directly and return `NULL` - _mi_arena_free(segment, segment_size, 0, memid, tld_os->stats); + _mi_arena_free(segment, segment_size, 0, memid); return NULL; } } @@ -578,7 +578,7 @@ static mi_segment_t* mi_segment_os_alloc(bool eager_delayed, size_t page_alignme // Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` . static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, size_t page_shift, size_t page_alignment, - mi_arena_id_t req_arena_id, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) + mi_arena_id_t req_arena_id, mi_segments_tld_t* tld) { // required is only > 0 for huge page allocations mi_assert_internal((required > 0 && page_kind > MI_PAGE_LARGE)|| (required==0 && page_kind <= MI_PAGE_LARGE)); @@ -610,7 +610,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, const bool init_commit = eager; // || (page_kind >= MI_PAGE_LARGE); // Allocate the segment from the OS (segment_size can change due to alignment) - mi_segment_t* segment = mi_segment_os_alloc(eager_delayed, page_alignment, req_arena_id, pre_size, info_size, init_commit, init_segment_size, tld, os_tld); + mi_segment_t* segment = mi_segment_os_alloc(eager_delayed, page_alignment, req_arena_id, pre_size, info_size, init_commit, init_segment_size, tld); if (segment == NULL) return NULL; mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0); mi_assert_internal(segment->memid.is_pinned ? segment->memid.initially_committed : true); @@ -638,7 +638,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, segment->cookie = _mi_ptr_cookie(segment); // set protection - mi_segment_protect(segment, true, tld->os); + mi_segment_protect(segment, true); // insert in free lists for small and medium pages if (page_kind <= MI_PAGE_MEDIUM) { @@ -1142,7 +1142,7 @@ void mi_collect_reduce(size_t target_size) mi_attr_noexcept { Reclaim or allocate ----------------------------------------------------------- */ -static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld) { mi_assert_internal(page_kind <= MI_PAGE_LARGE); mi_assert_internal(block_size <= MI_LARGE_OBJ_SIZE_MAX); @@ -1164,7 +1164,7 @@ static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_s return segment; } // 2. otherwise allocate a fresh segment - return mi_segment_alloc(0, page_kind, page_shift, 0, heap->arena_id, tld, os_tld); + return mi_segment_alloc(0, page_kind, page_shift, 0, heap->arena_id, tld); } @@ -1203,11 +1203,11 @@ static mi_page_t* mi_segment_page_try_alloc_in_queue(mi_heap_t* heap, mi_page_ki return NULL; } -static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { +static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t kind, size_t page_shift, mi_segments_tld_t* tld) { mi_page_t* page = mi_segment_page_try_alloc_in_queue(heap, kind, tld); if (page == NULL) { // possibly allocate or reclaim a fresh segment - mi_segment_t* const segment = mi_segment_reclaim_or_alloc(heap, block_size, kind, page_shift, tld, os_tld); + mi_segment_t* const segment = mi_segment_reclaim_or_alloc(heap, block_size, kind, page_shift, tld); if (segment == NULL) return NULL; // return NULL if out-of-memory (or reclaimed) mi_assert_internal(segment->page_kind==kind); mi_assert_internal(segment->used < segment->capacity); @@ -1222,20 +1222,20 @@ static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_p return page; } -static mi_page_t* mi_segment_small_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { - return mi_segment_page_alloc(heap, block_size, MI_PAGE_SMALL,MI_SMALL_PAGE_SHIFT,tld,os_tld); +static mi_page_t* mi_segment_small_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_SMALL,MI_SMALL_PAGE_SHIFT,tld); } -static mi_page_t* mi_segment_medium_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { - return mi_segment_page_alloc(heap, block_size, MI_PAGE_MEDIUM, MI_MEDIUM_PAGE_SHIFT, tld, os_tld); +static mi_page_t* mi_segment_medium_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_MEDIUM, MI_MEDIUM_PAGE_SHIFT, tld); } /* ----------------------------------------------------------- large page allocation ----------------------------------------------------------- */ -static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { - mi_segment_t* segment = mi_segment_reclaim_or_alloc(heap,block_size,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld); +static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld) { + mi_segment_t* segment = mi_segment_reclaim_or_alloc(heap,block_size,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld); if (segment == NULL) return NULL; mi_page_t* page = mi_segment_find_free(segment, tld); mi_assert_internal(page != NULL); @@ -1245,9 +1245,9 @@ static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size return page; } -static mi_page_t* mi_segment_huge_page_alloc(size_t size, size_t page_alignment, mi_arena_id_t req_arena_id, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +static mi_page_t* mi_segment_huge_page_alloc(size_t size, size_t page_alignment, mi_arena_id_t req_arena_id, mi_segments_tld_t* tld) { - mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT + 1, page_alignment, req_arena_id, tld, os_tld); + mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT + 1, page_alignment, req_arena_id, tld); if (segment == NULL) return NULL; mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size); #if MI_HUGE_PAGE_ABANDON @@ -1271,7 +1271,7 @@ static mi_page_t* mi_segment_huge_page_alloc(size_t size, size_t page_alignment, mi_assert_internal(psize - (aligned_p - start) >= size); uint8_t* decommit_start = start + sizeof(mi_block_t); // for the free list ptrdiff_t decommit_size = aligned_p - decommit_start; - _mi_os_reset(decommit_start, decommit_size, os_tld->stats); // do not decommit as it may be in a region + _mi_os_reset(decommit_start, decommit_size); // do not decommit as it may be in a region } return page; @@ -1318,7 +1318,7 @@ void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_bloc if (usize > sizeof(mi_block_t)) { usize = usize - sizeof(mi_block_t); uint8_t* p = (uint8_t*)block + sizeof(mi_block_t); - _mi_os_reset(p, usize, &_mi_stats_main); + _mi_os_reset(p, usize); } } } @@ -1328,26 +1328,26 @@ void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_bloc Page allocation ----------------------------------------------------------- */ -mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld) { mi_page_t* page; if mi_unlikely(page_alignment > MI_BLOCK_ALIGNMENT_MAX) { mi_assert_internal(_mi_is_power_of_two(page_alignment)); mi_assert_internal(page_alignment >= MI_SEGMENT_SIZE); //mi_assert_internal((MI_SEGMENT_SIZE % page_alignment) == 0); if (page_alignment < MI_SEGMENT_SIZE) { page_alignment = MI_SEGMENT_SIZE; } - page = mi_segment_huge_page_alloc(block_size, page_alignment, heap->arena_id, tld, os_tld); + page = mi_segment_huge_page_alloc(block_size, page_alignment, heap->arena_id, tld); } else if (block_size <= MI_SMALL_OBJ_SIZE_MAX) { - page = mi_segment_small_page_alloc(heap, block_size, tld, os_tld); + page = mi_segment_small_page_alloc(heap, block_size, tld); } else if (block_size <= MI_MEDIUM_OBJ_SIZE_MAX) { - page = mi_segment_medium_page_alloc(heap, block_size, tld, os_tld); + page = mi_segment_medium_page_alloc(heap, block_size, tld); } else if (block_size <= MI_LARGE_OBJ_SIZE_MAX /* || mi_is_good_fit(block_size, MI_LARGE_PAGE_SIZE - sizeof(mi_segment_t)) */ ) { - page = mi_segment_large_page_alloc(heap, block_size, tld, os_tld); + page = mi_segment_large_page_alloc(heap, block_size, tld); } else { - page = mi_segment_huge_page_alloc(block_size, page_alignment, heap->arena_id, tld, os_tld); + page = mi_segment_huge_page_alloc(block_size, page_alignment, heap->arena_id, tld); } mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld)); mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size); diff --git a/test/test-stress.c b/test/test-stress.c index 8ede5db2..261c5dfe 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -36,7 +36,7 @@ static int ITER = 400; static int THREADS = 8; static int SCALE = 25; static int ITER = 20; -#elif defined(xMI_GUARDED) // with debug guard pages reduce parameters to stay within the azure pipeline limits +#elif defined(MI_GUARDED) // with debug guard pages reduce parameters to stay within the azure pipeline limits static int THREADS = 8; static int SCALE = 10; static int ITER = 10; From ed318471126918fce7caf0001cf1e0c78f95173e Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 9 Dec 2024 20:45:22 -0800 Subject: [PATCH 07/16] fix generic ctz/clz --- include/mimalloc/internal.h | 57 ++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 703c44b9..012ce4f0 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -873,16 +873,18 @@ static inline size_t mi_ctz(uintptr_t x) { } #else -static inline size_t mi_ctz32(uint32_t x) { + +static inline size_t mi_ctz_generic32(uint32_t x) { // de Bruijn multiplication, see - static const unsigned char debruijn[32] = { + static const uint8_t debruijn[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; if (x==0) return 32; - return debruijn[((x & -(int32_t)x) * 0x077CB531UL) >> 27]; + return debruijn[(uint32_t)((x & -(int32_t)x) * (uint32_t)(0x077CB531U)) >> 27]; } -static inline size_t mi_clz32(uint32_t x) { + +static inline size_t mi_clz_generic32(uint32_t x) { // de Bruijn multiplication, see static const uint8_t debruijn[32] = { 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1, @@ -894,28 +896,37 @@ static inline size_t mi_clz32(uint32_t x) { x |= x >> 4; x |= x >> 8; x |= x >> 16; - return debruijn[(uint32_t)(x * 0x07C4ACDDUL) >> 27]; + return debruijn[(uint32_t)(x * (uint32_t)(0x07C4ACDDU)) >> 27]; } -static inline size_t mi_clz(uintptr_t x) { - if (x==0) return MI_INTPTR_BITS; -#if (MI_INTPTR_BITS <= 32) - return mi_clz32((uint32_t)x); -#else - size_t count = mi_clz32((uint32_t)(x >> 32)); - if (count < 32) return count; - return (32 + mi_clz32((uint32_t)x)); -#endif +static inline size_t mi_ctz(size_t x) { + if (x==0) return MI_SIZE_BITS; + #if (MI_SIZE_BITS <= 32) + return mi_ctz_generic32((uint32_t)x); + #else + const uint32_t lo = (uint32_t)x; + if (lo != 0) { + return mi_ctz_generic32(lo); + } + else { + return (32 + mi_ctz_generic32((uint32_t)(x>>32))); + } + #endif } -static inline size_t mi_ctz(uintptr_t x) { - if (x==0) return MI_INTPTR_BITS; -#if (MI_INTPTR_BITS <= 32) - return mi_ctz32((uint32_t)x); -#else - size_t count = mi_ctz32((uint32_t)x); - if (count < 32) return count; - return (32 + mi_ctz32((uint32_t)(x>>32))); -#endif + +static inline size_t mi_clz(size_t x) { + if (x==0) return MI_SIZE_BITS; + #if (MI_SIZE_BITS <= 32) + return mi_clz_generic32((uint32_t)x); + #else + const uint32_t hi = (uint32_t)(x>>32); + if (hi != 0) { + return mi_clz_generic32(hi); + } + else { + return 32 + mi_clz_generic32((uint32_t)x); + } + #endif } #endif From 2556a2022d78d7ab37e284fbea53255d3bdf766f Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 9 Dec 2024 20:50:00 -0800 Subject: [PATCH 08/16] fix missing void --- src/os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os.c b/src/os.c index 81dda8a1..32cb11c3 100644 --- a/src/os.c +++ b/src/os.c @@ -703,7 +703,7 @@ size_t _mi_os_numa_node_count_get(void) { return count; } -int _mi_os_numa_node_get() { +int _mi_os_numa_node_get(void) { size_t numa_count = _mi_os_numa_node_count(); if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0 // never more than the node count and >= 0 From 988637934996fcde3322f55215705abd03ba85d5 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 9 Dec 2024 21:22:30 -0800 Subject: [PATCH 09/16] fix macos 15 OS name --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 00bfe8e9..eb520aa0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -283,7 +283,7 @@ jobs: displayName: CTest - job: - displayName: macOS 15 (Sequia) + displayName: macOS 15 (Sequoia) pool: vmImage: macOS-15 From 7bb4767607cecda55059e59f1597a26697af1bc1 Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 10 Dec 2024 20:45:59 -0800 Subject: [PATCH 10/16] add asan/ubsan/tsan and valgrind to default debug build --- CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17f2071a..adf16a7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,16 +74,16 @@ else() endif() # ----------------------------------------------------------------------------- -# Convenience: set default build type depending on the build directory +# Convenience: set default build type and compiler depending on the build directory # ----------------------------------------------------------------------------- message(STATUS "") if (NOT CMAKE_BUILD_TYPE) - if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR MI_DEBUG_FULL) - message(STATUS "No build type selected, default to: Debug") + if ("${CMAKE_BINARY_DIR}" MATCHES ".*((D|d)ebug|asan|tsan|ubsan|valgrind)$" OR MI_DEBUG_FULL) + message(STATUS "No build type selected, default to 'Debug'") set(CMAKE_BUILD_TYPE "Debug") else() - message(STATUS "No build type selected, default to: Release") + message(STATUS "No build type selected, default to 'Release'") set(CMAKE_BUILD_TYPE "Release") endif() endif() @@ -93,7 +93,6 @@ if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$") set(MI_SECURE "ON") endif() - # ----------------------------------------------------------------------------- # Process options # ----------------------------------------------------------------------------- From 91215a5512ed4fa916ec26349f69d44235313308 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 11 Dec 2024 09:20:34 -0800 Subject: [PATCH 11/16] ensure incompatible heaps are not absorbed --- src/heap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/heap.c b/src/heap.c index 4459ff77..c2b5ae42 100644 --- a/src/heap.c +++ b/src/heap.c @@ -446,6 +446,12 @@ static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) { mi_heap_reset_pages(from); } +// are two heaps compatible with respect to heap-tag, exclusive arena etc. +static bool mi_heaps_are_compatible(mi_heap_t* heap1, mi_heap_t* heap2) { + return (heap1->tag == heap2->tag && // store same kind of objects + heap1->arena_id == heap2->arena_id); // same arena preference +} + // Safe delete a heap without freeing any still allocated blocks in that heap. void mi_heap_delete(mi_heap_t* heap) { @@ -454,9 +460,10 @@ void mi_heap_delete(mi_heap_t* heap) mi_assert_expensive(mi_heap_is_valid(heap)); if (heap==NULL || !mi_heap_is_initialized(heap)) return; - if (!mi_heap_is_backing(heap)) { + mi_heap_t* bheap = heap->tld->heap_backing; + if (bheap != heap && mi_heaps_are_compatible(bheap,heap)) { // transfer still used pages to the backing heap - mi_heap_absorb(heap->tld->heap_backing, heap); + mi_heap_absorb(bheap, heap); } else { // the backing heap abandons its pages From d5e1a62a7cebd4585a7f9de07f5acba15394fcf9 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 16 Dec 2024 22:51:30 -0800 Subject: [PATCH 12/16] add windows arm64 target to vs2022 --- bin/readme.md | 6 +- ide/vs2022/mimalloc-override-test.vcxproj | 82 ++++++++++ ide/vs2022/mimalloc-override.vcxproj | 107 ++++++++++++ ide/vs2022/mimalloc-test-api.vcxproj | 65 ++++++++ ide/vs2022/mimalloc-test-stress.vcxproj | 65 ++++++++ ide/vs2022/mimalloc-test.vcxproj | 64 ++++++++ ide/vs2022/mimalloc.sln | 188 ++++++++++++---------- ide/vs2022/mimalloc.vcxproj | 113 +++++++++++++ test/main-override.cpp | 8 +- test/test-stress.c | 2 +- 10 files changed, 613 insertions(+), 87 deletions(-) diff --git a/bin/readme.md b/bin/readme.md index 9b121bda..a699a2cd 100644 --- a/bin/readme.md +++ b/bin/readme.md @@ -15,7 +15,7 @@ There are four requirements to make the overriding work robustly: (or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project for an example on how to use this. -3. The `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be put +3. The `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`, or `mimalloc-redirect-arm64.dll`) must be put in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency of that DLL). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc functions (which reside in `mimalloc-override.dll`). @@ -40,7 +40,9 @@ if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the ` into the import table (and put `mimalloc-redirect.dll` in the same folder) Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388). -The `minject` program can also do this from the command line, use `minject --help` for options: +The `minject` program can also do this from the command line +(or `minject32` for 32-bit PE files, or `minject-arm64` on arm64 Windows). +Use `minject --help` for options: ``` > minject --help diff --git a/ide/vs2022/mimalloc-override-test.vcxproj b/ide/vs2022/mimalloc-override-test.vcxproj index a3c56f7b..ff5d53d0 100644 --- a/ide/vs2022/mimalloc-override-test.vcxproj +++ b/ide/vs2022/mimalloc-override-test.vcxproj @@ -1,10 +1,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -42,12 +50,23 @@ true v143 + + Application + true + v143 + Application false v143 true + + Application + false + v143 + true + @@ -62,9 +81,15 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -78,10 +103,18 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -128,6 +161,30 @@ + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + Sync + Default + false + + + Console + + + kernel32.lib;%(AdditionalDependencies) + + + + + + + Level3 @@ -176,6 +233,31 @@ + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + MultiThreadedDLL + + + true + true + Console + + + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override.vcxproj index 4383d886..16a48740 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override.vcxproj @@ -1,10 +1,18 @@  + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -41,11 +49,21 @@ true v143 + + DynamicLibrary + true + v143 + DynamicLibrary false v143 + + DynamicLibrary + false + v143 + @@ -60,9 +78,15 @@ + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -82,12 +106,24 @@ .dll mimalloc-override + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll mimalloc-override + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + Level3 @@ -144,6 +180,34 @@ copy mimalloc-redirect.dll to the output directory + + + Level3 + Disabled + true + true + ../../include + MI_DEBUG=4;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); + MultiThreadedDebugDLL + false + CompileAsCpp + + + $(ProjectDir)\..\..\bin\mimalloc-redirect-arm64.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect-arm64.dll" "$(OutputPath)" + + + copy mimalloc-redirect-arm64.dll to the output directory + + Level3 @@ -208,6 +272,39 @@ copy mimalloc-redirect.dll to the output directory + + + Level3 + MaxSpeed + true + true + true + ../../include + MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + MultiThreadedDLL + CompileAsCpp + false + CPUExtensionRequirementsARMv81 + + + true + true + $(ProjectDir)\..\..\bin\mimalloc-redirect-arm64.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect-arm64.dll" "$(OutputPath)" + + + copy mimalloc-redirect-arm64.dll to the output directory + + @@ -226,13 +323,17 @@ false false false + false false + false true true true + true true + true @@ -240,7 +341,9 @@ true true true + true true + true @@ -252,7 +355,9 @@ true true true + true true + true @@ -260,7 +365,9 @@ true true true + true true + true diff --git a/ide/vs2022/mimalloc-test-api.vcxproj b/ide/vs2022/mimalloc-test-api.vcxproj index d9b9cae4..babe7f96 100644 --- a/ide/vs2022/mimalloc-test-api.vcxproj +++ b/ide/vs2022/mimalloc-test-api.vcxproj @@ -1,10 +1,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -42,12 +50,23 @@ true v143 + + Application + true + v143 + Application false v143 true + + Application + false + v143 + true + @@ -62,9 +81,15 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -78,10 +103,18 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -106,6 +139,18 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + Level3 @@ -140,15 +185,35 @@ Console + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + true true true + true true + true false + false diff --git a/ide/vs2022/mimalloc-test-stress.vcxproj b/ide/vs2022/mimalloc-test-stress.vcxproj index c7e820df..c033aaeb 100644 --- a/ide/vs2022/mimalloc-test-stress.vcxproj +++ b/ide/vs2022/mimalloc-test-stress.vcxproj @@ -1,10 +1,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -42,12 +50,23 @@ true v143 + + Application + true + v143 + Application false v143 true + + Application + false + v143 + true + @@ -62,9 +81,15 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -78,10 +103,18 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -106,6 +139,18 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + Level3 @@ -140,12 +185,32 @@ Console + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + CPUExtensionRequirementsARMv81 + + + true + true + Console + + false false + false false false + false diff --git a/ide/vs2022/mimalloc-test.vcxproj b/ide/vs2022/mimalloc-test.vcxproj index 506dd7d4..bfd72287 100644 --- a/ide/vs2022/mimalloc-test.vcxproj +++ b/ide/vs2022/mimalloc-test.vcxproj @@ -1,10 +1,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -42,12 +50,23 @@ true v143 + + Application + true + v143 + Application false v143 true + + Application + false + v143 + true + @@ -62,9 +81,15 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -78,10 +103,18 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -108,6 +141,19 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + Level3 @@ -144,6 +190,24 @@ Console + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + _MBCS;%(PreprocessorDefinitions);NDEBUG + stdcpp17 + + + true + true + Console + + {abb5eae7-b3e6-432e-b636-333449892ea6} diff --git a/ide/vs2022/mimalloc.sln b/ide/vs2022/mimalloc.sln index 6ff01d3b..e4a6538b 100644 --- a/ide/vs2022/mimalloc.sln +++ b/ide/vs2022/mimalloc.sln @@ -1,81 +1,107 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-api", "mimalloc-test-api.vcxproj", "{FFF7958F-750E-4C21-A04D-22707CC66878}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-api", "mimalloc-test-api.vcxproj", "{FFF7958F-750E-4C21-A04D-22707CC66878}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|ARM64.Build.0 = Debug|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|ARM64.ActiveCfg = Release|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|ARM64.Build.0 = Release|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.Build.0 = Debug|ARM64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|ARM64.ActiveCfg = Release|ARM64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|ARM64.Build.0 = Release|ARM64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|ARM64.Build.0 = Debug|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|ARM64.ActiveCfg = Release|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|ARM64.Build.0 = Release|ARM64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|ARM64.Build.0 = Debug|ARM64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|ARM64.ActiveCfg = Release|ARM64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|ARM64.Build.0 = Release|ARM64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.Build.0 = Debug|ARM64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64.ActiveCfg = Release|ARM64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64.Build.0 = Release|ARM64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64.Build.0 = Debug|ARM64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64.ActiveCfg = Release|ARM64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64.Build.0 = Release|ARM64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} + EndGlobalSection +EndGlobal diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index dddab777..fb13cd1f 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -1,10 +1,18 @@  + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -42,12 +50,23 @@ true v143 + + StaticLibrary + true + v143 + StaticLibrary false v143 true + + StaticLibrary + false + v143 + true + @@ -62,9 +81,15 @@ + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -84,12 +109,24 @@ .lib mimalloc-static + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .lib mimalloc-static + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + Level4 @@ -136,6 +173,33 @@ + + + Level4 + Disabled + true + Default + ../../include + MI_DEBUG=3;MI_GUARDED=0;%(PreprocessorDefinitions); + CompileAsCpp + false + stdcpp20 + + + + + + + + + + + + + + + + Level4 @@ -198,18 +262,58 @@ + + + Level4 + MaxSpeed + true + Default + ../../include + %(PreprocessorDefinitions);NDEBUG + AssemblyAndSourceCode + $(IntDir) + false + false + Default + CompileAsCpp + true + stdcpp20 + CPUExtensionRequirementsARMv81 + Sync + + + true + true + + + + + + + + + + + + + + false false + false false false + false true true true + true true + true @@ -217,17 +321,22 @@ true true true + true true + true false + false true + true true true true + true @@ -237,14 +346,18 @@ true true true + true true + true true true true + true true + true diff --git a/test/main-override.cpp b/test/main-override.cpp index 3f64117a..3d56ae42 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -44,8 +44,8 @@ static void test_stl_allocators(); int main() { - // mi_stats_reset(); // ignore earlier allocations - + mi_stats_reset(); // ignore earlier allocations + various_tests(); test_mixed1(); //test_std_string(); //test_thread_local(); @@ -55,8 +55,10 @@ int main() { heap_no_delete(); heap_late_free(); padding_shrink(); - various_tests(); + tsan_numa_test(); + */ + /* strdup_test(); test_stl_allocators(); test_mt_shutdown(); diff --git a/test/test-stress.c b/test/test-stress.c index 261c5dfe..1848e9f5 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -23,7 +23,7 @@ terms of the MIT license. #include // #define MI_GUARDED -// #define USE_STD_MALLOC +#define USE_STD_MALLOC // > mimalloc-test-stress [THREADS] [SCALE] [ITER] // From b47c68fefd505f1b78284299309253fb9471bbd9 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 16 Dec 2024 22:53:23 -0800 Subject: [PATCH 13/16] add redirection dll for windows on arm64 --- bin/mimalloc-redirect-arm64.dll | Bin 0 -> 80896 bytes bin/mimalloc-redirect-arm64.lib | Bin 0 -> 2976 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 bin/mimalloc-redirect-arm64.dll create mode 100644 bin/mimalloc-redirect-arm64.lib diff --git a/bin/mimalloc-redirect-arm64.dll b/bin/mimalloc-redirect-arm64.dll new file mode 100644 index 0000000000000000000000000000000000000000..0cae1d5170e37a11e6e767b24f102a8811e322e5 GIT binary patch literal 80896 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 Q50(~TPy6Bz(SH+v04r#&VE_OC literal 0 HcmV?d00001 From de8d73d2086da80e8df902d1c1b262bc54c2894e Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 16 Dec 2024 22:53:52 -0800 Subject: [PATCH 14/16] add minject for windows arm64 --- bin/minject-arm64.exe | Bin 0 -> 20992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bin/minject-arm64.exe diff --git a/bin/minject-arm64.exe b/bin/minject-arm64.exe new file mode 100644 index 0000000000000000000000000000000000000000..63987afcacc42511aca435e78a70d56a64163ff2 GIT binary patch literal 20992 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 jM=FnOKhkof Date: Mon, 16 Dec 2024 23:09:50 -0800 Subject: [PATCH 15/16] add Windows arm64 support in cmame; name the mimalloc dll 'mimalloc-override.dll' on Windows with cmake (to match the IDE and minject --- CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index adf16a7f..490cb483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,13 +146,7 @@ if(MI_OVERRIDE) endif() endif() -if(WIN32) - if (MI_WIN_REDIRECT) - if (MSVC_C_ARCHITECTURE_ID MATCHES "ARM") - message(STATUS "Cannot use redirection on Windows ARM (MI_WIN_REDIRECT=OFF)") - set(MI_WIN_REDIRECT OFF) - endif() - endif() +if(WIN32) if (NOT MI_WIN_REDIRECT) # use a negative define for backward compatibility list(APPEND mi_defines MI_WIN_NOREDIRECT=1) @@ -340,7 +334,7 @@ if(APPLE) endif() elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") set(MI_ARCH "x64") -elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") set(MI_ARCH "arm64") endif() @@ -534,7 +528,9 @@ if(MI_BUILD_SHARED) ) if(WIN32 AND MI_WIN_REDIRECT) # On windows, link and copy the mimalloc redirection dll too. - if(CMAKE_SIZEOF_VOID_P EQUAL 4) + if(MI_ARCH STREQUAL "arm64") + set(MIMALLOC_REDIRECT_SUFFIX "-arm64") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) set(MIMALLOC_REDIRECT_SUFFIX "32") else() set(MIMALLOC_REDIRECT_SUFFIX "") @@ -656,6 +652,11 @@ endif() if (MI_OVERRIDE) if (MI_BUILD_SHARED) target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) + if (WIN32) + # on windows we should generate mimalloc-override.dll. + string(REPLACE "mimalloc" "mimalloc-override" mi_override_output_name ${mi_basename}) + set_target_properties(mimalloc PROPERTIES OUTPUT_NAME ${mi_override_output_name}) + endif() endif() if(NOT WIN32) # It is only possible to override malloc on Windows when building as a DLL. From 6ac636e2e2e0726d4360e5119cfbf7ad6a8725a7 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 16 Dec 2024 23:22:52 -0800 Subject: [PATCH 16/16] update readme --- bin/readme.md | 9 +++++---- test/test-stress.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bin/readme.md b/bin/readme.md index a699a2cd..d133eea2 100644 --- a/bin/readme.md +++ b/bin/readme.md @@ -11,11 +11,12 @@ There are four requirements to make the overriding work robustly: 2. Link your program explicitly with `mimalloc-override.dll` library. To ensure the `mimalloc-override.dll` is loaded at run-time it is easiest to insert some - call to the mimalloc API in the `main` function, like `mi_version()` - (or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project - for an example on how to use this. + call to the mimalloc API in the `main` function, like `mi_version()` + (or use the `/INCLUDE:mi_version` switch on the linker, or + use `#pragma comment(linker, "/include:mi_version")` in some source file). + See the `mimalloc-override-test` project for an example on how to use this. -3. The `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`, or `mimalloc-redirect-arm64.dll`) must be put +3. The `mimalloc-redirect.dll` (x64) (or `mimalloc-redirect32.dll` (x86), or `mimalloc-redirect-arm64.dll` (arm64)) must be put in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency of that DLL). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc functions (which reside in `mimalloc-override.dll`). diff --git a/test/test-stress.c b/test/test-stress.c index 1848e9f5..261c5dfe 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -23,7 +23,7 @@ terms of the MIT license. #include // #define MI_GUARDED -#define USE_STD_MALLOC +// #define USE_STD_MALLOC // > mimalloc-test-stress [THREADS] [SCALE] [ITER] //