From b7dd5d6564567f39ce5111ddbe5064a22259bd94 Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 17 Jun 2024 16:17:03 -0700 Subject: [PATCH 001/131] add extra assertions to check that blocks are always aligned to MI_MAX_ALIGN_SIZE --- src/alloc.c | 1 + src/segment.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/alloc.c b/src/alloc.c index 1eee1f2f..7be1a6e9 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -40,6 +40,7 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ page->free = mi_block_next(page, block); page->used++; mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); + mi_assert_internal(_mi_is_aligned(block, MI_MAX_ALIGN_SIZE)); #if MI_DEBUG>3 if (page->free_is_zero) { mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block))); diff --git a/src/segment.c b/src/segment.c index 54a917ea..d9631d48 100644 --- a/src/segment.c +++ b/src/segment.c @@ -436,6 +436,8 @@ uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* pa mi_assert_internal((uintptr_t)p % block_size == 0); } } + mi_assert_internal(_mi_is_aligned(p, MI_MAX_ALIGN_SIZE)); + mi_assert_internal(block_size > MI_MAX_ALIGN_GUARANTEE || _mi_is_aligned(p,block_size)); if (page_size != NULL) *page_size = psize; mi_assert_internal(_mi_ptr_page(p) == page); From 265767766bffda929c31a49e6e30ea812f7088f0 Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 17 Jun 2024 16:22:07 -0700 Subject: [PATCH 002/131] fix alignment test --- src/segment.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segment.c b/src/segment.c index d9631d48..7646c94c 100644 --- a/src/segment.c +++ b/src/segment.c @@ -437,7 +437,7 @@ uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* pa } } mi_assert_internal(_mi_is_aligned(p, MI_MAX_ALIGN_SIZE)); - mi_assert_internal(block_size > MI_MAX_ALIGN_GUARANTEE || _mi_is_aligned(p,block_size)); + mi_assert_internal(block_size == 0 || block_size > MI_MAX_ALIGN_GUARANTEE || _mi_is_aligned(p,block_size)); if (page_size != NULL) *page_size = psize; mi_assert_internal(_mi_ptr_page(p) == page); From 7b5df14beaeff29b9cee3e8de08b034879dca7fb Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 16 Jul 2024 09:15:59 -0700 Subject: [PATCH 003/131] initial work on guarded objects --- CMakeLists.txt | 10 ++++++++++ include/mimalloc.h | 2 ++ include/mimalloc/internal.h | 1 + src/options.c | 14 ++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a730557..e78ba9fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ option(MI_BUILD_OBJECT "Build object library" ON) option(MI_BUILD_TESTS "Build test executables" ON) option(MI_DEBUG_TSAN "Build with thread sanitizer (needs clang)" OFF) option(MI_DEBUG_UBSAN "Build with undefined-behavior sanitizer (needs clang++)" OFF) +option(MI_DEBUG_GUARDED "Build with guard pages behind certain object allocations (implies MI_NO_PADDING=ON)" OFF) option(MI_SKIP_COLLECT_ON_EXIT "Skip collecting memory on program exit" OFF) option(MI_NO_PADDING "Force no use of padding even in DEBUG mode etc." OFF) option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF) @@ -199,6 +200,15 @@ if(MI_TRACK_ETW) endif() endif() +if(MI_DEBUG_GUARDED) + message(STATUS "Compile guard pages behind certain object allocations (MI_DEBUG_GUARDED=ON)") + list(APPEND mi_defines MI_DEBUG_GUARDED=1) + if(NOT MI_NO_PADDING) + message(STATUS " Disabling padding due to guard pages (MI_NO_PADDING=ON)") + set(MI_NO_PADDING ON) + endif() +endif() + if(MI_SEE_ASM) message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)") list(APPEND mi_cflags -save-temps) diff --git a/include/mimalloc.h b/include/mimalloc.h index bc743fd7..a56f9b82 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -366,6 +366,8 @@ typedef enum mi_option_e { mi_option_disallow_arena_alloc, // 1 = do not use arena's for allocation (except if using specific arena id's) mi_option_retry_on_oom, // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows) mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0) + mi_option_debug_guarded_min, // only when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) + mi_option_debug_guarded_max, // only when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 6e87d5ae..05efa86f 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -61,6 +61,7 @@ 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 diff --git a/src/options.c b/src/options.c index 462a7c71..ca931855 100644 --- a/src/options.c +++ b/src/options.c @@ -99,6 +99,8 @@ static mi_option_desc_t options[_mi_option_last] = #else { 0, UNINIT, MI_OPTION(visit_abandoned) }, #endif + { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) + { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) }; static void mi_option_init(mi_option_desc_t* desc); @@ -124,6 +126,15 @@ void _mi_options_init(void) { mi_max_warning_count = mi_option_get(mi_option_max_warnings); } +long _mi_option_get_fast(mi_option_t option) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + //mi_assert(desc->init != UNINIT); + return desc->value; +} + + mi_decl_nodiscard long mi_option_get(mi_option_t option) { mi_assert(option >= 0 && option < _mi_option_last); if (option < 0 || option >= _mi_option_last) return 0; @@ -508,6 +519,9 @@ static void mi_option_init(mi_option_desc_t* desc) { if (*end == 0) { desc->value = value; desc->init = INITIALIZED; + if (desc->option == mi_option_debug_guarded_min && _mi_option_get_fast(mi_option_debug_guarded_max) < value) { + mi_option_set(mi_option_debug_guarded_max,value); + } } else { // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose. From 566b2c51fc42b476adf176063e84222e832a7d57 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Mon, 22 Jul 2024 09:43:43 +0900 Subject: [PATCH 004/131] Add a missing #include This change fixes the "implicit declaration of function 'getenv'" warning. Since stdlib.h is completely portable, as it is defined by the C standard, we can safely include it unconditionally. --- src/prim/unix/prim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c index 63a36f25..c48b4cbd 100644 --- a/src/prim/unix/prim.c +++ b/src/prim/unix/prim.c @@ -27,6 +27,7 @@ terms of the MIT license. A copy of the license can be found in the file #include // mmap #include // sysconf #include // open, close, read, access +#include // getenv, arc4random_buf #if defined(__linux__) #include @@ -773,7 +774,6 @@ bool _mi_prim_random_buf(void* buf, size_t buf_len) { defined(__sun) || \ (defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7)) -#include bool _mi_prim_random_buf(void* buf, size_t buf_len) { arc4random_buf(buf, buf_len); return true; From 9c9efc417dbe275cfa0b542b7298494d889fc84a Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Fri, 26 Jul 2024 12:11:21 +0200 Subject: [PATCH 005/131] Fix build on FreeBSD-derivate DragonFly --- src/alloc-override.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/alloc-override.c b/src/alloc-override.c index 12837cdd..dde37786 100644 --- a/src/alloc-override.c +++ b/src/alloc-override.c @@ -248,7 +248,7 @@ extern "C" { // Forward Posix/Unix calls as well void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize) size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p) - #if !defined(__ANDROID__) && !defined(__FreeBSD__) + #if !defined(__ANDROID__) && !defined(__FreeBSD__) && !defined(__DragonFly__) size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p) #else size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p) From 5eb8c752f7dc2aaef5080831b1f8ff8092bc25af Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 13 Aug 2024 16:36:53 -0700 Subject: [PATCH 006/131] fix UINT32_MAX constant (see issue #913) --- src/segment-map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segment-map.c b/src/segment-map.c index 8927a8bd..2c3964fe 100644 --- a/src/segment-map.c +++ b/src/segment-map.c @@ -22,7 +22,7 @@ terms of the MIT license. A copy of the license can be found in the file #elif (MI_INTPTR_SIZE > 4) #define MI_SEGMENT_MAP_MAX_ADDRESS (48*1024ULL*MI_GiB) // 48 TiB #else -#define MI_SEGMENT_MAP_MAX_ADDRESS (MAX_UINT32) +#define MI_SEGMENT_MAP_MAX_ADDRESS (UINT32_MAX) #endif #define MI_SEGMENT_MAP_PART_SIZE (MI_INTPTR_SIZE*MI_KiB - 128) // 128 > sizeof(mi_memid_t) ! From 0c19eb60cf9b70926a388b668bab574ca225afec Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 19 Aug 2024 21:21:40 -0700 Subject: [PATCH 007/131] initial working guarded pages --- include/mimalloc.h | 4 +- include/mimalloc/internal.h | 10 +++++ include/mimalloc/types.h | 10 ++++- src/alloc-aligned.c | 20 +++++++--- src/alloc.c | 75 +++++++++++++++++++++++++++++++++++-- src/free.c | 25 +++++++++++-- src/heap.c | 23 ++++++++---- src/options.c | 28 +++++++++----- src/page.c | 8 +++- src/segment.c | 9 ++++- test/main-override-static.c | 8 ++++ test/test-api.c | 13 ++++++- 12 files changed, 196 insertions(+), 37 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index a56f9b82..867c5c97 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -366,8 +366,8 @@ typedef enum mi_option_e { mi_option_disallow_arena_alloc, // 1 = do not use arena's for allocation (except if using specific arena id's) mi_option_retry_on_oom, // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows) mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0) - mi_option_debug_guarded_min, // only when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) - mi_option_debug_guarded_max, // only when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) + mi_option_debug_guarded_min, // only used when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) + mi_option_debug_guarded_max, // only used when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 05efa86f..6d9f25cb 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -323,6 +323,7 @@ static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) { } } + // Align a pointer upwards static inline void* mi_align_up_ptr(void* p, size_t alignment) { return (void*)_mi_align_up((uintptr_t)p, alignment); @@ -594,6 +595,15 @@ static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { page->flags.x.has_aligned = has_aligned; } +#if MI_DEBUG_GUARDED +static inline bool mi_page_has_guarded(const mi_page_t* page) { + return page->flags.x.has_guarded; +} + +static inline void mi_page_set_has_guarded(mi_page_t* page, bool has_guarded) { + page->flags.x.has_guarded = has_guarded; +} +#endif /* ------------------------------------------------------------------- Encoding/Decoding the free list next pointers diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 31ed35f8..ffe095a5 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -72,6 +72,12 @@ terms of the MIT license. A copy of the license can be found in the file #endif #endif +// Use guard pages behind objects of a certain size +#define MI_DEBUG_GUARDED 1 +#if defined(MI_DEBUG_GUARDED) || defined(MI_DEBUG_GUARDEDX) +#define MI_PADDING 0 +#endif + // Reserve extra padding at the end of each block to be more resilient against heap block overflows. // The padding can detect buffer overflow on free. #if !defined(MI_PADDING) && (MI_SECURE>=3 || MI_DEBUG>=1 || (MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_TRACK_ETW)) @@ -243,15 +249,17 @@ typedef union mi_page_flags_s { struct { uint8_t in_full : 1; uint8_t has_aligned : 1; + uint8_t has_guarded : 1; // only used with MI_DEBUG_GUARDED } x; } mi_page_flags_t; #else // under thread sanitizer, use a byte for each flag to suppress warning, issue #130 typedef union mi_page_flags_s { - uint16_t full_aligned; + uint32_t full_aligned; struct { uint8_t in_full; uint8_t has_aligned; + uint8_t has_guarded; // only used with MI_DEBUG_GUARDED } x; } mi_page_flags_t; #endif diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 20c36044..248c932d 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -20,8 +20,12 @@ static bool mi_malloc_is_naturally_aligned( size_t size, size_t alignment ) { mi_assert_internal(_mi_is_power_of_two(alignment) && (alignment > 0)); if (alignment > size) return false; if (alignment <= MI_MAX_ALIGN_SIZE) return true; + #if MI_DEBUG_GUARDED + return false; + #else const size_t bsize = mi_good_size(size); return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); + #endif } // Fallback aligned allocation that over-allocates -- split out for better codegen @@ -38,9 +42,9 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t // first (and single) page such that the segment info is `MI_SEGMENT_SIZE` bytes before it (so it can be found by aligning the pointer down) if mi_unlikely(offset != 0) { // todo: cannot support offset alignment for very large alignments yet - #if MI_DEBUG > 0 +#if MI_DEBUG > 0 _mi_error_message(EOVERFLOW, "aligned allocation with a very large alignment cannot be used with an alignment offset (size %zu, alignment %zu, offset %zu)\n", size, alignment, offset); - #endif +#endif return NULL; } oversize = (size <= MI_SMALL_SIZE_MAX ? MI_SMALL_SIZE_MAX + 1 /* ensure we use generic malloc path */ : size); @@ -54,7 +58,8 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t p = _mi_heap_malloc_zero(heap, oversize, zero); if (p == NULL) return NULL; } - + mi_page_t* page = _mi_ptr_page(p); + // .. and align within the allocation const uintptr_t align_mask = alignment - 1; // for any x, `(x & align_mask) == (x % alignment)` const uintptr_t poffset = ((uintptr_t)p + offset) & align_mask; @@ -62,17 +67,18 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t mi_assert_internal(adjust < alignment); void* aligned_p = (void*)((uintptr_t)p + adjust); if (aligned_p != p) { - mi_page_t* page = _mi_ptr_page(p); mi_page_set_has_aligned(page, true); _mi_padding_shrink(page, (mi_block_t*)p, adjust + size); } // todo: expand padding if overallocated ? - mi_assert_internal(mi_page_usable_block_size(_mi_ptr_page(p)) >= adjust + size); - mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_page(aligned_p), aligned_p)); + mi_assert_internal(mi_page_usable_block_size(page) >= adjust + size); mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); mi_assert_internal(mi_usable_size(aligned_p)>=size); mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); + #if !MI_DEBUG_GUARDED + mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_page(aligned_p), aligned_p)); + #endif // now zero the block if needed if (alignment > MI_BLOCK_ALIGNMENT_MAX) { @@ -133,6 +139,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t return NULL; } + #if !MI_DEBUG_GUARDED // try first if there happens to be a small block available with just the right alignment if mi_likely(size <= MI_SMALL_SIZE_MAX && alignment <= size) { const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` @@ -153,6 +160,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t } } } + #endif // fallback to generic aligned allocation return mi_heap_malloc_zero_aligned_at_generic(heap, size, alignment, offset, zero); diff --git a/src/alloc.c b/src/alloc.c index 7be1a6e9..ec008318 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -40,9 +40,9 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ page->free = mi_block_next(page, block); page->used++; mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); - mi_assert_internal(_mi_is_aligned(block, MI_MAX_ALIGN_SIZE)); + mi_assert_internal(page->block_size < MI_MAX_ALIGN_SIZE || _mi_is_aligned(block, MI_MAX_ALIGN_SIZE)); #if MI_DEBUG>3 - if (page->free_is_zero) { + if (page->free_is_zero && size > sizeof(*block)) { mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block))); } #endif @@ -56,6 +56,7 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ if mi_unlikely(zero) { mi_assert_internal(page->block_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic) mi_assert_internal(page->block_size >= MI_PADDING_SIZE); + mi_assert_internal(!mi_page_is_huge(page)); if (page->free_is_zero) { block->next = 0; mi_track_mem_defined(block, page->block_size - MI_PADDING_SIZE); @@ -114,6 +115,11 @@ extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t siz return _mi_page_malloc_zero(heap,page,size,true); } +#if MI_DEBUG_GUARDED +// forward declaration +static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept; +#endif + static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { mi_assert(heap != NULL); #if MI_DEBUG @@ -121,9 +127,14 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, mi_assert(heap->thread_id == 0 || heap->thread_id == tid); // heaps are thread local #endif mi_assert(size <= MI_SMALL_SIZE_MAX); - #if (MI_PADDING) + #if (MI_PADDING || MI_DEBUG_GUARDED) if (size == 0) { size = sizeof(void*); } #endif + #if MI_DEBUG_GUARDED + if (size >= _mi_option_get_fast(mi_option_debug_guarded_min) && size <= _mi_option_get_fast(mi_option_debug_guarded_max)) { + return mi_heap_malloc_guarded(heap, size, zero, 0); + } + #endif mi_page_t* page = _mi_heap_get_free_small_page(heap, size + MI_PADDING_SIZE); void* const p = _mi_page_malloc_zero(heap, page, size + MI_PADDING_SIZE, zero); @@ -158,6 +169,14 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z mi_assert_internal(huge_alignment == 0); return mi_heap_malloc_small_zero(heap, size, zero); } + #if MI_DEBUG_GUARDED + else if ( huge_alignment == 0 && // guarded pages do not work with huge aligments at the moment + ((size >= _mi_option_get_fast(mi_option_debug_guarded_min) && size <= _mi_option_get_fast(mi_option_debug_guarded_max)) + || ((size & (_mi_os_page_size()-1)) == 0)) ) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. + { + return mi_heap_malloc_guarded(heap, size, zero, 0); + } + #endif else { mi_assert(heap!=NULL); mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local @@ -578,6 +597,56 @@ mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } } +#if MI_DEBUG_GUARDED +static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept +{ + #if defined(MI_PADDING_SIZE) + mi_assert(MI_PADDING_SIZE==0); + #endif + // allocate multiple of page size ending in a guard page + const size_t bsize = _mi_align_up(size, MI_MAX_ALIGN_SIZE); // ensure minimal alignment requirement + const size_t psize = _mi_os_page_size(); + const size_t gsize = _mi_align_up(bsize + psize, psize); + void* const base = _mi_malloc_generic(heap, gsize, zero, huge_alignment); + if (base==NULL) return NULL; + mi_page_t* page = _mi_ptr_page(base); + mi_segment_t* segment = _mi_page_segment(page); + + const size_t fullsize = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` + void* const gpage = (uint8_t*)base + (fullsize - psize); + mi_assert_internal(_mi_is_aligned(gpage, psize)); + void* const p = (uint8_t*)base + (fullsize - psize - bsize); + mi_assert_internal(p >= base); + + // set page flags + if (p > base) { mi_page_set_has_aligned(page, true); } + + // set guard page + if (segment->allow_decommit) { + mi_page_set_has_guarded(page, true); + _mi_os_protect(gpage, psize); + } + else { + _mi_warning_message("unable to set a guard page behind an object due to pinned memory (large OS pages?) (object %p of size %zu)\n", p, size); + } + + // stats + mi_track_malloc(p, size, zero); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + #if MI_DEBUG>3 + if (p != NULL && zero) { + mi_assert_expensive(mi_mem_is_zero(p, size)); + } + #endif + return p; +} +#endif + // ------------------------------------------------------ // ensure explicit external inline definitions are emitted! // ------------------------------------------------------ diff --git a/src/free.c b/src/free.c index c6221fe7..07c06899 100644 --- a/src/free.c +++ b/src/free.c @@ -34,11 +34,21 @@ static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool if mi_unlikely(mi_check_is_double_free(page, block)) return; mi_check_padding(page, block); if (track_stats) { mi_stat_free(page, block); } - #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN + #if MI_DEBUG_GUARDED + if (mi_page_has_guarded(page)) { + const size_t bsize = mi_page_block_size(page); + const size_t psize = _mi_os_page_size(); + mi_assert_internal(bsize > psize); + mi_assert_internal(_mi_page_segment(page)->allow_decommit); + void* gpage = (uint8_t*)block + (bsize - psize); + _mi_os_unprotect(gpage, psize); + } + #endif + #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN && !MI_DEBUG_GUARDED memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); #endif if (track_stats) { mi_track_free_size(block, mi_page_usable_size_of(page, block)); } // faster then mi_usable_size as we already know the page and that p is unaligned - + // actual free: push on the local free list mi_block_set_next(page, block, page->local_free); page->local_free = block; @@ -51,8 +61,8 @@ static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool } // Adjust a block that was allocated aligned, to the actual start of the block in the page. -// note: this can be called from `mi_free_generic_mt` where a non-owning thread accesses the -// `page_start` and `block_size` fields; however these are constant and the page won't be +// note: this can be called from `mi_free_generic_mt` where a non-owning thread accesses the +// `page_start` and `block_size` fields; however these are constant and the page won't be // deallocated (as the block we are freeing keeps it alive) and thus safe to read concurrently. mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) { mi_assert_internal(page!=NULL && p!=NULL); @@ -298,6 +308,13 @@ static inline size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noe const mi_segment_t* const segment = mi_checked_ptr_segment(p, msg); if mi_unlikely(segment==NULL) return 0; const mi_page_t* const page = _mi_segment_page_of(segment, p); + #if MI_DEBUG_GUARDED + if (mi_page_has_guarded(page)) { + const size_t bsize = mi_page_usable_aligned_size_of(page, p); + mi_assert_internal(bsize > _mi_os_page_size()); + return (bsize > _mi_os_page_size() ? bsize - _mi_os_page_size() : bsize); + } else + #endif if mi_likely(!mi_page_has_aligned(page)) { const mi_block_t* block = (const mi_block_t*)p; return mi_page_usable_size_of(page, block); diff --git a/src/heap.c b/src/heap.c index 0d716f91..a3aaaf6b 100644 --- a/src/heap.c +++ b/src/heap.c @@ -32,7 +32,7 @@ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void #if MI_DEBUG>1 size_t total = heap->page_count; size_t count = 0; - #endif + #endif for (size_t i = 0; i <= MI_BIN_FULL; i++) { mi_page_queue_t* pq = &heap->pages[i]; @@ -164,9 +164,9 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) if (force && is_main_thread && mi_heap_is_backing(heap)) { _mi_thread_data_collect(); // collect thread data cache } - + // 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? */, &heap->tld->stats); } void _mi_heap_collect_abandon(mi_heap_t* heap) { @@ -240,7 +240,7 @@ mi_decl_nodiscard mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id) { } mi_decl_nodiscard mi_heap_t* mi_heap_new(void) { - // don't reclaim abandoned memory or otherwise destroy is unsafe + // don't reclaim abandoned memory or otherwise destroy is unsafe return mi_heap_new_ex(0 /* default heap tag */, true /* no reclaim */, _mi_arena_id_none()); } @@ -369,7 +369,13 @@ void mi_heap_destroy(mi_heap_t* heap) { mi_assert(heap->no_reclaim); mi_assert_expensive(mi_heap_is_valid(heap)); if (heap==NULL || !mi_heap_is_initialized(heap)) return; + #if MI_DEBUG_GUARDED + _mi_warning_message("'mi_heap_destroy' called but ignored as MI_DEBUG_GUARDED is enabled (heap at %p)\n", heap); + mi_heap_delete(heap); + return; + #else if (!heap->no_reclaim) { + _mi_warning_message("'mi_heap_destroy' called but ignored as the heap was not created with 'allow_destroy' (heap at %p)\n", heap); // don't free in case it may contain reclaimed pages mi_heap_delete(heap); } @@ -382,6 +388,7 @@ void mi_heap_destroy(mi_heap_t* heap) { _mi_heap_destroy_pages(heap); mi_heap_free(heap); } + #endif } // forcefully destroy all heaps in the current thread @@ -537,7 +544,7 @@ void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page) { static void mi_get_fast_divisor(size_t divisor, uint64_t* magic, size_t* shift) { mi_assert_internal(divisor > 0 && divisor <= UINT32_MAX); *shift = 64 - mi_clz(divisor - 1); - *magic = ((((uint64_t)1 << 32) * (((uint64_t)1 << *shift) - divisor)) / divisor + 1); + *magic = ((((uint64_t)1 << 32) * (((uint64_t)1 << *shift) - divisor)) / divisor + 1); } static size_t mi_fast_divide(size_t n, uint64_t magic, size_t shift) { @@ -581,7 +588,7 @@ bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_ // create a bitmap of free blocks. #define MI_MAX_BLOCKS (MI_SMALL_PAGE_SIZE / sizeof(void*)) uintptr_t free_map[MI_MAX_BLOCKS / MI_INTPTR_BITS]; - const uintptr_t bmapsize = _mi_divide_up(page->capacity, MI_INTPTR_BITS); + const uintptr_t bmapsize = _mi_divide_up(page->capacity, MI_INTPTR_BITS); memset(free_map, 0, bmapsize * sizeof(intptr_t)); if (page->capacity % MI_INTPTR_BITS != 0) { // mark left-over bits at the end as free @@ -591,7 +598,7 @@ bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_ } // fast repeated division by the block size - uint64_t magic; + uint64_t magic; size_t shift; mi_get_fast_divisor(bsize, &magic, &shift); @@ -665,7 +672,7 @@ static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_pa mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun; mi_heap_area_ex_t xarea; xarea.page = page; - _mi_heap_area_init(&xarea.area, page); + _mi_heap_area_init(&xarea.area, page); return fun(heap, &xarea, arg); } diff --git a/src/options.c b/src/options.c index ca931855..b8859235 100644 --- a/src/options.c +++ b/src/options.c @@ -99,8 +99,8 @@ static mi_option_desc_t options[_mi_option_last] = #else { 0, UNINIT, MI_OPTION(visit_abandoned) }, #endif - { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) - { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) + { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only used when built with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) + { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when built with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) }; static void mi_option_init(mi_option_desc_t* desc); @@ -110,8 +110,7 @@ static bool mi_option_has_size_in_kib(mi_option_t option) { } void _mi_options_init(void) { - // called on process load; should not be called before the CRT is initialized! - // (e.g. do not call this from process_init as that may run before CRT initialization) + // called on process load mi_add_stderr_output(); // now it safe to use stderr for output for(int i = 0; i < _mi_option_last; i++ ) { mi_option_t option = (mi_option_t)i; @@ -124,6 +123,14 @@ void _mi_options_init(void) { } mi_max_error_count = mi_option_get(mi_option_max_errors); mi_max_warning_count = mi_option_get(mi_option_max_warnings); + #if MI_DEBUG_GUARDED + if (mi_option_get(mi_option_debug_guarded_max) > 0) { + if (mi_option_is_enabled(mi_option_allow_large_os_pages)) { + mi_option_disable(mi_option_allow_large_os_pages); + _mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n"); + } + } + #endif } long _mi_option_get_fast(mi_option_t option) { @@ -168,6 +175,13 @@ void mi_option_set(mi_option_t option, long value) { mi_assert(desc->option == option); // index should match the option desc->value = value; desc->init = INITIALIZED; + // ensure min/max range; be careful to not recurse. + if (desc->option == mi_option_debug_guarded_min && _mi_option_get_fast(mi_option_debug_guarded_max) < value) { + mi_option_set(mi_option_debug_guarded_max, value); + } + else if (desc->option == mi_option_debug_guarded_max && _mi_option_get_fast(mi_option_debug_guarded_min) > value) { + mi_option_set(mi_option_debug_guarded_min, value); + } } void mi_option_set_default(mi_option_t option, long value) { @@ -517,11 +531,7 @@ static void mi_option_init(mi_option_desc_t* desc) { value = (size > LONG_MAX ? LONG_MAX : (long)size); } if (*end == 0) { - desc->value = value; - desc->init = INITIALIZED; - if (desc->option == mi_option_debug_guarded_min && _mi_option_get_fast(mi_option_debug_guarded_max) < value) { - mi_option_set(mi_option_debug_guarded_max,value); - } + mi_option_set(desc->option, value); } else { // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose. diff --git a/src/page.c b/src/page.c index 96d1b24c..49f9ed52 100644 --- a/src/page.c +++ b/src/page.c @@ -414,6 +414,9 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { // no more aligned blocks in here mi_page_set_has_aligned(page, false); + #if MI_DEBUG_GUARDED + mi_page_set_has_guarded(page, false); + #endif // remove from the page list // (no need to do _mi_heap_delayed_free first as all blocks are already free) @@ -440,6 +443,9 @@ void _mi_page_retire(mi_page_t* page) mi_attr_noexcept { mi_assert_internal(mi_page_all_free(page)); mi_page_set_has_aligned(page, false); + #if MI_DEBUG_GUARDED + mi_page_set_has_guarded(page, false); + #endif // don't retire too often.. // (or we end up retiring and re-allocating most of the time) @@ -912,7 +918,7 @@ void* _mi_malloc_generic(mi_heap_t* heap, size_t size, bool zero, size_t huge_al mi_assert_internal(mi_page_block_size(page) >= size); // and try again, this time succeeding! (i.e. this should never recurse through _mi_page_malloc) - if mi_unlikely(zero && page->block_size == 0) { + if mi_unlikely(zero && mi_page_is_huge(page)) { // note: we cannot call _mi_page_malloc with zeroing for huge blocks; we zero it afterwards in that case. void* p = _mi_page_malloc(heap, page, size); mi_assert_internal(p != NULL); diff --git a/src/segment.c b/src/segment.c index 7646c94c..ead8bb98 100644 --- a/src/segment.c +++ b/src/segment.c @@ -448,13 +448,18 @@ uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* pa static size_t mi_segment_calculate_sizes(size_t capacity, size_t required, size_t* pre_size, size_t* info_size) { - const size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */; + const size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */; size_t guardsize = 0; size_t isize = 0; + if (MI_SECURE == 0) { // normally no guard pages + #if MI_DEBUG_GUARDED + isize = _mi_align_up(minsize, _mi_os_page_size()); + #else isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE); + #endif } else { // in secure mode, we set up a protected page in between the segment info @@ -462,7 +467,7 @@ static size_t mi_segment_calculate_sizes(size_t capacity, size_t required, size_ const size_t page_size = _mi_os_page_size(); isize = _mi_align_up(minsize, page_size); guardsize = page_size; - required = _mi_align_up(required, page_size); + //required = _mi_align_up(required, isize + guardsize); } if (info_size != NULL) *info_size = isize; diff --git a/test/main-override-static.c b/test/main-override-static.c index bf1cc416..9cddb98d 100644 --- a/test/main-override-static.c +++ b/test/main-override-static.c @@ -11,6 +11,7 @@ static void double_free1(); static void double_free2(); static void corrupt_free(); static void block_overflow1(); +static void block_overflow2(); static void invalid_free(); static void test_aslr(void); static void test_process_info(void); @@ -28,6 +29,7 @@ int main() { // double_free2(); // corrupt_free(); // block_overflow1(); + block_overflow2(); // test_aslr(); // invalid_free(); // test_reserved(); @@ -76,6 +78,12 @@ static void block_overflow1() { free(p); } +static void block_overflow2() { + uint8_t* p = (uint8_t*)mi_malloc(16); + p[17] = 0; + free(p); +} + // The double free samples come ArcHeap [1] by Insu Yun (issue #161) // [1]: https://arxiv.org/pdf/1903.00503.pdf diff --git a/test/test-api.c b/test/test-api.c index 76101980..15484544 100644 --- a/test/test-api.c +++ b/test/test-api.c @@ -65,6 +65,15 @@ bool mem_is_zero(uint8_t* p, size_t size) { int main(void) { mi_option_disable(mi_option_verbose); + CHECK_BODY("malloc-aligned9a") { // test large alignments + void* p = mi_zalloc_aligned(1024 * 1024, 2); + mi_free(p); + p = mi_zalloc_aligned(1024 * 1024, 2); + mi_free(p); + result = true; + }; + + // --------------------------------------------------- // Malloc // --------------------------------------------------- @@ -157,6 +166,7 @@ int main(void) { printf("malloc_aligned5: usable size: %zi\n", usable); mi_free(p); }; + /* CHECK_BODY("malloc-aligned6") { bool ok = true; for (size_t align = 1; align <= MI_BLOCK_ALIGNMENT_MAX && ok; align *= 2) { @@ -174,6 +184,7 @@ int main(void) { } result = ok; }; + */ CHECK_BODY("malloc-aligned7") { void* p = mi_malloc_aligned(1024,MI_BLOCK_ALIGNMENT_MAX); mi_free(p); @@ -189,7 +200,7 @@ int main(void) { } result = ok; }; - CHECK_BODY("malloc-aligned9") { + CHECK_BODY("malloc-aligned9") { // test large alignments bool ok = true; void* p[8]; size_t sizes[8] = { 8, 512, 1024 * 1024, MI_BLOCK_ALIGNMENT_MAX, MI_BLOCK_ALIGNMENT_MAX + 1, 2 * MI_BLOCK_ALIGNMENT_MAX, 8 * MI_BLOCK_ALIGNMENT_MAX, 0 }; From 635cf7af6acae8d03767e5c158b79b94690813fa Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 20 Aug 2024 09:55:57 -0700 Subject: [PATCH 008/131] fix multi-threaded free to unprotect guarded blocks --- include/mimalloc/types.h | 2 +- src/alloc.c | 26 +++++++++++++++++++------- src/free.c | 33 ++++++++++++++++++++++----------- src/segment.c | 1 + test/test-api-fill.c | 2 +- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index ffe095a5..bf75f8c7 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -74,7 +74,7 @@ terms of the MIT license. A copy of the license can be found in the file // Use guard pages behind objects of a certain size #define MI_DEBUG_GUARDED 1 -#if defined(MI_DEBUG_GUARDED) || defined(MI_DEBUG_GUARDEDX) +#if defined(MI_DEBUG_GUARDED) #define MI_PADDING 0 #endif diff --git a/src/alloc.c b/src/alloc.c index ec008318..8f47e541 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -55,8 +55,10 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ // zero the block? note: we need to zero the full block size (issue #63) if mi_unlikely(zero) { mi_assert_internal(page->block_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic) - mi_assert_internal(page->block_size >= MI_PADDING_SIZE); mi_assert_internal(!mi_page_is_huge(page)); + #if MI_PADDING_SIZE > 0 + mi_assert_internal(page->block_size >= MI_PADDING_SIZE); + #endif if (page->free_is_zero) { block->next = 0; mi_track_mem_defined(block, page->block_size - MI_PADDING_SIZE); @@ -131,7 +133,7 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, if (size == 0) { size = sizeof(void*); } #endif #if MI_DEBUG_GUARDED - if (size >= _mi_option_get_fast(mi_option_debug_guarded_min) && size <= _mi_option_get_fast(mi_option_debug_guarded_max)) { + if (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)) { return mi_heap_malloc_guarded(heap, size, zero, 0); } #endif @@ -171,8 +173,9 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z } #if MI_DEBUG_GUARDED else if ( huge_alignment == 0 && // guarded pages do not work with huge aligments at the moment - ((size >= _mi_option_get_fast(mi_option_debug_guarded_min) && size <= _mi_option_get_fast(mi_option_debug_guarded_max)) - || ((size & (_mi_os_page_size()-1)) == 0)) ) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. + _mi_option_get_fast(mi_option_debug_guarded_max) > 0 && // guarded must be enabled + ((size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min) && size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max)) + || ((mi_good_size(size) & (_mi_os_page_size()-1)) == 0)) ) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. { return mi_heap_malloc_guarded(heap, size, zero, 0); } @@ -611,15 +614,24 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz if (base==NULL) return NULL; mi_page_t* page = _mi_ptr_page(base); mi_segment_t* segment = _mi_page_segment(page); - + const size_t fullsize = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` void* const gpage = (uint8_t*)base + (fullsize - psize); mi_assert_internal(_mi_is_aligned(gpage, psize)); - void* const p = (uint8_t*)base + (fullsize - psize - bsize); + + // place block in front of the guard page + size_t offset = fullsize - psize - bsize; + if (offset > MI_BLOCK_ALIGNMENT_MAX) { + // give up to place it right in front of the guard page if the offset is too large for unalignment + offset = MI_BLOCK_ALIGNMENT_MAX; + } + void* const p = (uint8_t*)base + offset; mi_assert_internal(p >= base); // set page flags - if (p > base) { mi_page_set_has_aligned(page, true); } + if (offset > 0) { + mi_page_set_has_aligned(page, true); + } // set guard page if (segment->allow_decommit) { diff --git a/src/free.c b/src/free.c index 07c06899..2137f7c9 100644 --- a/src/free.c +++ b/src/free.c @@ -26,6 +26,25 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block); // forward declaration of multi-threaded free (`_mt`) (or free in huge block if compiled with MI_HUGE_PAGE_ABANDON) static mi_decl_noinline void mi_free_block_mt(mi_page_t* page, mi_segment_t* segment, mi_block_t* block); +#if !MI_DEBUG_GUARDED +static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { + MI_UNUSED(page); + MI_UNUSED(block); +} +#else +static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { + if (mi_page_has_guarded(page)) { + const size_t bsize = mi_page_block_size(page); + const size_t psize = _mi_os_page_size(); + mi_assert_internal(bsize > psize); + mi_assert_internal(_mi_page_segment(page)->allow_decommit); + void* gpage = (uint8_t*)block + (bsize - psize); + mi_assert_internal(_mi_is_aligned(gpage, psize)); + _mi_os_unprotect(gpage, psize); + } +} +#endif + // regular free of a (thread local) block pointer // fast path written carefully to prevent spilling on the stack static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool track_stats, bool check_full) @@ -33,17 +52,7 @@ static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool // checks if mi_unlikely(mi_check_is_double_free(page, block)) return; mi_check_padding(page, block); - if (track_stats) { mi_stat_free(page, block); } - #if MI_DEBUG_GUARDED - if (mi_page_has_guarded(page)) { - const size_t bsize = mi_page_block_size(page); - const size_t psize = _mi_os_page_size(); - mi_assert_internal(bsize > psize); - mi_assert_internal(_mi_page_segment(page)->allow_decommit); - void* gpage = (uint8_t*)block + (bsize - psize); - _mi_os_unprotect(gpage, psize); - } - #endif + if (track_stats) { mi_stat_free(page, block); } #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN && !MI_DEBUG_GUARDED memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); #endif @@ -83,12 +92,14 @@ mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) { static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { MI_UNUSED(segment); mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(page, p) : (mi_block_t*)p); + mi_block_unguard(page,block); mi_free_block_local(page, block, true /* track stats */, true /* check for a full page */); } // free a pointer owned by another thread (page parameter comes first for better codegen) static void mi_decl_noinline mi_free_generic_mt(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { mi_block_t* const block = _mi_page_ptr_unalign(page, p); // don't check `has_aligned` flag to avoid a race (issue #865) + mi_block_unguard(page, block); mi_free_block_mt(page, segment, block); } diff --git a/src/segment.c b/src/segment.c index ead8bb98..b03c7e85 100644 --- a/src/segment.c +++ b/src/segment.c @@ -745,6 +745,7 @@ static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, mi_seg void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) { mi_assert(page != NULL); + mi_assert_internal(!mi_page_has_guarded(page)); mi_segment_t* segment = _mi_page_segment(page); mi_assert_expensive(mi_segment_is_valid(segment,tld)); mi_pages_try_purge(false /*force?*/, tld); diff --git a/test/test-api-fill.c b/test/test-api-fill.c index 3fca3b9d..3baee83d 100644 --- a/test/test-api-fill.c +++ b/test/test-api-fill.c @@ -271,7 +271,7 @@ int main(void) { mi_free(p); }; - #if !(MI_TRACK_VALGRIND || MI_TRACK_ASAN) + #if !(MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_DEBUG_GUARDED) CHECK_BODY("fill-freed-small") { size_t malloc_size = MI_SMALL_SIZE_MAX / 2; uint8_t* p = (uint8_t*)mi_malloc(malloc_size); From 8899a11c70e94a7cb92aa57c3c8919d90a873f61 Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 20 Aug 2024 11:09:17 -0700 Subject: [PATCH 009/131] clean up guarded pages code --- include/mimalloc.h | 4 ++-- include/mimalloc/types.h | 5 +++-- src/alloc.c | 26 ++++++++++++------------ src/free.c | 44 +++++++++++++++++++++++----------------- src/options.c | 5 +++-- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 867c5c97..e5133c96 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -366,8 +366,8 @@ typedef enum mi_option_e { mi_option_disallow_arena_alloc, // 1 = do not use arena's for allocation (except if using specific arena id's) mi_option_retry_on_oom, // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows) mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0) - mi_option_debug_guarded_min, // only used when build with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) - mi_option_debug_guarded_max, // only used when build with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) + mi_option_debug_guarded_min, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) + mi_option_debug_guarded_max, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index bf75f8c7..d1e6e5d8 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -72,8 +72,9 @@ terms of the MIT license. A copy of the license can be found in the file #endif #endif -// Use guard pages behind objects of a certain size -#define MI_DEBUG_GUARDED 1 +// Use guard pages behind objects of a certain size (set by the MIMALLOC_DEBUG_GUARDED_MIN/MAX options) +// Padding should be disabled when using guard pages +// #define MI_DEBUG_GUARDED 1 #if defined(MI_DEBUG_GUARDED) #define MI_PADDING 0 #endif diff --git a/src/alloc.c b/src/alloc.c index 8f47e541..6fc85952 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -607,26 +607,26 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz mi_assert(MI_PADDING_SIZE==0); #endif // allocate multiple of page size ending in a guard page - const size_t bsize = _mi_align_up(size, MI_MAX_ALIGN_SIZE); // ensure minimal alignment requirement - const size_t psize = _mi_os_page_size(); - const size_t gsize = _mi_align_up(bsize + psize, psize); - void* const base = _mi_malloc_generic(heap, gsize, zero, huge_alignment); - if (base==NULL) return NULL; - mi_page_t* page = _mi_ptr_page(base); + const size_t obj_size = _mi_align_up(size, MI_MAX_ALIGN_SIZE); // ensure minimal alignment requirement + const size_t os_page_size = _mi_os_page_size(); + const size_t req_size = _mi_align_up(obj_size + os_page_size, os_page_size); + void* const block = _mi_malloc_generic(heap, req_size, zero, huge_alignment); + if (block==NULL) return NULL; + mi_page_t* page = _mi_ptr_page(block); mi_segment_t* segment = _mi_page_segment(page); - const size_t fullsize = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` - void* const gpage = (uint8_t*)base + (fullsize - psize); - mi_assert_internal(_mi_is_aligned(gpage, psize)); + const size_t block_size = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` + void* const guard_page = (uint8_t*)block + (block_size - os_page_size); + mi_assert_internal(_mi_is_aligned(guard_page, os_page_size)); // place block in front of the guard page - size_t offset = fullsize - psize - bsize; + size_t offset = block_size - os_page_size - obj_size; if (offset > MI_BLOCK_ALIGNMENT_MAX) { // give up to place it right in front of the guard page if the offset is too large for unalignment offset = MI_BLOCK_ALIGNMENT_MAX; } - void* const p = (uint8_t*)base + offset; - mi_assert_internal(p >= base); + void* const p = (uint8_t*)block + offset; + mi_assert_internal(p>=block); // set page flags if (offset > 0) { @@ -636,7 +636,7 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz // set guard page if (segment->allow_decommit) { mi_page_set_has_guarded(page, true); - _mi_os_protect(gpage, psize); + _mi_os_protect(guard_page, os_page_size); } else { _mi_warning_message("unable to set a guard page behind an object due to pinned memory (large OS pages?) (object %p of size %zu)\n", p, size); diff --git a/src/free.c b/src/free.c index 2137f7c9..f2e5f8e3 100644 --- a/src/free.c +++ b/src/free.c @@ -26,25 +26,6 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block); // forward declaration of multi-threaded free (`_mt`) (or free in huge block if compiled with MI_HUGE_PAGE_ABANDON) static mi_decl_noinline void mi_free_block_mt(mi_page_t* page, mi_segment_t* segment, mi_block_t* block); -#if !MI_DEBUG_GUARDED -static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { - MI_UNUSED(page); - MI_UNUSED(block); -} -#else -static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { - if (mi_page_has_guarded(page)) { - const size_t bsize = mi_page_block_size(page); - const size_t psize = _mi_os_page_size(); - mi_assert_internal(bsize > psize); - mi_assert_internal(_mi_page_segment(page)->allow_decommit); - void* gpage = (uint8_t*)block + (bsize - psize); - mi_assert_internal(_mi_is_aligned(gpage, psize)); - _mi_os_unprotect(gpage, psize); - } -} -#endif - // regular free of a (thread local) block pointer // fast path written carefully to prevent spilling on the stack static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool track_stats, bool check_full) @@ -88,6 +69,9 @@ mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) { return (mi_block_t*)((uintptr_t)p - adjust); } +// forward declaration for a MI_DEBUG_GUARDED build +static void mi_block_unguard(mi_page_t* page, mi_block_t* block); + // free a local pointer (page parameter comes first for better codegen) static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { MI_UNUSED(segment); @@ -546,3 +530,25 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { MI_UNUSED(page); MI_UNUSED(block); } #endif + + +// Remove guard page when building with MI_DEBUG_GUARDED +#if !MI_DEBUG_GUARDED +static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { + MI_UNUSED(page); + MI_UNUSED(block); + // do nothing +} +#else +static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { + if (mi_page_has_guarded(page)) { + const size_t bsize = mi_page_block_size(page); + const size_t psize = _mi_os_page_size(); + mi_assert_internal(bsize > psize); + mi_assert_internal(_mi_page_segment(page)->allow_decommit); + void* gpage = (uint8_t*)block + (bsize - psize); + mi_assert_internal(_mi_is_aligned(gpage, psize)); + _mi_os_unprotect(gpage, psize); + } +} +#endif diff --git a/src/options.c b/src/options.c index b8859235..27122c78 100644 --- a/src/options.c +++ b/src/options.c @@ -99,8 +99,8 @@ static mi_option_desc_t options[_mi_option_last] = #else { 0, UNINIT, MI_OPTION(visit_abandoned) }, #endif - { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only used when built with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) - { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when built with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) + { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects + { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects }; static void mi_option_init(mi_option_desc_t* desc); @@ -130,6 +130,7 @@ void _mi_options_init(void) { _mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n"); } } + _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_debug_guarded_max) > 0 ? "enabled" : "disabled"); #endif } From f130808b5ce7c947b58343f780a67a07ccbcca32 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Tue, 20 Aug 2024 12:58:49 -0700 Subject: [PATCH 010/131] fix warnings --- src/alloc.c | 10 +++++----- src/segment.c | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 6fc85952..7c1284fb 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -56,7 +56,7 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ if mi_unlikely(zero) { mi_assert_internal(page->block_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic) mi_assert_internal(!mi_page_is_huge(page)); - #if MI_PADDING_SIZE > 0 + #if MI_PADDING mi_assert_internal(page->block_size >= MI_PADDING_SIZE); #endif if (page->free_is_zero) { @@ -173,7 +173,7 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z } #if MI_DEBUG_GUARDED else if ( huge_alignment == 0 && // guarded pages do not work with huge aligments at the moment - _mi_option_get_fast(mi_option_debug_guarded_max) > 0 && // guarded must be enabled + _mi_option_get_fast(mi_option_debug_guarded_max) > 0 && // guarded must be enabled ((size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min) && size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max)) || ((mi_good_size(size) & (_mi_os_page_size()-1)) == 0)) ) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. { @@ -620,7 +620,7 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz mi_assert_internal(_mi_is_aligned(guard_page, os_page_size)); // place block in front of the guard page - size_t offset = block_size - os_page_size - obj_size; + size_t offset = block_size - os_page_size - obj_size; if (offset > MI_BLOCK_ALIGNMENT_MAX) { // give up to place it right in front of the guard page if the offset is too large for unalignment offset = MI_BLOCK_ALIGNMENT_MAX; @@ -629,8 +629,8 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz mi_assert_internal(p>=block); // set page flags - if (offset > 0) { - mi_page_set_has_aligned(page, true); + if (offset > 0) { + mi_page_set_has_aligned(page, true); } // set guard page diff --git a/src/segment.c b/src/segment.c index b03c7e85..837a65e9 100644 --- a/src/segment.c +++ b/src/segment.c @@ -452,14 +452,14 @@ static size_t mi_segment_calculate_sizes(size_t capacity, size_t required, size_ size_t guardsize = 0; size_t isize = 0; - + if (MI_SECURE == 0) { // normally no guard pages #if MI_DEBUG_GUARDED isize = _mi_align_up(minsize, _mi_os_page_size()); #else isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE); - #endif + #endif } else { // in secure mode, we set up a protected page in between the segment info @@ -745,7 +745,6 @@ static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, mi_seg void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) { mi_assert(page != NULL); - mi_assert_internal(!mi_page_has_guarded(page)); mi_segment_t* segment = _mi_page_segment(page); mi_assert_expensive(mi_segment_is_valid(segment,tld)); mi_pages_try_purge(false /*force?*/, tld); From b5c6495f69fa0d642aa40211df61274b801c8915 Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 20 Aug 2024 15:58:36 -0700 Subject: [PATCH 011/131] don't consider memory as large OS pages if only madvise'd --- ide/vs2022/mimalloc-override.vcxproj | 8 +++--- src/prim/unix/prim.c | 9 ++++--- test/main-override-static.c | 39 +++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override.vcxproj index e895fa3c..4383d886 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override.vcxproj @@ -98,7 +98,7 @@ MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); MultiThreadedDebugDLL false - Default + CompileAsCpp $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) @@ -126,7 +126,7 @@ MI_DEBUG=4;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); MultiThreadedDebugDLL false - Default + CompileAsCpp $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) @@ -157,7 +157,7 @@ $(IntDir) false MultiThreadedDLL - Default + CompileAsCpp false @@ -189,7 +189,7 @@ $(IntDir) false MultiThreadedDLL - Default + CompileAsCpp false diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c index 63a36f25..0ea8189c 100644 --- a/src/prim/unix/prim.c +++ b/src/prim/unix/prim.c @@ -181,10 +181,11 @@ int _mi_prim_free(void* addr, size_t size ) { static int unix_madvise(void* addr, size_t size, int advice) { #if defined(__sun) - return madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520) + int res = madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520) #else - return madvise(addr, size, advice); + int res = madvise(addr, size, advice); #endif + return (res==0 ? 0 : errno); } static void* unix_mmap_prim(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) { @@ -331,7 +332,7 @@ static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protec // when large OS pages are enabled for mimalloc, we call `madvise` anyways. if (allow_large && _mi_os_use_large_page(size, try_alignment)) { if (unix_madvise(p, size, MADV_HUGEPAGE) == 0) { - *is_large = true; // possibly + // *is_large = true; // possibly }; } #elif defined(__sun) @@ -340,7 +341,7 @@ static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protec cmd.mha_pagesize = _mi_os_large_page_size(); cmd.mha_cmd = MHA_MAPSIZE_VA; if (memcntl((caddr_t)p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) { - *is_large = true; + // *is_large = true; // possibly } } #endif diff --git a/test/main-override-static.c b/test/main-override-static.c index bf1cc416..535a9aaf 100644 --- a/test/main-override-static.c +++ b/test/main-override-static.c @@ -18,11 +18,13 @@ static void test_reserved(void); static void negative_stat(void); static void alloc_huge(void); static void test_heap_walk(void); +// static void test_large_pages(void); int main() { mi_version(); mi_stats_reset(); + // test_large_pages(); // detect double frees and heap corruption // double_free1(); // double_free2(); @@ -61,7 +63,7 @@ int main() { //mi_stats_print(NULL); // test_process_info(); - + return 0; } @@ -216,6 +218,41 @@ static void test_heap_walk(void) { mi_heap_visit_blocks(heap, true, &test_visit, NULL); } +// Experiment with huge OS pages +#if 0 + +#include +#include +#include +#include + +static void test_large_pages(void) { + mi_memid_t memid; + + #if 0 + size_t pages_reserved; + size_t page_size; + uint8_t* p = (uint8_t*)_mi_os_alloc_huge_os_pages(1, -1, 30000, &pages_reserved, &page_size, &memid); + const size_t req_size = pages_reserved * page_size; + #else + const size_t req_size = 64*MI_MiB; + uint8_t* p = (uint8_t*)_mi_os_alloc(req_size,&memid,NULL); + #endif + + p[0] = 1; + + //_mi_os_protect(p, _mi_os_page_size()); + //_mi_os_unprotect(p, _mi_os_page_size()); + //_mi_os_decommit(p, _mi_os_page_size(), NULL); + if (madvise(p, req_size, MADV_HUGEPAGE) == 0) { + printf("advised huge pages\n"); + _mi_os_decommit(p, _mi_os_page_size(), NULL); + }; + _mi_os_free(p, req_size, memid, NULL); +} + +#endif + // ---------------------------- // bin size experiments // ------------------------------ From b9b529de2817ccaddbab814d5636f2569464cb1b Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 21 Aug 2024 10:45:19 -0700 Subject: [PATCH 012/131] shuffle for 128 bit --- include/mimalloc/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 6e87d5ae..9d1f6e51 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -731,7 +731,7 @@ static inline mi_memid_t _mi_memid_create_os(bool committed, bool is_zero, bool static inline uintptr_t _mi_random_shuffle(uintptr_t x) { if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros -#if (MI_INTPTR_SIZE==8) +#if (MI_INTPTR_SIZE>=8) // by Sebastiano Vigna, see: x ^= x >> 30; x *= 0xbf58476d1ce4e5b9UL; From 631ff581afb36d132c9157dc176d5dd94eff9e81 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 21 Aug 2024 10:47:38 -0700 Subject: [PATCH 013/131] set compile as C++ in VS IDE --- ide/vs2022/mimalloc-override.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override.vcxproj index e895fa3c..4383d886 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override.vcxproj @@ -98,7 +98,7 @@ MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); MultiThreadedDebugDLL false - Default + CompileAsCpp $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) @@ -126,7 +126,7 @@ MI_DEBUG=4;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); MultiThreadedDebugDLL false - Default + CompileAsCpp $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) @@ -157,7 +157,7 @@ $(IntDir) false MultiThreadedDLL - Default + CompileAsCpp false @@ -189,7 +189,7 @@ $(IntDir) false MultiThreadedDLL - Default + CompileAsCpp false From 96f7cc4ef2c1f03a1775c9a3fa3a08a1e572b7b2 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 21 Aug 2024 11:21:25 -0700 Subject: [PATCH 014/131] clean up guarded allocation --- src/alloc.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 7c1284fb..34adc861 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -118,8 +118,9 @@ extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t siz } #if MI_DEBUG_GUARDED -// forward declaration -static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept; +static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; +static inline bool mi_heap_malloc_use_guarded(size_t size, bool huge_alignment); +static inline bool mi_heap_malloc_small_use_guarded(size_t size); #endif static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { @@ -133,9 +134,7 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, if (size == 0) { size = sizeof(void*); } #endif #if MI_DEBUG_GUARDED - if (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)) { - return mi_heap_malloc_guarded(heap, size, zero, 0); - } + if (mi_heap_malloc_small_use_guarded(size)) { return mi_heap_malloc_guarded(heap, size, zero); } #endif mi_page_t* page = _mi_heap_get_free_small_page(heap, size + MI_PADDING_SIZE); @@ -172,13 +171,7 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z return mi_heap_malloc_small_zero(heap, size, zero); } #if MI_DEBUG_GUARDED - else if ( huge_alignment == 0 && // guarded pages do not work with huge aligments at the moment - _mi_option_get_fast(mi_option_debug_guarded_max) > 0 && // guarded must be enabled - ((size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min) && size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max)) - || ((mi_good_size(size) & (_mi_os_page_size()-1)) == 0)) ) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. - { - return mi_heap_malloc_guarded(heap, size, zero, 0); - } + else if (mi_use_guarded(size,huge_alignment)) { return mi_heap_malloc_guarded(heap, size, zero); } #endif else { mi_assert(heap!=NULL); @@ -601,7 +594,20 @@ mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } #if MI_DEBUG_GUARDED -static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept +static inline bool mi_heap_malloc_small_use_guarded(size_t size) { + return (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) + && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)); +} + +static inline bool mi_heap_malloc_use_guarded(size_t size, bool huge_alignment) { + return (huge_alignment == 0 // guarded pages do not work with huge aligments at the moment + && _mi_option_get_fast(mi_option_debug_guarded_max) > 0 // guarded must be enabled + && (mi_heap_malloc_small_use_guarded(size) + || ((mi_good_size(size) & (_mi_os_page_size() - 1)) == 0)) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. + ); +} + +static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { #if defined(MI_PADDING_SIZE) mi_assert(MI_PADDING_SIZE==0); @@ -610,7 +616,7 @@ static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t siz const size_t obj_size = _mi_align_up(size, MI_MAX_ALIGN_SIZE); // ensure minimal alignment requirement const size_t os_page_size = _mi_os_page_size(); const size_t req_size = _mi_align_up(obj_size + os_page_size, os_page_size); - void* const block = _mi_malloc_generic(heap, req_size, zero, huge_alignment); + void* const block = _mi_malloc_generic(heap, req_size, zero, 0 /* huge_alignment */); if (block==NULL) return NULL; mi_page_t* page = _mi_ptr_page(block); mi_segment_t* segment = _mi_page_segment(page); From cc4dc1bb53017da9862e1b4d3e74853fc9b6ec27 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 21 Aug 2024 11:26:12 -0700 Subject: [PATCH 015/131] add comments --- src/alloc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 34adc861..c91de62d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -31,18 +31,22 @@ terms of the MIT license. A copy of the license can be found in the file extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_t size, bool zero) mi_attr_noexcept { mi_assert_internal(page->block_size == 0 /* empty heap */ || mi_page_block_size(page) >= size); + + // check the free list mi_block_t* const block = page->free; if mi_unlikely(block == NULL) { return _mi_malloc_generic(heap, size, zero, 0); } mi_assert_internal(block != NULL && _mi_ptr_page(block) == page); + // pop from the free list page->free = mi_block_next(page, block); page->used++; mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); mi_assert_internal(page->block_size < MI_MAX_ALIGN_SIZE || _mi_is_aligned(block, MI_MAX_ALIGN_SIZE)); + #if MI_DEBUG>3 - if (page->free_is_zero && size > sizeof(*block)) { + if (page->free_is_zero && size > sizeof(*block)) { mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block))); } #endif @@ -125,11 +129,11 @@ static inline bool mi_heap_malloc_small_use_guarded(size_t size); static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { mi_assert(heap != NULL); + mi_assert(size <= MI_SMALL_SIZE_MAX); #if MI_DEBUG const uintptr_t tid = _mi_thread_id(); mi_assert(heap->thread_id == 0 || heap->thread_id == tid); // heaps are thread local #endif - mi_assert(size <= MI_SMALL_SIZE_MAX); #if (MI_PADDING || MI_DEBUG_GUARDED) if (size == 0) { size = sizeof(void*); } #endif @@ -137,6 +141,7 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, if (mi_heap_malloc_small_use_guarded(size)) { return mi_heap_malloc_guarded(heap, size, zero); } #endif + // get page in constant time, and allocate from it mi_page_t* page = _mi_heap_get_free_small_page(heap, size + MI_PADDING_SIZE); void* const p = _mi_page_malloc_zero(heap, page, size + MI_PADDING_SIZE, zero); mi_track_malloc(p,size,zero); @@ -166,6 +171,7 @@ mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc_small(size_t si // The main allocation function extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept { + // fast path for small objects if mi_likely(size <= MI_SMALL_SIZE_MAX) { mi_assert_internal(huge_alignment == 0); return mi_heap_malloc_small_zero(heap, size, zero); @@ -174,10 +180,12 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z else if (mi_use_guarded(size,huge_alignment)) { return mi_heap_malloc_guarded(heap, size, zero); } #endif else { + // regular allocation mi_assert(heap!=NULL); mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE, zero, huge_alignment); // note: size can overflow but it is detected in malloc_generic mi_track_malloc(p,size,zero); + #if MI_STAT>1 if (p != NULL) { if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } From 58e743b83f0949ecfa4732eaec0288672c55123f Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 21 Aug 2024 11:30:00 -0700 Subject: [PATCH 016/131] fix use_guarded signature --- src/alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index c91de62d..ca60c11a 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -123,7 +123,7 @@ extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t siz #if MI_DEBUG_GUARDED static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; -static inline bool mi_heap_malloc_use_guarded(size_t size, bool huge_alignment); +static inline bool mi_heap_malloc_use_guarded(size_t size, bool has_huge_alignment); static inline bool mi_heap_malloc_small_use_guarded(size_t size); #endif @@ -177,7 +177,7 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z return mi_heap_malloc_small_zero(heap, size, zero); } #if MI_DEBUG_GUARDED - else if (mi_use_guarded(size,huge_alignment)) { return mi_heap_malloc_guarded(heap, size, zero); } + else if (mi_heap_malloc_use_guarded(size,huge_alignment>0)) { return mi_heap_malloc_guarded(heap, size, zero); } #endif else { // regular allocation @@ -607,8 +607,8 @@ static inline bool mi_heap_malloc_small_use_guarded(size_t size) { && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)); } -static inline bool mi_heap_malloc_use_guarded(size_t size, bool huge_alignment) { - return (huge_alignment == 0 // guarded pages do not work with huge aligments at the moment +static inline bool mi_heap_malloc_use_guarded(size_t size, bool has_huge_alignment) { + return (!has_huge_alignment // guarded pages do not work with huge aligments at the moment && _mi_option_get_fast(mi_option_debug_guarded_max) > 0 // guarded must be enabled && (mi_heap_malloc_small_use_guarded(size) || ((mi_good_size(size) & (_mi_os_page_size() - 1)) == 0)) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. From 51025f1ac218811fb443dedea978af1551c52131 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 21 Aug 2024 15:29:32 -0700 Subject: [PATCH 017/131] set lower parameters for guarded test --- test/test-stress.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test-stress.c b/test/test-stress.c index f9b3c9d6..25942299 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -33,6 +33,10 @@ static int ITER = 200; static int THREADS = 8; static int SCALE = 25; static int ITER = 20; +#elif defined(MI_DEBUG_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; #else static int THREADS = 32; // more repeatable if THREADS <= #processors static int SCALE = 25; // scaling factor From bb3976760fa97b92f39580da7566a9ccd34378f5 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 21 Aug 2024 15:34:22 -0700 Subject: [PATCH 018/131] add guarded build to test pipeline --- azure-pipelines.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e3689407..235b2bf5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -113,6 +113,11 @@ jobs: CXX: clang++ BuildType: debug-tsan-clang-cxx cmakeExtraArgs: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMI_USE_CXX=ON -DMI_DEBUG_TSAN=ON + Debug Guarded Clang: + CC: clang + CXX: clang + BuildType: debug-guarded-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMI_DEBUG_FULL=ON -DMI_DEBUG_GUARDED=ON steps: - task: CMake@1 @@ -124,6 +129,8 @@ jobs: - script: ctest --verbose --timeout 180 workingDirectory: $(BuildType) displayName: CTest + env: + MIMALLOC_DEBUG_GUARDED_MAX: 1024 # - upload: $(Build.SourcesDirectory)/$(BuildType) # artifact: mimalloc-ubuntu-$(BuildType) From d8e0cb1a37e2b65551d4bf10558774c1ac5ef17c Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 21 Aug 2024 17:01:05 -0700 Subject: [PATCH 019/131] increase test timeout for azure pipeline --- azure-pipelines.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 235b2bf5..256f7088 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: solution: $(BuildType)/libmimalloc.sln configuration: '$(MSBuildConfiguration)' msbuildArguments: -m - - script: ctest --verbose --timeout 120 -C $(MSBuildConfiguration) + - script: ctest --verbose --timeout 240 -C $(MSBuildConfiguration) workingDirectory: $(BuildType) displayName: CTest #- script: $(BuildType)\$(BuildType)\mimalloc-test-stress @@ -126,7 +126,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(nproc) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest env: @@ -157,7 +157,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 120 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest # - upload: $(Build.SourcesDirectory)/$(BuildType) @@ -193,5 +193,5 @@ jobs: # configuration: '$(MSBuildConfiguration)' # - script: | # cd $(BuildType) -# ctest --verbose --timeout 120 +# ctest --verbose --timeout 240 # displayName: CTest From db3d8485d2f45a6f179d784f602f9eff4f60795c Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 21 Aug 2024 17:13:51 -0700 Subject: [PATCH 020/131] increase TSAN test to 400 iterations --- azure-pipelines.yml | 8 ++++---- test/test-stress.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 256f7088..4455dfeb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: solution: $(BuildType)/libmimalloc.sln configuration: '$(MSBuildConfiguration)' msbuildArguments: -m - - script: ctest --verbose --timeout 240 -C $(MSBuildConfiguration) + - script: ctest --verbose --timeout 180 -C $(MSBuildConfiguration) workingDirectory: $(BuildType) displayName: CTest #- script: $(BuildType)\$(BuildType)\mimalloc-test-stress @@ -126,7 +126,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(nproc) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 240 + - script: ctest --verbose --timeout 180 workingDirectory: $(BuildType) displayName: CTest env: @@ -157,7 +157,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 240 + - script: ctest --verbose --timeout 180 workingDirectory: $(BuildType) displayName: CTest # - upload: $(Build.SourcesDirectory)/$(BuildType) @@ -193,5 +193,5 @@ jobs: # configuration: '$(MSBuildConfiguration)' # - script: | # cd $(BuildType) -# ctest --verbose --timeout 240 +# ctest --verbose --timeout 180 # displayName: CTest diff --git a/test/test-stress.c b/test/test-stress.c index 25942299..30ad0e77 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -28,7 +28,7 @@ terms of the MIT license. #if defined(MI_TSAN) // with thread-sanitizer reduce the threads to test within the azure pipeline limits static int THREADS = 8; static int SCALE = 25; -static int ITER = 200; +static int ITER = 400; #elif defined(MI_UBSAN) // with undefined behavious sanitizer reduce parameters to stay within the azure pipeline limits static int THREADS = 8; static int SCALE = 25; From cd0c4ab67c06900dab2a01d96700b32bfc81e8b4 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Fri, 23 Aug 2024 00:31:14 +0900 Subject: [PATCH 021/131] docs: update readme.md speficic -> specific --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a0296b43..3ee2b280 100644 --- a/readme.md +++ b/readme.md @@ -113,7 +113,7 @@ memory usage * 2022-11-03, `v1.7.7`, `v2.0.7`: Initial support for [Valgrind](#valgrind) for leak testing and heap block overflow detection. Initial - support for attaching heaps to a speficic memory area (only in v2). Fix `realloc` behavior for zero size blocks, remove restriction to integral multiple of the alignment in `alloc_align`, improved aligned allocation performance, reduced contention with many threads on few processors (thank you @dposluns!), vs2022 support, support `pkg-config`, . + support for attaching heaps to a specific memory area (only in v2). Fix `realloc` behavior for zero size blocks, remove restriction to integral multiple of the alignment in `alloc_align`, improved aligned allocation performance, reduced contention with many threads on few processors (thank you @dposluns!), vs2022 support, support `pkg-config`, . * 2022-04-14, `v1.7.6`, `v2.0.6`: fix fallback path for aligned OS allocation on Windows, improve Windows aligned allocation even when compiling with older SDK's, fix dynamic overriding on macOS Monterey, fix MSVC C++ dynamic overriding, fix From 95f8fda113808e724dc63611da6b4e837426a32d Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Fri, 30 Aug 2024 19:58:57 +0100 Subject: [PATCH 022/131] Fix typo --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a0296b43..79d07ca2 100644 --- a/readme.md +++ b/readme.md @@ -540,7 +540,7 @@ clang -g -o test-wrong -Iinclude test/test-wrong.c out/debug/libmimalloc-asan-de Since the address sanitizer redirects the standard allocation functions, on some platforms (macOSX for example) it is required to compile mimalloc with `-DMI_OVERRIDE=OFF`. -Adress sanitizer support is in its initial development -- please report any issues. +Address sanitizer support is in its initial development -- please report any issues. [asan]: https://github.com/google/sanitizers/wiki/AddressSanitizer From f38816d4ed3fb4af588c6addf8ec11ec47b79c55 Mon Sep 17 00:00:00 2001 From: Philip Brown <122590765+asdf-bro@users.noreply.github.com> Date: Sun, 6 Oct 2024 15:42:46 -0500 Subject: [PATCH 023/131] Musl needs __libc* functions too --- src/alloc-override.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/alloc-override.c b/src/alloc-override.c index 12837cdd..82a98b80 100644 --- a/src/alloc-override.c +++ b/src/alloc-override.c @@ -289,8 +289,8 @@ mi_decl_weak int reallocarr(void* p, size_t count, size_t size) { return mi_r void __libc_free(void* p) MI_FORWARD0(mi_free, p) void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } -#elif defined(__GLIBC__) && defined(__linux__) - // forward __libc interface (needed for glibc-based Linux distributions) +#elif defined(__linux__) + // forward __libc interface (needed for glibc-based and musl-based Linux distributions) void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc,size) void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc,count,size) void* __libc_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc,p,size) From ffa8bce58165a044c7e29c025dfa6c53e4d4b00c Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 9 Oct 2024 11:27:57 -0700 Subject: [PATCH 024/131] prefer pages that do not expand --- src/page.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/page.c b/src/page.c index 49f9ed52..29f08b49 100644 --- a/src/page.c +++ b/src/page.c @@ -715,6 +715,14 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi Find pages with free blocks -------------------------------------------------------------*/ +#define MI_MAX_CANDIDATE_SEARCH (16) + +static inline bool mi_page_is_expandable(const mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_internal(page->capacity <= page->reserved); + return (page->capacity < page->reserved); +} + // Find a page with free blocks of `page->block_size`. static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* pq, bool first_try) { @@ -722,6 +730,8 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p #if MI_STAT size_t count = 0; #endif + size_t candidate_count = 0; // we reset this on the first candidate to limit the search + mi_page_t* page_candidate = NULL; // a page with free space mi_page_t* page = pq->first; while (page != NULL) { @@ -729,10 +739,36 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p #if MI_STAT count++; #endif - + candidate_count++; +#if defined(MI_MAX_CANDIDATE_SEARCH) // 0. collect freed blocks by us and other threads - _mi_page_free_collect(page, false); + _mi_page_free_collect(page, false); // todo: should we free empty pages? + // is the local free list non-empty? + const bool immediate_available = mi_page_immediate_available(page); + + // 1. If the page is completely full, move it to the `mi_pages_full` + // queue so we don't visit long-lived pages too often. + if (!immediate_available && !mi_page_is_expandable(page)) { + mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); + mi_page_to_full(page, pq); + } + else { + // the page has free space, make it a candidate + // we prefer non-expandable pages with high usage as candidates (to reduce commit, and increase chances of free-ing up pages) + if (page_candidate == NULL) { + page_candidate = page; + candidate_count = 0; + } + else if (!mi_page_is_expandable(page) && page->used > page_candidate->used) { + page_candidate = page; + } + if (immediate_available || candidate_count > MI_MAX_CANDIDATE_SEARCH) { + mi_assert_internal(page_candidate!=NULL); + break; + } + } +#else // 1. if the page contains free blocks, we are done if (mi_page_immediate_available(page)) { break; // pick this one @@ -749,12 +785,22 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // queue so we don't visit long-lived pages too often. mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); mi_page_to_full(page, pq); +#endif page = next; } // for each page mi_heap_stat_counter_increase(heap, searches, count); + // set the page to the best candidate + if (page_candidate != NULL) { + page = page_candidate; + } + if (page != NULL && !mi_page_immediate_available(page)) { + mi_assert_internal(mi_page_is_expandable(page)); + mi_page_extend_free(heap, page, heap->tld); + } + if (page == NULL) { _mi_heap_collect_retired(heap, false); // perhaps make a page available page = mi_page_fresh(heap, pq); From a05b5ab0a1ab94372c3db1b4580a16aee7821e0d Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 9 Oct 2024 14:21:50 -0700 Subject: [PATCH 025/131] search N pages for a best fit --- src/page.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/page.c b/src/page.c index 29f08b49..e3c2d643 100644 --- a/src/page.c +++ b/src/page.c @@ -715,14 +715,17 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi Find pages with free blocks -------------------------------------------------------------*/ +// search for a best next page to use for at most N pages (often cut short if immediate blocks are available) #define MI_MAX_CANDIDATE_SEARCH (16) -static inline bool mi_page_is_expandable(const mi_page_t* page) { +// is the page not yet used up to its reserved space? +static bool mi_page_is_expandable(const mi_page_t* page) { mi_assert_internal(page != NULL); mi_assert_internal(page->capacity <= page->reserved); return (page->capacity < page->reserved); } + // Find a page with free blocks of `page->block_size`. static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* pq, bool first_try) { @@ -740,14 +743,17 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p count++; #endif candidate_count++; -#if defined(MI_MAX_CANDIDATE_SEARCH) - // 0. collect freed blocks by us and other threads - _mi_page_free_collect(page, false); // todo: should we free empty pages? + // collect freed blocks by us and other threads + _mi_page_free_collect(page, false); + +#if defined(MI_MAX_CANDIDATE_SEARCH) + // search up to N pages for a best candidate + // is the local free list non-empty? const bool immediate_available = mi_page_immediate_available(page); - // 1. If the page is completely full, move it to the `mi_pages_full` + // if the page is completely full, move it to the `mi_pages_full` // queue so we don't visit long-lived pages too often. if (!immediate_available && !mi_page_is_expandable(page)) { mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); @@ -763,25 +769,20 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p else if (!mi_page_is_expandable(page) && page->used > page_candidate->used) { page_candidate = page; } + // if we find a non-expandable candidate, or searched for N pages, return with the best candidate if (immediate_available || candidate_count > MI_MAX_CANDIDATE_SEARCH) { mi_assert_internal(page_candidate!=NULL); break; } } #else - // 1. if the page contains free blocks, we are done - if (mi_page_immediate_available(page)) { + // first-fit algorithm + // If the page contains free blocks, we are done + if (mi_page_immediate_available(page) || mi_page_is_expandable(page)) { break; // pick this one } - // 2. Try to extend - if (page->capacity < page->reserved) { - mi_page_extend_free(heap, page, heap->tld); - mi_assert_internal(mi_page_immediate_available(page)); - break; - } - - // 3. If the page is completely full, move it to the `mi_pages_full` + // If the page is completely full, move it to the `mi_pages_full` // queue so we don't visit long-lived pages too often. mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); mi_page_to_full(page, pq); From 96877159c24d09a58fd7c7126261c177d15a5485 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 9 Oct 2024 14:35:33 -0700 Subject: [PATCH 026/131] insert full pages that became unfull, at the start of the page queue to increase potential reuse --- src/page-queue.c | 58 +++++++++++++++++++++++++++++++++++++++--------- src/page.c | 2 +- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/page-queue.c b/src/page-queue.c index 02a8008d..71e439d6 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -260,7 +260,7 @@ static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_ } -static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { +static void mi_page_queue_enqueue_from_ex(mi_page_queue_t* to, mi_page_queue_t* from, bool enqueue_at_end, mi_page_t* page) { mi_assert_internal(page != NULL); mi_assert_expensive(mi_page_queue_contains(from, page)); mi_assert_expensive(!mi_page_queue_contains(to, page)); @@ -273,6 +273,8 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro (mi_page_is_huge(page) && mi_page_queue_is_full(to))); mi_heap_t* heap = mi_page_heap(page); + + // delete from `from` if (page->prev != NULL) page->prev->next = page->next; if (page->next != NULL) page->next->prev = page->prev; if (page == from->last) from->last = page->prev; @@ -283,22 +285,58 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro mi_heap_queue_first_update(heap, from); } - page->prev = to->last; - page->next = NULL; - if (to->last != NULL) { - mi_assert_internal(heap == mi_page_heap(to->last)); - to->last->next = page; - to->last = page; + // insert into `to` + if (enqueue_at_end) { + // enqueue at the end + page->prev = to->last; + page->next = NULL; + if (to->last != NULL) { + mi_assert_internal(heap == mi_page_heap(to->last)); + to->last->next = page; + to->last = page; + } + else { + to->first = page; + to->last = page; + mi_heap_queue_first_update(heap, to); + } } else { - to->first = page; - to->last = page; - mi_heap_queue_first_update(heap, to); + if (to->first != NULL) { + // enqueue at 2nd place + mi_assert_internal(heap == mi_page_heap(to->first)); + mi_page_t* next = to->first->next; + page->prev = to->first; + page->next = next; + to->first->next = page; + if (next != NULL) { + next->prev = page; + } + else { + to->last = page; + } + } + else { + // enqueue at the head (singleton list) + page->prev = NULL; + page->next = NULL; + to->first = page; + to->last = page; + mi_heap_queue_first_update(heap, to); + } } mi_page_set_in_full(page, mi_page_queue_is_full(to)); } +static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + mi_page_queue_enqueue_from_ex(to, from, true, page); +} + +static void mi_page_queue_enqueue_from_at_start(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + mi_page_queue_enqueue_from_ex(to, from, false, page); +} + // Only called from `mi_heap_absorb`. size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { mi_assert_internal(mi_heap_contains_queue(heap,pq)); diff --git a/src/page.c b/src/page.c index e3c2d643..fdc2c612 100644 --- a/src/page.c +++ b/src/page.c @@ -357,7 +357,7 @@ void _mi_page_unfull(mi_page_t* page) { mi_page_set_in_full(page, false); // to get the right queue mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); mi_page_set_in_full(page, true); - mi_page_queue_enqueue_from(pq, pqfull, page); + mi_page_queue_enqueue_from_at_start(pq, pqfull, page); // insert at the start to increase the chance of reusing full pages (?) } static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { From cbc0e1980950949fbc0587a12eaad02f6c90317a Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 9 Oct 2024 14:41:12 -0700 Subject: [PATCH 027/131] revert back to unfull at the end of queues as it slows down some benchmarks (like alloc-test1) --- src/page.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/page.c b/src/page.c index fdc2c612..ab9152be 100644 --- a/src/page.c +++ b/src/page.c @@ -357,7 +357,9 @@ void _mi_page_unfull(mi_page_t* page) { mi_page_set_in_full(page, false); // to get the right queue mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); mi_page_set_in_full(page, true); - mi_page_queue_enqueue_from_at_start(pq, pqfull, page); // insert at the start to increase the chance of reusing full pages (?) + mi_page_queue_enqueue_from(pq, pqfull, page); + // we may instead insert at the front to increase reuse but it slows down some benchmarks like `alloc-test1` + // mi_page_queue_enqueue_from_at_start(pq, pqfull, page); } static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { From 0316cb1d882034fad7f1b6521ac7e81441a87513 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 9 Oct 2024 15:05:35 -0700 Subject: [PATCH 028/131] reduce page search to 8 --- src/page-queue.c | 6 +++--- src/page.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/page-queue.c b/src/page-queue.c index 71e439d6..54496222 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -333,9 +333,9 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro mi_page_queue_enqueue_from_ex(to, from, true, page); } -static void mi_page_queue_enqueue_from_at_start(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { - mi_page_queue_enqueue_from_ex(to, from, false, page); -} +// static void mi_page_queue_enqueue_from_at_start(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { +// mi_page_queue_enqueue_from_ex(to, from, false, page); +// } // Only called from `mi_heap_absorb`. size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { diff --git a/src/page.c b/src/page.c index ab9152be..a0224e41 100644 --- a/src/page.c +++ b/src/page.c @@ -358,7 +358,7 @@ void _mi_page_unfull(mi_page_t* page) { mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); mi_page_set_in_full(page, true); mi_page_queue_enqueue_from(pq, pqfull, page); - // we may instead insert at the front to increase reuse but it slows down some benchmarks like `alloc-test1` + // we could insert at the front to increase reuse, but it slows down certain benchmarks (like alloc-test) // mi_page_queue_enqueue_from_at_start(pq, pqfull, page); } @@ -718,7 +718,7 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi -------------------------------------------------------------*/ // search for a best next page to use for at most N pages (often cut short if immediate blocks are available) -#define MI_MAX_CANDIDATE_SEARCH (16) +#define MI_MAX_CANDIDATE_SEARCH (8) // is the page not yet used up to its reserved space? static bool mi_page_is_expandable(const mi_page_t* page) { @@ -768,7 +768,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p page_candidate = page; candidate_count = 0; } - else if (!mi_page_is_expandable(page) && page->used > page_candidate->used) { + else if (!mi_page_is_expandable(page) && page->capacity < page_candidate->capacity) { page_candidate = page; } // if we find a non-expandable candidate, or searched for N pages, return with the best candidate From a7e7cbac89d4dbacee9e184b450ca5bfc31e0a19 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 9 Oct 2024 15:15:57 -0700 Subject: [PATCH 029/131] use enqueue_from_full, and keep inserting at the end --- src/page-queue.c | 9 +++++---- src/page.c | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/page-queue.c b/src/page-queue.c index 54496222..3034e15d 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -330,12 +330,13 @@ static void mi_page_queue_enqueue_from_ex(mi_page_queue_t* to, mi_page_queue_t* } static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { - mi_page_queue_enqueue_from_ex(to, from, true, page); + mi_page_queue_enqueue_from_ex(to, from, true /* enqueue at the end */, page); } -// static void mi_page_queue_enqueue_from_at_start(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { -// mi_page_queue_enqueue_from_ex(to, from, false, page); -// } +static void mi_page_queue_enqueue_from_full(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + // note: we could insert at the front to increase reuse, but it slows down certain benchmarks (like `alloc-test`) + mi_page_queue_enqueue_from_ex(to, from, true /* enqueue at the end of the `to` queue? */, page); +} // Only called from `mi_heap_absorb`. size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { diff --git a/src/page.c b/src/page.c index a0224e41..acc72253 100644 --- a/src/page.c +++ b/src/page.c @@ -357,9 +357,7 @@ void _mi_page_unfull(mi_page_t* page) { mi_page_set_in_full(page, false); // to get the right queue mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); mi_page_set_in_full(page, true); - mi_page_queue_enqueue_from(pq, pqfull, page); - // we could insert at the front to increase reuse, but it slows down certain benchmarks (like alloc-test) - // mi_page_queue_enqueue_from_at_start(pq, pqfull, page); + mi_page_queue_enqueue_from_full(pq, pqfull, page); } static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { From bf251b27b187d36bec964e9d6e830dcf0e5b75a4 Mon Sep 17 00:00:00 2001 From: ArtSin Date: Tue, 15 Oct 2024 13:39:28 +0400 Subject: [PATCH 030/131] Fix int and long handling and the use of (u)intptr_t in _mi_vsnprintf 'va_arg' with type 'long' was used for both 'int' and 'long' arguments, but x86_64 Linux has 64-bit 'long', so passing an 'int' argument to '_mi_vsnprintf` results in undefined behaviour. 'intptr_t' was used as the largest integer type, but on 32-bit systems it is 32-bit wide, while 'long long' is 64-bit. 'intmax_t' can be used instead. --- src/libc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libc.c b/src/libc.c index dd6b4007..ce541f1b 100644 --- a/src/libc.c +++ b/src/libc.c @@ -130,7 +130,7 @@ static void mi_out_alignright(char fill, char* start, size_t len, size_t extra, } -static void mi_out_num(uintptr_t x, size_t base, char prefix, char** out, char* end) +static void mi_out_num(uintmax_t x, size_t base, char prefix, char** out, char* end) { if (x == 0 || base == 0 || base > 16) { if (prefix != 0) { mi_outc(prefix, out, end); } @@ -206,12 +206,13 @@ void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args) { } else if (c == 'p' || c == 'x' || c == 'u') { // unsigned - uintptr_t x = 0; + uintmax_t x = 0; if (c == 'x' || c == 'u') { if (numtype == 'z') x = va_arg(args, size_t); else if (numtype == 't') x = va_arg(args, uintptr_t); // unsigned ptrdiff_t - else if (numtype == 'L') x = (uintptr_t)va_arg(args, unsigned long long); - else x = va_arg(args, unsigned long); + else if (numtype == 'L') x = va_arg(args, unsigned long long); + else if (numtype == 'l') x = va_arg(args, unsigned long); + else x = va_arg(args, unsigned int); } else if (c == 'p') { x = va_arg(args, uintptr_t); @@ -228,20 +229,21 @@ void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args) { } else if (c == 'i' || c == 'd') { // signed - intptr_t x = 0; + intmax_t x = 0; if (numtype == 'z') x = va_arg(args, intptr_t ); else if (numtype == 't') x = va_arg(args, ptrdiff_t); - else if (numtype == 'L') x = (intptr_t)va_arg(args, long long); - else x = va_arg(args, long); + else if (numtype == 'L') x = va_arg(args, long long); + else if (numtype == 'l') x = va_arg(args, long); + else x = va_arg(args, int); char pre = 0; if (x < 0) { pre = '-'; - if (x > INTPTR_MIN) { x = -x; } + if (x > INTMAX_MIN) { x = -x; } } else if (numplus != 0) { pre = numplus; } - mi_out_num((uintptr_t)x, 10, pre, &out, end); + mi_out_num((uintmax_t)x, 10, pre, &out, end); } else if (c >= ' ' && c <= '~') { // unknown format From 394e8c27d8b924e8b0248adc2835f65451c4f2ab Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 05:02:24 -0700 Subject: [PATCH 031/131] add cmake option to add C pre processor definitions more easily --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e78ba9fd..b32542ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(MI_SKIP_COLLECT_ON_EXIT "Skip collecting memory on program exit" OFF) option(MI_NO_PADDING "Force no use of padding even in DEBUG mode etc." OFF) option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF) option(MI_NO_THP "Disable transparent huge pages support on Linux/Android for the mimalloc process only" OFF) +option(MI_EXTRA_CPPDEFS "Extra pre-processor definitions (use as `-DMI_EXTRA_CPPDEFS=\"opt1=val1;opt2=val2\"`)" "") # deprecated options option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF) @@ -62,8 +63,8 @@ set(mi_sources set(mi_cflags "") set(mi_cflags_static "") # extra flags for a static library build set(mi_cflags_dynamic "") # extra flags for a shared-object library build -set(mi_defines "") set(mi_libraries "") +set(mi_defines ${MI_EXTRA_CPPDEFS}) # ----------------------------------------------------------------------------- # Convenience: set default build type depending on the build directory From 638ea539de088390b36f646e6c342dd230d0c93a Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 05:04:01 -0700 Subject: [PATCH 032/131] allow certain options to have defaults set via the pre-processor at build time -- see issue #945 --- src/options.c | 62 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/options.c b/src/options.c index 27122c78..76d2cf82 100644 --- a/src/options.c +++ b/src/options.c @@ -47,6 +47,47 @@ typedef struct mi_option_desc_s { #define MI_OPTION(opt) mi_option_##opt, #opt, NULL #define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy +// Some options can be set at build time for statically linked libraries (use `-DMI_EXTRA_CPPDEFS="opt1=val1;opt2=val2"`) +// This is useful if we cannot pass them as environment variables +// (and setting them programmatically would be too late) + +#ifndef MI_DEFAULT_VERBOSE +#define MI_DEFAULT_VERBOSE 0 +#endif + +#ifndef MI_DEFAULT_EAGER_COMMIT +#define MI_DEFAULT_EAGER_COMMIT 1 +#endif + +#ifndef MI_DEFAULT_ARENA_EAGER_COMMIT +#define MI_DEFAULT_ARENA_EAGER_COMMIT 2 +#endif + +#ifndef MI_DEFAULT_ARENA_RESERVE + #if (MI_INTPTR_SIZE>4) + #define MI_DEFAULT_ARENA_RESERVE 1024L*1024L + #else + #define MI_DEFAULT_ARENA_RESERVE 128L*1024L + #endif +#endif + +#ifndef MI_DEFAULT_DISALLOW_ARENA_ALLOC +#define MI_DEFAULT_DISALLOW_ARENA_ALLOC 0 +#endif + +#ifndef MI_DEFAULT_ALLOW_LARGE_OS_PAGES +#define MI_DEFAULT_ALLOW_LARGE_OS_PAGES 0 +#endif + +#ifndef MI_DEFAULT_RESERVE_HUGE_OS_PAGES +#define MI_DEFAULT_RESERVE_HUGE_OS_PAGES 0 +#endif + +#ifndef MI_DEFAULT_RESERVE_OS_MEMORY +#define MI_DEFAULT_RESERVE_OS_MEMORY 0 +#endif + + static mi_option_desc_t options[_mi_option_last] = { // stable options @@ -56,16 +97,16 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(show_errors) }, #endif { 0, UNINIT, MI_OPTION(show_stats) }, - { 0, UNINIT, MI_OPTION(verbose) }, + { MI_DEFAULT_VERBOSE, UNINIT, MI_OPTION(verbose) }, // the following options are experimental and not all combinations make sense. - { 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) - { 2, UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) + { MI_DEFAULT_EAGER_COMMIT, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) + { MI_DEFAULT_ARENA_EAGER_COMMIT, UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) { 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) }, // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit) - { 0, UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's - { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages + { MI_DEFAULT_ALLOW_LARGE_OS_PAGES, UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { MI_DEFAULT_RESERVE_HUGE_OS_PAGES, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages {-1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N - { 0, UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`) + { MI_DEFAULT_RESERVE_OS_MEMORY, UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`) { 0, UNINIT, MI_OPTION(deprecated_segment_cache) }, // cache N segments per thread { 0, UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free { 0, UNINIT, MI_OPTION(abandoned_page_purge) }, // purge free page memory when a thread terminates @@ -83,16 +124,11 @@ static mi_option_desc_t options[_mi_option_last] = { 32, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output { 10, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. percentage of the abandoned segments to be reclaimed per try. { 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees! - #if (MI_INTPTR_SIZE>4) - { 1024L*1024L, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`) - #else - { 128L*1024L, UNINIT, MI_OPTION(arena_reserve) }, // =128MiB on 32-bit - #endif - + { MI_DEFAULT_ARENA_RESERVE, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`) { 10, UNINIT, MI_OPTION(arena_purge_mult) }, // purge delay multiplier for arena's { 1, UNINIT, MI_OPTION_LEGACY(purge_extend_delay, decommit_extend_delay) }, { 1, UNINIT, MI_OPTION(abandoned_reclaim_on_free) },// reclaim an abandoned segment on a free - { 0, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's) + { MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's) { 400, UNINIT, MI_OPTION(retry_on_oom) }, // windows only: retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. #if defined(MI_VISIT_ABANDONED) { 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandonded segments; requires taking locks during reclaim. From 50d3525a8c948a5943c89590629e869fc7cdbe0d Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 05:04:27 -0700 Subject: [PATCH 033/131] add test for issue #944 --- test/main-override.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/test/main-override.cpp b/test/main-override.cpp index fc7f70f0..50eb0267 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -37,6 +37,7 @@ static void tsan_numa_test(); // issue #414 static void strdup_test(); // issue #445 static void heap_thread_free_huge(); static void test_std_string(); // issue #697 +static void test_thread_local(); // issue #944 static void test_stl_allocators(); @@ -44,7 +45,8 @@ static void test_stl_allocators(); int main() { // mi_stats_reset(); // ignore earlier allocations - test_std_string(); + //test_std_string(); + test_thread_local(); // heap_thread_free_huge(); /* heap_thread_free_large(); @@ -312,3 +314,31 @@ static void tsan_numa_test() { dummy_worker(); t1.join(); } + + +class MTest +{ + char *data; +public: + MTest() { data = (char*)malloc(1024); } + ~MTest() { free(data); }; +}; + +thread_local MTest tlVariable; + +void threadFun( int i ) +{ + printf( "Thread %d\n", i ); + std::this_thread::sleep_for( std::chrono::milliseconds(100) ); +} + +void test_thread_local() +{ + for( int i=1; i < 100; ++i ) + { + std::thread t( threadFun, i ); + t.join(); + mi_stats_print(NULL); + } + return; +} \ No newline at end of file From 34e66778ecc40c58164c14ada56c15e8f38cf1f7 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 05:10:09 -0700 Subject: [PATCH 034/131] fix MI_EXTRA_CPPDEFS setting --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b32542ef..adf45bbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,12 @@ set(mi_cflags "") set(mi_cflags_static "") # extra flags for a static library build set(mi_cflags_dynamic "") # extra flags for a shared-object library build set(mi_libraries "") -set(mi_defines ${MI_EXTRA_CPPDEFS}) + +if(MI_EXTRA_CPPDEFS) + set(mi_defines ${MI_EXTRA_CPPDEFS}) +else() + set(mi_defines "") +endif() # ----------------------------------------------------------------------------- # Convenience: set default build type depending on the build directory From aa881733d7830e44b39bd16080fab803e468828c Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 22:56:59 -0700 Subject: [PATCH 035/131] reorganize primitives for process initialization; use special data segment on Windows for thread termination by default on Windows now (issue #869) --- include/mimalloc/internal.h | 5 + src/init.c | 114 ++------------------- src/prim/prim.c | 44 ++++++++ src/prim/windows/prim.c | 197 ++++++++++++++++++++++++++++-------- 4 files changed, 209 insertions(+), 151 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 2f21d88e..63a1e6f0 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -77,6 +77,11 @@ 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_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 diff --git a/src/init.c b/src/init.c index ead5a147..eaa7f5be 100644 --- a/src/init.c +++ b/src/init.c @@ -459,10 +459,6 @@ void mi_thread_init(void) mi_attr_noexcept //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id()); } -void mi_thread_done(void) mi_attr_noexcept { - _mi_thread_done(NULL); -} - void _mi_thread_done(mi_heap_t* heap) { // calling with NULL implies using the default heap @@ -508,54 +504,15 @@ void _mi_heap_set_default_direct(mi_heap_t* heap) { // -------------------------------------------------------- // Run functions on process init/done, and thread init/done // -------------------------------------------------------- -static void mi_cdecl mi_process_done(void); - static bool os_preloading = true; // true until this module is initialized -static bool mi_redirected = false; // true if malloc redirects to mi_malloc // Returns true if this module has not been initialized; Don't use C runtime routines until it returns false. bool mi_decl_noinline _mi_preloading(void) { return os_preloading; } -mi_decl_nodiscard bool mi_is_redirected(void) mi_attr_noexcept { - return mi_redirected; -} - -// Communicate with the redirection module on Windows -#if defined(_WIN32) && defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) -#ifdef __cplusplus -extern "C" { -#endif -mi_decl_export void _mi_redirect_entry(DWORD reason) { - // called on redirection; careful as this may be called before DllMain - if (reason == DLL_PROCESS_ATTACH) { - mi_redirected = true; - } - else if (reason == DLL_PROCESS_DETACH) { - mi_redirected = false; - } - else if (reason == DLL_THREAD_DETACH) { - mi_thread_done(); - } -} -__declspec(dllimport) bool mi_cdecl mi_allocator_init(const char** message); -__declspec(dllimport) void mi_cdecl mi_allocator_done(void); -#ifdef __cplusplus -} -#endif -#else -static bool mi_allocator_init(const char** message) { - if (message != NULL) *message = NULL; - return true; -} -static void mi_allocator_done(void) { - // nothing to do -} -#endif - -// Called once by the process loader -static void mi_process_load(void) { +// Called once by the process loader from `src/prim/prim.c` +void _mi_process_load(void) { mi_heap_main_init(); #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to allocate it before setting tls_initialized to true; @@ -563,17 +520,14 @@ static void mi_process_load(void) { #endif os_preloading = false; mi_assert_internal(_mi_is_main_thread()); - #if !(defined(_WIN32) && defined(MI_SHARED_LIB)) // use Dll process detach (see below) instead of atexit (issue #521) - atexit(&mi_process_done); - #endif _mi_options_init(); mi_process_setup_auto_thread_done(); mi_process_init(); - if (mi_redirected) _mi_verbose_message("malloc is redirected.\n"); + if (_mi_is_redirected()) _mi_verbose_message("malloc is redirected.\n"); // show message from the redirector (if present) const char* msg = NULL; - mi_allocator_init(&msg); + _mi_allocator_init(&msg); if (msg != NULL && (mi_option_is_enabled(mi_option_verbose) || mi_option_is_enabled(mi_option_show_errors))) { _mi_fputs(NULL,NULL,NULL,msg); } @@ -651,7 +605,7 @@ void mi_process_init(void) mi_attr_noexcept { } // Called when the process is done (through `at_exit`) -static void mi_cdecl mi_process_done(void) { +void mi_cdecl _mi_process_done(void) { // only shutdown if we were initialized if (!_mi_process_is_initialized) return; // ensure we are called once @@ -683,64 +637,8 @@ static void mi_cdecl mi_process_done(void) { if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { mi_stats_print(NULL); } - mi_allocator_done(); + _mi_allocator_done(); _mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id); os_preloading = true; // don't call the C runtime anymore } - - -#if defined(_WIN32) && defined(MI_SHARED_LIB) - // Windows DLL: easy to hook into process_init and thread_done - __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { - MI_UNUSED(reserved); - MI_UNUSED(inst); - if (reason==DLL_PROCESS_ATTACH) { - mi_process_load(); - } - else if (reason==DLL_PROCESS_DETACH) { - mi_process_done(); - } - else if (reason==DLL_THREAD_DETACH) { - if (!mi_is_redirected()) { - mi_thread_done(); - } - } - return TRUE; - } - -#elif defined(_MSC_VER) - // MSVC: use data section magic for static libraries - // See - static int _mi_process_init(void) { - mi_process_load(); - return 0; - } - typedef int(*_mi_crt_callback_t)(void); - #if defined(_M_X64) || defined(_M_ARM64) - __pragma(comment(linker, "/include:" "_mi_msvc_initu")) - #pragma section(".CRT$XIU", long, read) - #else - __pragma(comment(linker, "/include:" "__mi_msvc_initu")) - #endif - #pragma data_seg(".CRT$XIU") - mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &_mi_process_init }; - #pragma data_seg() - -#elif defined(__cplusplus) - // C++: use static initialization to detect process start - static bool _mi_process_init(void) { - mi_process_load(); - return (_mi_heap_main.thread_id != 0); - } - static bool mi_initialized = _mi_process_init(); - -#elif defined(__GNUC__) || defined(__clang__) - // GCC,Clang: use the constructor attribute - static void __attribute__((constructor)) _mi_process_init(void) { - mi_process_load(); - } - -#else -#pragma message("define a way to call mi_process_load on your platform") -#endif diff --git a/src/prim/prim.c b/src/prim/prim.c index 3b7d3736..242cd618 100644 --- a/src/prim/prim.c +++ b/src/prim/prim.c @@ -25,3 +25,47 @@ terms of the MIT license. A copy of the license can be found in the file #include "unix/prim.c" // mmap() (Linux, macOSX, BSD, Illumnos, Haiku, DragonFly, etc.) #endif + +// Generic process initialization +#ifndef MI_PRIM_HAS_PROCESS_ATTACH +#if defined(__GNUC__) || defined(__clang__) + // GCC,Clang: use the constructor attribute + #if defined(__clang__) + #define mi_attr_constructor __attribute__((constructor(101))) + #define mi_attr_destructor __attribute__((destructor(101))) + #else + #define mi_attr_constructor __attribute__((constructor)) + #define mi_attr_destructor __attribute__((destructor)) + #endif + static void mi_attr_constructor mi_process_attach(void) { + _mi_process_load(); + } + static void mi_attr_destructor mi_process_detach(void) { + _mi_process_done(); + } +#elif defined(__cplusplus) + // C++: use static initialization to detect process start + static bool mi_process_attach(void) { + _mi_process_load(); + atexit(&_mi_process_done); + return (_mi_heap_main.thread_id != 0); + } + static bool mi_initialized = mi_process_attach(); +#else + #pragma message("define a way to call _mi_process_load/done on your platform") +#endif +#endif + +// Generic allocator init/done callback +#ifndef MI_PRIM_HAS_ALLOCATOR_INIT +bool _mi_is_redirected(void) { + return false; +} +bool _mi_allocator_init(const char** message) { + if (message != NULL) *message = NULL; + return true; +} +void _mi_allocator_done(void) { + // nothing to do +} +#endif diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index bd874f9b..c62ea497 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -499,8 +499,7 @@ void _mi_prim_process_info(mi_process_info_t* pinfo) } // get process info - PROCESS_MEMORY_COUNTERS info; - memset(&info, 0, sizeof(info)); + PROCESS_MEMORY_COUNTERS info; _mi_memzero_var(info); if (pGetProcessMemoryInfo != NULL) { pGetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); } @@ -602,60 +601,172 @@ bool _mi_prim_random_buf(void* buf, size_t buf_len) { #endif // MI_USE_RTLGENRANDOM + + //---------------------------------------------------------------- -// Thread init/done +// Process & Thread Init/Done //---------------------------------------------------------------- -#if !defined(MI_SHARED_LIB) - -// use thread local storage keys to detect thread ending -// note: another design could be to use special linker sections (see issue #869) -#include -#if (_WIN32_WINNT < 0x600) // before Windows Vista -WINBASEAPI DWORD WINAPI FlsAlloc( _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback ); -WINBASEAPI PVOID WINAPI FlsGetValue( _In_ DWORD dwFlsIndex ); -WINBASEAPI BOOL WINAPI FlsSetValue( _In_ DWORD dwFlsIndex, _In_opt_ PVOID lpFlsData ); -WINBASEAPI BOOL WINAPI FlsFree(_In_ DWORD dwFlsIndex); -#endif - -static DWORD mi_fls_key = (DWORD)(-1); - -static void NTAPI mi_fls_done(PVOID value) { - mi_heap_t* heap = (mi_heap_t*)value; - if (heap != NULL) { - _mi_thread_done(heap); - FlsSetValue(mi_fls_key, NULL); // prevent recursion as _mi_thread_done may set it back to the main heap, issue #672 +static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { + MI_UNUSED(reserved); + MI_UNUSED(module); + if (reason==DLL_PROCESS_ATTACH) { + _mi_process_load(); } + else if (reason==DLL_PROCESS_DETACH) { + _mi_process_done(); + } + else if (reason==DLL_THREAD_DETACH && !_mi_is_redirected()) { + _mi_thread_done(NULL); + } } -void _mi_prim_thread_init_auto_done(void) { - mi_fls_key = FlsAlloc(&mi_fls_done); -} -void _mi_prim_thread_done_auto_done(void) { - // call thread-done on all threads (except the main thread) to prevent - // dangling callback pointer if statically linked with a DLL; Issue #208 - FlsFree(mi_fls_key); -} +#if defined(MI_SHARED_LIB) + #define MI_PRIM_HAS_PROCESS_INIT 1 -void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { - mi_assert_internal(mi_fls_key != (DWORD)(-1)); - FlsSetValue(mi_fls_key, heap); -} + // Windows DLL: easy to hook into process_init and thread_done + __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { + win_main((PVOID)inst,reason,reserved); + return TRUE; + } -#else + // nothing to do since `_mi_thread_done` is handled through the DLL_THREAD_DETACH event. + void _mi_prim_thread_init_auto_done(void) { } + void _mi_prim_thread_done_auto_done(void) { } + void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + MI_UNUSED(heap); + } -// Dll; nothing to do as in that case thread_done is handled through the DLL_THREAD_DETACH event. +#elif !defined(MI_WIN_USE_FLS) + #define MI_PRIM_HAS_PROCESS_INIT 1 -void _mi_prim_thread_init_auto_done(void) { -} + // Set up TLS callbacks in a statically linked library by using special data sections. + // See + // We may use ".CRT$XLY" instead of "B" -- see also issue #869. + #if defined(__cplusplus) + extern "C" { + #endif -void _mi_prim_thread_done_auto_done(void) { -} + #if defined(_WIN64) + #pragma comment(linker, "/INCLUDE:_tls_used") + #pragma comment(linker, "/INCLUDE:_mi_tls_callback") + #pragma const_seg(".CRT$XLB") + extern const PIMAGE_TLS_CALLBACK _mi_tls_callback[]; + const PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; + #pragma const_seg() + #else + #pragma comment(linker, "/INCLUDE:__tls_used") + #pragma comment(linker, "/INCLUDE:__mi_tls_callback") + #pragma data_seg(".CRT$XLB") + const PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; + #pragma data_seg() + #endif -void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { - MI_UNUSED(heap); -} + #if defined(__cplusplus) + } + #endif + // nothing to do since `_mi_thread_done` is handled through the DLL_THREAD_DETACH event. + void _mi_prim_thread_init_auto_done(void) { } + void _mi_prim_thread_done_auto_done(void) { } + void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + MI_UNUSED(heap); + } + +#else // statically linked, use fiber api + + #if defined(_MSC_VER) // on clang/gcc use the constructor attribute (in `src/prim/prim.c`) + // MSVC: use data section magic for static libraries + // See + #define MI_PRIM_HAS_PROCESS_INIT 1 + + static int mi_process_attach(void) { + mi_win_main(NULL,DLL_PROCESS_ATTACH,NULL); + atexit(&_mi_process_done); + return 0; + } + typedef int(*_mi_crt_callback_t)(void); + #if defined(_M_X64) || defined(_M_ARM64) + __pragma(comment(linker, "/include:" "_mi_msvc_initu")) + #pragma section(".CRT$XIU", long, read) + #else + __pragma(comment(linker, "/include:" "__mi_msvc_initu")) + #endif + #pragma data_seg(".CRT$XIU") + mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &mi_process_attach }; + #pragma data_seg() + #endif + + // use the fiber api for calling `_mi_thread_done`. + #include + #if (_WIN32_WINNT < 0x600) // before Windows Vista + WINBASEAPI DWORD WINAPI FlsAlloc( _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback ); + WINBASEAPI PVOID WINAPI FlsGetValue( _In_ DWORD dwFlsIndex ); + WINBASEAPI BOOL WINAPI FlsSetValue( _In_ DWORD dwFlsIndex, _In_opt_ PVOID lpFlsData ); + WINBASEAPI BOOL WINAPI FlsFree(_In_ DWORD dwFlsIndex); + #endif + + static DWORD mi_fls_key = (DWORD)(-1); + + static void NTAPI mi_fls_done(PVOID value) { + mi_heap_t* heap = (mi_heap_t*)value; + if (heap != NULL) { + _mi_thread_done(heap); + FlsSetValue(mi_fls_key, NULL); // prevent recursion as _mi_thread_done may set it back to the main heap, issue #672 + } + } + + void _mi_prim_thread_init_auto_done(void) { + mi_fls_key = FlsAlloc(&mi_fls_done); + } + + void _mi_prim_thread_done_auto_done(void) { + // call thread-done on all threads (except the main thread) to prevent + // dangling callback pointer if statically linked with a DLL; Issue #208 + FlsFree(mi_fls_key); + } + + void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + mi_assert_internal(mi_fls_key != (DWORD)(-1)); + FlsSetValue(mi_fls_key, heap); + } #endif +// ---------------------------------------------------- +// Communicate with the redirection module on Windows +// ---------------------------------------------------- +#if defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) + static bool mi_redirected = false; // true if malloc redirects to mi_malloc + + bool _mi_is_redirected(void) { + return mi_redirected; + } + + #ifdef __cplusplus + extern "C" { + #endif + mi_decl_export void _mi_redirect_entry(DWORD reason) { + // called on redirection; careful as this may be called before DllMain + if (reason == DLL_PROCESS_ATTACH) { + mi_redirected = true; + } + else if (reason == DLL_PROCESS_DETACH) { + mi_redirected = false; + } + else if (reason == DLL_THREAD_DETACH) { + _mi_thread_done(NULL); + } + } + __declspec(dllimport) bool mi_cdecl mi_allocator_init(const char** message); + __declspec(dllimport) void mi_cdecl mi_allocator_done(void); + #ifdef __cplusplus + } + #endif + bool _mi_allocator_init(const char** message) { + return mi_allocator_init(message); + } + void _mi_allocator_done(void) { + mi_allocator_done(); + } +#endif \ No newline at end of file From 4377abe017d59796845ec0266531d62e5873a917 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 22:59:41 -0700 Subject: [PATCH 036/131] add cmake option to fall back on the fiber api do detect thread termination on windows --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index adf45bbf..e0aa59b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ option(MI_NO_THP "Disable transparent huge pages support on Linux/And option(MI_EXTRA_CPPDEFS "Extra pre-processor definitions (use as `-DMI_EXTRA_CPPDEFS=\"opt1=val1;opt2=val2\"`)" "") # deprecated options +option(MI_WIN_USE_FLS "Use Fiber local storage on Windows to detect thread termination" OFF) option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF) option(MI_USE_LIBATOMIC "Explicitly link with -latomic (on older systems) (deprecated and detected automatically)" OFF) @@ -313,6 +314,11 @@ if(MI_LIBC_MUSL) list(APPEND mi_defines MI_LIBC_MUSL=1) endif() +if(MI_WIN_USE_FLS) + message(STATUS "Use the Fiber API to detect thread termination") + list(APPEND mi_defines MI_WIN_USE_FLS=1) +endif() + # On Haiku use `-DCMAKE_INSTALL_PREFIX` instead, issue #788 # if(CMAKE_SYSTEM_NAME MATCHES "Haiku") # SET(CMAKE_INSTALL_LIBDIR ~/config/non-packaged/lib) From f971bd6d749ccdea5b3622ef6272896b2d45ab28 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 23:05:51 -0700 Subject: [PATCH 037/131] fix build on windows --- src/prim/prim.c | 1 + src/prim/windows/prim.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/prim/prim.c b/src/prim/prim.c index 242cd618..8a2400c8 100644 --- a/src/prim/prim.c +++ b/src/prim/prim.c @@ -45,6 +45,7 @@ terms of the MIT license. A copy of the license can be found in the file } #elif defined(__cplusplus) // C++: use static initialization to detect process start + extern mi_heap_t _mi_heap_main; static bool mi_process_attach(void) { _mi_process_load(); atexit(&_mi_process_done); diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index c62ea497..ed160541 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -623,11 +623,11 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #if defined(MI_SHARED_LIB) - #define MI_PRIM_HAS_PROCESS_INIT 1 + #define MI_PRIM_HAS_PROCESS_ATTACH 1 // Windows DLL: easy to hook into process_init and thread_done __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { - win_main((PVOID)inst,reason,reserved); + mi_win_main((PVOID)inst,reason,reserved); return TRUE; } @@ -639,7 +639,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { } #elif !defined(MI_WIN_USE_FLS) - #define MI_PRIM_HAS_PROCESS_INIT 1 + #define MI_PRIM_HAS_PROCESS_ATTACH 1 // Set up TLS callbacks in a statically linked library by using special data sections. // See @@ -679,7 +679,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #if defined(_MSC_VER) // on clang/gcc use the constructor attribute (in `src/prim/prim.c`) // MSVC: use data section magic for static libraries // See - #define MI_PRIM_HAS_PROCESS_INIT 1 + #define MI_PRIM_HAS_PROCESS_ATTACH 1 static int mi_process_attach(void) { mi_win_main(NULL,DLL_PROCESS_ATTACH,NULL); From e55ae0aeb76f5205edce57b97031be6aa80f962a Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 21 Oct 2024 23:09:14 -0700 Subject: [PATCH 038/131] fix duplicate definition on windows --- src/prim/windows/prim.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index ed160541..90fab080 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -737,6 +737,8 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { // Communicate with the redirection module on Windows // ---------------------------------------------------- #if defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) + #define MI_PRIM_HAS_ALLOCATOR_INIT 1 + static bool mi_redirected = false; // true if malloc redirects to mi_malloc bool _mi_is_redirected(void) { From 46e9e7fdd08f017eded0c88538647c82752c668f Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 22 Oct 2024 06:06:15 -0700 Subject: [PATCH 039/131] fix win32 compilation --- src/prim/windows/prim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 90fab080..7ba1f1de 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -659,7 +659,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #pragma comment(linker, "/INCLUDE:__tls_used") #pragma comment(linker, "/INCLUDE:__mi_tls_callback") #pragma data_seg(".CRT$XLB") - const PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; + PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; #pragma data_seg() #endif @@ -738,7 +738,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { // ---------------------------------------------------- #if defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) #define MI_PRIM_HAS_ALLOCATOR_INIT 1 - + static bool mi_redirected = false; // true if malloc redirects to mi_malloc bool _mi_is_redirected(void) { From 104e82170912bffdc7228202abc897204ca747be Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 22 Oct 2024 06:08:56 -0700 Subject: [PATCH 040/131] fix fast divisor for 32-bit platforms --- src/heap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/heap.c b/src/heap.c index a3aaaf6b..206d3a36 100644 --- a/src/heap.c +++ b/src/heap.c @@ -543,13 +543,14 @@ void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page) { static void mi_get_fast_divisor(size_t divisor, uint64_t* magic, size_t* shift) { mi_assert_internal(divisor > 0 && divisor <= UINT32_MAX); - *shift = 64 - mi_clz(divisor - 1); + *shift = MI_INTPTR_BITS - mi_clz(divisor - 1); *magic = ((((uint64_t)1 << 32) * (((uint64_t)1 << *shift) - divisor)) / divisor + 1); } static size_t mi_fast_divide(size_t n, uint64_t magic, size_t shift) { mi_assert_internal(n <= UINT32_MAX); - return ((((uint64_t)n * magic) >> 32) + n) >> shift; + const uint64_t hi = ((uint64_t)n * magic) >> 32; + return (size_t)((hi + n) >> shift); } bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg) { From dfdb9cb8772f8fabf63ce81aaa7e2aac9621a1e3 Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 22 Oct 2024 06:52:34 -0700 Subject: [PATCH 041/131] cleanup process init/done --- src/prim/prim.c | 20 ++++++++++++++++---- src/prim/windows/prim.c | 12 ++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/prim/prim.c b/src/prim/prim.c index 8a2400c8..a4d3814f 100644 --- a/src/prim/prim.c +++ b/src/prim/prim.c @@ -29,7 +29,8 @@ terms of the MIT license. A copy of the license can be found in the file // Generic process initialization #ifndef MI_PRIM_HAS_PROCESS_ATTACH #if defined(__GNUC__) || defined(__clang__) - // GCC,Clang: use the constructor attribute + // gcc,clang: use the constructor/destructor attribute + // which for both seem to run before regular constructors/destructors #if defined(__clang__) #define mi_attr_constructor __attribute__((constructor(101))) #define mi_attr_destructor __attribute__((destructor(101))) @@ -44,7 +45,17 @@ terms of the MIT license. A copy of the license can be found in the file _mi_process_done(); } #elif defined(__cplusplus) - // C++: use static initialization to detect process start + // C++: use static initialization to detect process start/end + struct mi_init_done_t { + mi_init_done_t() { + _mi_process_load(); + } + ~mi_init_done_t() { + _mi_process_done(); + } + }; + static mi_init_done_t mi_init_done; + /* extern mi_heap_t _mi_heap_main; static bool mi_process_attach(void) { _mi_process_load(); @@ -52,7 +63,8 @@ terms of the MIT license. A copy of the license can be found in the file return (_mi_heap_main.thread_id != 0); } static bool mi_initialized = mi_process_attach(); -#else + */ + #else #pragma message("define a way to call _mi_process_load/done on your platform") #endif #endif @@ -63,7 +75,7 @@ bool _mi_is_redirected(void) { return false; } bool _mi_allocator_init(const char** message) { - if (message != NULL) *message = NULL; + if (message != NULL) { *message = NULL; } return true; } void _mi_allocator_done(void) { diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 7ba1f1de..b0631b81 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -674,7 +674,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { MI_UNUSED(heap); } -#else // statically linked, use fiber api +#else // deprecated: statically linked, use fiber api #if defined(_MSC_VER) // on clang/gcc use the constructor attribute (in `src/prim/prim.c`) // MSVC: use data section magic for static libraries @@ -686,15 +686,15 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { atexit(&_mi_process_done); return 0; } - typedef int(*_mi_crt_callback_t)(void); - #if defined(_M_X64) || defined(_M_ARM64) - __pragma(comment(linker, "/include:" "_mi_msvc_initu")) + typedef int(*mi_crt_callback_t)(void); + #if defined(_WIN64) + #pragma comment(linker, "/INCLUDE:_mi_tls_callback") #pragma section(".CRT$XIU", long, read) #else - __pragma(comment(linker, "/include:" "__mi_msvc_initu")) + #pragma comment(linker, "/INCLUDE:__mi_tls_callback") #endif #pragma data_seg(".CRT$XIU") - mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &mi_process_attach }; + mi_decl_externc mi_crt_callback_t _mi_tls_callback[] = { &mi_process_attach }; #pragma data_seg() #endif From 6e9b38ac126c301f6e6c3e47a642c2c8388c333d Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 22 Oct 2024 18:58:55 -0700 Subject: [PATCH 042/131] fix issue where searching for abandoned blocks would skip the first one --- src/arena-abandon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arena-abandon.c b/src/arena-abandon.c index eaa8c7c9..c40d3ce3 100644 --- a/src/arena-abandon.c +++ b/src/arena-abandon.c @@ -237,7 +237,7 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_at(mi_arena_t* arena, mi_s static mi_segment_t* mi_arena_segment_clear_abandoned_next_field(mi_arena_field_cursor_t* previous) { const size_t max_arena = mi_arena_get_count(); size_t field_idx = mi_bitmap_index_field(previous->bitmap_idx); - size_t bit_idx = mi_bitmap_index_bit_in_field(previous->bitmap_idx) + 1; + size_t bit_idx = mi_bitmap_index_bit_in_field(previous->bitmap_idx); // visit arena's (from the previous cursor) for (; previous->start < previous->end; previous->start++, field_idx = 0, bit_idx = 0) { // index wraps around @@ -266,11 +266,12 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_next_field(mi_arena_field_ // pre-check if the bit is set size_t mask = ((size_t)1 << bit_idx); if mi_unlikely((field & mask) == mask) { - previous->bitmap_idx = mi_bitmap_index_create(field_idx, bit_idx); - mi_segment_t* const segment = mi_arena_segment_clear_abandoned_at(arena, previous->subproc, previous->bitmap_idx); + mi_bitmap_index_t bitmap_idx = mi_bitmap_index_create(field_idx, bit_idx); + mi_segment_t* const segment = mi_arena_segment_clear_abandoned_at(arena, previous->subproc, bitmap_idx); if (segment != NULL) { //mi_assert_internal(arena->blocks_committed == NULL || _mi_bitmap_is_claimed(arena->blocks_committed, arena->field_count, 1, bitmap_idx)); if (has_lock) { mi_lock_release(&arena->abandoned_visit_lock); } + previous->bitmap_idx = mi_bitmap_index_create(field_idx, bit_idx + 1); // start at next one for the next iteration return segment; } } From d951b4dd234c165552521419ef2365a55fdcd454 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 23 Oct 2024 00:53:17 -0700 Subject: [PATCH 043/131] add missing mi_thread_done definition --- src/init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/init.c b/src/init.c index eaa7f5be..75458a1f 100644 --- a/src/init.c +++ b/src/init.c @@ -459,6 +459,10 @@ void mi_thread_init(void) mi_attr_noexcept //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id()); } +void mi_thread_done(void) mi_attr_noexcept { + _mi_thread_done(NULL); +} + void _mi_thread_done(mi_heap_t* heap) { // calling with NULL implies using the default heap From 925efaeac93f15408f001484e9ea4fa0fe3b8aec Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 23 Oct 2024 01:10:00 -0700 Subject: [PATCH 044/131] improve windows static library initialization to account for thread local destructors (issue #944) --- src/prim/windows/prim.c | 45 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index b0631b81..385354fc 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -641,26 +641,47 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #elif !defined(MI_WIN_USE_FLS) #define MI_PRIM_HAS_PROCESS_ATTACH 1 + static void NTAPI mi_win_main_attach(PVOID module, DWORD reason, LPVOID reserved) { + if (reason == DLL_PROCESS_ATTACH || reason == DLL_THREAD_ATTACH) { + mi_win_main(module, reason, reserved); + } + } + static void NTAPI mi_win_main_detach(PVOID module, DWORD reason, LPVOID reserved) { + if (reason == DLL_PROCESS_DETACH || reason == DLL_THREAD_DETACH) { + mi_win_main(module, reason, reserved); + } + } + // Set up TLS callbacks in a statically linked library by using special data sections. // See - // We may use ".CRT$XLY" instead of "B" -- see also issue #869. + // We use 2 entries to ensure we call attach events before constructors + // are called, and detach events after destructors are called. #if defined(__cplusplus) extern "C" { #endif #if defined(_WIN64) - #pragma comment(linker, "/INCLUDE:_tls_used") - #pragma comment(linker, "/INCLUDE:_mi_tls_callback") - #pragma const_seg(".CRT$XLB") - extern const PIMAGE_TLS_CALLBACK _mi_tls_callback[]; - const PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; - #pragma const_seg() + #pragma comment(linker, "/INCLUDE:_tls_used") + #pragma comment(linker, "/INCLUDE:_mi_tls_callback_pre") + #pragma comment(linker, "/INCLUDE:_mi_tls_callback_post") + #pragma const_seg(".CRT$XLB") + extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[]; + const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[] = { &mi_win_main_attach }; + #pragma const_seg() + #pragma const_seg(".CRT$XLY") + extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[]; + const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_win_main_detach }; + #pragma const_seg() #else - #pragma comment(linker, "/INCLUDE:__tls_used") - #pragma comment(linker, "/INCLUDE:__mi_tls_callback") - #pragma data_seg(".CRT$XLB") - PIMAGE_TLS_CALLBACK _mi_tls_callback[] = { &mi_win_main }; - #pragma data_seg() + #pragma comment(linker, "/INCLUDE:__tls_used") + #pragma comment(linker, "/INCLUDE:__mi_tls_callback_pre") + #pragma comment(linker, "/INCLUDE:__mi_tls_callback_post") + #pragma data_seg(".CRT$XLB") + PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[] = { &mi_win_main_attach }; + #pragma data_seg() + #pragma data_seg(".CRT$XLY") + PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_win_main_detach }; + #pragma data_seg() #endif #if defined(__cplusplus) From 2b0d039cf3cf6df8b5269814344626e10565eb04 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 23 Oct 2024 01:21:41 -0700 Subject: [PATCH 045/131] fix assertion check --- src/arena-abandon.c | 2 +- src/bitmap.h | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/arena-abandon.c b/src/arena-abandon.c index c40d3ce3..9c3356fc 100644 --- a/src/arena-abandon.c +++ b/src/arena-abandon.c @@ -271,7 +271,7 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_next_field(mi_arena_field_ if (segment != NULL) { //mi_assert_internal(arena->blocks_committed == NULL || _mi_bitmap_is_claimed(arena->blocks_committed, arena->field_count, 1, bitmap_idx)); if (has_lock) { mi_lock_release(&arena->abandoned_visit_lock); } - previous->bitmap_idx = mi_bitmap_index_create(field_idx, bit_idx + 1); // start at next one for the next iteration + previous->bitmap_idx = mi_bitmap_index_create_ex(field_idx, bit_idx + 1); // start at next one for the next iteration return segment; } } diff --git a/src/bitmap.h b/src/bitmap.h index a1e7686a..f8898935 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -35,9 +35,13 @@ typedef mi_bitmap_field_t* mi_bitmap_t; typedef size_t mi_bitmap_index_t; // Create a bit index. +static inline mi_bitmap_index_t mi_bitmap_index_create_ex(size_t idx, size_t bitidx) { + mi_assert_internal(bitidx <= MI_BITMAP_FIELD_BITS); + return (idx*MI_BITMAP_FIELD_BITS) + bitidx; +} static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) { mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS); - return (idx*MI_BITMAP_FIELD_BITS) + bitidx; + return mi_bitmap_index_create_ex(idx,bitidx); } // Get the field index from a bit index. From ee92b337b9e0f68f28a5eb374e5852c5e60baee3 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 24 Oct 2024 00:13:07 -0700 Subject: [PATCH 046/131] do not reclaim segments if free-ing from a thread with an already abandoned heap (issue #944) --- src/free.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/free.c b/src/free.c index f2e5f8e3..a85baa55 100644 --- a/src/free.c +++ b/src/free.c @@ -236,11 +236,12 @@ static void mi_decl_noinline mi_free_block_delayed_mt( mi_page_t* page, mi_block static void mi_decl_noinline mi_free_block_mt(mi_page_t* page, mi_segment_t* segment, mi_block_t* block) { // first see if the segment was abandoned and if we can reclaim it into our thread - if (mi_option_is_enabled(mi_option_abandoned_reclaim_on_free) && + if (_mi_option_get_fast(mi_option_abandoned_reclaim_on_free) != 0 && #if MI_HUGE_PAGE_ABANDON segment->page_kind != MI_PAGE_HUGE && #endif - mi_atomic_load_relaxed(&segment->thread_id) == 0) + mi_atomic_load_relaxed(&segment->thread_id) == 0 && // segment is abandoned? + mi_prim_get_default_heap() != (mi_heap_t*)&_mi_heap_empty) // and we did not already exit this thread (without this check, a fresh heap will be initalized (issue #944)) { // the segment is abandoned, try to reclaim it into our heap if (_mi_segment_attempt_reclaim(mi_heap_get_default(), segment)) { From 532904c85c23f777f29650eb48bd61f1115e2bab Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 24 Oct 2024 01:01:53 -0700 Subject: [PATCH 047/131] update mimalloc redirect to v1.2 to handle static destructors that free memory (issue #944) --- bin/mimalloc-redirect.dll | Bin 68096 -> 70144 bytes bin/mimalloc-redirect.lib | Bin 2874 -> 2874 bytes bin/mimalloc-redirect32.dll | Bin 41984 -> 47616 bytes bin/mimalloc-redirect32.lib | Bin 2928 -> 2928 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/mimalloc-redirect.dll b/bin/mimalloc-redirect.dll index a3a3591ff9b07edada16ad83ca1391963a126b2d..dec318976ca1b881bb5d165eef8d762533ed9b6f 100644 GIT binary patch delta 10362 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 A>i_@% delta 8766 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 delta 100 zcmdlbwo7b-1PjaM`aORp%dqTVQDo?=o}9&@Joz_^15;o1W?NQWMwavsuD>Sdu}wh8 lc5?6lWhdLRN=^1)7GiwV{%mH*$0`0RTALBn$um diff --git a/bin/mimalloc-redirect32.dll b/bin/mimalloc-redirect32.dll index 522723e5017b71b458afb4152bd6c7eec55e9e62..049c298189737481a44fbf45c1ed71ce86eb1d40 100644 GIT binary patch delta 8480 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 S8HbG{#!=%tMpSiUvi|{u)nG*c delta 6930 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 BA`Som delta 118 zcmew$_Caie84F7UkK4D&RxG<%6dC%eCu^~*PnKu3W9qBk9M5XV$Qe;K{r^!01_q|d z_AJtqx3Cq#l<5PNOpa%jnq0~r%ejdy_Sr+IDznLg9Q80&(v#P7a6naVzRWR~2>^ga BBijG~ From 3cba10e51060e2dd5399ea44b499d741ee58355b Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 27 Oct 2024 01:02:13 -0700 Subject: [PATCH 048/131] update mimalloc-redirect --- bin/mimalloc-redirect.dll | Bin 70144 -> 70656 bytes bin/mimalloc-redirect32.dll | Bin 47616 -> 47616 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/mimalloc-redirect.dll b/bin/mimalloc-redirect.dll index dec318976ca1b881bb5d165eef8d762533ed9b6f..ed001d64f7f70516577b3f3724b9a1279b73d51c 100644 GIT binary patch delta 6805 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 ZPiK8+EEo^=2K$5L_}SsKSfe52e*od*3grL* diff --git a/bin/mimalloc-redirect32.dll b/bin/mimalloc-redirect32.dll index 049c298189737481a44fbf45c1ed71ce86eb1d40..ec4ff1d521292a6fd1403d35c825e1cd1b060b3b 100644 GIT binary patch delta 5053 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 V)b|(;8Tt&z495+TFT$UR{s)yhnqmL| delta 4685 zcmZu!4^&&%d4KOAAvuU5*|L#?3<6{uJ4*c|J)wV3e{fJo9Fz!#5^DP-N{T(jAsM!X zLsK}GCp;rR$YkHFhbD9fH(o}A*N}=D{3osK!?B6uW^#jj+(pUM9JW1IoK9<%MO!tq z?>@;%cQ(%X?!CX?_uYHH@4Mf&@9wK^KVtqyuJ~d&&AMaOwfExLGz8x z(A+XWqi%ra1a3aV)5dDhK~Z({k{ZT;-U!VDbUhPUtq=YM8C+G$cX1LKvxv% zxTbuFvc3SGBMt32% zbl(PS@sKAQ_2f8j&hAwm)*b^-&?TwEQdH$nj+}rcN4)pA^#bG1bDnIO2Y9^R$Vsf_ z{Mj;p{-o#L2sn-CHTz81lmG`0QJHOmJ14!;5n)DgnaEW#Dy%0cOG$wEHpJ6wUKUZ| z8|a%~i-D8z%-7zhD)4IeZR)o_gOZ{{D7N-Ug|3H`AOA&&i8yGaSht;|5xZ`;2(x&p zazD2coQk6J>*^`!ezopt=;BtTi-PszuWZ;#l5G43)r}<9UROOVpJO?KOsO_9 zqz-vE?jUvXp^XD1&43<`i1WyOoLAPt`K6t!>oFON49Uv+H^5xMqLTB-e5>new7I6S zsyJzF#DNE72=zYjDAJUdD~bdW65o9tPW-x-)X#GsJ|oJUK^?L>I1&YN*L?$y;6&XPvI_mE?jcfw z{;_T^If~4hr;lnPLrNh4<^2F;9sKjlcqdWRvl1CvA^Ii8#N8PjoL}AvLHYQDf?gW+ zWFte_qCN(CVJRu+RYJ5;1>AsQ`9{4whn>om?PQ~#WzM@CxuS}C(-)-#v4^K&$CJgHHVp)K-ID``$gF`=!I#RP z6SO&do9b`?IL@;Ng3g!8Vo`63^QR!OG9UlFU*p6};fU=}1cDFRsQ(V+j`QBx&na8> z3rQ$$qmFu)s^)M~mhP{VJLDHOMUzqfreB4YOQj-MvDwAYY?q%A_vhowe6Jb zN%WSs)`2TZD5I~|KTDkHh>S-FXCw11^Dn8HTl6xz8BX|pA5s(`hgly7Wo;oj;hyk@!1pbT&J_{Zo! zxBU(Id3=2P2c*RCE4;M~Kd30IGfLX9$y;~OMcreP*qx%TemfI)Kl~^u31j8lFH!94 zk%~zebAAYT={Bm}(Mm;cqn;i06;qhTHTc|Z6x-2GRozCP?x=lW7Sr&k@)=Z4Td8wP zsD(Zw2`=Fc@M~UuTEB_%EulL7%MB+!!YtIsGL8=JiSPb%9L)VCIPg~=p?Ur98?+~2 z{MWz0wyL{tLoVS2BHvcRCHg*qs`Kkv^mD^lxeuHD3kn$Dq$+M9F|%Daff>auVUyq# z0HIhvNeaY>XEivBId8s$Ka)gznB9^Dp1>v1WyWr370g6c=NFH^AKC`B(iu!*^%KSE z2guS$bb#PJ0(aWxgXgn49y6UHHS!PfF8Fu9mV+y|Qv|U|IYnpiGEQyXhp5H;A{F^L znlVSndx)`^$!q8xGlM2A4oME14BkY`mOrg_!>^6qBkh;WkarV8?9ynZyC?p*)k*5R zM!<0Ph7b?FBwjhEJl4r41P0!>TxKpZlq32T!Cq|n<_+|ot=1%W!T7D>EXYFDdCw}i zSyOf1tAtRif-!76SX?7hyc(XIaFu-aO6u!3&@=Yxqgps1{J!%C-xs!r6|_MH$efHk<#F5I6;el^h%3<~SYef;X;>Z+>v z>S==mcxD)@aM6X|N0n^tjuBxcX(#_%Fa^u1^9k@zjkm==_Q7$`^EzP{*)=hXcC(Yz zsYO&^)siqi<7XC8ouiR@bTQuQ$dy;O310&n{`dDnTMv4o^{MLi|4-N6gWhX>gIf9- z+U;@I_ym&&Igb)*0DB;VT9?Aj_w~eo;#t2IefU%}@^vrQ!N>2P!4VVi$w~x3e1}2y zzySV07jNv=m&t$g!K(VV)|Qqx<}WGhbsv8b@7XgZBANK_o|z}h4BH6w_s{O44BJpk z_Z({f)_7dn6A($=vxK}02RL#@wGh=%(UcqCo`Zb=xWVU)!qMFB>#c|xuN`N}IDAPb1Q z#1_5s0SbVGKxTFk^0cu3D4+?H;9?h2l>16UANy z7}q$|z@%CWfG!!tN(OGgxX=ZIb^w8r0pTmIFaQ{rIW~|E19%Mtz^q~l2A4sSAUL`i z)N*oKu>z<7BDz>)i_s|oHG!}tHX+z{0}6r+f`q*g3udLS0XhdFY_b4@6i5yPZ<53& z$TuviWG;bYAec>KwlV}LTw>ffQONzgSO&yoi40@%6fG*B1tM_?efsi`0aYderAj7~ zB@@L85P1;kWypLxoEAD3omOZ7(IBlL31Bq>yBAOpWB`PKI0Bfh90fFq8Tgw7<{ia6 zpd`o&NCND#LKbB2!8#yKAlSB;F$`g(tqgCzL!G2eb2?y)4cTPcdTtTvt!yp(D1)K4#T+4 zs53smJj!%3dzjCed(2wXN9G?|jkdqFsqMGe4;(9wSDa6{_PY99w_RZGCI}X~?euQL ze;c1-dYN;kUz+}4s%idi^K|n}^FK5%H{WfRnm3sn%#WF0Fn`-@v2?p$bX{|O?1EZ7 zN@!s6MfxLJr#I*=dZ)fszf14aKdIlVe@>78&vk=-%6iVaXzj5DZNoN=U2AvSQ}(pI zU>|2E*m<_g(d`I1I~OB}3FunsHoAu<^dh}Re_5ZL@&$Ed^NWSwqjtFz6SbLO1|C*cyg zW?ZwbdDmrE0y{TJ5c5Z&@1^_b0Xj?%(@lDvp3$>$Cd2zM!8poHgt<28=z% zUZaXpGa9CeSz_)mDQ208nO-xEn5tdC45M3|mGmtkrF8 zv*xV@tH?HMo3|xwefE%jz&>aX+jVS!W*OGPvMkT8uvs?8=Gn83DaVW>;Oub*oxRRJ zr`n})X Date: Mon, 28 Oct 2024 02:06:58 +0000 Subject: [PATCH 049/131] fix build error on linux --- src/arena-abandon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arena-abandon.c b/src/arena-abandon.c index 9c3356fc..48e37794 100644 --- a/src/arena-abandon.c +++ b/src/arena-abandon.c @@ -148,7 +148,7 @@ static void mi_arena_segment_os_mark_abandoned(mi_segment_t* segment) { void _mi_arena_segment_mark_abandoned(mi_segment_t* segment) { mi_assert_internal(segment->used == segment->abandoned); - mi_atomic_store_release(&segment->thread_id, 0); // mark as abandoned for multi-thread free's + mi_atomic_store_release(&segment->thread_id, (uintptr_t)0); // mark as abandoned for multi-thread free's if mi_unlikely(segment->memid.memkind != MI_MEM_ARENA) { mi_arena_segment_os_mark_abandoned(segment); return; From f126b503822addadbdfcc82f940c5a086d3f75dc Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 27 Oct 2024 21:10:46 -0700 Subject: [PATCH 050/131] update comments, set constructor priority to 101 on macOS --- src/prim/osx/alloc-override-zone.c | 4 ++-- src/prim/prim.c | 10 +--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/prim/osx/alloc-override-zone.c b/src/prim/osx/alloc-override-zone.c index 1515b886..d3af170d 100644 --- a/src/prim/osx/alloc-override-zone.c +++ b/src/prim/osx/alloc-override-zone.c @@ -418,9 +418,9 @@ static inline malloc_zone_t* mi_get_default_zone(void) } #if defined(__clang__) -__attribute__((constructor(0))) +__attribute__((constructor(101))) // highest priority #else -__attribute__((constructor)) // seems not supported by g++-11 on the M1 +__attribute__((constructor)) // priority level is not supported by gcc #endif __attribute__((used)) static void _mi_macos_override_malloc(void) { diff --git a/src/prim/prim.c b/src/prim/prim.c index a4d3814f..2002853f 100644 --- a/src/prim/prim.c +++ b/src/prim/prim.c @@ -46,6 +46,7 @@ terms of the MIT license. A copy of the license can be found in the file } #elif defined(__cplusplus) // C++: use static initialization to detect process start/end + // This is not guaranteed to be first/last but the best we can generally do? struct mi_init_done_t { mi_init_done_t() { _mi_process_load(); @@ -55,15 +56,6 @@ terms of the MIT license. A copy of the license can be found in the file } }; static mi_init_done_t mi_init_done; - /* - extern mi_heap_t _mi_heap_main; - static bool mi_process_attach(void) { - _mi_process_load(); - atexit(&_mi_process_done); - return (_mi_heap_main.thread_id != 0); - } - static bool mi_initialized = mi_process_attach(); - */ #else #pragma message("define a way to call _mi_process_load/done on your platform") #endif From 5f3593333107066434e77177e0e79d56aba5189d Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 27 Oct 2024 21:39:07 -0700 Subject: [PATCH 051/131] add 0 byte to canary to prevent spurious read overflow to read the canary (issue #951, pr #953) --- include/mimalloc/internal.h | 10 ++++++++++ src/alloc.c | 2 +- src/free.c | 2 +- test/main-override-static.c | 13 ++++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 63a1e6f0..82e8c766 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -667,6 +667,16 @@ static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const return mi_rotl(x ^ keys[1], keys[0]) + keys[0]; } +static inline uint32_t mi_ptr_encode_canary(const void* null, const void* p, const uintptr_t* keys) { + const uint32_t x = (uint32_t)(mi_ptr_encode(null,p,keys)); + // make the lowest byte 0 to prevent spurious read overflows which could be a security issue (issue #951) + #ifdef MI_BIG_ENDIAN + return (x & 0x00FFFFFF); + #else + return (x & 0xFFFFFF00); + #endif +} + static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) { mi_track_mem_defined(block,sizeof(mi_block_t)); mi_block_t* next; diff --git a/src/alloc.c b/src/alloc.c index ca60c11a..119dfe75 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -99,7 +99,7 @@ extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_ mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta)); #endif mi_track_mem_defined(padding,sizeof(mi_padding_t)); // note: re-enable since mi_page_usable_block_size may set noaccess - padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys)); + padding->canary = mi_ptr_encode_canary(page,block,page->keys); padding->delta = (uint32_t)(delta); #if MI_PADDING_CHECK if (!mi_page_is_huge(page)) { diff --git a/src/free.c b/src/free.c index a85baa55..046a34e2 100644 --- a/src/free.c +++ b/src/free.c @@ -414,7 +414,7 @@ static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* bloc uintptr_t keys[2]; keys[0] = page->keys[0]; keys[1] = page->keys[1]; - bool ok = ((uint32_t)mi_ptr_encode(page,block,keys) == canary && *delta <= *bsize); + bool ok = (mi_ptr_encode_canary(page,block,keys) == canary && *delta <= *bsize); mi_track_mem_noaccess(padding,sizeof(mi_padding_t)); return ok; } diff --git a/test/main-override-static.c b/test/main-override-static.c index 1ac9bf87..4ad76d6a 100644 --- a/test/main-override-static.c +++ b/test/main-override-static.c @@ -19,6 +19,7 @@ static void test_reserved(void); static void negative_stat(void); static void alloc_huge(void); static void test_heap_walk(void); +static void test_canary_leak(void); // static void test_large_pages(void); @@ -31,7 +32,8 @@ int main() { // double_free2(); // corrupt_free(); // block_overflow1(); - block_overflow2(); + // block_overflow2(); + test_canary_leak(); // test_aslr(); // invalid_free(); // test_reserved(); @@ -226,6 +228,15 @@ static void test_heap_walk(void) { mi_heap_visit_blocks(heap, true, &test_visit, NULL); } +static void test_canary_leak(void) { + char* p = mi_mallocn_tp(char,23); + for(int i = 0; i < 23; i++) { + p[i] = '0'+i; + } + puts(p); + free(p); +} + // Experiment with huge OS pages #if 0 From b3828bba9e983e4a61cc82b1acc9965f7bb15add Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 27 Oct 2024 21:58:20 -0700 Subject: [PATCH 052/131] disable aligned hinting or SV39 mmu's, issue #939, and pr #949 --- CMakeLists.txt | 11 +++++++++++ src/os.c | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0aa59b0..4729e5b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,6 +319,17 @@ if(MI_WIN_USE_FLS) list(APPEND mi_defines MI_WIN_USE_FLS=1) endif() + + # Check /proc/cpuinfo for an SV39 MMU and define a constant if one is + # found. We will want to 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 "Disable aligned hints (SV39 MMU detected)" ) + list(APPEND mi_defines MI_NO_ALIGNED_HINT=1) + endif() + endif() + # On Haiku use `-DCMAKE_INSTALL_PREFIX` instead, issue #788 # if(CMAKE_SYSTEM_NAME MATCHES "Haiku") # SET(CMAKE_INSTALL_LIBDIR ~/config/non-packaged/lib) diff --git a/src/os.c b/src/os.c index 4babd8da..4b9d6125 100644 --- a/src/os.c +++ b/src/os.c @@ -92,8 +92,9 @@ static void* mi_align_down_ptr(void* p, size_t alignment) { -------------------------------------------------------------- */ // On 64-bit systems, we can do efficient aligned allocation by using -// the 2TiB to 30TiB area to allocate those. -#if (MI_INTPTR_SIZE >= 8) +// the 2TiB to 30TiB area to allocate those. We assume we have +// at least 48 bits of virtual address space on 64-bit systems (but see issue #939) +#if (MI_INTPTR_SIZE >= 8) && !defined(MI_NO_ALIGNED_HINT) static mi_decl_cache_align _Atomic(uintptr_t)aligned_base; // Return a MI_SEGMENT_SIZE aligned address that is probably available. @@ -239,7 +240,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL; size = _mi_align_up(size, _mi_os_page_size()); - // try first with a hint (this will be aligned directly on Win 10+ or BSD) + // 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); if (p == NULL) return NULL; From b5ae6fc555749e141d066987307d261f4d31a03a Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 29 Oct 2024 20:08:36 -0700 Subject: [PATCH 053/131] remove wrong assertion --- src/options.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/options.c b/src/options.c index 76d2cf82..cc39dd6d 100644 --- a/src/options.c +++ b/src/options.c @@ -196,7 +196,6 @@ mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long ma } mi_decl_nodiscard size_t mi_option_get_size(mi_option_t option) { - mi_assert_internal(mi_option_has_size_in_kib(option)); const long x = mi_option_get(option); size_t size = (x < 0 ? 0 : (size_t)x); if (mi_option_has_size_in_kib(option)) { From e2f4fe647e8aff4603a7d5119b8639fd1a47c8a6 Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 29 Oct 2024 22:23:21 -0700 Subject: [PATCH 054/131] update test file --- test/main-override.cpp | 91 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/test/main-override.cpp b/test/main-override.cpp index 50eb0267..9c47d3a1 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -11,7 +11,7 @@ #include #include -#include +//#include #include #ifdef _WIN32 @@ -38,15 +38,17 @@ static void strdup_test(); // issue #445 static void heap_thread_free_huge(); static void test_std_string(); // issue #697 static void test_thread_local(); // issue #944 - +// static void test_mixed0(); // issue #942 +static void test_mixed1(); // issue #942 static void test_stl_allocators(); int main() { // mi_stats_reset(); // ignore earlier allocations + test_mixed1(); //test_std_string(); - test_thread_local(); + //test_thread_local(); // heap_thread_free_huge(); /* heap_thread_free_large(); @@ -179,6 +181,89 @@ static void test_stl_allocators() { #endif } +#if 0 +#include +#include +#include +#include +#include +#include + +static void test_mixed0() { + std::vector> numbers(1024 * 1024 * 100); + std::vector threads(1); + + std::atomic index{}; + + auto start = std::chrono::system_clock::now(); + + for (auto& thread : threads) { + thread = std::thread{[&index, &numbers]() { + while (true) { + auto i = index.fetch_add(1, std::memory_order_relaxed); + if (i >= numbers.size()) return; + + numbers[i] = std::make_unique(i); + } + }}; + } + + for (auto& thread : threads) thread.join(); + + auto end = std::chrono::system_clock::now(); + + auto duration = + std::chrono::duration_cast(end - start); + std::cout << "Running on " << threads.size() << " threads took " << duration + << std::endl; +} +#endif + +void asd() { + void* p = malloc(128); + free(p); +} +static void test_mixed1() { + std::thread thread(asd); + thread.join(); +} + +#if 0 +// issue #691 +static char* cptr; + +static void* thread1_allocate() +{ + cptr = mi_calloc_tp(char,22085632); + return NULL; +} + +static void* thread2_free() +{ + assert(cptr); + mi_free(cptr); + cptr = NULL; + return NULL; +} + +static void test_large_migrate(void) { + auto t1 = std::thread(thread1_allocate); + t1.join(); + auto t2 = std::thread(thread2_free); + t2.join(); + /* + pthread_t thread1, thread2; + + pthread_create(&thread1, NULL, &thread1_allocate, NULL); + pthread_join(thread1, NULL); + + pthread_create(&thread2, NULL, &thread2_free, NULL); + pthread_join(thread2, NULL); + */ + return; +} +#endif + // issue 445 static void strdup_test() { #ifdef _MSC_VER From 54940a6a65d28c0d6499490899f6d420b3bb7e24 Mon Sep 17 00:00:00 2001 From: Daan Date: Tue, 5 Nov 2024 02:07:45 -0800 Subject: [PATCH 055/131] update mimalloc-redirect to potentially fix issue #957 --- bin/mimalloc-redirect.dll | Bin 70656 -> 70656 bytes bin/mimalloc-redirect32.dll | Bin 47616 -> 48128 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/mimalloc-redirect.dll b/bin/mimalloc-redirect.dll index ed001d64f7f70516577b3f3724b9a1279b73d51c..4702fec0175e66168151f1d995a6148a0e69a1eb 100644 GIT binary patch delta 5842 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 F{}q3uKPUqdCqg5 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 Y3ykCX66}xV2zINK<^5RoS|APm7ZjQ+JOBUy diff --git a/bin/mimalloc-redirect32.dll b/bin/mimalloc-redirect32.dll index ec4ff1d521292a6fd1403d35c825e1cd1b060b3b..17c0555027cd73317e893549e9831235c35d4d83 100644 GIT binary patch delta 3611 zcmY)x3s6&6_T6VNk;d{+zA6wtf+%W!k35J9vZj?Tu}Ma(R$J+4HAS>kq1sUj8d1VC z7ChQzMt6r*XUYt=rOj6AryZYwZwqaB6hQic(r`=tyxM$$sJEkp{3 zYZ3I3Y2;;yV$(|MbIz_K{B=c zH)?rF*c^lkg5Xvhf<7w9Q`5PWCQ@3|vk2x=`vtKGUW!L>hn~3>Mc|XzZ=fn9CdP

xmre(Uhf(;I)85s}9yaEqM|7)j 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 Date: Sat, 16 Nov 2024 09:38:26 +0000 Subject: [PATCH 056/131] _mi_memcpy/_mi_memzero: tighten criteria for intrinsics for windows. FSRM is better used for buffer <= 128 bytes and ERMS, if supported for larger chunks. --- include/mimalloc/internal.h | 5 +++-- src/init.c | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 82e8c766..71de25ad 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -911,8 +911,9 @@ static inline size_t mi_bsr(uintptr_t x) { #if !MI_TRACK_ENABLED && defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) #include extern bool _mi_cpu_has_fsrm; +extern bool _mi_cpu_has_erms; static inline void _mi_memcpy(void* dst, const void* src, size_t n) { - if (_mi_cpu_has_fsrm) { + if ((_mi_cpu_has_fsrm && n <= 128) || (_mi_cpu_has_erms && n > 128)) { __movsb((unsigned char*)dst, (const unsigned char*)src, n); } else { @@ -920,7 +921,7 @@ static inline void _mi_memcpy(void* dst, const void* src, size_t n) { } } static inline void _mi_memzero(void* dst, size_t n) { - if (_mi_cpu_has_fsrm) { + if ((_mi_cpu_has_fsrm && n <= 128) || (_mi_cpu_has_erms && n > 128)) { __stosb((unsigned char*)dst, 0, n); } else { diff --git a/src/init.c b/src/init.c index 75458a1f..e25abd98 100644 --- a/src/init.c +++ b/src/init.c @@ -543,12 +543,15 @@ void _mi_process_load(void) { #if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) #include mi_decl_cache_align bool _mi_cpu_has_fsrm = false; +mi_decl_cache_align bool _mi_cpu_has_erms = false; static void mi_detect_cpu_features(void) { - // FSRM for fast rep movsb support (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017)) + // FSRM for fast short rep movsb/stosb support (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017)) + // EMRS for fast enhanced rep movsb/stosb support int32_t cpu_info[4]; __cpuid(cpu_info, 7); _mi_cpu_has_fsrm = ((cpu_info[3] & (1 << 4)) != 0); // bit 4 of EDX : see + _mi_cpu_has_erms = ((cpu_info[2] & (1 << 9)) != 0); // bit 9 of ECX : see } #else static void mi_detect_cpu_features(void) { From b27d154ffda8e411a29d7267826ccf623f18cc41 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 16 Nov 2024 15:37:08 -0800 Subject: [PATCH 057/131] add virtual address bits and physical memory to the mem config --- CMakeLists.txt | 8 ++++---- include/mimalloc/prim.h | 2 ++ src/options.c | 25 ++++++++++++++++--------- src/os.c | 40 +++++++++++++++++++++++++++++----------- src/prim/unix/prim.c | 6 ++++++ src/prim/windows/prim.c | 12 ++++++++++++ 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4729e5b5..87837026 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,13 +320,13 @@ if(MI_WIN_USE_FLS) endif() - # Check /proc/cpuinfo for an SV39 MMU and define a constant if one is - # found. We will want to skip the aligned hinting in that case. Issue #939, #949 + # 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 "Disable aligned hints (SV39 MMU detected)" ) - list(APPEND mi_defines MI_NO_ALIGNED_HINT=1) + MESSAGE( STATUS "Set virtual address bits to 39 (SV39 MMU detected)" ) + list(APPEND mi_defines MI_DEFAULT_VIRTUAL_ADDRESS_BITS=39) endif() endif() diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index 640c966f..fb2a9434 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -25,6 +25,8 @@ typedef struct mi_os_mem_config_s { size_t page_size; // default to 4KiB size_t large_page_size; // 0 if not supported, usually 2MiB (4MiB on Windows) size_t alloc_granularity; // smallest allocation size (usually 4KiB, on Windows 64KiB) + size_t physical_memory; // physical memory size + size_t virtual_address_bits; // usually 48 or 56 bits on 64-bit systems. (used to determine secure randomization) bool has_overcommit; // can we reserve more memory than can be actually committed? bool has_partial_free; // can allocated blocks be freed partially? (true for mmap, false for VirtualAlloc) bool has_virtual_reserve; // supports virtual address space reservation? (if true we can reserve virtual address space without using commit or physical memory) diff --git a/src/options.c b/src/options.c index cc39dd6d..9ddf86ba 100644 --- a/src/options.c +++ b/src/options.c @@ -47,7 +47,9 @@ typedef struct mi_option_desc_s { #define MI_OPTION(opt) mi_option_##opt, #opt, NULL #define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy -// Some options can be set at build time for statically linked libraries (use `-DMI_EXTRA_CPPDEFS="opt1=val1;opt2=val2"`) +// Some options can be set at build time for statically linked libraries +// (use `-DMI_EXTRA_CPPDEFS="opt1=val1;opt2=val2"`) +// // This is useful if we cannot pass them as environment variables // (and setting them programmatically would be too late) @@ -99,14 +101,19 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(show_stats) }, { MI_DEFAULT_VERBOSE, UNINIT, MI_OPTION(verbose) }, - // the following options are experimental and not all combinations make sense. - { MI_DEFAULT_EAGER_COMMIT, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) - { MI_DEFAULT_ARENA_EAGER_COMMIT, UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) + // some of the following options are experimental and not all combinations are allowed. + { MI_DEFAULT_EAGER_COMMIT, + UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) + { MI_DEFAULT_ARENA_EAGER_COMMIT, + UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) { 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) }, // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit) - { MI_DEFAULT_ALLOW_LARGE_OS_PAGES, UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's - { MI_DEFAULT_RESERVE_HUGE_OS_PAGES, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages + { MI_DEFAULT_ALLOW_LARGE_OS_PAGES, + UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { MI_DEFAULT_RESERVE_HUGE_OS_PAGES, + UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages {-1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N - { MI_DEFAULT_RESERVE_OS_MEMORY, UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`) + { MI_DEFAULT_RESERVE_OS_MEMORY, + UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`) { 0, UNINIT, MI_OPTION(deprecated_segment_cache) }, // cache N segments per thread { 0, UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free { 0, UNINIT, MI_OPTION(abandoned_page_purge) }, // purge free page memory when a thread terminates @@ -124,11 +131,11 @@ static mi_option_desc_t options[_mi_option_last] = { 32, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output { 10, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. percentage of the abandoned segments to be reclaimed per try. { 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees! - { MI_DEFAULT_ARENA_RESERVE, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`) + { MI_DEFAULT_ARENA_RESERVE, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`) { 10, UNINIT, MI_OPTION(arena_purge_mult) }, // purge delay multiplier for arena's { 1, UNINIT, MI_OPTION_LEGACY(purge_extend_delay, decommit_extend_delay) }, { 1, UNINIT, MI_OPTION(abandoned_reclaim_on_free) },// reclaim an abandoned segment on a free - { MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's) + { MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's) { 400, UNINIT, MI_OPTION(retry_on_oom) }, // windows only: retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. #if defined(MI_VISIT_ABANDONED) { 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandonded segments; requires taking locks during reclaim. diff --git a/src/os.c b/src/os.c index 4b9d6125..827fc6cf 100644 --- a/src/os.c +++ b/src/os.c @@ -11,16 +11,33 @@ terms of the MIT license. A copy of the license can be found in the file /* ----------------------------------------------------------- - Initialization. + Initialization. ----------------------------------------------------------- */ +#ifndef MI_DEFAULT_VIRTUAL_ADDRESS_BITS +#if MI_INTPTR_SIZE < 8 +#define MI_DEFAULT_VIRTUAL_ADDRESS_BITS 32 +#else +#define MI_DEFAULT_VIRTUAL_ADDRESS_BITS 48 +#endif +#endif + +#ifndef MI_DEFAULT_PHYSICAL_MEMORY +#if MI_INTPTR_SIZE < 8 +#define MI_DEFAULT_PHYSICAL_MEMORY 4*MI_GiB +#else +#define MI_DEFAULT_PHYSICAL_MEMORY 32*MI_GiB +#endif +#endif static mi_os_mem_config_t mi_os_mem_config = { - 4096, // page size - 0, // large page size (usually 2MiB) - 4096, // allocation granularity - true, // has overcommit? (if true we use MAP_NORESERVE on mmap systems) - false, // can we partially free allocated blocks? (on mmap systems we can free anywhere in a mapped range, but on Windows we must free the entire span) - true // has virtual reserve? (if true we can reserve virtual address space without using commit or physical memory) + 4096, // page size + 0, // large page size (usually 2MiB) + 4096, // allocation granularity + MI_DEFAULT_PHYSICAL_MEMORY, + MI_DEFAULT_VIRTUAL_ADDRESS_BITS, + true, // has overcommit? (if true we use MAP_NORESERVE on mmap systems) + false, // can we partially free allocated blocks? (on mmap systems we can free anywhere in a mapped range, but on Windows we must free the entire span) + true // has virtual reserve? (if true we can reserve virtual address space without using commit or physical memory) }; bool _mi_os_has_overcommit(void) { @@ -91,9 +108,9 @@ static void* mi_align_down_ptr(void* p, size_t alignment) { aligned hinting -------------------------------------------------------------- */ -// On 64-bit systems, we can do efficient aligned allocation by using -// the 2TiB to 30TiB area to allocate those. We assume we have -// at least 48 bits of virtual address space on 64-bit systems (but see issue #939) +// On systems with enough virtual address bits, we can do efficient aligned allocation by using +// the 2TiB to 30TiB area to allocate those. If we have at least 46 bits of virtual address +// space (64TiB) we use this technique. (but see issue #939) #if (MI_INTPTR_SIZE >= 8) && !defined(MI_NO_ALIGNED_HINT) static mi_decl_cache_align _Atomic(uintptr_t)aligned_base; @@ -111,6 +128,7 @@ static mi_decl_cache_align _Atomic(uintptr_t)aligned_base; void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) { if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL; + if (mi_os_mem_config.virtual_address_bits < 46) return NULL; // < 64TiB virtual address space size = _mi_align_up(size, MI_SEGMENT_SIZE); if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096. #if (MI_SECURE>0) @@ -276,7 +294,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero, stats); if (p == NULL) return NULL; - // and selectively unmap parts around the over-allocated area. + // and selectively unmap parts around the over-allocated area. void* aligned_p = mi_align_up_ptr(p, alignment); size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p; size_t mid_size = _mi_align_up(size, _mi_os_page_size()); diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c index 0ea8189c..9075f9bd 100644 --- a/src/prim/unix/prim.c +++ b/src/prim/unix/prim.c @@ -139,6 +139,12 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config ) if (psize > 0) { config->page_size = (size_t)psize; config->alloc_granularity = (size_t)psize; + #if defined(_SC_PHYS_PAGES) + long pphys = sysconf(_SC_PHYS_PAGES); + if (pphys > 0 && (size_t)pphys < (SIZE_MAX/(size_t)psize)) { + config->physical_memory = (size_t)pphys * (size_t)psize; + } + #endif } config->large_page_size = 2*MI_MiB; // TODO: can we query the OS for this? config->has_overcommit = unix_detect_overcommit(); diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 385354fc..494fac78 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -118,6 +118,18 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config ) GetSystemInfo(&si); if (si.dwPageSize > 0) { config->page_size = si.dwPageSize; } if (si.dwAllocationGranularity > 0) { config->alloc_granularity = si.dwAllocationGranularity; } + // get virtual address bits + if ((uintptr_t)si.lpMaximumApplicationAddress > 0) { + const size_t vbits = MI_INTPTR_BITS - mi_clz((uintptr_t)si.lpMaximumApplicationAddress); + config->virtual_address_bits = vbits; + } + // get physical memory + ULONGLONG memInKiB = 0; + if (GetPhysicallyInstalledSystemMemory(&memInKiB)) { + if (memInKiB > 0 && memInKiB < (SIZE_MAX / MI_KiB)) { + config->physical_memory = memInKiB * MI_KiB; + } + } // get the VirtualAlloc2 function HINSTANCE hDll; hDll = LoadLibrary(TEXT("kernelbase.dll")); From 0e76fe3798ee975db1db4289f054a34175859c37 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 16 Nov 2024 16:57:37 -0800 Subject: [PATCH 058/131] add address hint to primitive allocation API --- ide/vs2022/mimalloc.vcxproj | 2 +- include/mimalloc/prim.h | 3 ++- src/arena.c | 2 +- src/os.c | 11 ++++++++--- src/prim/emscripten/prim.c | 4 ++-- src/prim/unix/prim.c | 4 ++-- src/prim/wasi/prim.c | 4 ++-- src/prim/windows/prim.c | 22 +++++++++++----------- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index 5efc8fd0..fd7d99d5 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -116,7 +116,7 @@ true Default ../../include - MI_DEBUG=4;%(PreprocessorDefinitions); + MI_DEBUG=1;%(PreprocessorDefinitions); CompileAsCpp false stdcpp20 diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index fb2a9434..f8bf948e 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -43,9 +43,10 @@ int _mi_prim_free(void* addr, size_t size ); // If `commit` is false, the virtual memory range only needs to be reserved (with no access) // which will later be committed explicitly using `_mi_prim_commit`. // `is_zero` is set to true if the memory was zero initialized (as on most OS's) +// The `hint_addr` address is either `NULL` or a preferred allocation address but can be ignored. // pre: !commit => !allow_large // try_alignment >= _mi_os_page_size() and a power of 2 -int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr); +int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr); // Commit memory. Returns error code or 0 on success. // For example, on Linux this would make the memory PROT_READ|PROT_WRITE. diff --git a/src/arena.c b/src/arena.c index 3bb8f502..8ca5aaf3 100644 --- a/src/arena.c +++ b/src/arena.c @@ -289,7 +289,7 @@ static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_no bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld ) { MI_UNUSED_RELEASE(alignment); - mi_assert_internal(alignment <= MI_SEGMENT_ALIGN); + mi_assert(alignment <= MI_SEGMENT_ALIGN); const size_t bcount = mi_block_count_of_size(size); const size_t arena_index = mi_arena_id_index(arena_id); mi_assert_internal(arena_index < mi_atomic_load_relaxed(&mi_arena_count)); diff --git a/src/os.c b/src/os.c index 827fc6cf..62c8c934 100644 --- a/src/os.c +++ b/src/os.c @@ -214,7 +214,8 @@ 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. -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) { +// 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) { mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); mi_assert_internal(is_zero != NULL); mi_assert_internal(is_large != NULL); @@ -223,9 +224,9 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning *is_zero = false; void* p = NULL; - int err = _mi_prim_alloc(size, try_alignment, commit, allow_large, is_large, is_zero, &p); + int err = _mi_prim_alloc(hint_addr, size, try_alignment, commit, allow_large, is_large, is_zero, &p); if (err != 0) { - _mi_warning_message("unable to allocate OS memory (error: %d (0x%x), size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, size, try_alignment, commit, allow_large); + _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); @@ -245,6 +246,10 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo 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); +} + // Primitive aligned allocation from the OS. // This function guarantees the allocated memory is aligned. diff --git a/src/prim/emscripten/prim.c b/src/prim/emscripten/prim.c index 944c0cb4..82147de7 100644 --- a/src/prim/emscripten/prim.c +++ b/src/prim/emscripten/prim.c @@ -71,8 +71,8 @@ int _mi_prim_free(void* addr, size_t size) { extern void* emmalloc_memalign(size_t alignment, size_t size); // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. -int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { - MI_UNUSED(try_alignment); MI_UNUSED(allow_large); MI_UNUSED(commit); +int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { + MI_UNUSED(try_alignment); MI_UNUSED(allow_large); MI_UNUSED(commit); MI_UNUSED(hint_addr); *is_large = false; // TODO: Track the highest address ever seen; first uses of it are zeroes. // That assumes no one else uses sbrk but us (they could go up, diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c index 9075f9bd..59421e52 100644 --- a/src/prim/unix/prim.c +++ b/src/prim/unix/prim.c @@ -357,14 +357,14 @@ static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protec } // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. -int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { +int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); mi_assert_internal(commit || !allow_large); mi_assert_internal(try_alignment > 0); *is_zero = true; int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE); - *addr = unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large); + *addr = unix_mmap(hint_addr, size, try_alignment, protect_flags, false, allow_large, is_large); return (*addr != NULL ? 0 : errno); } diff --git a/src/prim/wasi/prim.c b/src/prim/wasi/prim.c index 5d7a8132..e1e7de5e 100644 --- a/src/prim/wasi/prim.c +++ b/src/prim/wasi/prim.c @@ -119,8 +119,8 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) { } // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. -int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { - MI_UNUSED(allow_large); MI_UNUSED(commit); +int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { + MI_UNUSED(allow_large); MI_UNUSED(commit); MI_UNUSED(hint_addr); *is_large = false; *is_zero = false; *addr = mi_prim_mem_grow(size, try_alignment); diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 494fac78..1d3d6f41 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -123,7 +123,7 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config ) const size_t vbits = MI_INTPTR_BITS - mi_clz((uintptr_t)si.lpMaximumApplicationAddress); config->virtual_address_bits = vbits; } - // get physical memory + // get physical memory ULONGLONG memInKiB = 0; if (GetPhysicallyInstalledSystemMemory(&memInKiB)) { if (memInKiB > 0 && memInKiB < (SIZE_MAX / MI_KiB)) { @@ -203,7 +203,7 @@ static void* win_virtual_alloc_prim_once(void* addr, size_t size, size_t try_ali } #endif // on modern Windows try use VirtualAlloc2 for aligned allocation - if (try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) { + if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) { MI_MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 }; reqs.Alignment = try_alignment; MI_MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} }; @@ -291,14 +291,14 @@ static void* win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DW return p; } -int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { +int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); mi_assert_internal(commit || !allow_large); mi_assert_internal(try_alignment > 0); *is_zero = true; int flags = MEM_RESERVE; if (commit) { flags |= MEM_COMMIT; } - *addr = win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large); + *addr = win_virtual_alloc(hint_addr, size, try_alignment, flags, false, allow_large, is_large); return (*addr != NULL ? 0 : (int)GetLastError()); } @@ -629,8 +629,8 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { _mi_process_done(); } else if (reason==DLL_THREAD_DETACH && !_mi_is_redirected()) { - _mi_thread_done(NULL); - } + _mi_thread_done(NULL); + } } @@ -693,7 +693,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #pragma data_seg() #pragma data_seg(".CRT$XLY") PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_win_main_detach }; - #pragma data_seg() + #pragma data_seg() #endif #if defined(__cplusplus) @@ -707,13 +707,13 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { MI_UNUSED(heap); } -#else // deprecated: statically linked, use fiber api +#else // deprecated: statically linked, use fiber api #if defined(_MSC_VER) // on clang/gcc use the constructor attribute (in `src/prim/prim.c`) // MSVC: use data section magic for static libraries // See #define MI_PRIM_HAS_PROCESS_ATTACH 1 - + static int mi_process_attach(void) { mi_win_main(NULL,DLL_PROCESS_ATTACH,NULL); atexit(&_mi_process_done); @@ -766,9 +766,9 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { } #endif -// ---------------------------------------------------- +// ---------------------------------------------------- // Communicate with the redirection module on Windows -// ---------------------------------------------------- +// ---------------------------------------------------- #if defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) #define MI_PRIM_HAS_ALLOCATOR_INIT 1 From c57e9b855cc97ea53112ad755ce1d0290cef23af Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Sat, 16 Nov 2024 19:43:13 -0800 Subject: [PATCH 059/131] fix std malloc compile of the stress test --- test/test-stress.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/test-stress.c b/test/test-stress.c index 30ad0e77..9d40a6d9 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -47,10 +47,6 @@ static int ITER = 50; // N full iterations destructing and re-creating a #define STRESS // undefine for leak test -#ifndef NDEBUG -#define HEAP_WALK // walk the heap objects? -#endif - static bool allow_large_objects = true; // 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)`? @@ -66,6 +62,9 @@ static bool main_participates = false; // main thread participates as a #define custom_calloc(n,s) mi_calloc(n,s) #define custom_realloc(p,s) mi_realloc(p,s) #define custom_free(p) mi_free(p) +#ifndef NDEBUG +#define HEAP_WALK // walk the heap objects? +#endif #endif // transfer pointer between threads @@ -220,7 +219,7 @@ static void test_stress(void) { uintptr_t r = rand(); for (int n = 0; n < ITER; n++) { run_os_threads(THREADS, &stress); - #ifndef NDEBUG + #if !defined(NDEBUG) && !defined(USE_STD_MALLOC) // switch between arena and OS allocation for testing mi_option_set_enabled(mi_option_disallow_arena_alloc, (n%2)==1); #endif @@ -270,7 +269,7 @@ int main(int argc, char** argv) { #ifdef HEAP_WALK mi_option_enable(mi_option_visit_abandoned); #endif - #ifndef NDEBUG + #if !defined(NDEBUG) && !defined(USE_STD_MALLOC) mi_option_set(mi_option_arena_reserve, 32 * 1024 /* in kib = 32MiB */); #endif #ifndef USE_STD_MALLOC From 498c92e34894977b0e599fb276b1fcf9faebacb4 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 16 Nov 2024 21:15:50 -0800 Subject: [PATCH 060/131] update guarded implementation to use block tags --- ide/vs2022/mimalloc.vcxproj | 2 +- include/mimalloc.h | 2 + include/mimalloc/internal.h | 17 ++++-- include/mimalloc/types.h | 7 +++ src/alloc-aligned.c | 44 ++++++++++---- src/alloc.c | 116 +++++++++++++++++++----------------- src/free.c | 63 +++++++++++--------- src/heap.c | 2 +- src/options.c | 8 ++- src/page.c | 6 -- test/test-stress.c | 2 + 11 files changed, 161 insertions(+), 108 deletions(-) diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index fd7d99d5..5a614289 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -116,7 +116,7 @@ true Default ../../include - MI_DEBUG=1;%(PreprocessorDefinitions); + MI_DEBUG=4;MI_DEBUG_GUARDED=1;%(PreprocessorDefinitions); CompileAsCpp false stdcpp20 diff --git a/include/mimalloc.h b/include/mimalloc.h index e5133c96..940284b6 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -368,6 +368,8 @@ typedef enum mi_option_e { mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0) mi_option_debug_guarded_min, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) mi_option_debug_guarded_max, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) + mi_option_debug_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) + mi_option_debug_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 82e8c766..d73532e0 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -600,16 +600,25 @@ static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { page->flags.x.has_aligned = has_aligned; } +/* ------------------------------------------------------------------- + Guarded objects +------------------------------------------------------------------- */ #if MI_DEBUG_GUARDED -static inline bool mi_page_has_guarded(const mi_page_t* page) { - return page->flags.x.has_guarded; +static inline bool mi_block_ptr_is_guarded(const mi_block_t* block, const void* p) { + const ptrdiff_t offset = (uint8_t*)p - (uint8_t*)block; + return (offset >= (ptrdiff_t)(sizeof(mi_block_t)) && block->next == MI_BLOCK_TAG_GUARDED); } -static inline void mi_page_set_has_guarded(mi_page_t* page, bool has_guarded) { - page->flags.x.has_guarded = has_guarded; +static inline bool mi_heap_malloc_use_guarded(mi_heap_t* heap, size_t size) { + MI_UNUSED(heap); + return (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) + && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)); } + +mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; #endif + /* ------------------------------------------------------------------- Encoding/Decoding the free list next pointers diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index d1e6e5d8..e01754e2 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -232,6 +232,13 @@ typedef struct mi_block_s { mi_encoded_t next; } mi_block_t; +#if MI_DEBUG_GUARDED +// we always align guarded pointers in a block at an offset +// the block `next` field is then used as a tag to distinguish regular offset aligned blocks from guarded ones +#define MI_BLOCK_TAG_ALIGNED ((mi_encoded_t)(0)) +#define MI_BLOCK_TAG_GUARDED (~MI_BLOCK_TAG_ALIGNED) +#endif + // The delayed flags are used for efficient multi-threaded free-ing typedef enum mi_delayed_e { diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 248c932d..12815689 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -20,14 +20,24 @@ static bool mi_malloc_is_naturally_aligned( size_t size, size_t alignment ) { mi_assert_internal(_mi_is_power_of_two(alignment) && (alignment > 0)); if (alignment > size) return false; if (alignment <= MI_MAX_ALIGN_SIZE) return true; - #if MI_DEBUG_GUARDED - return false; - #else const size_t bsize = mi_good_size(size); - return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); - #endif + return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); } +#if MI_DEBUG_GUARDED +static mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, size_t size, size_t alignment, bool zero) mi_attr_noexcept { + // use over allocation for guarded blocksl + mi_assert_internal(alignment > 0 && alignment < MI_BLOCK_ALIGNMENT_MAX); + const size_t oversize = size + alignment - 1; + void* base = _mi_heap_malloc_guarded(heap, oversize, zero); + void* p = mi_align_up_ptr(base, alignment); + mi_track_align(base, p, (uint8_t*)p - (uint8_t*)base, size); + mi_assert_internal(mi_usable_size(p) >= size); + mi_assert_internal(_mi_is_aligned(p, alignment)); + return p; +} +#endif + // Fallback aligned allocation that over-allocates -- split out for better codegen static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept { @@ -68,6 +78,13 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t void* aligned_p = (void*)((uintptr_t)p + adjust); if (aligned_p != p) { mi_page_set_has_aligned(page, true); + #if MI_DEBUG_GUARDED + // set tag to aligned so mi_usable_size works with guard pages + if (adjust > sizeof(mi_block_t)) { + mi_block_t* const block = (mi_block_t*)p; + block->next = MI_BLOCK_TAG_ALIGNED; + } + #endif _mi_padding_shrink(page, (mi_block_t*)p, adjust + size); } // todo: expand padding if overallocated ? @@ -76,10 +93,8 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); mi_assert_internal(mi_usable_size(aligned_p)>=size); mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); - #if !MI_DEBUG_GUARDED mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_page(aligned_p), aligned_p)); - #endif - + // now zero the block if needed if (alignment > MI_BLOCK_ALIGNMENT_MAX) { // for the tracker, on huge aligned allocations only from the start of the large block is defined @@ -128,6 +143,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_generic(mi_heap_t* return mi_heap_malloc_zero_aligned_at_overalloc(heap,size,alignment,offset,zero); } + // Primitive aligned allocation static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept { @@ -138,8 +154,13 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t #endif return NULL; } + + #if MI_DEBUG_GUARDED + if (offset==0 && alignment < MI_BLOCK_ALIGNMENT_MAX && mi_heap_malloc_use_guarded(heap,size)) { + return mi_heap_malloc_guarded_aligned(heap, size, alignment, zero); + } + #endif - #if !MI_DEBUG_GUARDED // try first if there happens to be a small block available with just the right alignment if mi_likely(size <= MI_SMALL_SIZE_MAX && alignment <= size) { const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` @@ -160,8 +181,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t } } } - #endif - + // fallback to generic aligned allocation return mi_heap_malloc_zero_aligned_at_generic(heap, size, alignment, offset, zero); } @@ -313,3 +333,5 @@ mi_decl_nodiscard void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t mi_decl_nodiscard void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { return mi_heap_recalloc_aligned(mi_prim_get_default_heap(), p, newcount, size, alignment); } + + diff --git a/src/alloc.c b/src/alloc.c index 119dfe75..b4713ff1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -31,22 +31,22 @@ terms of the MIT license. A copy of the license can be found in the file extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_t size, bool zero) mi_attr_noexcept { mi_assert_internal(page->block_size == 0 /* empty heap */ || mi_page_block_size(page) >= size); - + // check the free list mi_block_t* const block = page->free; if mi_unlikely(block == NULL) { return _mi_malloc_generic(heap, size, zero, 0); } mi_assert_internal(block != NULL && _mi_ptr_page(block) == page); - + // pop from the free list page->free = mi_block_next(page, block); page->used++; mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); mi_assert_internal(page->block_size < MI_MAX_ALIGN_SIZE || _mi_is_aligned(block, MI_MAX_ALIGN_SIZE)); - + #if MI_DEBUG>3 - if (page->free_is_zero && size > sizeof(*block)) { + if (page->free_is_zero && size > sizeof(*block)) { mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block))); } #endif @@ -122,9 +122,7 @@ extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t siz } #if MI_DEBUG_GUARDED -static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; -static inline bool mi_heap_malloc_use_guarded(size_t size, bool has_huge_alignment); -static inline bool mi_heap_malloc_small_use_guarded(size_t size); +mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; #endif static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { @@ -138,7 +136,9 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, if (size == 0) { size = sizeof(void*); } #endif #if MI_DEBUG_GUARDED - if (mi_heap_malloc_small_use_guarded(size)) { return mi_heap_malloc_guarded(heap, size, zero); } + if (mi_heap_malloc_use_guarded(heap,size)) { + return _mi_heap_malloc_guarded(heap, size, zero); + } #endif // get page in constant time, and allocate from it @@ -171,13 +171,15 @@ mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc_small(size_t si // The main allocation function extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept { - // fast path for small objects + // fast path for small objects if mi_likely(size <= MI_SMALL_SIZE_MAX) { mi_assert_internal(huge_alignment == 0); return mi_heap_malloc_small_zero(heap, size, zero); } #if MI_DEBUG_GUARDED - else if (mi_heap_malloc_use_guarded(size,huge_alignment>0)) { return mi_heap_malloc_guarded(heap, size, zero); } + else if (huge_alignment==0 && mi_heap_malloc_use_guarded(heap,size)) { + return _mi_heap_malloc_guarded(heap, size, zero); + } #endif else { // regular allocation @@ -185,7 +187,7 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE, zero, huge_alignment); // note: size can overflow but it is detected in malloc_generic mi_track_malloc(p,size,zero); - + #if MI_STAT>1 if (p != NULL) { if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } @@ -602,61 +604,65 @@ mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } #if MI_DEBUG_GUARDED -static inline bool mi_heap_malloc_small_use_guarded(size_t size) { - return (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) - && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)); +// We always allocate a guarded allocation at an offset (`mi_page_has_aligned` will be true). +// We then set the first word of the block to `0` for regular offset aligned allocations (in `alloc-aligned.c`) +// and the first word to `~0` for guarded allocations to have a correct `mi_usable_size` + +static void* mi_block_ptr_set_guarded(mi_block_t* block, size_t obj_size) { + // TODO: we can still make padding work by moving it out of the guard page area + mi_page_t* const page = _mi_ptr_page(block); + mi_page_set_has_aligned(page, true); + block->next = MI_BLOCK_TAG_GUARDED; + + // set guard page at the end of the block + mi_segment_t* const segment = _mi_page_segment(page); + const size_t block_size = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` + const size_t os_page_size = _mi_os_page_size(); + mi_assert_internal(block_size >= obj_size + os_page_size + sizeof(mi_block_t)); + if (block_size < obj_size + os_page_size + sizeof(mi_block_t)) { + // should never happen + mi_free(block); + return NULL; + } + uint8_t* guard_page = (uint8_t*)block + block_size - os_page_size; + mi_assert_internal(_mi_is_aligned(guard_page, os_page_size)); + if (segment->allow_decommit && _mi_is_aligned(guard_page, os_page_size)) { + _mi_os_protect(guard_page, os_page_size); + } + else { + _mi_warning_message("unable to set a guard page behind an object due to pinned memory (large OS pages?) (object %p of size %zu)\n", block, block_size); + } + + // align pointer just in front of the guard page + size_t offset = block_size - os_page_size - obj_size; + mi_assert_internal(offset > sizeof(mi_block_t)); + if (offset > MI_BLOCK_ALIGNMENT_MAX) { + // give up to place it right in front of the guard page if the offset is too large for unalignment + offset = MI_BLOCK_ALIGNMENT_MAX; + } + void* p = (uint8_t*)block + offset; + mi_track_align(block, p, offset, obj_size); + return p; } -static inline bool mi_heap_malloc_use_guarded(size_t size, bool has_huge_alignment) { - return (!has_huge_alignment // guarded pages do not work with huge aligments at the moment - && _mi_option_get_fast(mi_option_debug_guarded_max) > 0 // guarded must be enabled - && (mi_heap_malloc_small_use_guarded(size) - || ((mi_good_size(size) & (_mi_os_page_size() - 1)) == 0)) // page-size multiple are always guarded so we can have a correct `mi_usable_size`. - ); -} - -static mi_decl_restrict void* mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept +mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { #if defined(MI_PADDING_SIZE) mi_assert(MI_PADDING_SIZE==0); #endif // allocate multiple of page size ending in a guard page - const size_t obj_size = _mi_align_up(size, MI_MAX_ALIGN_SIZE); // ensure minimal alignment requirement + // ensure minimal alignment requirement? const size_t os_page_size = _mi_os_page_size(); - const size_t req_size = _mi_align_up(obj_size + os_page_size, os_page_size); - void* const block = _mi_malloc_generic(heap, req_size, zero, 0 /* huge_alignment */); + const size_t obj_size = (mi_option_is_enabled(mi_option_debug_guarded_precise) ? size : _mi_align_up(size, MI_MAX_ALIGN_SIZE)); + const size_t bsize = _mi_align_up(_mi_align_up(obj_size, MI_MAX_ALIGN_SIZE) + sizeof(mi_block_t), MI_MAX_ALIGN_SIZE); + const size_t req_size = _mi_align_up(bsize + os_page_size, os_page_size); + mi_block_t* const block = (mi_block_t*)_mi_malloc_generic(heap, req_size, zero, 0 /* huge_alignment */); if (block==NULL) return NULL; - mi_page_t* page = _mi_ptr_page(block); - mi_segment_t* segment = _mi_page_segment(page); - - const size_t block_size = mi_page_block_size(page); // must use `block_size` to match `mi_free_local` - void* const guard_page = (uint8_t*)block + (block_size - os_page_size); - mi_assert_internal(_mi_is_aligned(guard_page, os_page_size)); - - // place block in front of the guard page - size_t offset = block_size - os_page_size - obj_size; - if (offset > MI_BLOCK_ALIGNMENT_MAX) { - // give up to place it right in front of the guard page if the offset is too large for unalignment - offset = MI_BLOCK_ALIGNMENT_MAX; - } - void* const p = (uint8_t*)block + offset; - mi_assert_internal(p>=block); - - // set page flags - if (offset > 0) { - mi_page_set_has_aligned(page, true); - } - - // set guard page - if (segment->allow_decommit) { - mi_page_set_has_guarded(page, true); - _mi_os_protect(guard_page, os_page_size); - } - else { - _mi_warning_message("unable to set a guard page behind an object due to pinned memory (large OS pages?) (object %p of size %zu)\n", p, size); - } + void* const p = mi_block_ptr_set_guarded(block, obj_size); // stats + const size_t usize = mi_usable_size(p); + mi_assert_internal(usize >= size); mi_track_malloc(p, size, zero); #if MI_STAT>1 if (p != NULL) { diff --git a/src/free.c b/src/free.c index 046a34e2..73c05c87 100644 --- a/src/free.c +++ b/src/free.c @@ -70,20 +70,29 @@ mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) { } // forward declaration for a MI_DEBUG_GUARDED build -static void mi_block_unguard(mi_page_t* page, mi_block_t* block); +#if MI_DEBUG_GUARDED +static void mi_block_unguard_prim(mi_page_t* page, mi_block_t* block, void* p); // forward declaration +static inline void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { + if (mi_block_ptr_is_guarded(block, p)) { mi_block_unguard_prim(page, block, p); } +} +#else +static inline void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { + MI_UNUSED(page); MI_UNUSED(block); MI_UNUSED(p); +} +#endif // free a local pointer (page parameter comes first for better codegen) static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { MI_UNUSED(segment); mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(page, p) : (mi_block_t*)p); - mi_block_unguard(page,block); + mi_block_unguard(page, block, p); mi_free_block_local(page, block, true /* track stats */, true /* check for a full page */); } // free a pointer owned by another thread (page parameter comes first for better codegen) static void mi_decl_noinline mi_free_generic_mt(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { mi_block_t* const block = _mi_page_ptr_unalign(page, p); // don't check `has_aligned` flag to avoid a race (issue #865) - mi_block_unguard(page, block); + mi_block_unguard(page, block, p); mi_free_block_mt(page, segment, block); } @@ -297,20 +306,19 @@ static size_t mi_decl_noinline mi_page_usable_aligned_size_of(const mi_page_t* p const size_t size = mi_page_usable_size_of(page, block); const ptrdiff_t adjust = (uint8_t*)p - (uint8_t*)block; mi_assert_internal(adjust >= 0 && (size_t)adjust <= size); - return (size - adjust); + const size_t aligned_size = (size - adjust); + #if MI_DEBUG_GUARDED + if (mi_block_ptr_is_guarded(block, p)) { + return aligned_size - _mi_os_page_size(); + } + #endif + return aligned_size; } static inline size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept { const mi_segment_t* const segment = mi_checked_ptr_segment(p, msg); if mi_unlikely(segment==NULL) return 0; - const mi_page_t* const page = _mi_segment_page_of(segment, p); - #if MI_DEBUG_GUARDED - if (mi_page_has_guarded(page)) { - const size_t bsize = mi_page_usable_aligned_size_of(page, p); - mi_assert_internal(bsize > _mi_os_page_size()); - return (bsize > _mi_os_page_size() ? bsize - _mi_os_page_size() : bsize); - } else - #endif + const mi_page_t* const page = _mi_segment_page_of(segment, p); if mi_likely(!mi_page_has_aligned(page)) { const mi_block_t* block = (const mi_block_t*)p; return mi_page_usable_size_of(page, block); @@ -534,22 +542,19 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { // Remove guard page when building with MI_DEBUG_GUARDED -#if !MI_DEBUG_GUARDED -static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { - MI_UNUSED(page); - MI_UNUSED(block); - // do nothing -} -#else -static void mi_block_unguard(mi_page_t* page, mi_block_t* block) { - if (mi_page_has_guarded(page)) { - const size_t bsize = mi_page_block_size(page); - const size_t psize = _mi_os_page_size(); - mi_assert_internal(bsize > psize); - mi_assert_internal(_mi_page_segment(page)->allow_decommit); - void* gpage = (uint8_t*)block + (bsize - psize); - mi_assert_internal(_mi_is_aligned(gpage, psize)); - _mi_os_unprotect(gpage, psize); - } +#if MI_DEBUG_GUARDED +static void mi_block_unguard_prim(mi_page_t* page, mi_block_t* block, void* p) { + mi_assert_internal(mi_block_ptr_is_guarded(block, p)); + mi_assert_internal(mi_page_has_aligned(page)); + mi_assert_internal((uint8_t*)p - (uint8_t*)block >= sizeof(mi_block_t)); + mi_assert_internal(block->next == MI_BLOCK_TAG_GUARDED); + + const size_t bsize = mi_page_block_size(page); + const size_t psize = _mi_os_page_size(); + mi_assert_internal(bsize > psize); + mi_assert_internal(_mi_page_segment(page)->allow_decommit); + void* gpage = (uint8_t*)block + bsize - psize; + mi_assert_internal(_mi_is_aligned(gpage, psize)); + _mi_os_unprotect(gpage, psize); } #endif diff --git a/src/heap.c b/src/heap.c index 206d3a36..eb0ab991 100644 --- a/src/heap.c +++ b/src/heap.c @@ -370,7 +370,7 @@ void mi_heap_destroy(mi_heap_t* heap) { mi_assert_expensive(mi_heap_is_valid(heap)); if (heap==NULL || !mi_heap_is_initialized(heap)) return; #if MI_DEBUG_GUARDED - _mi_warning_message("'mi_heap_destroy' called but ignored as MI_DEBUG_GUARDED is enabled (heap at %p)\n", heap); + // _mi_warning_message("'mi_heap_destroy' called but MI_DEBUG_GUARDED is enabled -- using `mi_heap_delete` instead (heap at %p)\n", heap); mi_heap_delete(heap); return; #else diff --git a/src/options.c b/src/options.c index 9ddf86ba..3d9017f1 100644 --- a/src/options.c +++ b/src/options.c @@ -143,7 +143,13 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(visit_abandoned) }, #endif { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects - { 0, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects + { MI_GiB, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects + { 0, UNINIT, MI_OPTION(debug_guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) +#if MI_DEBUG_GUARDED + { 1000,UNINIT, MI_OPTION(debug_guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) +#else + { 0, UNINIT, MI_OPTION(debug_guarded_sample_rate)}, +#endif }; static void mi_option_init(mi_option_desc_t* desc); diff --git a/src/page.c b/src/page.c index 49f9ed52..d6dcfb15 100644 --- a/src/page.c +++ b/src/page.c @@ -414,9 +414,6 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { // no more aligned blocks in here mi_page_set_has_aligned(page, false); - #if MI_DEBUG_GUARDED - mi_page_set_has_guarded(page, false); - #endif // remove from the page list // (no need to do _mi_heap_delayed_free first as all blocks are already free) @@ -443,9 +440,6 @@ void _mi_page_retire(mi_page_t* page) mi_attr_noexcept { mi_assert_internal(mi_page_all_free(page)); mi_page_set_has_aligned(page, false); - #if MI_DEBUG_GUARDED - mi_page_set_has_guarded(page, false); - #endif // don't retire too often.. // (or we end up retiring and re-allocating most of the time) diff --git a/test/test-stress.c b/test/test-stress.c index 30ad0e77..b062f2ce 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -22,6 +22,8 @@ terms of the MIT license. #include #include +#define MI_DEBUG_GUARDED + // > mimalloc-test-stress [THREADS] [SCALE] [ITER] // // argument defaults From 8b6017d976ed98b0ec71bf34f0c8089b00b52e67 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 16 Nov 2024 22:42:32 -0800 Subject: [PATCH 061/131] rename mi_debug_guarded_ to mi_guarded_ --- CMakeLists.txt | 8 +++--- azure-pipelines.yml | 6 ++--- ide/vs2022/mimalloc.vcxproj | 2 +- include/mimalloc.h | 18 ++++++------- include/mimalloc/internal.h | 6 ++--- include/mimalloc/types.h | 8 +++--- src/alloc-aligned.c | 26 +++++++++---------- src/alloc.c | 20 +++++++------- src/free.c | 48 +++++++++++++++++----------------- src/heap.c | 4 +-- src/options.c | 52 ++++++++++++++++++------------------- src/segment.c | 2 +- test/test-api-fill.c | 2 +- test/test-stress.c | 12 ++++----- 14 files changed, 106 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87837026..5fc1808e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ option(MI_BUILD_OBJECT "Build object library" ON) option(MI_BUILD_TESTS "Build test executables" ON) option(MI_DEBUG_TSAN "Build with thread sanitizer (needs clang)" OFF) option(MI_DEBUG_UBSAN "Build with undefined-behavior sanitizer (needs clang++)" OFF) -option(MI_DEBUG_GUARDED "Build with guard pages behind certain object allocations (implies MI_NO_PADDING=ON)" OFF) +option(MI_GUARDED "Build with guard pages behind certain object allocations (implies MI_NO_PADDING=ON)" OFF) option(MI_SKIP_COLLECT_ON_EXIT "Skip collecting memory on program exit" OFF) option(MI_NO_PADDING "Force no use of padding even in DEBUG mode etc." OFF) option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF) @@ -207,9 +207,9 @@ if(MI_TRACK_ETW) endif() endif() -if(MI_DEBUG_GUARDED) - message(STATUS "Compile guard pages behind certain object allocations (MI_DEBUG_GUARDED=ON)") - list(APPEND mi_defines MI_DEBUG_GUARDED=1) +if(MI_GUARDED) + message(STATUS "Compile guard pages behind certain object allocations (MI_GUARDED=ON)") + list(APPEND mi_defines MI_GUARDED=1) if(NOT MI_NO_PADDING) message(STATUS " Disabling padding due to guard pages (MI_NO_PADDING=ON)") set(MI_NO_PADDING ON) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4455dfeb..e4361f98 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -117,8 +117,8 @@ jobs: CC: clang CXX: clang BuildType: debug-guarded-clang - cmakeExtraArgs: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMI_DEBUG_FULL=ON -DMI_DEBUG_GUARDED=ON - + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMI_DEBUG_FULL=ON -DMI_GUARDED=ON + steps: - task: CMake@1 inputs: @@ -129,7 +129,7 @@ jobs: - script: ctest --verbose --timeout 180 workingDirectory: $(BuildType) displayName: CTest - env: + env: MIMALLOC_DEBUG_GUARDED_MAX: 1024 # - upload: $(Build.SourcesDirectory)/$(BuildType) # artifact: mimalloc-ubuntu-$(BuildType) diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index 5a614289..160f1436 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -116,7 +116,7 @@ true Default ../../include - MI_DEBUG=4;MI_DEBUG_GUARDED=1;%(PreprocessorDefinitions); + MI_DEBUG=4;MI_GUARDED=1;%(PreprocessorDefinitions); CompileAsCpp false stdcpp20 diff --git a/include/mimalloc.h b/include/mimalloc.h index 940284b6..4ecb8be0 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -290,7 +290,7 @@ mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t a #endif -// Experimental: allow sub-processes whose memory segments stay separated (and no reclamation between them) +// Experimental: allow sub-processes whose memory segments stay separated (and no reclamation between them) // Used for example for separate interpreter's in one process. typedef void* mi_subproc_id_t; mi_decl_export mi_subproc_id_t mi_subproc_main(void); @@ -349,7 +349,7 @@ typedef enum mi_option_e { mi_option_deprecated_segment_cache, mi_option_deprecated_page_reset, mi_option_abandoned_page_purge, // immediately purge delayed purges on thread termination - mi_option_deprecated_segment_reset, + mi_option_deprecated_segment_reset, mi_option_eager_commit_delay, // the first N segments per thread are not eagerly committed (but per page in the segment on demand) mi_option_purge_delay, // memory purging is delayed by N milli seconds; use 0 for immediate purging or -1 for no purging at all. (=10) mi_option_use_numa_nodes, // 0 = use all available numa nodes, otherwise use at most N nodes. @@ -366,10 +366,10 @@ typedef enum mi_option_e { mi_option_disallow_arena_alloc, // 1 = do not use arena's for allocation (except if using specific arena id's) mi_option_retry_on_oom, // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows) mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0) - mi_option_debug_guarded_min, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects (=0) - mi_option_debug_guarded_max, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects (=0) - mi_option_debug_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) - mi_option_debug_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000) + mi_option_guarded_min, // only used when building with MI_GUARDED: minimal rounded object size for guarded objects (=0) + mi_option_guarded_max, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects (=0) + mi_option_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) + mi_option_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, @@ -539,7 +539,7 @@ template struct _mi_heap_stl_allocator_common : publi protected: std::shared_ptr heap; template friend struct _mi_heap_stl_allocator_common; - + _mi_heap_stl_allocator_common() { mi_heap_t* hp = mi_heap_new(); this->heap.reset(hp, (_mi_destroy ? &heap_destroy : &heap_delete)); /* calls heap_delete/destroy when the refcount drops to zero */ @@ -556,7 +556,7 @@ private: template struct mi_heap_stl_allocator : public _mi_heap_stl_allocator_common { using typename _mi_heap_stl_allocator_common::size_type; mi_heap_stl_allocator() : _mi_heap_stl_allocator_common() { } // creates fresh heap that is deleted when the destructor is called - mi_heap_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap + mi_heap_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap template mi_heap_stl_allocator(const mi_heap_stl_allocator& x) mi_attr_noexcept : _mi_heap_stl_allocator_common(x) { } mi_heap_stl_allocator select_on_container_copy_construction() const { return *this; } @@ -573,7 +573,7 @@ template bool operator!=(const mi_heap_stl_allocator& x, template struct mi_heap_destroy_stl_allocator : public _mi_heap_stl_allocator_common { using typename _mi_heap_stl_allocator_common::size_type; mi_heap_destroy_stl_allocator() : _mi_heap_stl_allocator_common() { } // creates fresh heap that is destroyed when the destructor is called - mi_heap_destroy_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap + mi_heap_destroy_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap template mi_heap_destroy_stl_allocator(const mi_heap_destroy_stl_allocator& x) mi_attr_noexcept : _mi_heap_stl_allocator_common(x) { } mi_heap_destroy_stl_allocator select_on_container_copy_construction() const { return *this; } diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index d73532e0..ae3a3358 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -603,7 +603,7 @@ static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { /* ------------------------------------------------------------------- Guarded objects ------------------------------------------------------------------- */ -#if MI_DEBUG_GUARDED +#if MI_GUARDED static inline bool mi_block_ptr_is_guarded(const mi_block_t* block, const void* p) { const ptrdiff_t offset = (uint8_t*)p - (uint8_t*)block; return (offset >= (ptrdiff_t)(sizeof(mi_block_t)) && block->next == MI_BLOCK_TAG_GUARDED); @@ -611,8 +611,8 @@ static inline bool mi_block_ptr_is_guarded(const mi_block_t* block, const void* static inline bool mi_heap_malloc_use_guarded(mi_heap_t* heap, size_t size) { MI_UNUSED(heap); - return (size <= (size_t)_mi_option_get_fast(mi_option_debug_guarded_max) - && size >= (size_t)_mi_option_get_fast(mi_option_debug_guarded_min)); + return (size <= (size_t)_mi_option_get_fast(mi_option_guarded_max) + && size >= (size_t)_mi_option_get_fast(mi_option_guarded_min)); } mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index e01754e2..29ba8564 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -74,8 +74,8 @@ terms of the MIT license. A copy of the license can be found in the file // Use guard pages behind objects of a certain size (set by the MIMALLOC_DEBUG_GUARDED_MIN/MAX options) // Padding should be disabled when using guard pages -// #define MI_DEBUG_GUARDED 1 -#if defined(MI_DEBUG_GUARDED) +// #define MI_GUARDED 1 +#if defined(MI_GUARDED) #define MI_PADDING 0 #endif @@ -232,7 +232,7 @@ typedef struct mi_block_s { mi_encoded_t next; } mi_block_t; -#if MI_DEBUG_GUARDED +#if MI_GUARDED // we always align guarded pointers in a block at an offset // the block `next` field is then used as a tag to distinguish regular offset aligned blocks from guarded ones #define MI_BLOCK_TAG_ALIGNED ((mi_encoded_t)(0)) @@ -257,7 +257,6 @@ typedef union mi_page_flags_s { struct { uint8_t in_full : 1; uint8_t has_aligned : 1; - uint8_t has_guarded : 1; // only used with MI_DEBUG_GUARDED } x; } mi_page_flags_t; #else @@ -267,7 +266,6 @@ typedef union mi_page_flags_s { struct { uint8_t in_full; uint8_t has_aligned; - uint8_t has_guarded; // only used with MI_DEBUG_GUARDED } x; } mi_page_flags_t; #endif diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 12815689..86b13dea 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -21,10 +21,10 @@ static bool mi_malloc_is_naturally_aligned( size_t size, size_t alignment ) { if (alignment > size) return false; if (alignment <= MI_MAX_ALIGN_SIZE) return true; const size_t bsize = mi_good_size(size); - return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); + return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); } -#if MI_DEBUG_GUARDED +#if MI_GUARDED static mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, size_t size, size_t alignment, bool zero) mi_attr_noexcept { // use over allocation for guarded blocksl mi_assert_internal(alignment > 0 && alignment < MI_BLOCK_ALIGNMENT_MAX); @@ -69,7 +69,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t if (p == NULL) return NULL; } mi_page_t* page = _mi_ptr_page(p); - + // .. and align within the allocation const uintptr_t align_mask = alignment - 1; // for any x, `(x & align_mask) == (x % alignment)` const uintptr_t poffset = ((uintptr_t)p + offset) & align_mask; @@ -78,7 +78,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t void* aligned_p = (void*)((uintptr_t)p + adjust); if (aligned_p != p) { mi_page_set_has_aligned(page, true); - #if MI_DEBUG_GUARDED + #if MI_GUARDED // set tag to aligned so mi_usable_size works with guard pages if (adjust > sizeof(mi_block_t)) { mi_block_t* const block = (mi_block_t*)p; @@ -94,7 +94,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t mi_assert_internal(mi_usable_size(aligned_p)>=size); mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_page(aligned_p), aligned_p)); - + // now zero the block if needed if (alignment > MI_BLOCK_ALIGNMENT_MAX) { // for the tracker, on huge aligned allocations only from the start of the large block is defined @@ -115,27 +115,27 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_generic(mi_heap_t* { mi_assert_internal(alignment != 0 && _mi_is_power_of_two(alignment)); // we don't allocate more than MI_MAX_ALLOC_SIZE (see ) - if mi_unlikely(size > (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE)) { + if mi_unlikely(size > (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE)) { #if MI_DEBUG > 0 _mi_error_message(EOVERFLOW, "aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment); #endif return NULL; } - + // use regular allocation if it is guaranteed to fit the alignment constraints. // this is important to try as the fast path in `mi_heap_malloc_zero_aligned` only works when there exist // a page with the right block size, and if we always use the over-alloc fallback that would never happen. if (offset == 0 && mi_malloc_is_naturally_aligned(size,alignment)) { void* p = _mi_heap_malloc_zero(heap, size, zero); mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); - const bool is_aligned_or_null = (((uintptr_t)p) & (alignment-1))==0; + const bool is_aligned_or_null = (((uintptr_t)p) & (alignment-1))==0; if mi_likely(is_aligned_or_null) { return p; } else { // this should never happen if the `mi_malloc_is_naturally_aligned` check is correct.. mi_assert(false); - mi_free(p); + mi_free(p); } } @@ -155,16 +155,16 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t return NULL; } - #if MI_DEBUG_GUARDED + #if MI_GUARDED if (offset==0 && alignment < MI_BLOCK_ALIGNMENT_MAX && mi_heap_malloc_use_guarded(heap,size)) { return mi_heap_malloc_guarded_aligned(heap, size, alignment, zero); } #endif - + // try first if there happens to be a small block available with just the right alignment if mi_likely(size <= MI_SMALL_SIZE_MAX && alignment <= size) { const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` - const size_t padsize = size + MI_PADDING_SIZE; + const size_t padsize = size + MI_PADDING_SIZE; mi_page_t* page = _mi_heap_get_free_small_page(heap, padsize); if mi_likely(page->free != NULL) { const bool is_aligned = (((uintptr_t)page->free + offset) & align_mask)==0; @@ -181,7 +181,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t } } } - + // fallback to generic aligned allocation return mi_heap_malloc_zero_aligned_at_generic(heap, size, alignment, offset, zero); } diff --git a/src/alloc.c b/src/alloc.c index b4713ff1..561b0026 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -121,7 +121,7 @@ extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t siz return _mi_page_malloc_zero(heap,page,size,true); } -#if MI_DEBUG_GUARDED +#if MI_GUARDED mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; #endif @@ -132,12 +132,12 @@ static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, const uintptr_t tid = _mi_thread_id(); mi_assert(heap->thread_id == 0 || heap->thread_id == tid); // heaps are thread local #endif - #if (MI_PADDING || MI_DEBUG_GUARDED) + #if (MI_PADDING || MI_GUARDED) if (size == 0) { size = sizeof(void*); } #endif - #if MI_DEBUG_GUARDED - if (mi_heap_malloc_use_guarded(heap,size)) { - return _mi_heap_malloc_guarded(heap, size, zero); + #if MI_GUARDED + if (mi_heap_malloc_use_guarded(heap,size)) { + return _mi_heap_malloc_guarded(heap, size, zero); } #endif @@ -176,9 +176,9 @@ extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool z mi_assert_internal(huge_alignment == 0); return mi_heap_malloc_small_zero(heap, size, zero); } - #if MI_DEBUG_GUARDED - else if (huge_alignment==0 && mi_heap_malloc_use_guarded(heap,size)) { - return _mi_heap_malloc_guarded(heap, size, zero); + #if MI_GUARDED + else if (huge_alignment==0 && mi_heap_malloc_use_guarded(heap,size)) { + return _mi_heap_malloc_guarded(heap, size, zero); } #endif else { @@ -603,7 +603,7 @@ mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } } -#if MI_DEBUG_GUARDED +#if MI_GUARDED // We always allocate a guarded allocation at an offset (`mi_page_has_aligned` will be true). // We then set the first word of the block to `0` for regular offset aligned allocations (in `alloc-aligned.c`) // and the first word to `~0` for guarded allocations to have a correct `mi_usable_size` @@ -653,7 +653,7 @@ mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, boo // allocate multiple of page size ending in a guard page // ensure minimal alignment requirement? const size_t os_page_size = _mi_os_page_size(); - const size_t obj_size = (mi_option_is_enabled(mi_option_debug_guarded_precise) ? size : _mi_align_up(size, MI_MAX_ALIGN_SIZE)); + const size_t obj_size = (mi_option_is_enabled(mi_option_guarded_precise) ? size : _mi_align_up(size, MI_MAX_ALIGN_SIZE)); const size_t bsize = _mi_align_up(_mi_align_up(obj_size, MI_MAX_ALIGN_SIZE) + sizeof(mi_block_t), MI_MAX_ALIGN_SIZE); const size_t req_size = _mi_align_up(bsize + os_page_size, os_page_size); mi_block_t* const block = (mi_block_t*)_mi_malloc_generic(heap, req_size, zero, 0 /* huge_alignment */); diff --git a/src/free.c b/src/free.c index 73c05c87..afbafae6 100644 --- a/src/free.c +++ b/src/free.c @@ -33,8 +33,8 @@ static inline void mi_free_block_local(mi_page_t* page, mi_block_t* block, bool // checks if mi_unlikely(mi_check_is_double_free(page, block)) return; mi_check_padding(page, block); - if (track_stats) { mi_stat_free(page, block); } - #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN && !MI_DEBUG_GUARDED + if (track_stats) { mi_stat_free(page, block); } + #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN && !MI_GUARDED memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); #endif if (track_stats) { mi_track_free_size(block, mi_page_usable_size_of(page, block)); } // faster then mi_usable_size as we already know the page and that p is unaligned @@ -69,14 +69,14 @@ mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) { return (mi_block_t*)((uintptr_t)p - adjust); } -// forward declaration for a MI_DEBUG_GUARDED build -#if MI_DEBUG_GUARDED -static void mi_block_unguard_prim(mi_page_t* page, mi_block_t* block, void* p); // forward declaration -static inline void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { - if (mi_block_ptr_is_guarded(block, p)) { mi_block_unguard_prim(page, block, p); } +// forward declaration for a MI_GUARDED build +#if MI_GUARDED +static void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p); // forward declaration +static inline void mi_block_check_unguard(mi_page_t* page, mi_block_t* block, void* p) { + if (mi_block_ptr_is_guarded(block, p)) { mi_block_unguard(page, block, p); } } #else -static inline void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { +static inline void mi_block_check_unguard(mi_page_t* page, mi_block_t* block, void* p) { MI_UNUSED(page); MI_UNUSED(block); MI_UNUSED(p); } #endif @@ -85,14 +85,14 @@ static inline void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { MI_UNUSED(segment); mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(page, p) : (mi_block_t*)p); - mi_block_unguard(page, block, p); + mi_block_check_unguard(page, block, p); mi_free_block_local(page, block, true /* track stats */, true /* check for a full page */); } // free a pointer owned by another thread (page parameter comes first for better codegen) static void mi_decl_noinline mi_free_generic_mt(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { mi_block_t* const block = _mi_page_ptr_unalign(page, p); // don't check `has_aligned` flag to avoid a race (issue #865) - mi_block_unguard(page, block, p); + mi_block_check_unguard(page, block, p); mi_free_block_mt(page, segment, block); } @@ -109,17 +109,17 @@ static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* ms { MI_UNUSED(msg); -#if (MI_DEBUG>0) - if mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) { + #if (MI_DEBUG>0) + if mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0 && !mi_option_is_enabled(mi_option_guarded_precise)) { _mi_error_message(EINVAL, "%s: invalid (unaligned) pointer: %p\n", msg, p); return NULL; } -#endif + #endif mi_segment_t* const segment = _mi_ptr_segment(p); if mi_unlikely(segment==NULL) return segment; -#if (MI_DEBUG>0) + #if (MI_DEBUG>0) if mi_unlikely(!mi_is_in_heap_region(p)) { _mi_warning_message("%s: pointer might not point to a valid heap region: %p\n" "(this may still be a valid very large allocation (over 64MiB))\n", msg, p); @@ -127,13 +127,13 @@ static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* ms _mi_warning_message("(yes, the previous pointer %p was valid after all)\n", p); } } -#endif -#if (MI_DEBUG>0 || MI_SECURE>=4) + #endif + #if (MI_DEBUG>0 || MI_SECURE>=4) if mi_unlikely(_mi_ptr_cookie(segment) != segment->cookie) { _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", msg, p); return NULL; } -#endif + #endif return segment; } @@ -307,7 +307,7 @@ static size_t mi_decl_noinline mi_page_usable_aligned_size_of(const mi_page_t* p const ptrdiff_t adjust = (uint8_t*)p - (uint8_t*)block; mi_assert_internal(adjust >= 0 && (size_t)adjust <= size); const size_t aligned_size = (size - adjust); - #if MI_DEBUG_GUARDED + #if MI_GUARDED if (mi_block_ptr_is_guarded(block, p)) { return aligned_size - _mi_os_page_size(); } @@ -318,7 +318,7 @@ static size_t mi_decl_noinline mi_page_usable_aligned_size_of(const mi_page_t* p static inline size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept { const mi_segment_t* const segment = mi_checked_ptr_segment(p, msg); if mi_unlikely(segment==NULL) return 0; - const mi_page_t* const page = _mi_segment_page_of(segment, p); + const mi_page_t* const page = _mi_segment_page_of(segment, p); if mi_likely(!mi_page_has_aligned(page)) { const mi_block_t* block = (const mi_block_t*)p; return mi_page_usable_size_of(page, block); @@ -541,12 +541,12 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { #endif -// Remove guard page when building with MI_DEBUG_GUARDED -#if MI_DEBUG_GUARDED -static void mi_block_unguard_prim(mi_page_t* page, mi_block_t* block, void* p) { +// Remove guard page when building with MI_GUARDED +#if MI_GUARDED +static void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { mi_assert_internal(mi_block_ptr_is_guarded(block, p)); mi_assert_internal(mi_page_has_aligned(page)); - mi_assert_internal((uint8_t*)p - (uint8_t*)block >= sizeof(mi_block_t)); + mi_assert_internal((uint8_t*)p - (uint8_t*)block >= (ptrdiff_t)sizeof(mi_block_t)); mi_assert_internal(block->next == MI_BLOCK_TAG_GUARDED); const size_t bsize = mi_page_block_size(page); @@ -555,6 +555,6 @@ static void mi_block_unguard_prim(mi_page_t* page, mi_block_t* block, void* p) { mi_assert_internal(_mi_page_segment(page)->allow_decommit); void* gpage = (uint8_t*)block + bsize - psize; mi_assert_internal(_mi_is_aligned(gpage, psize)); - _mi_os_unprotect(gpage, psize); + _mi_os_unprotect(gpage, psize); } #endif diff --git a/src/heap.c b/src/heap.c index eb0ab991..78ebcd1e 100644 --- a/src/heap.c +++ b/src/heap.c @@ -369,8 +369,8 @@ void mi_heap_destroy(mi_heap_t* heap) { mi_assert(heap->no_reclaim); mi_assert_expensive(mi_heap_is_valid(heap)); if (heap==NULL || !mi_heap_is_initialized(heap)) return; - #if MI_DEBUG_GUARDED - // _mi_warning_message("'mi_heap_destroy' called but MI_DEBUG_GUARDED is enabled -- using `mi_heap_delete` instead (heap at %p)\n", heap); + #if MI_GUARDED + // _mi_warning_message("'mi_heap_destroy' called but MI_GUARDED is enabled -- using `mi_heap_delete` instead (heap at %p)\n", heap); mi_heap_delete(heap); return; #else diff --git a/src/options.c b/src/options.c index 3d9017f1..c5f1e2a1 100644 --- a/src/options.c +++ b/src/options.c @@ -47,9 +47,9 @@ typedef struct mi_option_desc_s { #define MI_OPTION(opt) mi_option_##opt, #opt, NULL #define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy -// Some options can be set at build time for statically linked libraries +// Some options can be set at build time for statically linked libraries // (use `-DMI_EXTRA_CPPDEFS="opt1=val1;opt2=val2"`) -// +// // This is useful if we cannot pass them as environment variables // (and setting them programmatically would be too late) @@ -102,17 +102,17 @@ static mi_option_desc_t options[_mi_option_last] = { MI_DEFAULT_VERBOSE, UNINIT, MI_OPTION(verbose) }, // some of the following options are experimental and not all combinations are allowed. - { MI_DEFAULT_EAGER_COMMIT, + { MI_DEFAULT_EAGER_COMMIT, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) - { MI_DEFAULT_ARENA_EAGER_COMMIT, + { MI_DEFAULT_ARENA_EAGER_COMMIT, UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) { 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) }, // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit) - { MI_DEFAULT_ALLOW_LARGE_OS_PAGES, + { MI_DEFAULT_ALLOW_LARGE_OS_PAGES, UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's - { MI_DEFAULT_RESERVE_HUGE_OS_PAGES, + { MI_DEFAULT_RESERVE_HUGE_OS_PAGES, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages {-1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N - { MI_DEFAULT_RESERVE_OS_MEMORY, + { MI_DEFAULT_RESERVE_OS_MEMORY, UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`) { 0, UNINIT, MI_OPTION(deprecated_segment_cache) }, // cache N segments per thread { 0, UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free @@ -137,18 +137,18 @@ static mi_option_desc_t options[_mi_option_last] = { 1, UNINIT, MI_OPTION(abandoned_reclaim_on_free) },// reclaim an abandoned segment on a free { MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's) { 400, UNINIT, MI_OPTION(retry_on_oom) }, // windows only: retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. -#if defined(MI_VISIT_ABANDONED) +#if defined(MI_VISIT_ABANDONED) { 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandonded segments; requires taking locks during reclaim. #else - { 0, UNINIT, MI_OPTION(visit_abandoned) }, + { 0, UNINIT, MI_OPTION(visit_abandoned) }, #endif - { 0, UNINIT, MI_OPTION(debug_guarded_min) }, // only used when building with MI_DEBUG_GUARDED: minimal rounded object size for guarded objects - { MI_GiB, UNINIT, MI_OPTION(debug_guarded_max) }, // only used when building with MI_DEBUG_GUARDED: maximal rounded object size for guarded objects - { 0, UNINIT, MI_OPTION(debug_guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) -#if MI_DEBUG_GUARDED - { 1000,UNINIT, MI_OPTION(debug_guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) + { 0, UNINIT, MI_OPTION(guarded_min) }, // only used when building with MI_GUARDED: minimal rounded object size for guarded objects + { MI_GiB, UNINIT, MI_OPTION(guarded_max) }, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects + { 0, UNINIT, MI_OPTION(guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) +#if MI_GUARDED + { 1000,UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) #else - { 0, UNINIT, MI_OPTION(debug_guarded_sample_rate)}, + { 0, UNINIT, MI_OPTION(guarded_sample_rate)}, #endif }; @@ -172,25 +172,25 @@ void _mi_options_init(void) { } mi_max_error_count = mi_option_get(mi_option_max_errors); mi_max_warning_count = mi_option_get(mi_option_max_warnings); - #if MI_DEBUG_GUARDED - if (mi_option_get(mi_option_debug_guarded_max) > 0) { + #if MI_GUARDED + if (mi_option_get(mi_option_guarded_max) > 0) { if (mi_option_is_enabled(mi_option_allow_large_os_pages)) { mi_option_disable(mi_option_allow_large_os_pages); _mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n"); } } - _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_debug_guarded_max) > 0 ? "enabled" : "disabled"); + _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_guarded_max) > 0 ? "enabled" : "disabled"); #endif } long _mi_option_get_fast(mi_option_t option) { mi_assert(option >= 0 && option < _mi_option_last); - mi_option_desc_t* desc = &options[option]; + mi_option_desc_t* desc = &options[option]; mi_assert(desc->option == option); // index should match the option //mi_assert(desc->init != UNINIT); return desc->value; } - + mi_decl_nodiscard long mi_option_get(mi_option_t option) { mi_assert(option >= 0 && option < _mi_option_last); @@ -225,11 +225,11 @@ void mi_option_set(mi_option_t option, long value) { desc->value = value; desc->init = INITIALIZED; // ensure min/max range; be careful to not recurse. - if (desc->option == mi_option_debug_guarded_min && _mi_option_get_fast(mi_option_debug_guarded_max) < value) { - mi_option_set(mi_option_debug_guarded_max, value); + if (desc->option == mi_option_guarded_min && _mi_option_get_fast(mi_option_guarded_max) < value) { + mi_option_set(mi_option_guarded_max, value); } - else if (desc->option == mi_option_debug_guarded_max && _mi_option_get_fast(mi_option_debug_guarded_min) > value) { - mi_option_set(mi_option_debug_guarded_min, value); + else if (desc->option == mi_option_guarded_max && _mi_option_get_fast(mi_option_guarded_min) > value) { + mi_option_set(mi_option_guarded_min, value); } } @@ -565,7 +565,7 @@ static void mi_option_init(mi_option_desc_t* desc) { char* end = buf; long value = strtol(buf, &end, 10); if (mi_option_has_size_in_kib(desc->option)) { - // this option is interpreted in KiB to prevent overflow of `long` for large allocations + // this option is interpreted in KiB to prevent overflow of `long` for large allocations // (long is 32-bit on 64-bit windows, which allows for 4TiB max.) size_t size = (value < 0 ? 0 : (size_t)value); bool overflow = false; @@ -580,7 +580,7 @@ static void mi_option_init(mi_option_desc_t* desc) { value = (size > LONG_MAX ? LONG_MAX : (long)size); } if (*end == 0) { - mi_option_set(desc->option, value); + mi_option_set(desc->option, value); } else { // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose. diff --git a/src/segment.c b/src/segment.c index 837a65e9..18736818 100644 --- a/src/segment.c +++ b/src/segment.c @@ -455,7 +455,7 @@ static size_t mi_segment_calculate_sizes(size_t capacity, size_t required, size_ if (MI_SECURE == 0) { // normally no guard pages - #if MI_DEBUG_GUARDED + #if MI_GUARDED isize = _mi_align_up(minsize, _mi_os_page_size()); #else isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE); diff --git a/test/test-api-fill.c b/test/test-api-fill.c index 3baee83d..eebbd394 100644 --- a/test/test-api-fill.c +++ b/test/test-api-fill.c @@ -271,7 +271,7 @@ int main(void) { mi_free(p); }; - #if !(MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_DEBUG_GUARDED) + #if !(MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_GUARDED) CHECK_BODY("fill-freed-small") { size_t malloc_size = MI_SMALL_SIZE_MAX / 2; uint8_t* p = (uint8_t*)mi_malloc(malloc_size); diff --git a/test/test-stress.c b/test/test-stress.c index b062f2ce..cb769dbf 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -22,21 +22,22 @@ terms of the MIT license. #include #include -#define MI_DEBUG_GUARDED +// #define MI_GUARDED +// #define USE_STD_MALLOC // > mimalloc-test-stress [THREADS] [SCALE] [ITER] // // argument defaults #if defined(MI_TSAN) // with thread-sanitizer reduce the threads to test within the azure pipeline limits -static int THREADS = 8; +static int THREADS = 8; static int SCALE = 25; static int ITER = 400; #elif defined(MI_UBSAN) // with undefined behavious sanitizer reduce parameters to stay within the azure pipeline limits -static int THREADS = 8; +static int THREADS = 8; static int SCALE = 25; static int ITER = 20; -#elif defined(MI_DEBUG_GUARDED) // with debug guard pages reduce parameters to stay within the azure pipeline limits -static int THREADS = 8; +#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; #else @@ -58,7 +59,6 @@ static size_t use_one_size = 0; // use single object size of `N * static bool main_participates = false; // main thread participates as a worker too -// #define USE_STD_MALLOC #ifdef USE_STD_MALLOC #define custom_calloc(n,s) calloc(n,s) #define custom_realloc(p,s) realloc(p,s) From 8ba1879073785ebbc0a27e2aeace3a0d3e6ff076 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 00:06:16 -0800 Subject: [PATCH 062/131] add sampling for guarded objects --- include/mimalloc.h | 1 + include/mimalloc/internal.h | 16 +++++++++++++--- include/mimalloc/types.h | 8 ++++++++ src/alloc-aligned.c | 25 +++++++++++++++++++++---- src/alloc.c | 1 + src/heap.c | 1 + src/init.c | 26 +++++++++++++++++++++++++- src/options.c | 3 ++- src/stats.c | 2 ++ test/test-stress.c | 3 +-- 10 files changed, 75 insertions(+), 11 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 4ecb8be0..8cbe265f 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -370,6 +370,7 @@ typedef enum mi_option_e { mi_option_guarded_max, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects (=0) mi_option_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) mi_option_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000) + mi_option_guarded_sample_seed, // can be set to allow for a (more) deterministic re-execution when a guard page is triggered (=0) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index ae3a3358..7809503b 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -91,6 +91,7 @@ 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); // os.c void _mi_os_init(void); // called from process init @@ -610,12 +611,21 @@ static inline bool mi_block_ptr_is_guarded(const mi_block_t* block, const void* } static inline bool mi_heap_malloc_use_guarded(mi_heap_t* heap, size_t size) { - MI_UNUSED(heap); - return (size <= (size_t)_mi_option_get_fast(mi_option_guarded_max) - && size >= (size_t)_mi_option_get_fast(mi_option_guarded_min)); + MI_UNUSED(heap); + if (heap->guarded_sample_rate==0 || + size > heap->guarded_size_max || + size < heap->guarded_size_min) { + return false; + } + if (++heap->guarded_sample_count < heap->guarded_sample_rate) { + return false; + } + heap->guarded_sample_count = 0; // reset + return true; } mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; + #endif diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 29ba8564..ec181e61 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -502,6 +502,13 @@ struct mi_heap_s { mi_heap_t* next; // list of heaps per thread bool no_reclaim; // `true` if this heap should not reclaim abandoned pages uint8_t tag; // custom tag, can be used for separating heaps based on the object types + #if MI_GUARDED + size_t guarded_size_min; // minimal size for guarded objects + size_t guarded_size_max; // maximal size for guarded objects + size_t guarded_sample_rate; // sample rate (set to 0 to disable guarded pages) + size_t guarded_sample_seed; // starting sample count + size_t guarded_sample_count; // current sample count (wraps at `sample_rate`) + #endif mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") }; @@ -594,6 +601,7 @@ typedef struct mi_stats_s { mi_stat_counter_t arena_count; mi_stat_counter_t arena_crossover_count; mi_stat_counter_t arena_rollback_count; + mi_stat_counter_t guarded_alloc_count; #if MI_STAT>1 mi_stat_count_t normal_bins[MI_BIN_HUGE+1]; #endif diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 86b13dea..6aee38c3 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -36,6 +36,18 @@ static mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, si mi_assert_internal(_mi_is_aligned(p, alignment)); return p; } + +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; + void* p = _mi_heap_malloc_zero(heap, size, zero); + heap->guarded_sample_rate = rate; + return p; +} +#else +static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero) { + return _mi_heap_malloc_zero(heap, size, zero); +} #endif // Fallback aligned allocation that over-allocates -- split out for better codegen @@ -58,6 +70,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t return NULL; } oversize = (size <= MI_SMALL_SIZE_MAX ? MI_SMALL_SIZE_MAX + 1 /* ensure we use generic malloc path */ : size); + // note: no guarded as alignment > 0 p = _mi_heap_malloc_zero_ex(heap, oversize, false, alignment); // the page block size should be large enough to align in the single huge page block // zero afterwards as only the area from the aligned_p may be committed! if (p == NULL) return NULL; @@ -65,7 +78,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t else { // otherwise over-allocate oversize = size + alignment - 1; - p = _mi_heap_malloc_zero(heap, oversize, zero); + p = mi_heap_malloc_zero_no_guarded(heap, oversize, zero); if (p == NULL) return NULL; } mi_page_t* page = _mi_ptr_page(p); @@ -80,7 +93,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t mi_page_set_has_aligned(page, true); #if MI_GUARDED // set tag to aligned so mi_usable_size works with guard pages - if (adjust > sizeof(mi_block_t)) { + if (adjust >= sizeof(mi_block_t)) { mi_block_t* const block = (mi_block_t*)p; block->next = MI_BLOCK_TAG_ALIGNED; } @@ -93,7 +106,11 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); mi_assert_internal(mi_usable_size(aligned_p)>=size); mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); - mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_page(aligned_p), aligned_p)); + #if MI_DEBUG > 1 + mi_page_t* const apage = _mi_ptr_page(aligned_p); + void* unalign_p = _mi_page_ptr_unalign(apage, aligned_p); + mi_assert_internal(p == unalign_p); + #endif // now zero the block if needed if (alignment > MI_BLOCK_ALIGNMENT_MAX) { @@ -126,7 +143,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_generic(mi_heap_t* // this is important to try as the fast path in `mi_heap_malloc_zero_aligned` only works when there exist // a page with the right block size, and if we always use the over-alloc fallback that would never happen. if (offset == 0 && mi_malloc_is_naturally_aligned(size,alignment)) { - void* p = _mi_heap_malloc_zero(heap, size, zero); + void* p = mi_heap_malloc_zero_no_guarded(heap, size, zero); mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); const bool is_aligned_or_null = (((uintptr_t)p) & (alignment-1))==0; if mi_likely(is_aligned_or_null) { diff --git a/src/alloc.c b/src/alloc.c index 561b0026..25b05526 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -668,6 +668,7 @@ mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, boo if (p != NULL) { if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + mi_heap_stat_counter_increase(heap, guarded_alloc_count, 1); } #endif #if MI_DEBUG>3 diff --git a/src/heap.c b/src/heap.c index 78ebcd1e..581b3f71 100644 --- a/src/heap.c +++ b/src/heap.c @@ -221,6 +221,7 @@ void _mi_heap_init(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool heap->cookie = _mi_heap_random_next(heap) | 1; heap->keys[0] = _mi_heap_random_next(heap); heap->keys[1] = _mi_heap_random_next(heap); + _mi_heap_guarded_init(heap); // push on the thread local heaps list heap->next = heap->tld->heaps; heap->tld->heaps = heap; diff --git a/src/init.c b/src/init.c index 75458a1f..822d5a18 100644 --- a/src/init.c +++ b/src/init.c @@ -86,7 +86,8 @@ const mi_page_t _mi_page_empty = { MI_STAT_COUNT_NULL(), \ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 } \ MI_STAT_COUNT_END_NULL() // -------------------------------------------------------- @@ -111,6 +112,9 @@ mi_decl_cache_align const mi_heap_t _mi_heap_empty = { NULL, // next false, // can reclaim 0, // tag + #if MI_GUARDED + 0, 0, 0, 0, 0, + #endif MI_SMALL_PAGES_EMPTY, MI_PAGE_QUEUES_EMPTY }; @@ -151,6 +155,9 @@ mi_decl_cache_align mi_heap_t _mi_heap_main = { NULL, // next heap false, // can reclaim 0, // tag + #if MI_GUARDED + 0, 0, 0, 0, 0, + #endif MI_SMALL_PAGES_EMPTY, MI_PAGE_QUEUES_EMPTY }; @@ -159,6 +166,22 @@ bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`. mi_stats_t _mi_stats_main = { MI_STATS_NULL }; +#if MI_GUARDED +void _mi_heap_guarded_init(mi_heap_t* heap) { + heap->guarded_sample_rate = mi_option_get_clamp(mi_option_guarded_sample_rate, 0, LONG_MAX); + heap->guarded_size_max = mi_option_get_clamp(mi_option_guarded_max, 0, LONG_MAX); + heap->guarded_size_min = mi_option_get_clamp(mi_option_guarded_min, 0, (long)heap->guarded_size_max); + heap->guarded_sample_seed = (size_t)mi_option_get(mi_option_guarded_sample_seed); + if (heap->guarded_sample_seed == 0) { heap->guarded_sample_seed = _mi_heap_random_next(heap); } + heap->guarded_sample_seed = heap->guarded_sample_seed % heap->guarded_sample_rate; + heap->guarded_sample_count = heap->guarded_sample_seed; +} +#else +void _mi_heap_guarded_init(mi_heap_t* heap) { + MI_UNUSED(heap); +} +#endif + static void mi_heap_main_init(void) { if (_mi_heap_main.cookie == 0) { @@ -174,6 +197,7 @@ static void mi_heap_main_init(void) { _mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main); mi_lock_init(&mi_subproc_default.abandoned_os_lock); mi_lock_init(&mi_subproc_default.abandoned_os_visit_lock); + _mi_heap_guarded_init(&_mi_heap_main); } } diff --git a/src/options.c b/src/options.c index c5f1e2a1..2c6814c8 100644 --- a/src/options.c +++ b/src/options.c @@ -150,6 +150,7 @@ static mi_option_desc_t options[_mi_option_last] = #else { 0, UNINIT, MI_OPTION(guarded_sample_rate)}, #endif + { 0, UNINIT, MI_OPTION(guarded_sample_seed)}, }; static void mi_option_init(mi_option_desc_t* desc); @@ -173,7 +174,7 @@ void _mi_options_init(void) { mi_max_error_count = mi_option_get(mi_option_max_errors); mi_max_warning_count = mi_option_get(mi_option_max_warnings); #if MI_GUARDED - if (mi_option_get(mi_option_guarded_max) > 0) { + if (mi_option_get(mi_option_guarded_sample_rate) > 0) { if (mi_option_is_enabled(mi_option_allow_large_os_pages)) { mi_option_disable(mi_option_allow_large_os_pages); _mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n"); diff --git a/src/stats.c b/src/stats.c index 99cf89c5..29376ace 100644 --- a/src/stats.c +++ b/src/stats.c @@ -118,6 +118,7 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { mi_stat_counter_add(&stats->searches, &src->searches, 1); mi_stat_counter_add(&stats->normal_count, &src->normal_count, 1); mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1); + mi_stat_counter_add(&stats->guarded_alloc_count, &src->guarded_alloc_count, 1); #if MI_STAT>1 for (size_t i = 0; i <= MI_BIN_HUGE; i++) { if (src->normal_bins[i].allocated > 0 || src->normal_bins[i].freed > 0) { @@ -342,6 +343,7 @@ static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_stat_counter_print(&stats->commit_calls, "commits", out, arg); mi_stat_counter_print(&stats->reset_calls, "resets", out, arg); mi_stat_counter_print(&stats->purge_calls, "purges", out, arg); + mi_stat_counter_print(&stats->guarded_alloc_count, "guarded", out, arg); mi_stat_print(&stats->threads, "threads", -1, out, arg); mi_stat_counter_print_avg(&stats->searches, "searches", out, arg); _mi_fprintf(out, arg, "%10s: %5zu\n", "numa nodes", _mi_os_numa_node_count()); diff --git a/test/test-stress.c b/test/test-stress.c index cb769dbf..88c39f23 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -22,7 +22,6 @@ terms of the MIT license. #include #include -// #define MI_GUARDED // #define USE_STD_MALLOC // > mimalloc-test-stress [THREADS] [SCALE] [ITER] @@ -36,7 +35,7 @@ static int ITER = 400; static int THREADS = 8; static int SCALE = 25; static int ITER = 20; -#elif defined(MI_GUARDED) // with debug guard pages reduce parameters to stay within the azure pipeline limits +#elif defined(MI_XGUARDED) // 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 d57cb0765d4673ee10a577d741455ead9396b944 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 22:45:09 -0800 Subject: [PATCH 063/131] add guarded objects that are sampled (and fit a size range). guarded sample rate etc can be set per heap as well as defaulted with options --- include/mimalloc.h | 6 ++++++ include/mimalloc/internal.h | 22 ++++++++++++-------- include/mimalloc/types.h | 2 +- src/alloc.c | 8 +++----- src/free.c | 1 + src/init.c | 41 +++++++++++++++++++++++++++++-------- src/options.c | 2 +- test/main-override.cpp | 2 +- test/test-stress.c | 3 ++- 9 files changed, 61 insertions(+), 26 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 8cbe265f..e3fecdf1 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -309,6 +309,12 @@ mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_ex(int heap_tag, bool al // deprecated mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept; +// Experimental: objects followed by a guard page. +// A sample rate of 0 disables guarded objects, while 1 uses a guard page for every object. +// A seed of 0 uses a random start point. Only objects within the size bound are eligable for guard pages. +mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed); +mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max); + // ------------------------------------------------------ // Convenience diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 7809503b..d58bd9ca 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -611,17 +611,23 @@ static inline bool mi_block_ptr_is_guarded(const mi_block_t* block, const void* } static inline bool mi_heap_malloc_use_guarded(mi_heap_t* heap, size_t size) { - MI_UNUSED(heap); - if (heap->guarded_sample_rate==0 || - size > heap->guarded_size_max || - size < heap->guarded_size_min) { + // this code is written to result in fast assembly as it is on the hot path for allocation + const size_t count = heap->guarded_sample_count - 1; // if the rate was 0, this will underflow and count for a long time.. + if mi_likely(count != 0) { + // no sample + heap->guarded_sample_count = count; return false; } - if (++heap->guarded_sample_count < heap->guarded_sample_rate) { - return false; + else if (size >= heap->guarded_size_min && size <= heap->guarded_size_max) { + // use guarded allocation + heap->guarded_sample_count = heap->guarded_sample_rate; // reset + return (heap->guarded_sample_rate != 0); } - heap->guarded_sample_count = 0; // reset - return true; + else { + // failed size criteria, rewind count (but don't write to an empty heap) + if (heap->guarded_sample_rate != 0) { heap->guarded_sample_count = 1; } + return false; + } } mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index ec181e61..f7bca137 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -507,7 +507,7 @@ struct mi_heap_s { size_t guarded_size_max; // maximal size for guarded objects size_t guarded_sample_rate; // sample rate (set to 0 to disable guarded pages) size_t guarded_sample_seed; // starting sample count - size_t guarded_sample_count; // current sample count (wraps at `sample_rate`) + size_t guarded_sample_count; // current sample count (counting down to 0) #endif mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") diff --git a/src/alloc.c b/src/alloc.c index 25b05526..bc4f2aa5 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -661,16 +661,14 @@ mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, boo void* const p = mi_block_ptr_set_guarded(block, obj_size); // stats - const size_t usize = mi_usable_size(p); - mi_assert_internal(usize >= size); mi_track_malloc(p, size, zero); - #if MI_STAT>1 if (p != NULL) { if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } + #if MI_STAT>1 mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); - mi_heap_stat_counter_increase(heap, guarded_alloc_count, 1); + #endif + _mi_stat_counter_increase(&heap->tld->stats.guarded_alloc_count, 1); } - #endif #if MI_DEBUG>3 if (p != NULL && zero) { mi_assert_expensive(mi_mem_is_zero(p, size)); diff --git a/src/free.c b/src/free.c index afbafae6..f2e30b65 100644 --- a/src/free.c +++ b/src/free.c @@ -544,6 +544,7 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { // Remove guard page when building with MI_GUARDED #if MI_GUARDED static void mi_block_unguard(mi_page_t* page, mi_block_t* block, void* p) { + MI_UNUSED(p); mi_assert_internal(mi_block_ptr_is_guarded(block, p)); mi_assert_internal(mi_page_has_aligned(page)); mi_assert_internal((uint8_t*)p - (uint8_t*)block >= (ptrdiff_t)sizeof(mi_block_t)); diff --git a/src/init.c b/src/init.c index 822d5a18..ed161831 100644 --- a/src/init.c +++ b/src/init.c @@ -113,7 +113,7 @@ mi_decl_cache_align const mi_heap_t _mi_heap_empty = { false, // can reclaim 0, // tag #if MI_GUARDED - 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, // count is 1 so we never write to it (see `internal.h:mi_heap_malloc_use_guarded`) #endif MI_SMALL_PAGES_EMPTY, MI_PAGE_QUEUES_EMPTY @@ -167,16 +167,39 @@ bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`. mi_stats_t _mi_stats_main = { MI_STATS_NULL }; #if MI_GUARDED +mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) { + heap->guarded_sample_seed = seed; + if (heap->guarded_sample_seed == 0) { + heap->guarded_sample_seed = _mi_heap_random_next(heap); + } + heap->guarded_sample_rate = sample_rate; + if (heap->guarded_sample_rate >= 1) { + heap->guarded_sample_seed = heap->guarded_sample_seed % heap->guarded_sample_rate; + } + heap->guarded_sample_count = heap->guarded_sample_seed; // count down samples +} + +mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max) { + heap->guarded_size_min = min; + heap->guarded_size_max = (min > max ? min : max); +} + void _mi_heap_guarded_init(mi_heap_t* heap) { - heap->guarded_sample_rate = mi_option_get_clamp(mi_option_guarded_sample_rate, 0, LONG_MAX); - heap->guarded_size_max = mi_option_get_clamp(mi_option_guarded_max, 0, LONG_MAX); - heap->guarded_size_min = mi_option_get_clamp(mi_option_guarded_min, 0, (long)heap->guarded_size_max); - heap->guarded_sample_seed = (size_t)mi_option_get(mi_option_guarded_sample_seed); - if (heap->guarded_sample_seed == 0) { heap->guarded_sample_seed = _mi_heap_random_next(heap); } - heap->guarded_sample_seed = heap->guarded_sample_seed % heap->guarded_sample_rate; - heap->guarded_sample_count = heap->guarded_sample_seed; + mi_heap_guarded_set_sample_rate(heap, + (size_t)mi_option_get_clamp(mi_option_guarded_sample_rate, 0, LONG_MAX), + (size_t)mi_option_get(mi_option_guarded_sample_seed)); + mi_heap_guarded_set_size_bound(heap, + (size_t)mi_option_get_clamp(mi_option_guarded_min, 0, LONG_MAX), + (size_t)mi_option_get_clamp(mi_option_guarded_max, 0, LONG_MAX) ); } #else +mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) { + MI_UNUSED(heap); MI_UNUSED(sample_rate); MI_UNUSED(seed); +} + +mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max) { + MI_UNUSED(heap); MI_UNUSED(min); MI_UNUSED(max); +} void _mi_heap_guarded_init(mi_heap_t* heap) { MI_UNUSED(heap); } @@ -576,7 +599,7 @@ static void mi_detect_cpu_features(void) { } #else static void mi_detect_cpu_features(void) { - // nothing + // nothing } #endif diff --git a/src/options.c b/src/options.c index 2c6814c8..4f95e601 100644 --- a/src/options.c +++ b/src/options.c @@ -146,7 +146,7 @@ static mi_option_desc_t options[_mi_option_last] = { MI_GiB, UNINIT, MI_OPTION(guarded_max) }, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects { 0, UNINIT, MI_OPTION(guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) #if MI_GUARDED - { 1000,UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) + { 4000,UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) #else { 0, UNINIT, MI_OPTION(guarded_sample_rate)}, #endif diff --git a/test/main-override.cpp b/test/main-override.cpp index 9c47d3a1..3f64117a 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -62,7 +62,7 @@ int main() { test_mt_shutdown(); */ //fail_aslr(); - // mi_stats_print(NULL); + mi_stats_print(NULL); return 0; } diff --git a/test/test-stress.c b/test/test-stress.c index 88c39f23..ba9ab459 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -22,6 +22,7 @@ terms of the MIT license. #include #include +// #define MI_GUARDED // #define USE_STD_MALLOC // > mimalloc-test-stress [THREADS] [SCALE] [ITER] @@ -35,7 +36,7 @@ static int ITER = 400; static int THREADS = 8; static int SCALE = 25; static int ITER = 20; -#elif defined(MI_XGUARDED) // with debug guard pages reduce parameters to stay within the azure pipeline limits +#elif defined(xMI_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 b8dc09e3d2adde248daabe1303b161c714bff298 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 22:56:26 -0800 Subject: [PATCH 064/131] fix asan with MI_GUARDED --- src/alloc-aligned.c | 3 +++ src/alloc.c | 5 +++-- src/os.c | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 6aee38c3..b4da4ded 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -123,6 +123,9 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t if (p != aligned_p) { mi_track_align(p,aligned_p,adjust,mi_usable_size(aligned_p)); + #if MI_GUARDED + mi_track_mem_defined(p, sizeof(mi_block_t)); + #endif } return aligned_p; } diff --git a/src/alloc.c b/src/alloc.c index bc4f2aa5..a093f108 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -640,8 +640,9 @@ static void* mi_block_ptr_set_guarded(mi_block_t* block, size_t obj_size) { // give up to place it right in front of the guard page if the offset is too large for unalignment offset = MI_BLOCK_ALIGNMENT_MAX; } - void* p = (uint8_t*)block + offset; + void* p = (uint8_t*)block + offset; mi_track_align(block, p, offset, obj_size); + mi_track_mem_defined(block, sizeof(mi_block_t)); return p; } @@ -661,7 +662,7 @@ mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, boo void* const p = mi_block_ptr_set_guarded(block, obj_size); // stats - mi_track_malloc(p, size, zero); + mi_track_malloc(p, size, zero); if (p != NULL) { if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } #if MI_STAT>1 diff --git a/src/os.c b/src/os.c index 62c8c934..a7130b90 100644 --- a/src/os.c +++ b/src/os.c @@ -273,7 +273,9 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit } else { // if not aligned, free it, overallocate, and unmap around it + #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); if (size >= (SIZE_MAX - alignment)) return NULL; // overflow const size_t over_size = size + alignment; From ff56f6acbc786ddf533d348b27d249256d14dc44 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 23:01:16 -0800 Subject: [PATCH 065/131] update azure pipeline to use sample rate of 1000 for guarded objects --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e4361f98..1fd71663 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -130,7 +130,7 @@ jobs: workingDirectory: $(BuildType) displayName: CTest env: - MIMALLOC_DEBUG_GUARDED_MAX: 1024 + MIMALLOC_GUARDED_SAMPLE_RATE: 1000 # - upload: $(Build.SourcesDirectory)/$(BuildType) # artifact: mimalloc-ubuntu-$(BuildType) From e7198ce3977f26716c014819df92d48b6058f569 Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 23:16:59 -0800 Subject: [PATCH 066/131] Extend azure pipeline with Ubuntu 24 & 20, windows 2019, and macOS 15 --- azure-pipelines.yml | 163 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 36 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1fd71663..6a2544f8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,7 +15,7 @@ trigger: jobs: - job: - displayName: Windows + displayName: Windows 2022 pool: vmImage: windows-2022 @@ -52,7 +52,7 @@ jobs: # artifact: mimalloc-windows-$(BuildType) - job: - displayName: Linux + displayName: Ubuntu 22.04 pool: vmImage: ubuntu-22.04 @@ -135,10 +135,10 @@ jobs: # artifact: mimalloc-ubuntu-$(BuildType) - job: - displayName: macOS + displayName: macOS 14 (Sonoma) pool: vmImage: - macOS-latest + macOS-14 strategy: matrix: Debug: @@ -163,35 +163,126 @@ jobs: # - upload: $(Build.SourcesDirectory)/$(BuildType) # artifact: mimalloc-macos-$(BuildType) -# - job: -# displayName: Windows-2017 -# pool: -# vmImage: -# vs2017-win2016 -# strategy: -# matrix: -# Debug: -# BuildType: debug -# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -# MSBuildConfiguration: Debug -# Release: -# BuildType: release -# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release -# MSBuildConfiguration: Release -# Secure: -# BuildType: secure -# cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON -# MSBuildConfiguration: Release -# steps: -# - task: CMake@1 -# inputs: -# workingDirectory: $(BuildType) -# cmakeArgs: .. $(cmakeExtraArgs) -# - task: MSBuild@1 -# inputs: -# solution: $(BuildType)/libmimalloc.sln -# configuration: '$(MSBuildConfiguration)' -# - script: | -# cd $(BuildType) -# ctest --verbose --timeout 180 -# displayName: CTest +# ---------------------------------------------------------- +# Other OS versions (just debug mode) +# ---------------------------------------------------------- + +- job: + displayName: Windows 2019 + pool: + vmImage: + windows-2019 + strategy: + matrix: + Debug: + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + MSBuildConfiguration: Debug + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - task: MSBuild@1 + inputs: + solution: $(BuildType)/libmimalloc.sln + configuration: '$(MSBuildConfiguration)' + msbuildArguments: -m + - script: ctest --verbose --timeout 180 -C $(MSBuildConfiguration) + workingDirectory: $(BuildType) + displayName: CTest + +- job: + displayName: Ubuntu 24.04 + pool: + vmImage: + ubuntu-24.04 + strategy: + matrix: + Debug: + CC: gcc + CXX: g++ + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Debug++: + CC: gcc + CXX: g++ + BuildType: debug-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + Debug Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - script: make -j$(nproc) -C $(BuildType) + displayName: Make + - script: ctest --verbose --timeout 180 + workingDirectory: $(BuildType) + displayName: CTest + +- job: + displayName: Ubuntu 20.04 + pool: + vmImage: + ubuntu-20.04 + strategy: + matrix: + Debug: + CC: gcc + CXX: g++ + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Debug++: + CC: gcc + CXX: g++ + BuildType: debug-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + Debug Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - script: make -j$(nproc) -C $(BuildType) + displayName: Make + - script: ctest --verbose --timeout 180 + workingDirectory: $(BuildType) + displayName: CTest + +- job: + displayName: macOS 15 (Sequia) + pool: + vmImage: + macOS-15 + strategy: + matrix: + Debug: + BuildType: debug + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON + Release: + BuildType: release + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + Secure: + BuildType: secure + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON + steps: + - task: CMake@1 + inputs: + workingDirectory: $(BuildType) + cmakeArgs: .. $(cmakeExtraArgs) + - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) + displayName: Make + - script: ctest --verbose --timeout 180 + workingDirectory: $(BuildType) + displayName: CTest From 41029d9d49439cb1191fcc984592d0e9e56e73af Mon Sep 17 00:00:00 2001 From: daanx Date: Sun, 17 Nov 2024 23:20:18 -0800 Subject: [PATCH 067/131] fix azure pipeline --- azure-pipelines.yml | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6a2544f8..00bfe8e9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -178,6 +178,10 @@ jobs: BuildType: debug cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON MSBuildConfiguration: Debug + Release: + BuildType: release + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release + MSBuildConfiguration: Release steps: - task: CMake@1 inputs: @@ -214,7 +218,16 @@ jobs: CXX: clang++ BuildType: debug-clang cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON - + Debug++ Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + Release Clang: + CC: clang + CXX: clang++ + BuildType: release-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release steps: - task: CMake@1 inputs: @@ -248,7 +261,16 @@ jobs: CXX: clang++ BuildType: debug-clang cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON - + Debug++ Clang: + CC: clang + CXX: clang++ + BuildType: debug-clang-cxx + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON + Release Clang: + CC: clang + CXX: clang++ + BuildType: release-clang + cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release steps: - task: CMake@1 inputs: @@ -273,9 +295,6 @@ jobs: Release: BuildType: release cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release - Secure: - BuildType: secure - cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON steps: - task: CMake@1 inputs: From 3a7b6f0a8d83052adcb1b0ae27840b2f6d61ab06 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 18 Nov 2024 10:28:00 -0800 Subject: [PATCH 068/131] allow build time setting of sample rate --- src/options.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/options.c b/src/options.c index 4f95e601..6635f661 100644 --- a/src/options.c +++ b/src/options.c @@ -89,6 +89,14 @@ typedef struct mi_option_desc_s { #define MI_DEFAULT_RESERVE_OS_MEMORY 0 #endif +#ifndef MI_DEFAULT_GUARDED_SAMPLE_RATE +#if MI_GUARDED +#define MI_DEFAULT_GUARDED_SAMPLE_RATE 4000 +#else +#define MI_DEFAULT_GUARDED_SAMPLE_RATE 0 +#endif +#endif + static mi_option_desc_t options[_mi_option_last] = { @@ -145,11 +153,8 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(guarded_min) }, // only used when building with MI_GUARDED: minimal rounded object size for guarded objects { MI_GiB, UNINIT, MI_OPTION(guarded_max) }, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects { 0, UNINIT, MI_OPTION(guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) -#if MI_GUARDED - { 4000,UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded(= 1000) -#else - { 0, UNINIT, MI_OPTION(guarded_sample_rate)}, -#endif + { MI_DEFAULT_GUARDED_SAMPLE_RATE, + UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded (=4000) { 0, UNINIT, MI_OPTION(guarded_sample_seed)}, }; @@ -180,7 +185,7 @@ void _mi_options_init(void) { _mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n"); } } - _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_guarded_max) > 0 ? "enabled" : "disabled"); + _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_guarded_sample_rate) != 0 ? "enabled" : "disabled"); #endif } From 71fec8caf5a6f3219f37ccfe38b71d73d6274c37 Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 18 Nov 2024 15:05:22 -0800 Subject: [PATCH 069/131] add target_segments_per_thread option --- include/mimalloc.h | 1 + include/mimalloc/internal.h | 6 ++- src/options.c | 2 + src/page.c | 33 +++++++++++++--- src/segment.c | 79 ++++++++++++++++++++++++++++++++++++- 5 files changed, 112 insertions(+), 9 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index e3fecdf1..83cbda12 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -377,6 +377,7 @@ typedef enum mi_option_e { mi_option_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0) mi_option_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000) mi_option_guarded_sample_seed, // can be set to allow for a (more) deterministic re-execution when a guard page is triggered (=0) + mi_option_target_segments_per_thread, // experimental (=0) _mi_option_last, // legacy option names mi_option_large_os_pages = mi_option_allow_large_os_pages, diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index d58bd9ca..8de37edf 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -178,6 +178,8 @@ void _mi_page_retire(mi_page_t* page) mi_attr_noexcept; / 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); @@ -625,9 +627,9 @@ static inline bool mi_heap_malloc_use_guarded(mi_heap_t* heap, size_t size) { } else { // failed size criteria, rewind count (but don't write to an empty heap) - if (heap->guarded_sample_rate != 0) { heap->guarded_sample_count = 1; } + if (heap->guarded_sample_rate != 0) { heap->guarded_sample_count = 1; } return false; - } + } } mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; diff --git a/src/options.c b/src/options.c index 4f95e601..d49d4aa8 100644 --- a/src/options.c +++ b/src/options.c @@ -65,6 +65,7 @@ typedef struct mi_option_desc_s { #define MI_DEFAULT_ARENA_EAGER_COMMIT 2 #endif +// in KiB #ifndef MI_DEFAULT_ARENA_RESERVE #if (MI_INTPTR_SIZE>4) #define MI_DEFAULT_ARENA_RESERVE 1024L*1024L @@ -151,6 +152,7 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(guarded_sample_rate)}, #endif { 0, UNINIT, MI_OPTION(guarded_sample_seed)}, + { 0, UNINIT, MI_OPTION(target_segments_per_thread) }, // abandon segments beyond this point, or 0 to disable. }; static void mi_option_init(mi_option_desc_t* desc); diff --git a/src/page.c b/src/page.c index 9d8a7b0d..3cf91ba8 100644 --- a/src/page.c +++ b/src/page.c @@ -357,7 +357,7 @@ void _mi_page_unfull(mi_page_t* page) { mi_page_set_in_full(page, false); // to get the right queue mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); mi_page_set_in_full(page, true); - mi_page_queue_enqueue_from_full(pq, pqfull, page); + mi_page_queue_enqueue_from_full(pq, pqfull, page); } static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { @@ -403,6 +403,29 @@ void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq) { _mi_segment_page_abandon(page,segments_tld); } +// force abandon a page +void _mi_page_force_abandon(mi_page_t* page) { + mi_heap_t* heap = mi_page_heap(page); + // mark page as not using delayed free + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + + // ensure this page is no longer in the heap delayed free list + _mi_heap_delayed_free_all(heap); + // TODO: can we still access the page as it may have been + // freed and the memory decommitted? + // A way around this is to explicitly unlink this page from + // the heap delayed free list. + if (page->capacity == 0) return; // it may have been freed now + + // and now unlink it from the page queue and abandon (or free) + mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); + if (mi_page_all_free(page)) { + _mi_page_free(page, pq, false); + } + else { + _mi_page_abandon(page, pq); + } +} // Free a page with no more free blocks void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { @@ -743,7 +766,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p #if defined(MI_MAX_CANDIDATE_SEARCH) // search up to N pages for a best candidate - + // is the local free list non-empty? const bool immediate_available = mi_page_immediate_available(page); @@ -758,9 +781,9 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // we prefer non-expandable pages with high usage as candidates (to reduce commit, and increase chances of free-ing up pages) if (page_candidate == NULL) { page_candidate = page; - candidate_count = 0; + candidate_count = 0; } - else if (!mi_page_is_expandable(page) && page->capacity < page_candidate->capacity) { + else if (!mi_page_is_expandable(page) && page->used >= page_candidate->used) { page_candidate = page; } // if we find a non-expandable candidate, or searched for N pages, return with the best candidate @@ -805,7 +828,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p } } else { - mi_assert(pq->first == page); + // mi_assert(pq->first == page); page->retire_expire = 0; } mi_assert_internal(page == NULL || mi_page_immediate_available(page)); diff --git a/src/segment.c b/src/segment.c index 18736818..d2604436 100644 --- a/src/segment.c +++ b/src/segment.c @@ -952,6 +952,9 @@ bool _mi_segment_attempt_reclaim(mi_heap_t* heap, mi_segment_t* segment) { if (mi_atomic_load_relaxed(&segment->thread_id) != 0) return false; // it is not abandoned if (segment->subproc != heap->tld->segments.subproc) return false; // only reclaim within the same subprocess if (!_mi_heap_memid_is_suitable(heap,segment->memid)) return false; // don't reclaim between exclusive and non-exclusive arena's + const long target = _mi_option_get_fast(mi_option_target_segments_per_thread); + if (target > 0 && (size_t)target <= heap->tld->segments.count) return false; // don't reclaim if going above the target count + // don't reclaim more from a `free` call than half the current segments // this is to prevent a pure free-ing thread to start owning too many segments // (but not for out-of-arena segments as that is the main way to be reclaimed for those) @@ -1023,8 +1026,8 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, result = mi_segment_reclaim(segment, heap, block_size, reclaimed, tld); break; } - else if (segment->abandoned_visits >= 3 && is_suitable) { - // always reclaim on 3rd visit to limit the list length. + else if (segment->abandoned_visits > 3 && is_suitable && !mi_option_is_enabled(mi_option_target_segments_per_thread)) { + // always reclaim on 3rd visit to limit the abandoned segment count. mi_segment_reclaim(segment, heap, 0, NULL, tld); } else { @@ -1038,6 +1041,75 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, } +/* ----------------------------------------------------------- + Force abandon a segment that is in use by our thread +----------------------------------------------------------- */ + +// force abandon a segment +static void mi_segment_force_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) +{ + mi_assert_internal(segment->abandoned < segment->used); + + // for all pages + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->segment_in_use) { + // ensure used count is up to date and collect potential concurrent frees + _mi_page_free_collect(page, false); + { + // abandon the page if it is still in-use (this will free it if possible as well) + mi_assert_internal(segment->used > 0); + if (segment->used == segment->abandoned+1) { + // the last page.. abandon and return as the segment will be abandoned after this + // and we should no longer access it. + _mi_page_force_abandon(page); + return; + } + else { + // abandon and continue + _mi_page_force_abandon(page); + } + } + } + } + mi_assert(segment->used == segment->abandoned); + mi_assert(segment->used == 0); + if (segment->used == 0) { + // all free now + mi_segment_free(segment, false, tld); + } + else { + // perform delayed purges + mi_pages_try_purge(false /* force? */, tld); + } +} + + +// try abandon segments. +// this should be called from `reclaim_or_alloc` so we know all segments are (about) fully in use. +static void mi_segments_try_abandon(mi_heap_t* heap, mi_segments_tld_t* tld) { + const size_t target = (size_t)mi_option_get_clamp(mi_option_target_segments_per_thread,0,1024); + // we call this when we are about to add a fresh segment so we should be under our target segment count. + if (target == 0 || tld->count < target) return; + + const size_t min_target = (target > 4 ? (target*3)/4 : target); // 75% + + // todo: we should maintain a list of segments per thread; for now, only consider segments from the heap full pages + for (int i = 0; i < 16 && tld->count >= min_target; i++) { + mi_page_t* page = heap->pages[MI_BIN_FULL].first; + while (page != NULL && mi_page_is_huge(page)) { + page = page->next; + } + if (page==NULL) { + break; + } + mi_segment_t* segment = _mi_page_segment(page); + mi_segment_force_abandon(segment, tld); + mi_assert_internal(page != heap->pages[MI_BIN_FULL].first); // as it is just abandoned + } +} + + /* ----------------------------------------------------------- Reclaim or allocate ----------------------------------------------------------- */ @@ -1047,6 +1119,9 @@ static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_s mi_assert_internal(page_kind <= MI_PAGE_LARGE); mi_assert_internal(block_size <= MI_LARGE_OBJ_SIZE_MAX); + // try to abandon some segments to increase reuse between threads + mi_segments_try_abandon(heap,tld); + // 1. try to reclaim an abandoned segment bool reclaimed; mi_segment_t* segment = mi_segment_try_reclaim(heap, block_size, page_kind, &reclaimed, tld); From 3adb19c84cec47c3012e1253d952823e4d45f61b Mon Sep 17 00:00:00 2001 From: Diego Russo Date: Mon, 21 Oct 2024 17:32:45 +0100 Subject: [PATCH 070/131] Fix illegal instruction for older Arm architectures This is a port of the PR https://github.com/python/cpython/issues/125444 --- include/mimalloc/prim.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index f8bf948e..56715df4 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -138,9 +138,9 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); // but unfortunately we can not detect support reliably (see issue #883) // We also use it on Apple OS as we use a TLS slot for the default heap there. #if defined(__GNUC__) && ( \ - (defined(__GLIBC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \ + (defined(__GLIBC__) && (defined(__x86_64__) || defined(__i386__) || (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__))) \ || (defined(__APPLE__) && (defined(__x86_64__) || defined(__aarch64__) || defined(__POWERPC__))) \ - || (defined(__BIONIC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \ + || (defined(__BIONIC__) && (defined(__x86_64__) || defined(__i386__) || (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__))) \ || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \ || (defined(__OpenBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \ ) From 9b7ac9a1a67308a26d09f0b87d2e876fbc61c86c Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 25 Nov 2024 16:58:02 -0800 Subject: [PATCH 071/131] clean up candidate search; add mi_collect_reduce --- ide/vs2022/mimalloc.vcxproj | 2 +- include/mimalloc.h | 1 + src/page-queue.c | 10 +++++++++- src/page.c | 23 ++++++++++++++------- src/segment.c | 40 ++++++++++++++++++++++++++++--------- 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index 160f1436..dddab777 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -116,7 +116,7 @@ true Default ../../include - MI_DEBUG=4;MI_GUARDED=1;%(PreprocessorDefinitions); + MI_DEBUG=3;MI_GUARDED=0;%(PreprocessorDefinitions); CompileAsCpp false stdcpp20 diff --git a/include/mimalloc.h b/include/mimalloc.h index 83cbda12..5916228b 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -148,6 +148,7 @@ typedef void (mi_cdecl mi_error_fun)(int err, void* arg); mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg); mi_decl_export void mi_collect(bool force) mi_attr_noexcept; +mi_decl_export void mi_collect_reduce(size_t target_thread_owned) mi_attr_noexcept; mi_decl_export int mi_version(void) mi_attr_noexcept; mi_decl_export void mi_stats_reset(void) mi_attr_noexcept; mi_decl_export void mi_stats_merge(void) mi_attr_noexcept; diff --git a/src/page-queue.c b/src/page-queue.c index 3034e15d..9796f3dc 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -259,6 +259,14 @@ static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_ heap->page_count++; } +static void mi_page_queue_move_to_front(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(mi_page_queue_contains(queue, page)); + if (queue->first == page) return; + mi_page_queue_remove(queue, page); + mi_page_queue_push(heap, queue, page); + mi_assert_internal(queue->first == page); +} static void mi_page_queue_enqueue_from_ex(mi_page_queue_t* to, mi_page_queue_t* from, bool enqueue_at_end, mi_page_t* page) { mi_assert_internal(page != NULL); @@ -335,7 +343,7 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro static void mi_page_queue_enqueue_from_full(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { // note: we could insert at the front to increase reuse, but it slows down certain benchmarks (like `alloc-test`) - mi_page_queue_enqueue_from_ex(to, from, true /* enqueue at the end of the `to` queue? */, page); + mi_page_queue_enqueue_from_ex(to, from, false /* enqueue at the end of the `to` queue? */, page); } // Only called from `mi_heap_absorb`. diff --git a/src/page.c b/src/page.c index 3cf91ba8..43ac7c4e 100644 --- a/src/page.c +++ b/src/page.c @@ -471,6 +471,7 @@ void _mi_page_retire(mi_page_t* page) mi_attr_noexcept { // how to check this efficiently though... // for now, we don't retire if it is the only page left of this size class. mi_page_queue_t* pq = mi_page_queue_of(page); + #if MI_RETIRE_CYCLES > 0 const size_t bsize = mi_page_block_size(page); if mi_likely( /* bsize < MI_MAX_RETIRE_SIZE && */ !mi_page_queue_is_special(pq)) { // not full or huge queue? if (pq->last==page && pq->first==page) { // the only page in the queue? @@ -486,7 +487,7 @@ void _mi_page_retire(mi_page_t* page) mi_attr_noexcept { return; // don't free after all } } - + #endif _mi_page_free(page, pq, false); } @@ -753,6 +754,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p size_t candidate_count = 0; // we reset this on the first candidate to limit the search mi_page_t* page_candidate = NULL; // a page with free space mi_page_t* page = pq->first; + while (page != NULL) { mi_page_t* next = page->next; // remember next @@ -764,7 +766,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // collect freed blocks by us and other threads _mi_page_free_collect(page, false); -#if defined(MI_MAX_CANDIDATE_SEARCH) + #if MI_MAX_CANDIDATE_SEARCH > 1 // search up to N pages for a best candidate // is the local free list non-empty? @@ -783,7 +785,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p page_candidate = page; candidate_count = 0; } - else if (!mi_page_is_expandable(page) && page->used >= page_candidate->used) { + else if (/* !mi_page_is_expandable(page) && */ page->used >= page_candidate->used) { page_candidate = page; } // if we find a non-expandable candidate, or searched for N pages, return with the best candidate @@ -792,7 +794,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p break; } } -#else + #else // first-fit algorithm // If the page contains free blocks, we are done if (mi_page_immediate_available(page) || mi_page_is_expandable(page)) { @@ -803,7 +805,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // queue so we don't visit long-lived pages too often. mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); mi_page_to_full(page, pq); -#endif + #endif page = next; } // for each page @@ -828,10 +830,14 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p } } else { - // mi_assert(pq->first == page); + // move the page to the front of the queue + mi_page_queue_move_to_front(heap, pq, page); page->retire_expire = 0; + // _mi_heap_collect_retired(heap, false); // update retire counts; note: increases rss on MemoryLoad bench so don't do this } mi_assert_internal(page == NULL || mi_page_immediate_available(page)); + + return page; } @@ -839,7 +845,9 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // Find a page with free blocks of `size`. static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { - mi_page_queue_t* pq = mi_page_queue(heap,size); + mi_page_queue_t* pq = mi_page_queue(heap, size); + + // check the first page: we even do this with candidate search or otherwise we re-search every time mi_page_t* page = pq->first; if (page != NULL) { #if (MI_SECURE>=3) // in secure mode, we extend half the time to increase randomness @@ -858,6 +866,7 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { return page; // fast path } } + return mi_page_queue_find_free_ex(heap, pq, true); } diff --git a/src/segment.c b/src/segment.c index d2604436..16764da8 100644 --- a/src/segment.c +++ b/src/segment.c @@ -979,6 +979,13 @@ void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld) { _mi_arena_field_cursor_done(¤t); } + +static bool segment_count_is_within_target(mi_segments_tld_t* tld, size_t* ptarget) { + const size_t target = (size_t)mi_option_get_clamp(mi_option_target_segments_per_thread, 0, 1024); + if (ptarget != NULL) { *ptarget = target; } + return (target == 0 || tld->count < target); +} + static long mi_segment_get_reclaim_tries(mi_segments_tld_t* tld) { // limit the tries to 10% (default) of the abandoned segments with at least 8 and at most 1024 tries. const size_t perc = (size_t)mi_option_get_clamp(mi_option_max_segment_reclaim, 0, 100); @@ -1001,7 +1008,7 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, mi_segment_t* segment = NULL; mi_arena_field_cursor_t current; _mi_arena_field_cursor_init(heap, tld->subproc, false /* non-blocking */, ¤t); - while ((max_tries-- > 0) && ((segment = _mi_arena_segment_clear_abandoned_next(¤t)) != NULL)) + while (segment_count_is_within_target(tld,NULL) && (max_tries-- > 0) && ((segment = _mi_arena_segment_clear_abandoned_next(¤t)) != NULL)) { mi_assert(segment->subproc == heap->tld->segments.subproc); // cursor only visits segments in our sub-process segment->abandoned_visits++; @@ -1026,7 +1033,7 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, result = mi_segment_reclaim(segment, heap, block_size, reclaimed, tld); break; } - else if (segment->abandoned_visits > 3 && is_suitable && !mi_option_is_enabled(mi_option_target_segments_per_thread)) { + else if (segment->abandoned_visits > 3 && is_suitable) { // always reclaim on 3rd visit to limit the abandoned segment count. mi_segment_reclaim(segment, heap, 0, NULL, tld); } @@ -1087,15 +1094,11 @@ static void mi_segment_force_abandon(mi_segment_t* segment, mi_segments_tld_t* t // try abandon segments. // this should be called from `reclaim_or_alloc` so we know all segments are (about) fully in use. -static void mi_segments_try_abandon(mi_heap_t* heap, mi_segments_tld_t* tld) { - const size_t target = (size_t)mi_option_get_clamp(mi_option_target_segments_per_thread,0,1024); - // we call this when we are about to add a fresh segment so we should be under our target segment count. - if (target == 0 || tld->count < target) return; - +static void mi_segments_try_abandon_to_target(mi_heap_t* heap, size_t target, mi_segments_tld_t* tld) { + if (target <= 1) return; const size_t min_target = (target > 4 ? (target*3)/4 : target); // 75% - // todo: we should maintain a list of segments per thread; for now, only consider segments from the heap full pages - for (int i = 0; i < 16 && tld->count >= min_target; i++) { + for (int i = 0; i < 64 && tld->count >= min_target; i++) { mi_page_t* page = heap->pages[MI_BIN_FULL].first; while (page != NULL && mi_page_is_huge(page)) { page = page->next; @@ -1109,6 +1112,25 @@ static void mi_segments_try_abandon(mi_heap_t* heap, mi_segments_tld_t* tld) { } } +// try abandon segments. +// this should be called from `reclaim_or_alloc` so we know all segments are (about) fully in use. +static void mi_segments_try_abandon(mi_heap_t* heap, mi_segments_tld_t* tld) { + // we call this when we are about to add a fresh segment so we should be under our target segment count. + size_t target = 0; + if (segment_count_is_within_target(tld, &target)) return; + mi_segments_try_abandon_to_target(heap, target, tld); +} + +void mi_collect_reduce(size_t target_size) mi_attr_noexcept { + mi_collect(true); + mi_heap_t* heap = mi_heap_get_default(); + mi_segments_tld_t* tld = &heap->tld->segments; + size_t target = target_size / MI_SEGMENT_SIZE; + if (target == 0) { + target = (size_t)mi_option_get_clamp(mi_option_target_segments_per_thread, 1, 1024); + } + mi_segments_try_abandon_to_target(heap, target, tld); +} /* ----------------------------------------------------------- Reclaim or allocate From 7673aa2517fa44080c51df8833aa7e79dad12ea8 Mon Sep 17 00:00:00 2001 From: daanx Date: Mon, 25 Nov 2024 18:41:57 -0800 Subject: [PATCH 072/131] ensure forced abandoned pages can be accessed after free --- include/mimalloc/types.h | 3 ++- src/page.c | 6 ++---- src/segment.c | 38 ++++++++++++++++++++++---------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index f7bca137..44074450 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -416,7 +416,8 @@ typedef struct mi_segment_s { // segment fields struct mi_segment_s* next; // must be the first (non-constant) segment field -- see `segment.c:segment_init` struct mi_segment_s* prev; - bool was_reclaimed; // true if it was reclaimed (used to limit on-free reclamation) + bool was_reclaimed; // true if it was reclaimed (used to limit reclaim-on-free reclamation) + bool dont_free; // can be temporarily true to ensure the segment is not freed size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) size_t abandoned_visits; // count how often this segment is visited for reclaiming (to force reclaim if it is too long) diff --git a/src/page.c b/src/page.c index 43ac7c4e..c681d6d0 100644 --- a/src/page.c +++ b/src/page.c @@ -411,10 +411,8 @@ void _mi_page_force_abandon(mi_page_t* page) { // ensure this page is no longer in the heap delayed free list _mi_heap_delayed_free_all(heap); - // TODO: can we still access the page as it may have been - // freed and the memory decommitted? - // A way around this is to explicitly unlink this page from - // the heap delayed free list. + // We can still access the page meta-info even if it is freed as we ensure + // in `mi_segment_force_abandon` that the segment is not freed (yet) if (page->capacity == 0) return; // it may have been freed now // and now unlink it from the page queue and abandon (or free) diff --git a/src/segment.c b/src/segment.c index 16764da8..74abcdbc 100644 --- a/src/segment.c +++ b/src/segment.c @@ -652,6 +652,10 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) { MI_UNUSED(force); mi_assert(segment != NULL); + + // in `mi_segment_force_abandon` we set this to true to ensure the segment's memory stays valid + if (segment->dont_free) return; + // don't purge as we are freeing now mi_segment_remove_all_purges(segment, false /* don't force as we are about to free */, tld); mi_segment_remove_from_free_queue(segment, tld); @@ -1056,32 +1060,34 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, static void mi_segment_force_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { mi_assert_internal(segment->abandoned < segment->used); + mi_assert_internal(!segment->dont_free); + + // ensure the segment does not get free'd underneath us (so we can check if a page has been freed in `mi_page_force_abandon`) + segment->dont_free = true; // for all pages for (size_t i = 0; i < segment->capacity; i++) { mi_page_t* page = &segment->pages[i]; if (page->segment_in_use) { - // ensure used count is up to date and collect potential concurrent frees - _mi_page_free_collect(page, false); - { - // abandon the page if it is still in-use (this will free it if possible as well) - mi_assert_internal(segment->used > 0); - if (segment->used == segment->abandoned+1) { - // the last page.. abandon and return as the segment will be abandoned after this - // and we should no longer access it. - _mi_page_force_abandon(page); - return; - } - else { - // abandon and continue - _mi_page_force_abandon(page); - } + // abandon the page if it is still in-use (this will free the page if possible as well (but not our segment)) + mi_assert_internal(segment->used > 0); + if (segment->used == segment->abandoned+1) { + // the last page.. abandon and return as the segment will be abandoned after this + // and we should no longer access it. + segment->dont_free = false; + _mi_page_force_abandon(page); + return; + } + else { + // abandon and continue + _mi_page_force_abandon(page); } } } + segment->dont_free = false; mi_assert(segment->used == segment->abandoned); mi_assert(segment->used == 0); - if (segment->used == 0) { + if (segment->used == 0) { // paranoia // all free now mi_segment_free(segment, false, tld); } From bdc87fc91b3654f73a5c0ea78ccb210769c84244 Mon Sep 17 00:00:00 2001 From: Joris van der Geer Date: Mon, 2 Dec 2024 20:50:08 +1000 Subject: [PATCH 073/131] readme - describe how to run under Valgrind with dynamic override --- readme.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index a0296b43..5c85392e 100644 --- a/readme.md +++ b/readme.md @@ -505,9 +505,13 @@ you also need to tell `valgrind` to not intercept those calls itself, and use: By setting the `MIMALLOC_SHOW_STATS` environment variable you can check that mimalloc is indeed used and not the standard allocator. Even though the [Valgrind option][valgrind-soname] -is called `--soname-synonyms`, this also -works when overriding with a static library or object file. Unfortunately, it is not possible to -dynamically override mimalloc using `LD_PRELOAD` together with `valgrind`. +is called `--soname-synonyms`, this also works when overriding with a static library or object file. +To dynamically override mimalloc using `LD_PRELOAD` together with `valgrind`, use: + +``` +> valgrind --trace-children=yes --soname-synonyms=somalloc=*mimalloc* /usr/bin/env LD_PRELOAD=/usr/lib/libmimalloc.so -- +``` + See also the `test/test-wrong.c` file to test with `valgrind`. Valgrind support is in its initial development -- please report any issues. From 469ade882dbff3226be92e71e2d75d04d84029b1 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 7 Dec 2024 14:03:16 -0800 Subject: [PATCH 074/131] 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 075/131] 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 076/131] 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 077/131] 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 078/131] 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 079/131] 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 080/131] 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 081/131] 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 082/131] 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 083/131] 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 084/131] 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 085/131] 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 086/131] 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 087/131] 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 088/131] 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 089/131] 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] // From ac52b6967d06bac6515e8325c9dd34121154a6b5 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Tue, 17 Dec 2024 00:06:03 -0800 Subject: [PATCH 090/131] update arm64 redirection --- bin/mimalloc-redirect-arm64.dll | Bin 80896 -> 53760 bytes test/test-stress.c | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/mimalloc-redirect-arm64.dll b/bin/mimalloc-redirect-arm64.dll index 0cae1d5170e37a11e6e767b24f102a8811e322e5..2b1d3e355ccd3bb8aa3442f90f3490a3a4a167f0 100644 GIT binary patch delta 10318 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 u`8z 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 Date: Tue, 17 Dec 2024 00:35:28 -0800 Subject: [PATCH 091/131] make timeout for tests in the pipeline up to 4 min --- azure-pipelines.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eb520aa0..bccf7a3f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: solution: $(BuildType)/libmimalloc.sln configuration: '$(MSBuildConfiguration)' msbuildArguments: -m - - script: ctest --verbose --timeout 180 -C $(MSBuildConfiguration) + - script: ctest --verbose --timeout 240 -C $(MSBuildConfiguration) workingDirectory: $(BuildType) displayName: CTest #- script: $(BuildType)\$(BuildType)\mimalloc-test-stress @@ -126,7 +126,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(nproc) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest env: @@ -157,7 +157,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest # - upload: $(Build.SourcesDirectory)/$(BuildType) @@ -192,7 +192,7 @@ jobs: solution: $(BuildType)/libmimalloc.sln configuration: '$(MSBuildConfiguration)' msbuildArguments: -m - - script: ctest --verbose --timeout 180 -C $(MSBuildConfiguration) + - script: ctest --verbose --timeout 240 -C $(MSBuildConfiguration) workingDirectory: $(BuildType) displayName: CTest @@ -235,7 +235,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(nproc) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest @@ -278,7 +278,7 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(nproc) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest @@ -302,6 +302,6 @@ jobs: cmakeArgs: .. $(cmakeExtraArgs) - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType) displayName: Make - - script: ctest --verbose --timeout 180 + - script: ctest --verbose --timeout 240 workingDirectory: $(BuildType) displayName: CTest From c2e0aa49c46894d4fe41037067a9048c1094ab3f Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 17 Dec 2024 16:07:18 -0800 Subject: [PATCH 092/131] update minject to v1.1 --- bin/minject-arm64.exe | Bin 20992 -> 20992 bytes bin/minject.exe | Bin 22016 -> 22016 bytes bin/minject32.exe | Bin 18944 -> 18944 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/minject-arm64.exe b/bin/minject-arm64.exe index 63987afcacc42511aca435e78a70d56a64163ff2..97188c4f14e644b66d938ce44a940f3058153a13 100644 GIT binary patch delta 1887 zcmeIyPe_wt90%~<`}&79E38b#L?)P+$x;&&v3jKuDkjUO){>YtY(WQ!AtJ(dD3DI+ z>%mL0LSj^e_;v{CVB*1p$PN;o!u}j2q9i(ui0J$5{jO%W?!GWS`+c9^^JinvqBB}_ zMw@kLS^BQ4W}bFOU-OxhTD4X>QGUo=*8=)dsnx7Mt#m%jn{bFE3SQ@#U#qS--?7wo zqinZgM*@0e>$0St#(vvDdYgKwle(zgEwbKczkAHQg)XwObVhTxgyRn{<}? z>3qLc?Ow~xaShkG>#Sc5_j9aR^ORPIpW$`2&K|r%x=7TESBt4-HCiJlTeL_51MXYF zf$)Gmrh4qUVsvygn3}xVErQ=F^6<5a_SROl-qyCvpZXe-nVHY-lM5MheRiJ%*@}ks zMuKNj8?X69UZ@RjsDo70s}06`M2i1r$5j?X)}#(-_cf?&z0Vpx-K$47FqVFr@TC|A zK2UEu5y{47+CWytAG;cRv6w zQrNUlq!z}Z0TZwjy7r3%VJ!?p1CBw@0g)-_g)ta_FJTle!M20AYOtV4cc$_XjGYfzd9a$D}F4BD3J6l-uok~HTpH1 zAB9=zpEzNW-D?U3hrUH)EAuAP$ds9>Of4G8o3zza))TL2_7>}3nD3ds?fc#In>YMq z-e-miw6bk%)|9(fLmrK;oi@jXqI7JVm@2b4NH@`WF7TWk^USZz4JL7+Pt0UyCi4ul zn0bM@&K%}EFWFuYME$=bj{~xqQ5^V)+0BhsF_SrNi0$u82Xllu%bZ|_3NFLe3nPXT zO>@91)5kP1r(68l`nP-i5&2Id{f~m*DSK6QsL z7Pe92uGhgZ|1T3uE|ptn_YpxK!N0|RQCc<9x7BAhPhE?Z`0S((VS zwoPjezSs3|twD?1+@@)9)IhW(Az!~*9xS|MCYlii+C?LoXG8%{BT?!C2Z=_&I&d7c zfK#9coCS@CkONFgA^HFsQmCHRu?RpQG~zpnW978CT_;KdyEo;txc@FqQxS diff --git a/bin/minject.exe b/bin/minject.exe index dba8f80fd2a0ef8b0137d50a8e67996c5b84a9c9..53c42f5d6dc7f643c03e832ff9e0aff42b2fc265 100644 GIT binary patch delta 10296 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 XSWvGy4SYjULvce%LwN&~I@tdPn9V1t delta 9946 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%0DVy0e+#w&*e+l+?3>Rs^t`bhntS{I_mhnMZ%?w` z7feMm<}Tq+)|uW}l9dj3nWv+}(eAG9*uKTl*}1BPWZit8`U+tGjh`TkCE|O=WARy8=_lW71WfD;)QF?z_*?QQhI_#4E@f z^4fOi=Ju90M~i*e7DwI=ckA|c*l{~L2-zvGak&3Yeyf-hj@V|UJxrab+TP-6b5um_ zpsq56_iQQ5LE&TD!%vo~71$SK%_p{#y}r@|j1ZJKdy`gNXS{S9FzjM>BkN_KW#49h z#r~fCD?3e_uGMRsv_I5-q*dxNbjx*3x?Q?H{crV(d{cgZezxI$!%K!Ytxq|S#f&tv&AnJzgc{~ z_@m-*vCN$0HP1B9H!n38nqM&g#{5U~Kh4>er51yw*|Nj(kcG26Yx$|=q-D_Z2g_B9 z)S6+{ShZHGwbI&X-D-W%y5IV;^=)g=dcpds^=m64$;L^8KxJ$)JD1I4JK1jb6#FH+ zP`gq4q_$uCtyZVos(W5{Q76-9>&x_<-utBf2l^NFefkmoH~O^v1^I>f4f*@?f0F-U z{&;@6!D?7<_@3dA;W@+0hBpjf88Qp}1+N!`3eFV#uHbJ4UlowTqQcF~1IvTUKUx0u za-}iZm~Nb7)EJi-S)<*!!MNFYpYb81-#BUv8?%daMLUapMO@L-MXwcoQuOyCscD+m zRA6c{IZXGP9x<&hb``se4;Q~*e7U&5Y&EYi*PHJ*?=bt#N6e?p#3HxMw9L2US$=Q% z(DI38o;A;Euv)A&)+Q@&J#77<^;PRz)=SnuS+7~ITM6pF8wr_)Ow49AY$0oB?_}4q z^=vb{g>|tz*H+@N>G~%{tpi@_0a$T From 617190880daf359249844aa447b28aabe9d28434 Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 17 Dec 2024 17:53:34 -0800 Subject: [PATCH 093/131] add ajust stats to compensate for double counting --- include/mimalloc/types.h | 15 ++++++++++++--- src/stats.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 3d8014c3..ad948d36 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -609,18 +609,27 @@ typedef struct mi_stats_s { } mi_stats_t; +// add to stat keeping track of the peak void _mi_stat_increase(mi_stat_count_t* stat, size_t amount); void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount); +// adjust stat in special cases to compensate for double counting +void _mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount); +void _mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount); +// counters can just be increased void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount); #if (MI_STAT) #define mi_stat_increase(stat,amount) _mi_stat_increase( &(stat), amount) #define mi_stat_decrease(stat,amount) _mi_stat_decrease( &(stat), amount) #define mi_stat_counter_increase(stat,amount) _mi_stat_counter_increase( &(stat), amount) +#define mi_stat_adjust_increase(stat,amount) _mi_stat_adjust_increase( &(stat), amount) +#define mi_stat_adjust_decrease(stat,amount) _mi_stat_adjust_decrease( &(stat), amount) #else -#define mi_stat_increase(stat,amount) (void)0 -#define mi_stat_decrease(stat,amount) (void)0 -#define mi_stat_counter_increase(stat,amount) (void)0 +#define mi_stat_increase(stat,amount) ((void)0) +#define mi_stat_decrease(stat,amount) ((void)0) +#define mi_stat_counter_increase(stat,amount) ((void)0) +#define mi_stat_adjuct_increase(stat,amount) ((void)0) +#define mi_stat_adjust_decrease(stat,amount) ((void)0) #endif #define mi_heap_stat_counter_increase(heap,stat,amount) mi_stat_counter_increase( (heap)->tld->stats.stat, amount) diff --git a/src/stats.c b/src/stats.c index 29376ace..8566e8f2 100644 --- a/src/stats.c +++ b/src/stats.c @@ -26,7 +26,7 @@ static bool mi_is_in_main(void* stat) { static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { if (amount == 0) return; - if (mi_is_in_main(stat)) + if mi_unlikely(mi_is_in_main(stat)) { // add atomically (for abandoned pages) int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount); @@ -51,6 +51,27 @@ static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { } } +// Adjust stats to compensate; for example before committing a range, +// first adjust downwards with parts that were already committed so +// we avoid double counting. +static void mi_stat_adjust(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + if mi_unlikely(mi_is_in_main(stat)) + { + // adjust atomically + mi_atomic_addi64_relaxed(&stat->current, amount); + mi_atomic_addi64_relaxed(&stat->allocated, amount); + mi_atomic_addi64_relaxed(&stat->freed, amount); + } + else { + // don't affect the peak + stat->current += amount; + // add to both + stat->allocated += amount; + stat->freed += amount; + } +} + void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) { if (mi_is_in_main(stat)) { mi_atomic_addi64_relaxed( &stat->count, 1 ); @@ -70,6 +91,14 @@ void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { mi_stat_update(stat, -((int64_t)amount)); } +void _mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust(stat, (int64_t)amount); +} + +void _mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust(stat, -((int64_t)amount)); +} + // must be thread safe as it is called from stats_merge static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) { if (stat==src) return; From 636d646b9ca9a20fe23239150da823844804dd44 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 18 Dec 2024 14:20:49 -0800 Subject: [PATCH 094/131] update arch detection in cmake --- CMakeLists.txt | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 490cb483..c329d385 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,7 +146,7 @@ if(MI_OVERRIDE) endif() endif() -if(WIN32) +if(WIN32) if (NOT MI_WIN_REDIRECT) # use a negative define for backward compatibility list(APPEND mi_defines MI_WIN_NOREDIRECT=1) @@ -324,19 +324,24 @@ endif() # Determine architecture set(MI_OPT_ARCH_FLAGS "") 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") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|i[3456]86" OR CMAKE_GENERATOR_PLATFORM MATCHES "x86|Win32") + set(MI_ARCH "x86") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|x64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") set(MI_ARCH "x64") -elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|armv8.?" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM64") set(MI_ARCH "arm64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") + set(MI_ARCH "arm32") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv") + if(CMAKE_SIZEOF_VOID_P==4) + set(MI_ARCH "riscv32") + else + set(MI_ARCH "riscv64") + endif() +else() + set(MI_ARCH ${CMAKE_SYSTEM_PROCESSOR}) endif() +message(STATUS "Architecture: ${MI_ARCH}") # 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) @@ -528,12 +533,12 @@ if(MI_BUILD_SHARED) ) if(WIN32 AND MI_WIN_REDIRECT) # On windows, link and copy the mimalloc redirection dll too. - if(MI_ARCH STREQUAL "arm64") - set(MIMALLOC_REDIRECT_SUFFIX "-arm64") - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + if(MI_ARCH STREQUAL "x64") + set(MIMALLOC_REDIRECT_SUFFIX "") + elseif(MI_ARCH STREQUAL "x86") set(MIMALLOC_REDIRECT_SUFFIX "32") else() - set(MIMALLOC_REDIRECT_SUFFIX "") + set(MIMALLOC_REDIRECT_SUFFIX "-${MI_ARCH}") # -arm64 etc. endif() target_link_libraries(mimalloc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect${MIMALLOC_REDIRECT_SUFFIX}.lib) From 515ae84174fb1d91e2523a8b2ef3162b5c0aa7c0 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 18 Dec 2024 14:35:10 -0800 Subject: [PATCH 095/131] syntax error --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c329d385..859c0e23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 17) option(MI_SECURE "Use full security mitigations (like guard pages, allocation randomization, double-free mitigation, and free-list corruption detection)" OFF) option(MI_DEBUG_FULL "Use full internal heap invariant checking in DEBUG mode (expensive)" OFF) option(MI_PADDING "Enable padding to detect heap block overflow (always on in DEBUG or SECURE mode, or with Valgrind/ASAN)" OFF) -option(MI_OVERRIDE "Override the standard malloc interface (e.g. define entry points for malloc() etc)" ON) +option(MI_OVERRIDE "Override the standard malloc interface (i.e. define entry points for 'malloc', 'free', etc)" ON) option(MI_XMALLOC "Enable abort() call on memory allocation failure by default" OFF) option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF) option(MI_TRACK_VALGRIND "Compile with Valgrind support (adds a small overhead)" OFF) @@ -326,7 +326,7 @@ set(MI_OPT_ARCH_FLAGS "") set(MI_ARCH "unknown") if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|i[3456]86" OR CMAKE_GENERATOR_PLATFORM MATCHES "x86|Win32") set(MI_ARCH "x86") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|x64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|x64|amd64|AMD64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") set(MI_ARCH "x64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|armv8.?" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM64") set(MI_ARCH "arm64") @@ -335,7 +335,7 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv") if(CMAKE_SIZEOF_VOID_P==4) set(MI_ARCH "riscv32") - else + else() set(MI_ARCH "riscv64") endif() else() From 69d2b4e991a15b2564ac21b0b555147825f24fa9 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 18 Dec 2024 14:41:20 -0800 Subject: [PATCH 096/131] add comments/doc --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 859c0e23..e216a4a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ 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) option(MI_WIN_REDIRECT "Use redirection module ('mimalloc-redirect') on Windows if compiling mimalloc as a DLL" ON) -option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF) +option(MI_LOCAL_DYNAMIC_TLS "Use local-dynamic-tls, a slightly slower but dlopen-compatible thread local storage mechanism (Unix)" OFF) option(MI_LIBC_MUSL "Set this when linking with musl libc" OFF) option(MI_BUILD_SHARED "Build shared library" ON) option(MI_BUILD_STATIC "Build static library" ON) @@ -162,8 +162,8 @@ if(MI_TRACK_VALGRIND) CHECK_INCLUDE_FILES("valgrind/valgrind.h;valgrind/memcheck.h" MI_HAS_VALGRINDH) if (NOT MI_HAS_VALGRINDH) set(MI_TRACK_VALGRIND OFF) - message(WARNING "Cannot find the 'valgrind/valgrind.h' and 'valgrind/memcheck.h' -- install valgrind first") - message(STATUS "Compile **without** Valgrind support (MI_TRACK_VALGRIND=OFF)") + message(WARNING "Cannot find the 'valgrind/valgrind.h' and 'valgrind/memcheck.h' -- install valgrind first?") + message(STATUS "Disabling Valgrind support (MI_TRACK_VALGRIND=OFF)") else() message(STATUS "Compile with Valgrind support (MI_TRACK_VALGRIND=ON)") list(APPEND mi_defines MI_TRACK_VALGRIND=1) @@ -317,7 +317,7 @@ if(MI_LIBC_MUSL) endif() if(MI_WIN_USE_FLS) - message(STATUS "Use the Fiber API to detect thread termination") + message(STATUS "Use the Fiber API to detect thread termination (MI_WIN_USE_FLS=ON)") list(APPEND mi_defines MI_WIN_USE_FLS=1) endif() From 61a112cde5c083c6fa0ba71374adccabdf0b8b4a Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 18 Dec 2024 14:45:44 -0800 Subject: [PATCH 097/131] fix MI_ARCH test --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e216a4a3..8896dfd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,15 +324,15 @@ endif() # Determine architecture set(MI_OPT_ARCH_FLAGS "") set(MI_ARCH "unknown") -if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|i[3456]86" OR CMAKE_GENERATOR_PLATFORM MATCHES "x86|Win32") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|i[3456]86)$" OR CMAKE_GENERATOR_PLATFORM MATCHES "^(x86|Win32)$") set(MI_ARCH "x86") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|x64|amd64|AMD64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|x64|amd64|AMD64)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") set(MI_ARCH "x64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|armv8.?" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8.?)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") set(MI_ARCH "arm64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|armv[34567])$") set(MI_ARCH "arm32") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv|riscv32|riscv64)$") if(CMAKE_SIZEOF_VOID_P==4) set(MI_ARCH "riscv32") else() From 27d929f338a7da875a734920f473e04562c5bfc3 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Wed, 18 Dec 2024 23:55:37 -0800 Subject: [PATCH 098/131] add support for arm64ec --- bin/mimalloc-redirect-arm64.dll | Bin 53760 -> 55296 bytes bin/mimalloc-redirect-arm64ec.dll | Bin 0 -> 100864 bytes bin/mimalloc-redirect-arm64ec.lib | Bin 0 -> 3308 bytes bin/mimalloc-redirect.dll | Bin 70656 -> 54272 bytes bin/mimalloc-redirect.lib | Bin 2874 -> 2874 bytes bin/mimalloc-redirect32.dll | Bin 48128 -> 35840 bytes bin/mimalloc-redirect32.lib | Bin 2928 -> 2928 bytes 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 | 28 +++++- ide/vs2022/mimalloc.vcxproj | 113 ++++++++++++++++++++++ test/main-override.cpp | 3 + 15 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 bin/mimalloc-redirect-arm64ec.dll create mode 100644 bin/mimalloc-redirect-arm64ec.lib diff --git a/bin/mimalloc-redirect-arm64.dll b/bin/mimalloc-redirect-arm64.dll index 2b1d3e355ccd3bb8aa3442f90f3490a3a4a167f0..98268796c03f790362d628c25ab684a96a6b4fd4 100644 GIT binary patch delta 8358 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 literal 0 HcmV?d00001 diff --git a/bin/mimalloc-redirect-arm64ec.lib b/bin/mimalloc-redirect-arm64ec.lib new file mode 100644 index 0000000000000000000000000000000000000000..1c7c368fc6ae255df671dd2ca96ae9e66ef76659 GIT binary patch literal 3308 zcmc&$&1(}u6n{xtTVs*<0iIeS7OX;>G)-a)rEI@wOVg$#DcI9=n_cZf(v)qg0S{7I zdJyrS5Ij`yA}C%;LA=zf$BHNM*n=nq1${F+v)N5{lP*XdNM`0YZ+3p~&HI?^!?K=V z9SKIl_SV~PpNm#6uB&S$HdZA9DKpwcMf1W1PP)CTrSCB z=)%DzJWt3`T!Qd{ANy{=M1!rfVbI=$D0UY9lera6 z&CJj8bz6rSjb>_0WVB(s00D5vjAaN>#0GKj~DnfD7wm3HUT2=DH1H{ih8GH7)SaQ(JnaZ9Y9*$IwKAI{4 zIC-3c>(*xRxB-Dvk9#X7yr&*_MxJyUZ|Fo?uEpJJsimsy{i7^`-JXI4WF XtR87whiT+A?aWHNLcCEkb_M?eX{j9D literal 0 HcmV?d00001 diff --git a/bin/mimalloc-redirect.dll b/bin/mimalloc-redirect.dll index 4702fec0175e66168151f1d995a6148a0e69a1eb..5dee3713751104a965b40d13f21bbaac571b99f5 100644 GIT binary patch delta 13047 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 diff --git a/bin/mimalloc-redirect.lib b/bin/mimalloc-redirect.lib index 7d5f19cee2052225b3f95447945c4b937371c055..851455a50a661f904b6a977f203e77a6e04d9958 100644 GIT binary patch delta 100 zcmdlbwo7b-1Pe>dy|ZU0%dqTV(PC(Bo1Dd=Joz_^15?saGKI(E2rZK&ktjU1g!01|H^egFUf delta 100 zcmdlbwo7b-1Pe<;VeF5|GAuh-G#R{GCueaePyWr~z~tS!*_Kt8k!2#E^XtiZY!eW& kog6$s*~zx7Qj>kzV_7x@#9p7gjvcOD8!EYZBS$9_0B67-?*IS* diff --git a/bin/mimalloc-redirect32.dll b/bin/mimalloc-redirect32.dll index 17c0555027cd73317e893549e9831235c35d4d83..1bb909e199e55ff9212e913471866c86e0a9bf59 100644 GIT binary patch delta 11168 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 b&O-=^=4o>X8V?k|RypZ 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 diff --git a/bin/mimalloc-redirect32.lib b/bin/mimalloc-redirect32.lib index a7100afcbe011e36358bedf663a5e77a7bdae736..45d7297d8ebd45aee3b18c8a0bc71a691ec862d7 100644 GIT binary patch delta 118 zcmew$_Caie84C-q{=@^5typ%kXfZUmP1a&ppDfR6$JE@mIiA&!kuzxNw&zC~7#Nr) z+p|bd-ojP{Q>G78GC7`AYH}%iENAa+`AZL>s>~(}a@50ANl#wS!2wmd`7*~`CIFm& BByj)$ delta 118 zcmew$_Caie84JryC+YK(typ%kXfk-WPS#>qpDfR6$K>6*IiA&!k<&tj_194b1_q|d z_AJtqx3Cq#l<5PNOpa%jnq0~r%Xuc!`Nc!1DznLg9Q80&(v#P7a6naVzRWR~2>=MW BA`Som diff --git a/ide/vs2022/mimalloc-override-test.vcxproj b/ide/vs2022/mimalloc-override-test.vcxproj index ff5d53d0..97803b9c 100644 --- a/ide/vs2022/mimalloc-override-test.vcxproj +++ b/ide/vs2022/mimalloc-override-test.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -55,6 +63,11 @@ true v143 + + Application + true + v143 + Application false @@ -67,6 +80,12 @@ v143 true + + Application + false + v143 + true + @@ -84,12 +103,18 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -107,6 +132,10 @@ $(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)\ @@ -115,6 +144,10 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -185,6 +218,30 @@ + + + Level3 + Disabled + true + true + ..\..\include + MultiThreadedDebugDLL + Sync + Default + false + + + Console + + + kernel32.lib;%(AdditionalDependencies) + + + + + + + Level3 @@ -258,6 +315,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 16a48740..9de18895 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -54,6 +62,11 @@ true v143 + + DynamicLibrary + true + v143 + DynamicLibrary false @@ -64,6 +77,11 @@ false v143 + + DynamicLibrary + false + v143 + @@ -81,12 +99,18 @@ + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -112,6 +136,12 @@ .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)\ @@ -124,6 +154,12 @@ .dll mimalloc-override + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .dll + mimalloc-override + Level3 @@ -208,6 +244,34 @@ copy mimalloc-redirect-arm64.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-arm64ec.lib;%(AdditionalDependencies) + + + + + Default + false + + + COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect-arm64ec.dll" "$(OutputPath)" + + + copy mimalloc-redirect-arm64ec.dll to the output directory + + Level3 @@ -305,6 +369,39 @@ copy mimalloc-redirect-arm64.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-arm64ec.lib;%(AdditionalDependencies) + + + Default + false + + + COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect-arm64ec.dll" "$(OutputPath)" + + + copy mimalloc-redirect-arm64ec.dll to the output directory + + @@ -324,16 +421,20 @@ false false false + false false false + false true true true true + true true true + true @@ -342,8 +443,10 @@ true true true + true true true + true @@ -356,8 +459,10 @@ true true true + true true true + true @@ -366,8 +471,10 @@ true true true + true true true + true diff --git a/ide/vs2022/mimalloc-test-api.vcxproj b/ide/vs2022/mimalloc-test-api.vcxproj index babe7f96..27247569 100644 --- a/ide/vs2022/mimalloc-test-api.vcxproj +++ b/ide/vs2022/mimalloc-test-api.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -55,6 +63,11 @@ true v143 + + Application + true + v143 + Application false @@ -67,6 +80,12 @@ v143 true + + Application + false + v143 + true + @@ -84,12 +103,18 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -107,6 +132,10 @@ $(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)\ @@ -115,6 +144,10 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -151,6 +184,18 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + Level3 @@ -202,18 +247,38 @@ Console + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + + + true + true + Console + + true true true true + true true true + true false false + false diff --git a/ide/vs2022/mimalloc-test-stress.vcxproj b/ide/vs2022/mimalloc-test-stress.vcxproj index c033aaeb..fd88cd8e 100644 --- a/ide/vs2022/mimalloc-test-stress.vcxproj +++ b/ide/vs2022/mimalloc-test-stress.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -55,6 +63,11 @@ true v143 + + Application + true + v143 + Application false @@ -67,6 +80,12 @@ v143 true + + Application + false + v143 + true + @@ -84,12 +103,18 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -107,6 +132,10 @@ $(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)\ @@ -115,6 +144,10 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -151,6 +184,18 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + + + Console + + Level3 @@ -203,14 +248,34 @@ Console + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include + %(PreprocessorDefinitions);NDEBUG + CPUExtensionRequirementsARMv81 + + + true + true + Console + + false false false + false false false false + false diff --git a/ide/vs2022/mimalloc-test.vcxproj b/ide/vs2022/mimalloc-test.vcxproj index bfd72287..fc9e9102 100644 --- a/ide/vs2022/mimalloc-test.vcxproj +++ b/ide/vs2022/mimalloc-test.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -55,6 +63,11 @@ true v143 + + Application + true + v143 + Application false @@ -67,6 +80,12 @@ v143 true + + Application + false + v143 + true + @@ -84,12 +103,18 @@ + + + + + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -107,6 +132,10 @@ $(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)\ @@ -115,6 +144,10 @@ $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + + $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + Level3 @@ -154,6 +187,19 @@ Console + + + Level3 + Disabled + true + true + ..\..\include + stdcpp17 + + + Console + + Level3 @@ -208,6 +254,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 e4a6538b..5a55c98b 100644 --- a/ide/vs2022/mimalloc.sln +++ b/ide/vs2022/mimalloc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.12.35527.113 d17.12 +VisualStudioVersion = 17.12.35527.113 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" EndProject @@ -18,81 +18,107 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 + Debug|ARM64EC = Debug|ARM64EC Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|ARM64 = Release|ARM64 + Release|ARM64EC = Release|ARM64EC 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|ARM64EC.ActiveCfg = Debug|ARM64EC + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|ARM64EC.Build.0 = Release|ARM64EC {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|ARM64EC.ActiveCfg = Debug|ARM64EC + {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|ARM64EC.Build.0 = Release|ARM64EC {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|ARM64EC.ActiveCfg = Debug|ARM64EC + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|ARM64EC.Build.0 = Release|ARM64EC {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|ARM64EC.ActiveCfg = Debug|ARM64EC + {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|ARM64EC.Build.0 = Release|ARM64EC {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|ARM64EC.ActiveCfg = Debug|ARM64EC + {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64EC.Build.0 = Release|ARM64EC {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|ARM64EC.ActiveCfg = Debug|ARM64EC + {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {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|ARM64EC.ActiveCfg = Release|ARM64EC + {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|ARM64EC.Build.0 = Release|ARM64EC {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 diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index fb13cd1f..34a9317a 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + ARM64EC + Debug Win32 @@ -13,6 +17,10 @@ Release ARM64 + + Release + ARM64EC + Release Win32 @@ -55,6 +63,11 @@ true v143 + + StaticLibrary + true + v143 + StaticLibrary false @@ -67,6 +80,12 @@ v143 true + + StaticLibrary + false + v143 + true + @@ -84,12 +103,18 @@ + + + + + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ @@ -115,6 +140,12 @@ .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)\ @@ -127,6 +158,12 @@ .lib mimalloc-static + + $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ + $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ + .lib + mimalloc-static + Level4 @@ -200,6 +237,33 @@ + + + Level4 + Disabled + true + Default + ../../include + MI_DEBUG=3;MI_GUARDED=0;%(PreprocessorDefinitions); + CompileAsCpp + false + stdcpp20 + + + + + + + + + + + + + + + + Level4 @@ -298,22 +362,62 @@ + + + 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 false + false true true true true + true true true + true @@ -322,21 +426,26 @@ true true true + true true true + true false false + false true true + true true true true true + true @@ -347,8 +456,10 @@ true true true + true true true + true @@ -356,8 +467,10 @@ true true true + true true true + true diff --git a/test/main-override.cpp b/test/main-override.cpp index 3d56ae42..e7499f2a 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -47,6 +47,9 @@ int main() { mi_stats_reset(); // ignore earlier allocations various_tests(); test_mixed1(); + const char* ptr = ::_Getdays(); + free((void*)ptr); + //test_std_string(); //test_thread_local(); // heap_thread_free_huge(); From 130227e39909d9ba078b84406fff3ea48caa887f Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 11:10:17 -0800 Subject: [PATCH 099/131] update redirection modules to v1.3 --- bin/mimalloc-redirect-arm64.dll | Bin 55296 -> 55296 bytes bin/mimalloc-redirect-arm64ec.dll | Bin 100864 -> 96768 bytes bin/mimalloc-redirect-arm64ec.lib | Bin 3308 -> 3308 bytes bin/mimalloc-redirect.dll | Bin 54272 -> 53760 bytes bin/mimalloc-redirect32.dll | Bin 35840 -> 35328 bytes bin/readme.md | 55 ++++++++++++++++++++++-------- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/bin/mimalloc-redirect-arm64.dll b/bin/mimalloc-redirect-arm64.dll index 98268796c03f790362d628c25ab684a96a6b4fd4..455f8394df8e935ddda80feb9acac3fbe2c9615e 100644 GIT binary patch delta 3442 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 delta 13100 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 diff --git a/bin/mimalloc-redirect-arm64ec.lib b/bin/mimalloc-redirect-arm64ec.lib index 1c7c368fc6ae255df671dd2ca96ae9e66ef76659..eb724d7405ec7783206578377aab5158d39c11b8 100644 GIT binary patch delta 64 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 U!}>1mpgxv%c{BC1=F5-$A16z~0ssI2 delta 7230 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 LP+-89B%k~*LBs2s delta 5732 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 diff --git a/bin/readme.md b/bin/readme.md index d133eea2..259d74d6 100644 --- a/bin/readme.md +++ b/bin/readme.md @@ -5,24 +5,26 @@ is robust and has the particular advantage to be able to redirect all malloc/fre the (dynamic) C runtime allocator, including those from other DLL's or libraries. As it intercepts all allocation calls on a low level, it can be used reliably on large programs that include other 3rd party components. -There are four requirements to make the overriding work robustly: +There are four requirements to make the overriding work well: 1. Use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). -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, 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. +2. Link your program explicitly with the `mimalloc-override.lib` export library for + the `mimalloc-override.dll` -- which contains all mimalloc functionality. + To ensure the `mimalloc-override.dll` is actually 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, 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` (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`). +3. The `mimalloc-redirect.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`). 4. Ensure the `mimalloc-override.dll` comes as early as possible in the import list of the final executable (so it can intercept all potential allocations). + You can use `minject -l ` to check this if needed. For best performance on Windows with C++, it is also recommended to also override the `new`/`delete` operations (by including @@ -32,17 +34,39 @@ a single(!) source file in your project). The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. -## Minject +### Other Platforms + +You always link with `mimalloc-override.dll` but for different platforms you may +need a specific `mimalloc-redirect.dll`: + +- __x64__: `mimalloc-redirect.dll`. +- __x86__: `mimalloc-redirect32.dll`. Use for older 32-bit Windows programs. +- __arm64__: `mimalloc-redirect-arm64.dll`. Use for native Windows arm64 programs. +- __arm64ec__: `mimalloc-redirect-arm64ec.dll`. The [arm64ec] ABI is "emulation compatible" + mode on Windows arm64. Unfortunately we cannot run x64 code emulated on Windows arm64 with + the x64 mimalloc override directly (since the C runtime always uses `arm64ec`). Instead: + 1. Build the program as normal for x64 and link as normal with the x64 + `mimalloc-override.lib` export library. + 2. Now separately build `mimalloc-override.dll` in `arm64ec` mode and _overwrite_ your + previous (x64) `mimalloc-override.dll` -- the loader can handle the mix of arm64ec + and x64 code. Now use `mimalloc-redirect-arm64ec.dll` in this case to match your + arm64ec `mimalloc-override.dll`. The main program stays as is and can be fully x64 + or contain more arm64ec modules. At runtime, the arm64ec `mimalloc-override.dll` will + run with native arm64 instructions while the rest of the program runs emulated x64. + +[arm64ec]: https://learn.microsoft.com/en-us/windows/arm/arm64ec + + +### Minject We cannot always re-link an executable with `mimalloc-override.dll`, and similarly, we cannot always -ensure the the DLL comes first in the import table of the final executable. +ensure that the DLL comes first in the import table of the final executable. In many cases though we can patch existing executables without any recompilation if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll` into the import table (and put `mimalloc-redirect.dll` in the same folder) Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388). 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: ``` @@ -72,3 +96,6 @@ examples: > minject --list myprogram.exe > minject --force --inplace myprogram.exe ``` + +For x86 32-bit binaries, use `minject32`, and for arm64 binaries use `minject-arm64`. + From 0c6235e1297844623af4d74b91ea56a917b089c6 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 11:37:42 -0800 Subject: [PATCH 100/131] add _base test for redirection --- test/main-override.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/main-override.cpp b/test/main-override.cpp index e7499f2a..c4300420 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -47,9 +47,7 @@ int main() { mi_stats_reset(); // ignore earlier allocations various_tests(); test_mixed1(); - const char* ptr = ::_Getdays(); - free((void*)ptr); - + //test_std_string(); //test_thread_local(); // heap_thread_free_huge(); @@ -110,6 +108,9 @@ static void various_tests() { t = new (tbuf) Test(42); t->~Test(); delete[] tbuf; + + const char* ptr = ::_Getdays(); // test _base overrid + free((void*)ptr); } class Static { From 2876b8c0c54de004fb87ecf7624781d8090acef3 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 11:42:38 -0800 Subject: [PATCH 101/131] update redirection readme --- bin/readme.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/bin/readme.md b/bin/readme.md index 259d74d6..d6c3775f 100644 --- a/bin/readme.md +++ b/bin/readme.md @@ -1,9 +1,9 @@ # Windows Override Dynamically overriding on mimalloc on Windows -is robust and has the particular advantage to be able to redirect all malloc/free calls that go through -the (dynamic) C runtime allocator, including those from other DLL's or libraries. -As it intercepts all allocation calls on a low level, it can be used reliably +is robust and has the particular advantage to be able to redirect all malloc/free calls +that go through the (dynamic) C runtime allocator, including those from other DLL's or +libraries. As it intercepts all allocation calls on a low level, it can be used reliably on large programs that include other 3rd party components. There are four requirements to make the overriding work well: @@ -11,8 +11,8 @@ There are four requirements to make the overriding work well: 2. Link your program explicitly with the `mimalloc-override.lib` export library for the `mimalloc-override.dll` -- which contains all mimalloc functionality. - To ensure the `mimalloc-override.dll` is actually loaded at run-time it is easiest to insert some - call to the mimalloc API in the `main` function, like `mi_version()` + To ensure the `mimalloc-override.dll` is actually 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, 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. @@ -32,7 +32,8 @@ is also recommended to also override the `new`/`delete` operations (by including a single(!) source file in your project). The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic -overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. +overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully +redirected. ### Other Platforms @@ -49,7 +50,7 @@ need a specific `mimalloc-redirect.dll`: `mimalloc-override.lib` export library. 2. Now separately build `mimalloc-override.dll` in `arm64ec` mode and _overwrite_ your previous (x64) `mimalloc-override.dll` -- the loader can handle the mix of arm64ec - and x64 code. Now use `mimalloc-redirect-arm64ec.dll` in this case to match your + and x64 code. Now use `mimalloc-redirect-arm64ec.dll` to match your new arm64ec `mimalloc-override.dll`. The main program stays as is and can be fully x64 or contain more arm64ec modules. At runtime, the arm64ec `mimalloc-override.dll` will run with native arm64 instructions while the rest of the program runs emulated x64. @@ -59,12 +60,12 @@ need a specific `mimalloc-redirect.dll`: ### Minject -We cannot always re-link an executable with `mimalloc-override.dll`, and similarly, we cannot always -ensure that the DLL comes first in the import table of the final executable. +We cannot always re-link an executable with `mimalloc-override.dll`, and similarly, we +cannot always ensure that the DLL comes first in the import table of the final executable. In many cases though we can patch existing executables without any recompilation -if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll` -into the import table (and put `mimalloc-redirect.dll` in the same folder) -Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388). +if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the +`mimalloc-override.dll` into the import table (and put `mimalloc-redirect.dll` in the same +directory) 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: From b51c0974d357cda597ab3a242f5723ab516f5503 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 14:00:54 -0800 Subject: [PATCH 102/131] fix cmake for visual studio on arm64 --- CMakeLists.txt | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8896dfd7..e371a33d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,11 @@ if (NOT CMAKE_BUILD_TYPE) endif() endif() +if (CMAKE_GENERATOR MATCHES "^Visual Studio.*$") + message(STATUS "Note: when building with Visual Studio the build type is specified when building.") + message(STATUS "For example: 'cmake --build . --config=Release") +endif() + if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$") message(STATUS "Default to secure build") set(MI_SECURE "ON") @@ -326,11 +331,11 @@ set(MI_OPT_ARCH_FLAGS "") set(MI_ARCH "unknown") if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|i[3456]86)$" OR CMAKE_GENERATOR_PLATFORM MATCHES "^(x86|Win32)$") set(MI_ARCH "x86") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|x64|amd64|AMD64)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|x64|amd64|AMD64)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x64") # must be before arm64 set(MI_ARCH "x64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8.?)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8.?|ARM64)$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") set(MI_ARCH "arm64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|armv[34567])$") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|armv[34567]|ARM)$") set(MI_ARCH "arm32") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv|riscv32|riscv64)$") if(CMAKE_SIZEOF_VOID_P==4) @@ -341,7 +346,7 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv|riscv32|riscv64)$") else() set(MI_ARCH ${CMAKE_SYSTEM_PROCESSOR}) endif() -message(STATUS "Architecture: ${MI_ARCH}") +message(STATUS "Architecture: ${MI_ARCH}") # (${CMAKE_SYSTEM_PROCESSOR}, ${CMAKE_GENERATOR_PLATFORM}, ${CMAKE_GENERATOR})") # 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) @@ -533,8 +538,14 @@ if(MI_BUILD_SHARED) ) if(WIN32 AND MI_WIN_REDIRECT) # On windows, link and copy the mimalloc redirection dll too. - if(MI_ARCH STREQUAL "x64") + if(CMAKE_GENERATOR_PLATFORM STREQUAL "arm64ec") + set(MIMALLOC_REDIRECT_SUFFIX "-arm64ec") + elseif(MI_ARCH STREQUAL "x64") set(MIMALLOC_REDIRECT_SUFFIX "") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + message(STATUS "Note: x64 code emulated on Windows for arm64 should use an arm64ec build of 'mimalloc-override.dll'") + message(STATUS " with 'mimalloc-redirect-arm64ec.dll'. See the 'bin\\readme.md' for more information.") + endif() elseif(MI_ARCH STREQUAL "x86") set(MIMALLOC_REDIRECT_SUFFIX "32") else() From 3a9c402e5107984324bfea6424370aac37c97a88 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 14:18:16 -0800 Subject: [PATCH 103/131] update readme for cmake on windows --- readme.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index a0296b43..7fa5eb54 100644 --- a/readme.md +++ b/readme.md @@ -164,7 +164,7 @@ The `mimalloc` project builds a static library (in `out/msvc-x64`), while the `mimalloc-override` project builds a DLL for overriding malloc in the entire program. -## macOS, Linux, BSD, etc. +## Linux, macOS, BSD, etc. We use [`cmake`](https://cmake.org)1 as the build system: @@ -200,13 +200,25 @@ free lists, etc., as: > make ``` This will name the shared library as `libmimalloc-secure.so`. -Use `ccmake`2 instead of `cmake` -to see and customize all the available build options. +Use `cmake ../.. -LH` to see all the available build options. -Notes: -1. Install CMake: `sudo apt-get install cmake` -2. Install CCMake: `sudo apt-get install cmake-curses-gui` +The examples use the default compiler. If you like to use another, use: +``` +> CC=clang CXX=clang++ cmake ../.. +``` +## Cmake with Visual Studio + +You can also use cmake on Windows. Open a Visual Studio development prompt +and invoke `cmake` with the right generator and architecture, like: +``` +> cmake ..\.. -G "Visual Studio 17 2022" -A x64 -DMI_OVERRIDE=ON +``` + +The cmake build type is specified when actually building, for example: +``` +> cmake --build . --config=Release +``` ## Single source From 7456d22fe36b21a025b2be33ab043256a9e6a3e3 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Thu, 19 Dec 2024 14:22:10 -0800 Subject: [PATCH 104/131] add link for VS generator --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 7fa5eb54..564ac6d7 100644 --- a/readme.md +++ b/readme.md @@ -210,7 +210,8 @@ The examples use the default compiler. If you like to use another, use: ## Cmake with Visual Studio You can also use cmake on Windows. Open a Visual Studio development prompt -and invoke `cmake` with the right generator and architecture, like: +and invoke `cmake` with the right [generator](https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html) +and architecture, like: ``` > cmake ..\.. -G "Visual Studio 17 2022" -A x64 -DMI_OVERRIDE=ON ``` From f8a253e6e8e0f3a811745d7a9449cd73e49509f2 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 12:51:13 -0800 Subject: [PATCH 105/131] update IDE settings to match cmake output; in particular mimalloc-override.dll -> mimalloc.dll --- ide/vs2022/mimalloc-override-test.vcxproj | 2 +- ide/vs2022/mimalloc-override.vcxproj | 18 +++++++++--------- ide/vs2022/mimalloc-test.vcxproj | 2 +- ide/vs2022/mimalloc.vcxproj | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ide/vs2022/mimalloc-override-test.vcxproj b/ide/vs2022/mimalloc-override-test.vcxproj index 97803b9c..0e87cf36 100644 --- a/ide/vs2022/mimalloc-override-test.vcxproj +++ b/ide/vs2022/mimalloc-override-test.vcxproj @@ -39,7 +39,7 @@ {FEF7868F-750E-4C21-A04D-22707CC66879} mimalloc-override-test 10.0 - mimalloc-override-test + mimalloc-test-override diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override.vcxproj index 9de18895..1278cd0f 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override.vcxproj @@ -39,7 +39,7 @@ {ABB5EAE7-B3E6-432E-B636-333449892EA7} mimalloc-override 10.0 - mimalloc-override + mimalloc-override-dll @@ -116,49 +116,49 @@ $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ .dll - mimalloc-override + mimalloc diff --git a/ide/vs2022/mimalloc-test.vcxproj b/ide/vs2022/mimalloc-test.vcxproj index fc9e9102..a8b36d5e 100644 --- a/ide/vs2022/mimalloc-test.vcxproj +++ b/ide/vs2022/mimalloc-test.vcxproj @@ -39,7 +39,7 @@ {FEF7858F-750E-4C21-A04D-22707CC66878} mimalloctest 10.0 - mimalloc-test + mimalloc-test-static diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj index 34a9317a..9964310d 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc.vcxproj @@ -39,7 +39,7 @@ {ABB5EAE7-B3E6-432E-B636-333449892EA6} mimalloc 10.0 - mimalloc + mimalloc-lib From 4b7313914ee702f1abe16d9021f5ac4867894cf4 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 12:52:00 -0800 Subject: [PATCH 106/131] add updated minject v1.2 that defaults to mimalloc.dll instead of mimalloc-override.dll --- bin/minject-arm64.exe | Bin 20992 -> 20992 bytes bin/minject.exe | Bin 22016 -> 22016 bytes bin/minject32.exe | Bin 18944 -> 18944 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/minject-arm64.exe b/bin/minject-arm64.exe index 97188c4f14e644b66d938ce44a940f3058153a13..637c95d91576043ff83cf2f0ceb5a5555c544764 100644 GIT binary patch delta 1656 zcmY*ZZERCz6h7zPwrjU_9qqc+t)m}Hwh(CnD57uBdb|nEqU?Uo;B+3v7BuX~HglNpB#2=N7d2T;~-lTax&d2+n z_rAUH(-=RE!&($i-Rz)OCtbQ$x($j=|1{}%e7<_TJeG$70#kCrjZS* zODIIc@(s07ZH$Hk69z~h1ZZ*r3~Rf>@>F36@nc$2Y+AX$0FK%9;L`$3cTwWsUb<%jTY0(yr zoY3SVW7)_?_8{+#XT1pN^_zvz0eV~S-HQ96{hkvfGeB8N7!BCYLvN71^9eZrHxFT8 z-v#lu$1g*mIKyGMvRf0-<$0GTpvm(dO+d`^sD_^C9rJ$`q3r#A@Kx^20(^eH3DKOq z{%mgGfk@txttiovl1gpGe&{F{<85@fw4GFj5A_(jSP1c3hXwF`iS&t~6^ZT}UY93I zi?L+Y?A${&7iRj09Mau9chqoldGc0XC!87meO_aWbR*A0^LSqs$?JKYFiKzN zITlG{c^)c~u29tGpjMkfHTHsZE+>q5n%PnupwDa_0vc(`<`kj@WU_x}_J%In)X-}$ zg!UK@qFkhym;SOZM=!Y@NBL!qIa0!;iVit93F9hy=xh_Nts#GnGlFXA9`c3G{@?l` zs+MlEjwASh+vv0RtY6D{I*1?DErdax4$_%(jTlcp5Aw^HhJ=PXU%VzbO5_^X&mxtI7e*E@6YA_<2%^%VG=~c3$JhLS zovNp)mh!^sx~zRhk#2d|-KIgWEH?dtr1dYN7Qa>Q^oK-sric7_%kk_d&c9+EZCkO- z7^wwt_jT>*ThOyhN$F^olPi8hy@$8p-VyENdBG!}eCZujr&K}v2c!=!ZJXia6*yp7 z%-d>Ein6$ydHg@R7=l_J6%sR#9yY;l?c{-(M@p?Sp0yF+HvbNC?d?YSXz-a%9$g0i%#&T*x@h=wZK~7gGFT#uKbd-2fX|#~9Blnw$4AK4x44 zA@q0v)-mp3e1kE?nCZuO2UZKyO8^?Uewi0wC5*0u3rwonxW|}a>{yyjILLUJ8(Vw; xU9cMCIaE#|#=bJqv35dnR4!@N2xYFJ;LzG39ytQQpGV%U_Jq77@&ig9-M_fB&V6h7zPmfk{3p?rft+wswgAYc)Sy0sVu-DFBoNz5`};!2!O9GJO8ZFNqa zOt~B8Qcu#2(PNU%0DJIQV zC|IkN%UZM6Y^`=pm|*%KK$#t2Sjw$d9z=T(&ryjXVac!#j#-T0lmMpiVU|20CI?Qb znqgMM?2z_3YrdFS%^KGF$j=!*WzU3u*5e6#dRTKuw5G7ut!mP2oIk96KvxY3j)Uy! zjhgiY!=8PtK}5S6)^?N8xL&|Rw8>byA$S1lZ`wdk0!SPaMqSzGpbZW}ea8Vf_a`@D zV%-kDx_e8(WeC|YobJ%M^btE(=ZcEhg*ulQv8_7#!)VP)&_H6@ei)gZnTzM=oDh=& z-#(k^F=(hXb^`|KNNl?4#sO$Z7JYS{0yxj0NQX_UNMqV*Eb&~32H&-i9HjS6wW!c7 z)60e;-st|wiMj$!|8`m&+d#vy^@=^tfU)sUXL_bZ2&mg!e@a#HrMOnhCInL36e3h z2S1_y%=ueR@tRN;k5wLs*w*JbE;(>A!u_@o@BNoo%AZASPdt~J68I>>{bu=i#Kstz zBDN=n+x28Ez|IWKY_{5=<}pJ^?H~Njf-Rd)WqGU3O*(m0eDz1*hle`_9vyv=cTvE2Wpn;*@$9?` zVeZXRaHAR!H;byx&umNjP3<>BV_;rJI3d6@rCN5 zFxvToR`4gn4d9k|7~p?$=a(|rCQa^paz|aO4&nNIfX-q7H?Qq1R=VBK^p1)%JKN5j z{ac9XJb!%a)KHZ(u|9p*Yu^34?+@uNM?KmSx9Y|rUJ9TbT3LgHFCE>(Ljp@Z*T|(< zVHA9fxr_sh#jMwGIjZhu>}5X2xR$wvw?D0N#&*VDE@c^b@E+p|#^MryHH<#SP(H>V zph_4h1t{e8Q;bVs^aa?q03efvE=E6NoHHEYX8f8Hk2AJF6;^QHDyp;bvaa@hte#LD hRbp$Sgv6Sm#v$(z_r`xv1_n#7y;mt&eFf!W{XYp<>%ag2 diff --git a/bin/minject.exe b/bin/minject.exe index 53c42f5d6dc7f643c03e832ff9e0aff42b2fc265..bb445706b65269a336d6e6b3ba2eca4f7399acd4 100644 GIT binary patch delta 6740 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 B3n>5q delta 6993 zcmeHMdstIfw%_NF@P?oej64$vPeGArp&~U=s3#U3s?=Japaj7|VtxhXw3nL#)F&&Rrv8)=nRulJ&WDD{5KnEe2h7c_|^)n*zxN z&GMB*`3;j462?bnlS~lVKGK~_Q@9%L4cg9SaErP{=ClRHJVgUb`zA2;eP6_)vyhlSr<)pLaGC+K=gjCxWc_Lp@) z5X7%7`?K@UKCVeN)6}5iiN(ui6H?ZZ)^=5rOkY|Kj6y0U;%V!9ue|L0wMvfa*+m0Q z%Su~6F4dHrr(1#&I4gZED6Z^#{&?4C0T#{PBiTnzUYpT2mA6U`?z zMq3Uqbd(wOWgY7137ALh7sQj2cIJ3lmNPmK6L~njW;4|VPnmV3jPa*2lcSQ&xu{jL zXi6lpx7!nC>aFX`o$Pgq-Q6CIsk^RE{IB|rR6Q~|z2%sy*&8@D*O9QX%b`OuNUIR3ASXFXNn4ZaOH$5R?2(h5 z3-0m(EQ@8|e}7=el#@obdY91RRXIQMYJdUW5cIq^K#=-N#Kf`(SeRq%IaXnzNm)^U zQ&nl}39R3sMLdY7v6v42UypO4L>y3_$I^Wzs>C$Fca@qx@~`#b>?4+w-kEI)F3u`- z&lGn&>Befar+gMq$(al5je5<-J;--o5jy$7_Tv~3N&6Jenb6wh7_(XE5IET^9g?(< z`Do`AVMYJGU^YhTmbBfB^{vCOq>aykCieM4ink^0^z1Q=Im_bZTg6*~_?Mml%yDBJ z6+_0(i(;c?t8)M*N!vRP#EN6qcGZX2G;fqV(L27pX27|uV~3F)S*y56Zxw%;X%(CD ztm1}3tN1s|GRsoS;zRVCkd~P12;({Stt1^4IwDRprR!VzRH&Vcp-AeE3c0P`gNpL zB6eZ?Ak#l%I+X8>P);k#r%dU)PB)F3!9S2f`$sM3zc6%87(ImxOHDzFAF?FJQb%+) zf5|}I(G!B+WFyWF(=*WpK~FRJ*3Xd_l?V2PBIOI8|k2jZz zs`G4xz~c~mRx^`yNGLjIzvvBz;V2vM@HP6d))4f$9`awlqAqQUevtukAiVdnt$BwP zCrP_Bi4fDrcv+6=X}30p|3xw#)F$g|l3DOF;{r(=;1^3xU8WPl3Xh}}l4)#g>V&@~ zvR464W#R`oKtg+<99hyHK~SOS15N9vm`Mq9DT&s`?kJCv#|#xF-Y6!-8C;ln73e4u z#M8(;9;@W(LA4TEzjVZJo-L|A0h`O#?xg26##_SAY5(W%fv2^mYICiR_3af^^S;lnR46f+tDaIuE(n=H;}F8 zoTBtFw*fExm2NrzV;sGpGvvg@v&eY(Gwk`rvy!%r&D!yR)T0_ln%8lVt(^0gs222e z{8&@8+xOn8qp>fVhjE;WaURBIx+>#PRlA(aN;lqem6Wl3r- z-ZBNQnvK6j-(1|v6z6@u7mfLOmcWT+ZNu=pvfc{nPSznphdDxrAzqWvQNeDr4<&8h zSb14OWF;PoywZ3@lOea_i+YSA53DfqlXfT)E?O%_I9XD?a72PY)(~6pL2I_W7izpZVPR3GIuG!9shzF-o9+h@ZU1%=Kb!Ihh;MO@uH*esHGrUK=M>Z~0jNvfWI|G@~ zk#0JSow}Yx9SH{RmvnoAfqyfJzLRh-zbT2{OvnpcjGX0yHB(0?Bx*y=em#TENz{k2 zS6ep!IEJoEoN(_W1xUji)T5rm1VQSt7Twf58TpeWm2Q+Ak$Aw@F~XC0Ns_$Ng;q(k zaVvJSxmZsxB*u&?z!S?=|4TH=kZGq>q|BAW6=(!itDm2uMDS>Qc7GT$#v%ysuw$$UIMIxvFn2K0lGZmojeb zJ{YjBe{}|VmImSQYkW)f!bHlaPM=knhhh8k|Koh_?{S3*MTeXYp~V)3)tDV6X-7wa z6HB9n_EKEq3D9ssO=L3h$sMzGK7EgdK9zd!s5kMQCWwoT<-#||k@uwu^lWN!>P0q* zl(t<%$kC&FxI;$|Lcka3r{E7E*-TF=jWfn2gk!X3TNi4Q`j~9$P`}HtCGEvLT5e3? zM$;x^4*y~#-D%YEG?MN&PU9Cw(jSa-xk&npw1fyQ5;LJ{nI-L45p-?ZBz`!8zLr+O zuZp0m^wqjo*qhu@`~tu`S`Y)+2S}i#okZKyjbmLt2Y)@ePN^lA2L$f z@H9yy^r}Oska4ee13vI9Eqz=`ySfpgH>gBZucX^Einwv~M22PNL@ew6K!RyohJNZ* zr$c3ju2-#x#52BK9RX3Z?~9nGcsO0_RdaVt*YPdUo_IT(F3h~g)dl7Cp_abjUiGUG z12DQ>{R$+@t!}+zNlTx;SG^6YS~hHj^bWj^3!-{G&DIt7lr#VP`(}R-bZk z%0Z_AKJ&r0L@YvYhTq5SiL)WX`#yj-2oBMcA!+tq8q*XmX!Z^3U`wSbS(zoTAz$G) zhjHI?!Z!m#YQ$ysq0=7m8KC7h_h^{Va^V2<6VNT1eV=KYV%W?GG8Eku0+{?(7JVu! z$)#r#{I2WJow|4QsFXH3l&!i-?r()K*(3KK$xL_{V|rwHf!seK_lxCzsoYn}{c^dl zmiwRNzEle=YaTvd?t6{~?sxv&~#6 z?ac0Qjb4hqz^_fg9SZJM@Q8xv6#P!X1q$XUs9WZXGhNZ`3QkgZpOuhGMIU}dW?ZCv zq0f}BV1j}w1;6t-lKFQ9>Qd~Pi+tmg6!cHjrr7NY|Hfj!#fQ(!y6X=4{9OT#D*9In zMkxUj6wFreb;WL0^f?MHRaZ3=PS5W@vl(Otl%#A%g-OH5L=Z1dlkH-;1LD=6RuLW;vQw(CyG5((N8G) z&!EcMCU-K(z^VDFM4ptNxVg^P5yHRWh(N^Nlcn??H zFk1d(*wJ>PT}3Ot2Rdq#871OTe3C#VGiOwku>j@_LdH96YaPbb4Qx)cV)t{#yu6>s zfa?q@4#DMu>t(#Xy2??75f9R&`(krh)@{h%M;q6#UtcZ%o#yO3LU7N6cdRg4EfzM% z5Usi|+T|H(sqk5b|A|{DZ|rSwe`b-_`X+p1J|SXi;*)@o+J_0z-Qi4(YX;ZI z#`*m4m4ns6TfPz30=PIfn5_hg1r{6!WxVo0mTSYUDhe?YL}pl-uB>jZkva=(kw?8k5zJLdnfy>B!l>;gYSNIEK%&VnKC1e_T8)VxE@;DrW5peAYZW!Ec_^~79 z{|T%*nYS3?{&lzcmxTQ5Zu|eb+svfNVP8>e$A@I+hSD)ASEK4dr_H{u+-9#?V_#j> zu);QDjkCdFvlA0P)8?4rwA*bBj&l2&6}F}(Yc(kt!B*7TZB^AENoW9k=dEjU*j886 zt+rX3?ysx2F^N18U~Q;#)K%5jt+&l9t7~!y7()K8n(L^aQPt>(aN02;=3DC^KdNZb zEM1mL4cq)WyTe&k|4_qYbq$E`4zMdEgm-geE{9 zS>aiwKRz1&0Rf(&7p)ocFz~HdLN-J0ip6KngJUo$luDo#HUDkMKi6@{BWpaX^`96} zS->-#j7k}fO3rXPS_0&e)tOa)f3;^g*@%M9{DA{#wGX*`!UZU8FfjZ9Z3kqA>1l-Q zg3Qo_RtuS-S>YMpkB^J@!IuMz@y##6HUix)+yScj z5P+|vF~b|cFBN$hn2kGt@j1Y^&{)v7f#tXtN-&n81C8+vpHpNv@FPY31b73D#kmP| z=Mhqmv941PuAwnQ%tS&K=cACrPz`(&jq!cJRD2<{fj0sx6`A1 zqP+weUykynw+Ax2{Mbb{6*9wJ1tfq}&+oKUv~iu0bHn+#w%zXCFYPAf$OR=b&n>vi S-3#26?pimT4scroBK`r<)^nr) diff --git a/bin/minject32.exe b/bin/minject32.exe index 926facfda8018cf58df19310837661b76dac67c9..6dcb8da9ccb189f0e31daf31b06aa9449c840f9d 100644 GIT binary patch delta 3508 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 delta 3670 zcmd^CeOOdg8b5bn_=wL;1O%540Yydcy)rlh3^Sl86cFeLSg8Zd=pE!sm?`8*nF0(J zNc6b&@j&WoE%x+bO&_j(ECym9ZqcgMvsr6pbrYWr3yn2v_IEC_v48I0dwhQH?|pyg zJ?FgV%(?fXb1&!I%k`wI#>noBtmdSnUQgLRl&(&}eB|e=n-Mpb*v2ar-ZCyJTs3Z0 zxO%(^9DBqzz6EUi&~`N%e5u5&>OxVgSBsR)TKAVj-6CW155cerKTHp;2ysb+`M1*!z@C@oUm$-U${ zsM^TU5mm72Siei<>CJJyu3OX(uwT9tz&caZk{|8Ijx~x^PB3x1Scx z$bix_V^`o4EH$XL2Xi>}`&~)5ee1#9Nkc+o3sO*dcY#kw{@CbBXGT&`Ybu16?Gq%Z zEgoLyFcuhH(wRN+BGPJZ8?5P7K@ zXD|QA+!(l>V{&K!A(dPQFMq_2Ysh~?>wuj;7w)?*D+#0T@I>Y{m_m6U2CZAyHsC0d zzh|lu<59DpbZ!9>>shbt1x?27BJ!s!<+w8NNu}!)d`zvDO*DA+;-G3K4pz>T>WVPh zgXYhUkJsXGm%fvkb|R>C362Fz<#q%xQ8H!1zy}Y@WeRt1J&s)+ai* ze@oEsO=(1eZx{OAjtlZ}`c}m1;PXDpj-xFH!|bnKned6- z^C-7|u(;FV({|0SZuymSl*?-;M<%pgbHqw3kR{*3R>ls4q(T<{?5l+Kh2p>{-|~*T zBYp}e)7mz{beeQnOXFt(7}?eKAU%O9c4QNPIohv@Y=r&Go&<#q(S9sb4A90AwFXvX#*#IM;h6p53;PFvy|>1Q#o za`)3e#1_C_jIHGwscCK^?2fscV85Qr!_JCZ0eg3x#M$XkTwk-ZoE`Z6%!V{FJIBtf zrjA*C73`+2kVh2?=u&8oq>$R8P`p{8q+AR1V}7@8-LfQc`H zpN2LJoCPid4+E@SM}HXlcObqDUW_;pd;pwhLd7OHt-uIS2W$dZI}T0(hJby*7|;c< zHe;btVP@`3_|5N)H_t{O{7=A43tNo+1MdOeO9&BxLEvrR zJ>Y#n#}kqX906Vcl0-uEKyN$_8xJ;{|1ms6*Pz{pIae(=<&j`Qw#~(1+pVs@qy%vB zVW@L)y`{`vhR-AxNB+$?uAy;KCav_!ve0n05w@Yp?6{_;CX4dt$2~Mgdz;=|G&R;< z5tn<{U6_Vgrfa6mOr}ZD@P@)H$TLmm)zPh(;TiP2#CmLO**FwUhTGR+Px z8K0J$dC5%crzfPQ0 zxQ*@5*ae(wGw_IAfYvol6QPA+N9U)FH9?b*cY2y;hgNDNX=Hqw_&7u-5-(5FjzepN z#FkI{cV8T{y)79TxDr#o?JEUGlVxMsa9F-%N_Og)*5?ZeQkxcp&{2o zglVcts<)O|AQBG`w>Dr2a!$RrMk=eZR9P+AjTP2Kb#_~A4d$_1>j~MbUSqZYSO4_x zCux~6B4igUEx*>{sIulL^WbJIqPvZ^;ZOD_jS<|QtoC^Av)i^l`{K_kzphvJ)r>u# zl|0ildwYe{wqx{p@Atf}RR`yP+(BGzS!LXzz!e_NTa))B4=0~b{#SCeMx&85^_uOP zcFi8mS4T6WqUX&cfOq%Tj; zPp?UTwmIFE9;^@7|4uLHv-P*@*Xy_HAJ&iP&*{I@|ERyAKbSF=kz*(@lo-qgo1xa= zF#O)I&(Lf5qd_)YFYQjbO}^=TsSE73(pI$2yX}{g}(~t zgfE0k!uP^e!7ccT;bNkw6SKrZu~@uEEEgrQMzo7fqEp-{c8Pn$N5v<^!{XE8QSlY= zb@46nZSj5atoV2Fg7}SiS^Pn~A=WN+u(y>F-$VQl?V+52$X@*ceZQV$gk?Z4#0MGF PDzpoSQHSe=oILK|rd?g| From 4ed44f96210c71f6d1945ae950387bc262a75f20 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 12:52:34 -0800 Subject: [PATCH 107/131] update readme to use mimalloc.dll (instead of mimalloc-override.dll) --- bin/readme.md | 38 ++++++++++++++++++------------------ readme.md | 53 ++++++++++++++++++++++++++++----------------------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/bin/readme.md b/bin/readme.md index d6c3775f..bc115ce1 100644 --- a/bin/readme.md +++ b/bin/readme.md @@ -9,20 +9,20 @@ There are four requirements to make the overriding work well: 1. Use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). -2. Link your program explicitly with the `mimalloc-override.lib` export library for - the `mimalloc-override.dll` -- which contains all mimalloc functionality. - To ensure the `mimalloc-override.dll` is actually loaded at run-time it is easiest +2. Link your program explicitly with the `mimalloc.lib` export library for + the `mimalloc.dll` -- which contains all mimalloc functionality. + To ensure the `mimalloc.dll` is actually 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, 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. + similarly, `#pragma comment(linker, "/include:mi_version")` in some source file). + See the `mimalloc-test-override` project for an example on how to use this. 3. The `mimalloc-redirect.dll` must be put in the same folder as the main - `mimalloc-override.dll` at runtime (as it is a dependency of that DLL). + `mimalloc.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`). + redirected to mimalloc functions (which reside in `mimalloc.dll`). -4. Ensure the `mimalloc-override.dll` comes as early as possible in the import +4. Ensure the `mimalloc.dll` comes as early as possible in the import list of the final executable (so it can intercept all potential allocations). You can use `minject -l ` to check this if needed. @@ -37,8 +37,8 @@ redirected. ### Other Platforms -You always link with `mimalloc-override.dll` but for different platforms you may -need a specific `mimalloc-redirect.dll`: +You always link with `mimalloc.dll` but for different platforms you may +need a specific redirection DLL: - __x64__: `mimalloc-redirect.dll`. - __x86__: `mimalloc-redirect32.dll`. Use for older 32-bit Windows programs. @@ -47,12 +47,12 @@ need a specific `mimalloc-redirect.dll`: mode on Windows arm64. Unfortunately we cannot run x64 code emulated on Windows arm64 with the x64 mimalloc override directly (since the C runtime always uses `arm64ec`). Instead: 1. Build the program as normal for x64 and link as normal with the x64 - `mimalloc-override.lib` export library. - 2. Now separately build `mimalloc-override.dll` in `arm64ec` mode and _overwrite_ your - previous (x64) `mimalloc-override.dll` -- the loader can handle the mix of arm64ec + `mimalloc.lib` export library. + 2. Now separately build `mimalloc.dll` in `arm64ec` mode and _overwrite_ your + previous (x64) `mimalloc.dll` -- the loader can handle the mix of arm64ec and x64 code. Now use `mimalloc-redirect-arm64ec.dll` to match your new - arm64ec `mimalloc-override.dll`. The main program stays as is and can be fully x64 - or contain more arm64ec modules. At runtime, the arm64ec `mimalloc-override.dll` will + arm64ec `mimalloc.dll`. The main program stays as is and can be fully x64 + or contain more arm64ec modules. At runtime, the arm64ec `mimalloc.dll` will run with native arm64 instructions while the rest of the program runs emulated x64. [arm64ec]: https://learn.microsoft.com/en-us/windows/arm/arm64ec @@ -60,11 +60,11 @@ need a specific `mimalloc-redirect.dll`: ### Minject -We cannot always re-link an executable with `mimalloc-override.dll`, and similarly, we +We cannot always re-link an executable with `mimalloc.dll`, and similarly, we cannot always ensure that the DLL comes first in the import table of the final executable. In many cases though we can patch existing executables without any recompilation if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the -`mimalloc-override.dll` into the import table (and put `mimalloc-redirect.dll` in the same +`mimalloc.dll` into the import table (and put `mimalloc-redirect.dll` in the same directory) 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 @@ -86,8 +86,8 @@ options: -l --list only list imported modules -i --inplace update the exe in-place (make sure there is a backup!) -f --force always overwrite without prompting - --postfix=

use

as a postfix to the mimalloc dll (default is 'override') - e.g. use --postfix=override-debug to link with mimalloc-override-debug.dll + --postfix=

use

as a postfix to the mimalloc dll. + e.g. use --postfix=debug to link with mimalloc-debug.dll notes: Without '--inplace' an injected is generated with the same name ending in '-mi'. diff --git a/readme.md b/readme.md index 564ac6d7..11f62da4 100644 --- a/readme.md +++ b/readme.md @@ -428,43 +428,48 @@ Note that certain security restrictions may apply when doing this from the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash). -### Dynamic Override on Windows +# Windows Override Dynamically overriding on mimalloc on Windows -is robust and has the particular advantage to be able to redirect all malloc/free calls that go through -the (dynamic) C runtime allocator, including those from other DLL's or libraries. -As it intercepts all allocation calls on a low level, it can be used reliably +is robust and has the particular advantage to be able to redirect all malloc/free calls +that go through the (dynamic) C runtime allocator, including those from other DLL's or +libraries. As it intercepts all allocation calls on a low level, it can be used reliably on large programs that include other 3rd party components. -There are four requirements to make the overriding work robustly: +There are four requirements to make the overriding work well: 1. Use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). -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. -3. The [`mimalloc-redirect.dll`](bin) (or `mimalloc-redirect32.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`). -4. Ensure the `mimalloc-override.dll` comes as early as possible in the import + +2. Link your program explicitly with the `mimalloc.lib` export library for the `mimalloc.dll`. + (which must be compiled with `-DMI_OVERRIDE=ON`, which is the default though). + To ensure the `mimalloc.dll` is actually 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 command, or + similarly, `#pragma comment(linker, "/include:mi_version")` in some source file). + See the `mimalloc-test-override` project for an example on how to use this. + +3. The `mimalloc-redirect.dll` must be put in the same folder as the main + `mimalloc.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.dll`). + +4. Ensure the `mimalloc.dll` comes as early as possible in the import list of the final executable (so it can intercept all potential allocations). + You can use `minject -l ` to check this if needed. For best performance on Windows with C++, it is also recommended to also override the `new`/`delete` operations (by including -[`mimalloc-new-delete.h`](include/mimalloc-new-delete.h) +[`mimalloc-new-delete.h`](../include/mimalloc-new-delete.h) a single(!) source file in your project). The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic -overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. +overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully +redirected. + +For different platforms than x64, you may need a specific [redirection dll](bin). +Furthermore, we cannot always re-link an executable or ensure `mimalloc.dll` comes +first in the import table. In such cases the [`minject`](bin) tool can be used +to patch the executable's import tables. -We cannot always re-link an executable with `mimalloc-override.dll`, and similarly, we cannot always -ensure the the DLL comes first in the import table of the final executable. -In many cases though we can patch existing executables without any recompilation -if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll` -into the import table (and put `mimalloc-redirect.dll` in the same folder) -Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388) or -the [`minject`](bin) program. ## Static override From 26eaa1f4e2804fc7dd3cc3997a481c55d484b4f1 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 12:52:58 -0800 Subject: [PATCH 108/131] fix cmake to generate mimalloc.dll on windows --- CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e371a33d..e84283fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -667,12 +667,7 @@ 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() + target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) endif() if(NOT WIN32) # It is only possible to override malloc on Windows when building as a DLL. From df82338d8a2f118954d82b8421f8c1b9294a78a2 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 13:04:30 -0800 Subject: [PATCH 109/131] don't override a page candidate with a page that is too full --- src/page.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page.c b/src/page.c index 85e831d2..4b25ed5d 100644 --- a/src/page.c +++ b/src/page.c @@ -783,7 +783,7 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p page_candidate = page; candidate_count = 0; } - else if (/* !mi_page_is_expandable(page) && */ page->used >= page_candidate->used) { + else if (!mi_page_mostly_used(page) && page->used >= page_candidate->used) { page_candidate = page; } // if we find a non-expandable candidate, or searched for N pages, return with the best candidate From f3d83e5fa62f9d5ec653d13db8eec2d814e72046 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Fri, 20 Dec 2024 13:55:31 -0800 Subject: [PATCH 110/131] insert full pages at the end of the queue; only override page candidate if the page is not too full --- ide/vs2022/mimalloc-test.vcxproj | 6 +++--- include/mimalloc/internal.h | 2 +- src/page-queue.c | 2 +- src/page.c | 3 ++- test/test-stress.c | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ide/vs2022/mimalloc-test.vcxproj b/ide/vs2022/mimalloc-test.vcxproj index a8b36d5e..6e4576fd 100644 --- a/ide/vs2022/mimalloc-test.vcxproj +++ b/ide/vs2022/mimalloc-test.vcxproj @@ -272,14 +272,14 @@ Console + + + {abb5eae7-b3e6-432e-b636-333449892ea6} - - - diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 012ce4f0..8b22e1c6 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -571,7 +571,7 @@ static inline bool mi_page_immediate_available(const mi_page_t* page) { } // is more than 7/8th of a page in use? -static inline bool mi_page_mostly_used(const mi_page_t* page) { +static inline bool mi_page_is_mostly_used(const mi_page_t* page) { if (page==NULL) return true; uint16_t frac = page->reserved / 8U; return (page->reserved - page->used <= frac); diff --git a/src/page-queue.c b/src/page-queue.c index 9796f3dc..67b54650 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -343,7 +343,7 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro static void mi_page_queue_enqueue_from_full(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { // note: we could insert at the front to increase reuse, but it slows down certain benchmarks (like `alloc-test`) - mi_page_queue_enqueue_from_ex(to, from, false /* enqueue at the end of the `to` queue? */, page); + mi_page_queue_enqueue_from_ex(to, from, true /* enqueue at the end of the `to` queue? */, page); } // Only called from `mi_heap_absorb`. diff --git a/src/page.c b/src/page.c index 4b25ed5d..8808c358 100644 --- a/src/page.c +++ b/src/page.c @@ -783,7 +783,8 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p page_candidate = page; candidate_count = 0; } - else if (!mi_page_mostly_used(page) && page->used >= page_candidate->used) { + // prefer to reuse fuller pages (in the hope the less used page gets freed) + else if (page->used >= page_candidate->used && !mi_page_is_mostly_used(page) && !mi_page_is_expandable(page)) { page_candidate = page; } // if we find a non-expandable candidate, or searched for N pages, return with the best candidate diff --git a/test/test-stress.c b/test/test-stress.c index 574d241b..6284ad39 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -319,7 +319,7 @@ int main(int argc, char** argv) { mi_collect(true); #endif #endif - //mi_stats_print(NULL); + mi_stats_print(NULL); //bench_end_program(); return 0; } From 93e14344c7be10f186a39f7bee998db8adcead9b Mon Sep 17 00:00:00 2001 From: daanx Date: Fri, 20 Dec 2024 17:32:26 -0800 Subject: [PATCH 111/131] use srw lock on windows --- include/mimalloc/atomic.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index 3a0d4892..0c967896 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -402,28 +402,34 @@ static inline void mi_atomic_yield(void) { // ---------------------------------------------------------------------- -// Locks are only used for abandoned segment visiting in `arena.c` +// Locks +// These do not have to be recursive and should be light-weight +// in-process only locks. Only used for reserving arena's and to +// maintain the abandoned list. // ---------------------------------------------------------------------- +#if _MSC_VER +#pragma warning(disable:26110) // unlock with holding lock +#endif #if defined(_WIN32) -#define mi_lock_t CRITICAL_SECTION +#define mi_lock_t SRWLOCK // slim reader-writer lock static inline bool mi_lock_try_acquire(mi_lock_t* lock) { - return TryEnterCriticalSection(lock); + return TryAcquireSRWLockExclusive(lock); } static inline bool mi_lock_acquire(mi_lock_t* lock) { - EnterCriticalSection(lock); + AcquireSRWLockExclusive(lock); return true; } static inline void mi_lock_release(mi_lock_t* lock) { - LeaveCriticalSection(lock); + ReleaseSRWLockExclusive(lock); } static inline void mi_lock_init(mi_lock_t* lock) { - InitializeCriticalSection(lock); + InitializeSRWLock(lock); } static inline void mi_lock_done(mi_lock_t* lock) { - DeleteCriticalSection(lock); + // nothing } @@ -447,14 +453,13 @@ static inline void mi_lock_done(mi_lock_t* lock) { pthread_mutex_destroy(lock); } -/* #elif defined(__cplusplus) #include #define mi_lock_t std::mutex static inline bool mi_lock_try_acquire(mi_lock_t* lock) { - return lock->lock_try_acquire(); + return lock->try_lock(); } static inline bool mi_lock_acquire(mi_lock_t* lock) { lock->lock(); @@ -469,7 +474,6 @@ static inline void mi_lock_init(mi_lock_t* lock) { static inline void mi_lock_done(mi_lock_t* lock) { (void)(lock); } -*/ #else From e3ebebb9902c56b6899f70f046cbcc8089674569 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 21 Dec 2024 14:39:17 -0800 Subject: [PATCH 112/131] update lock primitive; fix arena exclusive allocation --- include/mimalloc/atomic.h | 31 ++++++++++++++++++++++++++++--- src/arena-abandon.c | 33 +++++++++++---------------------- src/arena.c | 5 +++-- src/init.c | 15 +++++++-------- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index 0c967896..733dbf42 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- -Copyright (c) 2018-2023 Microsoft Research, Daan Leijen +Copyright (c) 2018-2024 Microsoft Research, Daan Leijen This is free software; you can redistribute it and/or modify it under the terms of the MIT license. A copy of the license can be found in the file "LICENSE" at the root of this distribution. @@ -411,8 +411,11 @@ static inline void mi_atomic_yield(void) { #pragma warning(disable:26110) // unlock with holding lock #endif +#define mi_lock(lock) for(bool _go = (mi_lock_acquire(lock),true); _go; (mi_lock_release(lock), _go=false) ) + #if defined(_WIN32) +#if 1 #define mi_lock_t SRWLOCK // slim reader-writer lock static inline bool mi_lock_try_acquire(mi_lock_t* lock) { @@ -432,6 +435,30 @@ static inline void mi_lock_done(mi_lock_t* lock) { // nothing } +#else +#define mi_lock_t CRITICAL_SECTION + +static inline bool mi_lock_try_acquire(mi_lock_t* lock) { + return TryEnterCriticalSection(lock); + +} +static inline void mi_lock_acquire(mi_lock_t* lock) { + EnterCriticalSection(lock); + +} +static inline void mi_lock_release(mi_lock_t* lock) { + LeaveCriticalSection(lock); + +} +static inline void mi_lock_init(mi_lock_t* lock) { + InitializeCriticalSection(lock); + +} +static inline void mi_lock_done(mi_lock_t* lock) { + DeleteCriticalSection(lock); + +} +#endif #elif defined(MI_USE_PTHREADS) @@ -506,6 +533,4 @@ static inline void mi_lock_done(mi_lock_t* lock) { #endif - - #endif // __MIMALLOC_ATOMIC_H diff --git a/src/arena-abandon.c b/src/arena-abandon.c index 48e37794..460c80fc 100644 --- a/src/arena-abandon.c +++ b/src/arena-abandon.c @@ -120,11 +120,7 @@ static void mi_arena_segment_os_mark_abandoned(mi_segment_t* segment) { mi_assert(segment->memid.memkind != MI_MEM_ARENA); // not in an arena; we use a list of abandoned segments mi_subproc_t* const subproc = segment->subproc; - if (!mi_lock_acquire(&subproc->abandoned_os_lock)) { - _mi_error_message(EFAULT, "internal error: failed to acquire the abandoned (os) segment lock to mark abandonment"); - // we can continue but cannot visit/reclaim such blocks.. - } - else { + mi_lock(&subproc->abandoned_os_lock) { // push on the tail of the list (important for the visitor) mi_segment_t* prev = subproc->abandoned_os_list_tail; mi_assert_internal(prev == NULL || prev->abandoned_os_next == NULL); @@ -138,7 +134,6 @@ static void mi_arena_segment_os_mark_abandoned(mi_segment_t* segment) { mi_atomic_increment_relaxed(&subproc->abandoned_os_list_count); mi_atomic_increment_relaxed(&subproc->abandoned_count); // and release the lock - mi_lock_release(&subproc->abandoned_os_lock); } return; } @@ -251,7 +246,7 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_next_field(mi_arena_field_ if mi_unlikely(field != 0) { // skip zero fields quickly // we only take the arena lock if there are actually abandoned segments present if (!has_lock && mi_option_is_enabled(mi_option_visit_abandoned)) { - has_lock = (previous->visit_all ? mi_lock_acquire(&arena->abandoned_visit_lock) : mi_lock_try_acquire(&arena->abandoned_visit_lock)); + has_lock = (previous->visit_all ? (mi_lock_acquire(&arena->abandoned_visit_lock),true) : mi_lock_try_acquire(&arena->abandoned_visit_lock)); if (!has_lock) { if (previous->visit_all) { _mi_error_message(EFAULT, "internal error: failed to visit all abandoned segments due to failure to acquire the visitor lock"); @@ -289,8 +284,8 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_next_list(mi_arena_field_c // we only allow one thread per sub-process to do to visit guarded by the `abandoned_os_visit_lock`. // The lock is released when the cursor is released. if (!previous->hold_visit_lock) { - previous->hold_visit_lock = (previous->visit_all ? mi_lock_acquire(&previous->subproc->abandoned_os_visit_lock) - : mi_lock_try_acquire(&previous->subproc->abandoned_os_visit_lock)); + previous->hold_visit_lock = (previous->visit_all ? (mi_lock_acquire(&previous->subproc->abandoned_os_visit_lock),true) + : mi_lock_try_acquire(&previous->subproc->abandoned_os_visit_lock)); if (!previous->hold_visit_lock) { if (previous->visit_all) { _mi_error_message(EFAULT, "internal error: failed to visit all abandoned segments due to failure to acquire the OS visitor lock"); @@ -301,21 +296,15 @@ static mi_segment_t* mi_arena_segment_clear_abandoned_next_list(mi_arena_field_c // One list entry at a time while (previous->os_list_count > 0) { previous->os_list_count--; - const bool has_lock = mi_lock_acquire(&previous->subproc->abandoned_os_lock); // this could contend with concurrent OS block abandonment and reclaim from `free` - if (has_lock) { - mi_segment_t* segment = previous->subproc->abandoned_os_list; - // pop from head of the list, a subsequent mark will push at the end (and thus we iterate through os_list_count entries) - if (segment == NULL || mi_arena_segment_os_clear_abandoned(segment, false /* we already have the lock */)) { - mi_lock_release(&previous->subproc->abandoned_os_lock); - return segment; - } - // already abandoned, try again + mi_lock_acquire(&previous->subproc->abandoned_os_lock); // this could contend with concurrent OS block abandonment and reclaim from `free` + mi_segment_t* segment = previous->subproc->abandoned_os_list; + // pop from head of the list, a subsequent mark will push at the end (and thus we iterate through os_list_count entries) + if (segment == NULL || mi_arena_segment_os_clear_abandoned(segment, false /* we already have the lock */)) { mi_lock_release(&previous->subproc->abandoned_os_lock); + return segment; } - else { - _mi_error_message(EFAULT, "failed to acquire abandoned OS list lock during abandoned block visit\n"); - return NULL; - } + // already abandoned, try again + mi_lock_release(&previous->subproc->abandoned_os_lock); } // done mi_assert_internal(previous->os_list_count == 0); diff --git a/src/arena.c b/src/arena.c index 164f3116..86ac5955 100644 --- a/src/arena.c +++ b/src/arena.c @@ -394,8 +394,9 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset 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) { + if (!mi_option_is_enabled(mi_option_disallow_arena_alloc)) { // 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); if (p != NULL) return p; diff --git a/src/init.c b/src/init.c index 3e4da831..68a1d7e2 100644 --- a/src/init.c +++ b/src/init.c @@ -168,8 +168,8 @@ mi_stats_t _mi_stats_main = { MI_STATS_NULL }; #if MI_GUARDED mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) { heap->guarded_sample_seed = seed; - if (heap->guarded_sample_seed == 0) { - heap->guarded_sample_seed = _mi_heap_random_next(heap); + if (heap->guarded_sample_seed == 0) { + heap->guarded_sample_seed = _mi_heap_random_next(heap); } heap->guarded_sample_rate = sample_rate; if (heap->guarded_sample_rate >= 1) { @@ -187,9 +187,9 @@ void _mi_heap_guarded_init(mi_heap_t* heap) { mi_heap_guarded_set_sample_rate(heap, (size_t)mi_option_get_clamp(mi_option_guarded_sample_rate, 0, LONG_MAX), (size_t)mi_option_get(mi_option_guarded_sample_seed)); - mi_heap_guarded_set_size_bound(heap, + mi_heap_guarded_set_size_bound(heap, (size_t)mi_option_get_clamp(mi_option_guarded_min, 0, LONG_MAX), - (size_t)mi_option_get_clamp(mi_option_guarded_max, 0, LONG_MAX) ); + (size_t)mi_option_get_clamp(mi_option_guarded_max, 0, LONG_MAX) ); } #else mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed) { @@ -257,11 +257,10 @@ void mi_subproc_delete(mi_subproc_id_t subproc_id) { mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id); // check if there are no abandoned segments still.. bool safe_to_delete = false; - if (mi_lock_acquire(&subproc->abandoned_os_lock)) { + mi_lock(&subproc->abandoned_os_lock) { if (subproc->abandoned_os_list == NULL) { safe_to_delete = true; } - mi_lock_release(&subproc->abandoned_os_lock); } if (!safe_to_delete) return; // safe to release @@ -398,7 +397,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.stats = &tld->stats; } // Free the thread local default heap (called from `mi_thread_done`) @@ -599,7 +598,7 @@ static void mi_detect_cpu_features(void) { } #else static void mi_detect_cpu_features(void) { - // nothing + // nothing } #endif From 476d4699ff93380009ae35780c2261ae674e4200 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 21 Dec 2024 15:24:46 -0800 Subject: [PATCH 113/131] limit purgeing to one purge cycle per purge delay --- include/mimalloc/atomic.h | 26 +++++++-------- src/arena.c | 69 +++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index 733dbf42..c6083102 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -421,9 +421,8 @@ static inline void mi_atomic_yield(void) { static inline bool mi_lock_try_acquire(mi_lock_t* lock) { return TryAcquireSRWLockExclusive(lock); } -static inline bool mi_lock_acquire(mi_lock_t* lock) { +static inline void mi_lock_acquire(mi_lock_t* lock) { AcquireSRWLockExclusive(lock); - return true; } static inline void mi_lock_release(mi_lock_t* lock) { ReleaseSRWLockExclusive(lock); @@ -432,7 +431,7 @@ static inline void mi_lock_init(mi_lock_t* lock) { InitializeSRWLock(lock); } static inline void mi_lock_done(mi_lock_t* lock) { - // nothing + (void)(lock); } #else @@ -440,24 +439,20 @@ static inline void mi_lock_done(mi_lock_t* lock) { static inline bool mi_lock_try_acquire(mi_lock_t* lock) { return TryEnterCriticalSection(lock); - } static inline void mi_lock_acquire(mi_lock_t* lock) { EnterCriticalSection(lock); - } static inline void mi_lock_release(mi_lock_t* lock) { LeaveCriticalSection(lock); - } static inline void mi_lock_init(mi_lock_t* lock) { InitializeCriticalSection(lock); - } static inline void mi_lock_done(mi_lock_t* lock) { DeleteCriticalSection(lock); - } + #endif #elif defined(MI_USE_PTHREADS) @@ -467,8 +462,11 @@ static inline void mi_lock_done(mi_lock_t* lock) { static inline bool mi_lock_try_acquire(mi_lock_t* lock) { return (pthread_mutex_trylock(lock) == 0); } -static inline bool mi_lock_acquire(mi_lock_t* lock) { - return (pthread_mutex_lock(lock) == 0); +static inline void mi_lock_acquire(mi_lock_t* lock) { + const int err = pthread_mutex_lock(lock); + if (err != 0) { + mi_error_message(EFAULT, "internal error: lock cannot be acquired\n"); + } } static inline void mi_lock_release(mi_lock_t* lock) { pthread_mutex_unlock(lock); @@ -488,9 +486,8 @@ static inline void mi_lock_done(mi_lock_t* lock) { static inline bool mi_lock_try_acquire(mi_lock_t* lock) { return lock->try_lock(); } -static inline bool mi_lock_acquire(mi_lock_t* lock) { +static inline void mi_lock_acquire(mi_lock_t* lock) { lock->lock(); - return true; } static inline void mi_lock_release(mi_lock_t* lock) { lock->unlock(); @@ -513,12 +510,11 @@ static inline bool mi_lock_try_acquire(mi_lock_t* lock) { uintptr_t expected = 0; return mi_atomic_cas_strong_acq_rel(lock, &expected, (uintptr_t)1); } -static inline bool mi_lock_acquire(mi_lock_t* lock) { +static inline void mi_lock_acquire(mi_lock_t* lock) { for (int i = 0; i < 1000; i++) { // for at most 1000 tries? - if (mi_lock_try_acquire(lock)) return true; + if (mi_lock_try_acquire(lock)) return; mi_atomic_yield(); } - return true; } static inline void mi_lock_release(mi_lock_t* lock) { mi_atomic_store_release(lock, (uintptr_t)0); diff --git a/src/arena.c b/src/arena.c index 86ac5955..0ddb2936 100644 --- a/src/arena.c +++ b/src/arena.c @@ -33,7 +33,7 @@ The arena allocation needs to be thread safe and we use an atomic bitmap to allo typedef struct mi_arena_s { mi_arena_id_t id; // arena id; 0 for non-specific mi_memid_t memid; // memid of the memory area - _Atomic(uint8_t*)start; // the start of the memory area + _Atomic(uint8_t*) start; // the start of the memory area size_t block_count; // size of the area in arena blocks (of `MI_ARENA_BLOCK_SIZE`) size_t field_count; // number of bitmap fields (where `field_count * MI_BITMAP_FIELD_BITS >= block_count`) size_t meta_size; // size of the arena structure itself (including its bitmaps) @@ -42,12 +42,13 @@ typedef struct mi_arena_s { bool exclusive; // only allow allocations if specifically for this arena bool is_large; // memory area consists of large- or huge OS pages (always committed) mi_lock_t abandoned_visit_lock; // lock is only used when abandoned segments are being visited - _Atomic(size_t)search_idx; // optimization to start the search for free blocks - _Atomic(mi_msecs_t)purge_expire; // expiration time when blocks should be decommitted from `blocks_decommit`. - mi_bitmap_field_t* blocks_dirty; // are the blocks potentially non-zero? - mi_bitmap_field_t* blocks_committed; // are the blocks committed? (can be NULL for memory that cannot be decommitted) - mi_bitmap_field_t* blocks_purge; // blocks that can be (reset) decommitted. (can be NULL for memory that cannot be (reset) decommitted) - mi_bitmap_field_t* blocks_abandoned; // blocks that start with an abandoned segment. (This crosses API's but it is convenient to have here) + _Atomic(size_t) search_idx; // optimization to start the search for free blocks + _Atomic(mi_msecs_t) purge_expire; // expiration time when blocks should be purged from `blocks_purge`. + + mi_bitmap_field_t* blocks_dirty; // are the blocks potentially non-zero? + mi_bitmap_field_t* blocks_committed; // are the blocks committed? (can be NULL for memory that cannot be decommitted) + mi_bitmap_field_t* blocks_purge; // blocks that can be (reset) decommitted. (can be NULL for memory that cannot be (reset) decommitted) + mi_bitmap_field_t* blocks_abandoned; // blocks that start with an abandoned segment. (This crosses API's but it is convenient to have here) mi_bitmap_field_t blocks_inuse[1]; // in-place bitmap of in-use blocks (of size `field_count`) // do not add further fields here as the dirty, committed, purged, and abandoned bitmaps follow the inuse bitmap fields. } mi_arena_t; @@ -60,6 +61,7 @@ typedef struct mi_arena_s { // The available arenas static mi_decl_cache_align _Atomic(mi_arena_t*) mi_arenas[MI_MAX_ARENAS]; static mi_decl_cache_align _Atomic(size_t) mi_arena_count; // = 0 +static mi_decl_cache_align _Atomic(int64_t) mi_arenas_purge_expire; // set if there exist purgeable arenas #define MI_IN_ARENA_C #include "arena-abandon.c" @@ -349,11 +351,10 @@ static mi_decl_noinline void* mi_arena_try_alloc(int numa_node, size_t size, siz } // try to reserve a fresh arena space -static bool mi_arena_reserve(size_t req_size, bool allow_large, mi_arena_id_t req_arena_id, mi_arena_id_t *arena_id) +static bool mi_arena_reserve(size_t req_size, bool allow_large, mi_arena_id_t *arena_id) { if (_mi_preloading()) return false; // use OS only while pre loading - if (req_arena_id != _mi_arena_id_none()) return false; - + const size_t arena_count = mi_atomic_load_acquire(&mi_arena_count); if (arena_count > (MI_MAX_ARENAS - 4)) return false; @@ -403,7 +404,7 @@ void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset // otherwise, try to first eagerly reserve a new arena if (req_arena_id == _mi_arena_id_none()) { mi_arena_id_t arena_id = 0; - if (mi_arena_reserve(size, allow_large, req_arena_id, &arena_id)) { + if (mi_arena_reserve(size, allow_large, &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); @@ -497,13 +498,16 @@ static void mi_arena_schedule_purge(mi_arena_t* arena, size_t bitmap_idx, size_t mi_arena_purge(arena, bitmap_idx, blocks); } else { - // schedule decommit - mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire); - if (expire != 0) { - mi_atomic_addi64_acq_rel(&arena->purge_expire, (mi_msecs_t)(delay/10)); // add smallish extra delay + // schedule purge + const mi_msecs_t expire = _mi_clock_now() + delay; + mi_msecs_t expire0 = 0; + if (mi_atomic_casi64_strong_acq_rel(&arena->purge_expire, &expire0, expire)) { + // expiration was not yet set + // maybe set the global arenas expire as well (if it wasn't set already) + mi_atomic_casi64_strong_acq_rel(&mi_arenas_purge_expire, &expire0, expire); } else { - mi_atomic_storei64_release(&arena->purge_expire, _mi_clock_now() + delay); + // already an expiration was set } _mi_bitmap_claim_across(arena->blocks_purge, arena->field_count, blocks, bitmap_idx, NULL); } @@ -538,14 +542,16 @@ 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) { - if (arena->memid.is_pinned || arena->blocks_purge == NULL) return false; + // check pre-conditions + if (arena->memid.is_pinned) return false; + + // expired yet? mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire); - if (expire == 0) return false; - if (!force && expire > now) return false; + if (!force && (expire == 0 || expire > now)) return false; // reset expire (if not already set concurrently) mi_atomic_casi64_strong_acq_rel(&arena->purge_expire, &expire, (mi_msecs_t)0); - + // potential purges scheduled, walk through the bitmap bool any_purged = false; bool full_purge = true; @@ -592,9 +598,15 @@ static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force) return any_purged; } -static void mi_arenas_try_purge( bool force, bool visit_all ) { +static void mi_arenas_try_purge( bool force, bool visit_all ) +{ if (_mi_preloading() || mi_arena_purge_delay() <= 0) return; // nothing will be scheduled + // check if any arena needs purging? + const mi_msecs_t now = _mi_clock_now(); + mi_msecs_t arenas_expire = mi_atomic_load_acquire(&mi_arenas_purge_expire); + if (!force && (arenas_expire == 0 || arenas_expire < now)) return; + const size_t max_arena = mi_atomic_load_acquire(&mi_arena_count); if (max_arena == 0) return; @@ -602,17 +614,26 @@ static void mi_arenas_try_purge( bool force, bool visit_all ) { static mi_atomic_guard_t purge_guard; mi_atomic_guard(&purge_guard) { - mi_msecs_t now = _mi_clock_now(); - size_t max_purge_count = (visit_all ? max_arena : 1); + // increase global expire: at most one purge per delay cycle + mi_atomic_store_release(&mi_arenas_purge_expire, now + mi_arena_purge_delay()); + size_t max_purge_count = (visit_all ? max_arena : 2); + bool all_visited = true; 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)) { - if (max_purge_count <= 1) break; + if (max_purge_count <= 1) { + all_visited = false; + break; + } max_purge_count--; } } } + if (all_visited) { + // all arena's were visited and purged: reset global expire + mi_atomic_store_release(&mi_arenas_purge_expire, 0); + } } } From 825dd41769bc01984f7db515fe7df597a71547ab Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 21 Dec 2024 15:29:39 -0800 Subject: [PATCH 114/131] fix build error --- include/mimalloc/atomic.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index c6083102..c4fac766 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -457,6 +457,8 @@ static inline void mi_lock_done(mi_lock_t* lock) { #elif defined(MI_USE_PTHREADS) +void _mi_error_message(int err, const char* fmt, ...); + #define mi_lock_t pthread_mutex_t static inline bool mi_lock_try_acquire(mi_lock_t* lock) { @@ -465,7 +467,7 @@ static inline bool mi_lock_try_acquire(mi_lock_t* lock) { static inline void mi_lock_acquire(mi_lock_t* lock) { const int err = pthread_mutex_lock(lock); if (err != 0) { - mi_error_message(EFAULT, "internal error: lock cannot be acquired\n"); + _mi_error_message(err, "internal error: lock cannot be acquired\n"); } } static inline void mi_lock_release(mi_lock_t* lock) { From 7085b6cec31641fddaca3d40932cda82e91baf07 Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 21 Dec 2024 15:38:27 -0800 Subject: [PATCH 115/131] limit candidate search to 4 --- src/page.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page.c b/src/page.c index 8808c358..e1c07a93 100644 --- a/src/page.c +++ b/src/page.c @@ -732,7 +732,7 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi -------------------------------------------------------------*/ // search for a best next page to use for at most N pages (often cut short if immediate blocks are available) -#define MI_MAX_CANDIDATE_SEARCH (8) +#define MI_MAX_CANDIDATE_SEARCH (4) // is the page not yet used up to its reserved space? static bool mi_page_is_expandable(const mi_page_t* page) { From 83dacd190ef208e7e4aa792a8f46b12d75bbb952 Mon Sep 17 00:00:00 2001 From: Javier Blazquez Date: Sun, 22 Dec 2024 22:24:13 -0800 Subject: [PATCH 116/131] free segment map when destroy_on_exit is set --- include/mimalloc/internal.h | 1 + src/init.c | 1 + src/segment-map.c | 10 ++++++++++ 3 files changed, 12 insertions(+) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 8b22e1c6..b0e363cf 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -164,6 +164,7 @@ 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_destroy(void); // "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); diff --git a/src/init.c b/src/init.c index 68a1d7e2..ab99a8f8 100644 --- a/src/init.c +++ b/src/init.c @@ -682,6 +682,7 @@ void mi_cdecl _mi_process_done(void) { 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_segment_map_destroy(); } if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { diff --git a/src/segment-map.c b/src/segment-map.c index 399f221c..f6dff96d 100644 --- a/src/segment-map.c +++ b/src/segment-map.c @@ -57,6 +57,7 @@ static mi_segmap_part_t* mi_segment_map_index_of(const mi_segment_t* segment, bo mi_memid_t memid; part = (mi_segmap_part_t*)_mi_os_alloc(sizeof(mi_segmap_part_t), &memid); if (part == NULL) return NULL; + part->memid = memid; 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); @@ -124,3 +125,12 @@ static bool mi_is_valid_pointer(const void* p) { mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { return mi_is_valid_pointer(p); } + +void _mi_segment_map_destroy(void) { + for (size_t i = 0; i < MI_SEGMENT_MAP_MAX_PARTS; i++) { + mi_segmap_part_t* part = mi_segment_map[i]; + if (part != NULL) { + _mi_os_free(part, sizeof(mi_segmap_part_t), part->memid); + } + } +} \ No newline at end of file From 095f848ae85b57fd0d478b2db150cf1821bbde47 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Tue, 24 Dec 2024 17:22:58 -0800 Subject: [PATCH 117/131] fix issue #976 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e84283fa..cde8144f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -412,7 +412,7 @@ if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) endif() if(MINGW) - add_definitions(-D_WIN32_WINNT=0x600) + add_definitions(-D_WIN32_WINNT=0x601) # issue #976 endif() if(MI_OPT_ARCH_FLAGS) From cfe73e9d48d6b27401f28ada8ac5d1a36b0f2747 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 25 Dec 2024 10:56:43 -0800 Subject: [PATCH 118/131] wip: merging from upstream --- include/mimalloc/types.h | 2 +- src/os.c | 47 +++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index ad948d36..f2fea3f7 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -377,7 +377,7 @@ static inline bool mi_memkind_is_os(mi_memkind_t memkind) { typedef struct mi_memid_os_info { void* base; // actual base address of the block (used for offset aligned allocations) - size_t alignment; // alignment at allocation + size_t size; // full allocation size } mi_memid_os_info_t; typedef struct mi_memid_arena_info { diff --git a/src/os.c b/src/os.c index 32cb11c3..7e7dcb2c 100644 --- a/src/os.c +++ b/src/os.c @@ -157,34 +157,42 @@ void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) { } #endif - /* ----------------------------------------------------------- Free memory -------------------------------------------------------------- */ 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) { +static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) { 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(&os_stats->committed, size); } + if (commit_size > 0) { + _mi_stat_decrease(&os_stats->committed, commit_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) { if (mi_memkind_is_os(memid.memkind)) { - size_t csize = _mi_os_good_alloc_size(size); + size_t csize = memid.mem.os.size; + if (csize==0) { _mi_os_good_alloc_size(size); } + size_t commit_size = (still_committed ? csize : 0); void* base = addr; // different base? (due to alignment) - if (memid.mem.os.base != NULL) { - mi_assert(memid.mem.os.base <= addr); - mi_assert((uint8_t*)memid.mem.os.base + memid.mem.os.alignment >= (uint8_t*)addr); + if (memid.mem.os.base != base) { + mi_assert(memid.mem.os.base <= addr); base = memid.mem.os.base; - csize += ((uint8_t*)addr - (uint8_t*)memid.mem.os.base); + const size_t diff = (uint8_t*)addr - (uint8_t*)memid.mem.os.base; + if (memid.mem.os.size==0) { + csize += diff; + } + if (still_committed) { + commit_size -= diff; // the (addr-base) part was already un-committed + } } // free it if (memid.memkind == MI_MEM_OS_HUGE) { @@ -192,7 +200,7 @@ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t me mi_os_free_huge_os_pages(base, csize); } else { - mi_os_prim_free(base, csize, still_committed); + mi_os_prim_free(base, csize, (still_committed ? commit_size : 0)); } } else { @@ -273,7 +281,7 @@ 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); + if (p != NULL) { mi_os_prim_free(p, size, (commit ? size : 0)); } if (size >= (SIZE_MAX - alignment)) return NULL; // overflow const size_t over_size = size + alignment; @@ -304,8 +312,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); } - if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit); } + if (pre_size > 0) { mi_os_prim_free(p, pre_size, (commit ? pre_size : 0)); } + if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, (commit ? post_size : 0)); } // we can return the aligned pointer on `mmap` systems p = aligned_p; *base = aligned_p; // since we freed the pre part, `*base == p`. @@ -446,8 +454,13 @@ bool _mi_os_commit(void* addr, size_t size, bool* is_zero) { return true; } -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); +bool _mi_os_commit(void* addr, size_t size, bool* is_zero) { + return _mi_os_commit_ex(addr, size, is_zero, size); +} + +static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, size_t stat_size) { + mi_assert_internal(needs_recommit!=NULL); + mi_os_stat_decrease(committed, stat_size); // page align size_t csize; @@ -466,7 +479,7 @@ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit) { bool _mi_os_decommit(void* addr, size_t size) { bool needs_recommit; - return mi_os_decommit_ex(addr, size, &needs_recommit); + return mi_os_decommit_ex(addr, size, &needs_recommit, size); } @@ -628,7 +641,7 @@ 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_os_prim_free(p, MI_HUGE_OS_PAGE_SIZE, MI_HUGE_OS_PAGE_SIZE); } break; } @@ -674,7 +687,7 @@ 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); + mi_os_prim_free(base, MI_HUGE_OS_PAGE_SIZE, MI_HUGE_OS_PAGE_SIZE); size -= MI_HUGE_OS_PAGE_SIZE; base += MI_HUGE_OS_PAGE_SIZE; } From 587e08ccd44430bb3f5d2975653fffd18008de24 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 25 Dec 2024 11:12:26 -0800 Subject: [PATCH 119/131] improve commit stats --- include/mimalloc/internal.h | 2 +- src/arena.c | 3 +-- src/os.c | 41 ++++++++++++++++++++----------------- test/test-stress.c | 3 ++- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 8b22e1c6..48ec3f1c 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -121,7 +121,7 @@ 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); +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stat_size); 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); diff --git a/src/arena.c b/src/arena.c index 0ddb2936..5952c544 100644 --- a/src/arena.c +++ b/src/arena.c @@ -474,8 +474,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? */); - if (needs_recommit) { _mi_stat_increase(&_mi_stats_main.committed, size); } + needs_recommit = _mi_os_purge_ex(p, size, false /* allow reset? */, 0); } // clear the purged blocks diff --git a/src/os.c b/src/os.c index 7e7dcb2c..77469775 100644 --- a/src/os.c +++ b/src/os.c @@ -9,7 +9,9 @@ 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) +#define mi_os_stat_increase(stat,amount) _mi_stat_increase(&_mi_stats_main.stat, amount) +#define mi_os_stat_decrease(stat,amount) _mi_stat_decrease(&_mi_stats_main.stat, amount) +#define mi_os_stat_counter_increase(stat,inc) _mi_stat_counter_increase(&_mi_stats_main.stat, inc) /* ----------------------------------------------------------- Initialization. @@ -171,9 +173,9 @@ static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) { _mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr); } if (commit_size > 0) { - _mi_stat_decrease(&os_stats->committed, commit_size); + mi_os_stat_decrease(committed, commit_size); } - _mi_stat_decrease(&os_stats->reserved, size); + mi_os_stat_decrease(reserved, size); } void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid) { @@ -236,11 +238,11 @@ static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignm - mi_stat_counter_increase(os_stats->mmap_calls, 1); + mi_os_stat_counter_increase(mmap_calls, 1); if (p != NULL) { - _mi_stat_increase(&os_stats->reserved, size); + mi_os_stat_increase(reserved, size); if (commit) { - _mi_stat_increase(&os_stats->committed, size); + mi_os_stat_increase(committed, size); // seems needed for asan (or `mimalloc-test-api` fails) #ifdef MI_TRACK_ASAN if (*is_zero) { mi_track_mem_defined(p,size); } @@ -357,7 +359,8 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allo if (p != NULL) { *memid = _mi_memid_create_os(commit, os_is_zero, os_is_large); memid->mem.os.base = os_base; - memid->mem.os.alignment = alignment; + // memid->mem.os.alignment = alignment; + memid->mem.os.size += ((uint8_t*)p - (uint8_t*)os_base); // todo: return from prim_alloc_aligned } return p; } @@ -425,10 +428,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) { +bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size) { if (is_zero != NULL) { *is_zero = false; } - _mi_stat_increase(&os_stats->committed, size); // use size for precise commit vs. decommit - _mi_stat_counter_increase(&os_stats->commit_calls, 1); + mi_os_stat_increase(committed, stat_size); // use size for precise commit vs. decommit + mi_os_stat_counter_increase(commit_calls, 1); // page align range size_t csize; @@ -492,8 +495,8 @@ bool _mi_os_reset(void* addr, size_t size) { 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(&os_stats->reset, csize); - _mi_stat_counter_increase(&os_stats->reset_calls, 1); + mi_os_stat_increase(reset, csize); + mi_os_stat_counter_increase(reset_calls, 1); #if (MI_DEBUG>1) && !MI_SECURE && !MI_TRACK_ENABLED // && !MI_TSAN memset(start, 0, csize); // pretend it is eagerly reset @@ -509,17 +512,17 @@ bool _mi_os_reset(void* addr, size_t size) { // 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) +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stat_size) { if (mi_option_get(mi_option_purge_delay) < 0) return false; // is purging allowed? - _mi_stat_counter_increase(&os_stats->purge_calls, 1); - _mi_stat_increase(&os_stats->purged, size); + mi_os_stat_counter_increase(purge_calls, 1); + mi_os_stat_increase(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); + mi_os_decommit_ex(p, size, &needs_recommit, stat_size); return needs_recommit; } else { @@ -533,7 +536,7 @@ bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset) // 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) { - return _mi_os_purge_ex(p, size, true); + return _mi_os_purge_ex(p, size, true, size); } @@ -648,8 +651,8 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse // success, record it page++; // increase before timeout check (see issue #711) - _mi_stat_increase(&os_stats->committed, MI_HUGE_OS_PAGE_SIZE); - _mi_stat_increase(&os_stats->reserved, MI_HUGE_OS_PAGE_SIZE); + mi_os_stat_increase(committed, MI_HUGE_OS_PAGE_SIZE); + mi_os_stat_increase(reserved, MI_HUGE_OS_PAGE_SIZE); // check for timeout if (max_msecs > 0) { diff --git a/test/test-stress.c b/test/test-stress.c index 6284ad39..9b8eb2d0 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -64,6 +64,7 @@ static bool main_participates = false; // main thread participates as a #define custom_calloc(n,s) mi_calloc(n,s) #define custom_realloc(p,s) mi_realloc(p,s) #define custom_free(p) mi_free(p) + #ifndef NDEBUG #define HEAP_WALK // walk the heap objects? #endif @@ -223,7 +224,7 @@ static void test_stress(void) { run_os_threads(THREADS, &stress); #if !defined(NDEBUG) && !defined(USE_STD_MALLOC) // switch between arena and OS allocation for testing - mi_option_set_enabled(mi_option_disallow_arena_alloc, (n%2)==1); + // mi_option_set_enabled(mi_option_disallow_arena_alloc, (n%2)==1); #endif #ifdef HEAP_WALK size_t total = 0; From 63f47569f2c3211d13b8acac932ef78f4445f771 Mon Sep 17 00:00:00 2001 From: daanx Date: Wed, 25 Dec 2024 13:35:54 -0800 Subject: [PATCH 120/131] fix debug_show_arenas parameters --- include/mimalloc.h | 2 +- src/arena.c | 22 +++++++++++----------- test/test-stress.c | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 5916228b..95a76c2d 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -276,7 +276,7 @@ mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept; mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept; -mi_decl_export void mi_debug_show_arenas(bool show_inuse, bool show_abandoned, bool show_purge) mi_attr_noexcept; +mi_decl_export void mi_debug_show_arenas(bool show_inuse) mi_attr_noexcept; // Experimental: heaps associated with specific memory arena's typedef int mi_arena_id_t; diff --git a/src/arena.c b/src/arena.c index 5952c544..0e508115 100644 --- a/src/arena.c +++ b/src/arena.c @@ -911,11 +911,11 @@ static size_t mi_debug_show_bitmap(const char* prefix, const char* header, size_ return inuse_count; } -void mi_debug_show_arenas(bool show_inuse, bool show_abandoned, bool show_purge) mi_attr_noexcept { +void mi_debug_show_arenas(bool show_inuse) mi_attr_noexcept { size_t max_arenas = mi_atomic_load_relaxed(&mi_arena_count); size_t inuse_total = 0; - size_t abandoned_total = 0; - size_t purge_total = 0; + //size_t abandoned_total = 0; + //size_t purge_total = 0; for (size_t i = 0; i < max_arenas; i++) { mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); if (arena == NULL) break; @@ -926,16 +926,16 @@ void mi_debug_show_arenas(bool show_inuse, bool show_abandoned, bool show_purge) if (arena->blocks_committed != NULL) { mi_debug_show_bitmap(" ", "committed blocks", arena->block_count, arena->blocks_committed, arena->field_count); } - if (show_abandoned) { - abandoned_total += mi_debug_show_bitmap(" ", "abandoned blocks", arena->block_count, arena->blocks_abandoned, arena->field_count); - } - if (show_purge && arena->blocks_purge != NULL) { - purge_total += mi_debug_show_bitmap(" ", "purgeable blocks", arena->block_count, arena->blocks_purge, arena->field_count); - } + //if (show_abandoned) { + // abandoned_total += mi_debug_show_bitmap(" ", "abandoned blocks", arena->block_count, arena->blocks_abandoned, arena->field_count); + //} + //if (show_purge && arena->blocks_purge != NULL) { + // purge_total += mi_debug_show_bitmap(" ", "purgeable blocks", arena->block_count, arena->blocks_purge, arena->field_count); + //} } if (show_inuse) _mi_verbose_message("total inuse blocks : %zu\n", inuse_total); - if (show_abandoned) _mi_verbose_message("total abandoned blocks: %zu\n", abandoned_total); - if (show_purge) _mi_verbose_message("total purgeable blocks: %zu\n", purge_total); + //if (show_abandoned) _mi_verbose_message("total abandoned blocks: %zu\n", abandoned_total); + //if (show_purge) _mi_verbose_message("total purgeable blocks: %zu\n", purge_total); } diff --git a/test/test-stress.c b/test/test-stress.c index 9b8eb2d0..8c5fca9c 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -238,7 +238,7 @@ static void test_stress(void) { } #ifndef NDEBUG //mi_collect(false); - //mi_debug_show_arenas(); + //mi_debug_show_arenas(true); #endif #if !defined(NDEBUG) || defined(MI_TSAN) if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); } @@ -316,7 +316,7 @@ int main(int argc, char** argv) { #ifndef USE_STD_MALLOC #ifndef NDEBUG - mi_debug_show_arenas(true,true,true); + mi_debug_show_arenas(true); mi_collect(true); #endif #endif From 47b5f48b2909055dfe0e3caea5ec13cad74369bb Mon Sep 17 00:00:00 2001 From: daanx Date: Thu, 26 Dec 2024 09:52:46 -0800 Subject: [PATCH 121/131] renamed vcxproj --- CMakeLists.txt | 16 ++- ...{mimalloc.vcxproj => mimalloc-lib.vcxproj} | 2 +- ....vcxproj => mimalloc-override-dll.vcxproj} | 2 +- ide/vs2022/mimalloc-override-test.vcxproj | 2 +- ide/vs2022/mimalloc-override.vcxproj.filters | 113 ------------------ ide/vs2022/mimalloc-test-api.vcxproj | 2 +- ide/vs2022/mimalloc-test-stress.vcxproj | 2 +- ide/vs2022/mimalloc-test.vcxproj | 2 +- ide/vs2022/mimalloc.sln | 4 +- ide/vs2022/mimalloc.vcxproj.filters | 105 ---------------- include/mimalloc/internal.h | 2 +- include/mimalloc/prim.h | 37 +++++- src/prim/windows/prim.c | 12 +- 13 files changed, 67 insertions(+), 234 deletions(-) rename ide/vs2022/{mimalloc.vcxproj => mimalloc-lib.vcxproj} (99%) rename ide/vs2022/{mimalloc-override.vcxproj => mimalloc-override-dll.vcxproj} (99%) delete mode 100644 ide/vs2022/mimalloc-override.vcxproj.filters delete mode 100644 ide/vs2022/mimalloc.vcxproj.filters diff --git a/CMakeLists.txt b/CMakeLists.txt index cde8144f..ca69fc6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ 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) option(MI_WIN_REDIRECT "Use redirection module ('mimalloc-redirect') on Windows if compiling mimalloc as a DLL" ON) +option(MI_WIN_USE_FIXED_TLS "Use a fixed TLS slot on Windows to avoid extra tests in the malloc fast path" OFF) option(MI_LOCAL_DYNAMIC_TLS "Use local-dynamic-tls, a slightly slower but dlopen-compatible thread local storage mechanism (Unix)" OFF) option(MI_LIBC_MUSL "Set this when linking with musl libc" OFF) option(MI_BUILD_SHARED "Build shared library" ON) @@ -35,7 +36,7 @@ option(MI_NO_THP "Disable transparent huge pages support on Linux/And option(MI_EXTRA_CPPDEFS "Extra pre-processor definitions (use as `-DMI_EXTRA_CPPDEFS=\"opt1=val1;opt2=val2\"`)" "") # deprecated options -option(MI_WIN_USE_FLS "Use Fiber local storage on Windows to detect thread termination" OFF) +option(MI_WIN_USE_FLS "Use Fiber local storage on Windows to detect thread termination (deprecated)" OFF) option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF) option(MI_USE_LIBATOMIC "Explicitly link with -latomic (on older systems) (deprecated and detected automatically)" OFF) @@ -90,7 +91,7 @@ endif() if (CMAKE_GENERATOR MATCHES "^Visual Studio.*$") message(STATUS "Note: when building with Visual Studio the build type is specified when building.") - message(STATUS "For example: 'cmake --build . --config=Release") + message(STATUS "For example: 'cmake --build . --config=Release") endif() if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$") @@ -322,10 +323,15 @@ if(MI_LIBC_MUSL) endif() if(MI_WIN_USE_FLS) - message(STATUS "Use the Fiber API to detect thread termination (MI_WIN_USE_FLS=ON)") + message(STATUS "Use the Fiber API to detect thread termination (deprecated) (MI_WIN_USE_FLS=ON)") list(APPEND mi_defines MI_WIN_USE_FLS=1) endif() +if(MI_WIN_USE_FIXED_TLS) + message(STATUS "Use fixed TLS slot on Windows to avoid extra tests in the malloc fast path (MI_WIN_USE_FIXED_TLS=ON)") + list(APPEND mi_defines MI_WIN_USE_FIXED_TLS=1) +endif() + # Determine architecture set(MI_OPT_ARCH_FLAGS "") set(MI_ARCH "unknown") @@ -543,7 +549,7 @@ if(MI_BUILD_SHARED) elseif(MI_ARCH STREQUAL "x64") set(MIMALLOC_REDIRECT_SUFFIX "") if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") - message(STATUS "Note: x64 code emulated on Windows for arm64 should use an arm64ec build of 'mimalloc-override.dll'") + message(STATUS "Note: x64 code emulated on Windows for arm64 should use an arm64ec build of 'mimalloc-override.dll'") message(STATUS " with 'mimalloc-redirect-arm64ec.dll'. See the 'bin\\readme.md' for more information.") endif() elseif(MI_ARCH STREQUAL "x86") @@ -667,7 +673,7 @@ endif() # ----------------------------------------------------------------------------- if (MI_OVERRIDE) if (MI_BUILD_SHARED) - target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) + target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) endif() if(NOT WIN32) # It is only possible to override malloc on Windows when building as a DLL. diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc-lib.vcxproj similarity index 99% rename from ide/vs2022/mimalloc.vcxproj rename to ide/vs2022/mimalloc-lib.vcxproj index 9964310d..6c652b8a 100644 --- a/ide/vs2022/mimalloc.vcxproj +++ b/ide/vs2022/mimalloc-lib.vcxproj @@ -37,7 +37,7 @@ 15.0 {ABB5EAE7-B3E6-432E-B636-333449892EA6} - mimalloc + mimalloc-lib 10.0 mimalloc-lib diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override-dll.vcxproj similarity index 99% rename from ide/vs2022/mimalloc-override.vcxproj rename to ide/vs2022/mimalloc-override-dll.vcxproj index 1278cd0f..c1849bb2 100644 --- a/ide/vs2022/mimalloc-override.vcxproj +++ b/ide/vs2022/mimalloc-override-dll.vcxproj @@ -37,7 +37,7 @@ 15.0 {ABB5EAE7-B3E6-432E-B636-333449892EA7} - mimalloc-override + mimalloc-override-dll 10.0 mimalloc-override-dll diff --git a/ide/vs2022/mimalloc-override-test.vcxproj b/ide/vs2022/mimalloc-override-test.vcxproj index 0e87cf36..427a75ae 100644 --- a/ide/vs2022/mimalloc-override-test.vcxproj +++ b/ide/vs2022/mimalloc-override-test.vcxproj @@ -344,7 +344,7 @@ - + {abb5eae7-b3e6-432e-b636-333449892ea7} diff --git a/ide/vs2022/mimalloc-override.vcxproj.filters b/ide/vs2022/mimalloc-override.vcxproj.filters deleted file mode 100644 index a9f66c35..00000000 --- a/ide/vs2022/mimalloc-override.vcxproj.filters +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - - - {9ef1cf48-7bb2-4af1-8cc1-603486e08a7a} - - - {cfcf1674-81e3-487a-a8dd-5f956ae4007d} - - - - - Headers - - - \ No newline at end of file diff --git a/ide/vs2022/mimalloc-test-api.vcxproj b/ide/vs2022/mimalloc-test-api.vcxproj index 27247569..b7f97ad2 100644 --- a/ide/vs2022/mimalloc-test-api.vcxproj +++ b/ide/vs2022/mimalloc-test-api.vcxproj @@ -282,7 +282,7 @@ - + {abb5eae7-b3e6-432e-b636-333449892ea6} diff --git a/ide/vs2022/mimalloc-test-stress.vcxproj b/ide/vs2022/mimalloc-test-stress.vcxproj index fd88cd8e..cb761f94 100644 --- a/ide/vs2022/mimalloc-test-stress.vcxproj +++ b/ide/vs2022/mimalloc-test-stress.vcxproj @@ -279,7 +279,7 @@ - + {abb5eae7-b3e6-432e-b636-333449892ea6} diff --git a/ide/vs2022/mimalloc-test.vcxproj b/ide/vs2022/mimalloc-test.vcxproj index 6e4576fd..83202dbe 100644 --- a/ide/vs2022/mimalloc-test.vcxproj +++ b/ide/vs2022/mimalloc-test.vcxproj @@ -276,7 +276,7 @@ - + {abb5eae7-b3e6-432e-b636-333449892ea6} diff --git a/ide/vs2022/mimalloc.sln b/ide/vs2022/mimalloc.sln index 5a55c98b..040af3ac 100644 --- a/ide/vs2022/mimalloc.sln +++ b/ide/vs2022/mimalloc.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.12.35527.113 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-lib", "mimalloc-lib.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}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-dll", "mimalloc-override-dll.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 diff --git a/ide/vs2022/mimalloc.vcxproj.filters b/ide/vs2022/mimalloc.vcxproj.filters deleted file mode 100644 index 54ee0fcb..00000000 --- a/ide/vs2022/mimalloc.vcxproj.filters +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - Sources - - - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - Headers - - - - - {dd2da697-c33c-4348-bf80-a802ebaa06fb} - - - {8027057b-4b93-4321-b93c-d51dd0c8077b} - - - \ No newline at end of file diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 48ec3f1c..ecb49a4e 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -419,7 +419,7 @@ static inline bool mi_heap_is_backing(const mi_heap_t* heap) { static inline bool mi_heap_is_initialized(mi_heap_t* heap) { mi_assert_internal(heap != NULL); - return (heap != &_mi_heap_empty); + return (heap != NULL && heap != &_mi_heap_empty); } static inline uintptr_t _mi_ptr_cookie(const void* p) { diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index 56715df4..c21ffa63 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- -Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +Copyright (c) 2018-2024, Microsoft Research, Daan Leijen This is free software; you can redistribute it and/or modify it under the terms of the MIT license. A copy of the license can be found in the file "LICENSE" at the root of this distribution. @@ -129,6 +129,7 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); // for each thread (unequal to zero). //------------------------------------------------------------------- + // On some libc + platform combinations we can directly access a thread-local storage (TLS) slot. // The TLS layout depends on both the OS and libc implementation so we use specific tests for each main platform. // If you test on another platform and it works please send a PR :-) @@ -206,8 +207,40 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce #endif } +#elif _WIN32 && MI_WIN_USE_FIXED_TLS && !defined(MI_WIN_USE_FLS) + +// On windows we can store the thread-local heap at a fixed TLS slot to avoid +// thread-local initialization checks in the fast path. This use a fixed location +// in the TCB though (last user-reserved slot by default) which may clash with other applications. + +#define MI_HAS_TLS_SLOT 2 // 2 = we can reliable initialize the slot (saving a test on each malloc) + +#if MI_WIN_USE_FIXED_TLS > 1 +#define MI_TLS_SLOT (MI_WIN_USE_FIXED_TLS) +#elif MI_SIZE_SIZE == 4 +#define MI_TLS_SLOT (0x710) // Last user-reserved slot +// #define MI_TLS_SLOT (0xF0C) // Last TlsSlot (might clash with other app reserved slot) +#else +#define MI_TLS_SLOT (0x888) // Last user-reserved slot +// #define MI_TLS_SLOT (0x1678) // Last TlsSlot (might clash with other app reserved slot) #endif +static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept { + #if (_M_X64 || _M_AMD64) && !defined(_M_ARM64EC) + return (void*)__readgsqword((unsigned long)slot); // direct load at offset from gs + #elif _M_IX86 && !defined(_M_ARM64EC) + return (void*)__readfsdword((unsigned long)slot); // direct load at offset from fs + #else + return ((void**)NtCurrentTeb())[slot / sizeof(void*)]; + #endif +} +static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexcept { + ((void**)NtCurrentTeb())[slot / sizeof(void*)] = value; +} + +#endif + + // Do we have __builtin_thread_pointer? This would be the preferred way to get a unique thread id // but unfortunately, it seems we cannot test for this reliably at this time (see issue #883) // Nevertheless, it seems needed on older graviton platforms (see issue #851). @@ -322,12 +355,14 @@ static inline mi_heap_t* mi_prim_get_default_heap(void); static inline mi_heap_t* mi_prim_get_default_heap(void) { mi_heap_t* heap = (mi_heap_t*)mi_prim_tls_slot(MI_TLS_SLOT); + #if MI_TLS_SLOT == 1 // check if the TLS slot is initialized if mi_unlikely(heap == NULL) { #ifdef __GNUC__ __asm(""); // prevent conditional load of the address of _mi_heap_empty #endif heap = (mi_heap_t*)&_mi_heap_empty; } + #endif return heap; } diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 1d3d6f41..ac228b53 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -622,6 +622,11 @@ bool _mi_prim_random_buf(void* buf, size_t buf_len) { static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { MI_UNUSED(reserved); MI_UNUSED(module); + #if MI_TLS_SLOT >= 2 + if ((reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) && mi_prim_get_default_heap() == NULL) { + _mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty); + } + #endif if (reason==DLL_PROCESS_ATTACH) { _mi_process_load(); } @@ -630,7 +635,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { } else if (reason==DLL_THREAD_DETACH && !_mi_is_redirected()) { _mi_thread_done(NULL); - } + } } @@ -783,6 +788,11 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { #endif mi_decl_export void _mi_redirect_entry(DWORD reason) { // called on redirection; careful as this may be called before DllMain + #if MI_TLS_SLOT >= 2 + if ((reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) && mi_prim_get_default_heap() == NULL) { + _mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty); + } + #endif if (reason == DLL_PROCESS_ATTACH) { mi_redirected = true; } From 783dcb4129730928ffb6a43da7d2df14a45a3e6f Mon Sep 17 00:00:00 2001 From: daanx Date: Thu, 26 Dec 2024 10:24:20 -0800 Subject: [PATCH 122/131] add comments about TLS --- include/mimalloc/prim.h | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index c21ffa63..aa0b188d 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -119,17 +119,15 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); -//------------------------------------------------------------------- -// Thread id: `_mi_prim_thread_id()` -// -// Getting the thread id should be performant as it is called in the -// fast path of `_mi_free` and we specialize for various platforms as -// inlined definitions. Regular code should call `init.c:_mi_thread_id()`. -// We only require _mi_prim_thread_id() to return a unique id -// for each thread (unequal to zero). -//------------------------------------------------------------------- +//------------------------------------------------------------------- +// Access to TLS (thread local storage) slots. +// We need fast access to both a unique thread id (in `free.c:mi_free`) and +// to a thread-local heap pointer (in `alloc.c:mi_malloc`). +// To achieve this we use specialized code for various platforms. +//------------------------------------------------------------------- + // On some libc + platform combinations we can directly access a thread-local storage (TLS) slot. // The TLS layout depends on both the OS and libc implementation so we use specific tests for each main platform. // If you test on another platform and it works please send a PR :-) @@ -210,7 +208,7 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce #elif _WIN32 && MI_WIN_USE_FIXED_TLS && !defined(MI_WIN_USE_FLS) // On windows we can store the thread-local heap at a fixed TLS slot to avoid -// thread-local initialization checks in the fast path. This use a fixed location +// thread-local initialization checks in the fast path. This uses a fixed location // in the TCB though (last user-reserved slot by default) which may clash with other applications. #define MI_HAS_TLS_SLOT 2 // 2 = we can reliable initialize the slot (saving a test on each malloc) @@ -241,6 +239,18 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce #endif + +//------------------------------------------------------------------- +// Get a fast unique thread id. +// +// Getting the thread id should be performant as it is called in the +// fast path of `_mi_free` and we specialize for various platforms as +// inlined definitions. Regular code should call `init.c:_mi_thread_id()`. +// We only require _mi_prim_thread_id() to return a unique id +// for each thread (unequal to zero). +//------------------------------------------------------------------- + + // Do we have __builtin_thread_pointer? This would be the preferred way to get a unique thread id // but unfortunately, it seems we cannot test for this reliably at this time (see issue #883) // Nevertheless, it seems needed on older graviton platforms (see issue #851). @@ -311,7 +321,8 @@ static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { /* ---------------------------------------------------------------------------------------- -The thread local default heap: `_mi_prim_get_default_heap()` +Get the thread local default heap: `_mi_prim_get_default_heap()` + This is inlined here as it is on the fast path for allocation functions. On most platforms (Windows, Linux, FreeBSD, NetBSD, etc), this just returns a @@ -404,7 +415,4 @@ static inline mi_heap_t* mi_prim_get_default_heap(void) { #endif // mi_prim_get_default_heap() - - - #endif // MIMALLOC_PRIM_H From e10d0d2dee8a7c4d010bea1af0f4ed6815d480f9 Mon Sep 17 00:00:00 2001 From: daanx Date: Thu, 26 Dec 2024 10:33:25 -0800 Subject: [PATCH 123/131] add declspec hidden to improve codegen on arm64 --- include/mimalloc/internal.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index ecb49a4e..1302e128 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -31,16 +31,19 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_decl_thread __declspec(thread) #define mi_decl_cache_align __declspec(align(MI_CACHE_LINE)) #define mi_decl_weak +#define mi_decl_hidden #elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) // includes clang and icc #define mi_decl_noinline __attribute__((noinline)) #define mi_decl_thread __thread #define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE))) #define mi_decl_weak __attribute__((weak)) +#define mi_decl_hidden __attribute__((visibility("hidden"))) #else #define mi_decl_noinline #define mi_decl_thread __thread // hope for the best :-) #define mi_decl_cache_align #define mi_decl_weak +#define mi_decl_hidden #endif #if defined(__EMSCRIPTEN__) && !defined(__wasi__) @@ -87,7 +90,7 @@ 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; +extern mi_decl_hidden mi_decl_cache_align const mi_page_t _mi_page_empty; void _mi_process_load(void); void mi_cdecl _mi_process_done(void); bool _mi_is_redirected(void); @@ -411,7 +414,7 @@ static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* tot Heap functions ------------------------------------------------------------------------------------------- */ -extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap +extern mi_decl_hidden const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap static inline bool mi_heap_is_backing(const mi_heap_t* heap) { return (heap->tld->heap_backing == heap); @@ -423,7 +426,7 @@ static inline bool mi_heap_is_initialized(mi_heap_t* heap) { } static inline uintptr_t _mi_ptr_cookie(const void* p) { - extern mi_heap_t _mi_heap_main; + extern mi_decl_hidden mi_heap_t _mi_heap_main; mi_assert_internal(_mi_heap_main.cookie != 0); return ((uintptr_t)p ^ _mi_heap_main.cookie); } @@ -808,7 +811,7 @@ static inline uintptr_t _mi_random_shuffle(uintptr_t x) { int _mi_os_numa_node_get(void); size_t _mi_os_numa_node_count_get(void); -extern _Atomic(size_t) _mi_numa_node_count; +extern mi_decl_hidden _Atomic(size_t) _mi_numa_node_count; 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(); From 095abc9e3d71ced049d7b6a400cb3866cc2d5999 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 26 Dec 2024 11:16:04 -0800 Subject: [PATCH 124/131] fix TLS slot on macOS --- include/mimalloc/prim.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index aa0b188d..9a1ab4f9 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -144,7 +144,7 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); || (defined(__OpenBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \ ) -#define MI_HAS_TLS_SLOT +#define MI_HAS_TLS_SLOT 1 static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept { void* res; @@ -294,7 +294,7 @@ static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { return (uintptr_t)__builtin_thread_pointer(); } -#elif defined(MI_HAS_TLS_SLOT) +#elif MI_HAS_TLS_SLOT static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { #if defined(__BIONIC__) @@ -359,14 +359,14 @@ static inline mi_heap_t* mi_prim_get_default_heap(void); #endif -#if defined(MI_TLS_SLOT) +#if MI_TLS_SLOT # if !defined(MI_HAS_TLS_SLOT) # error "trying to use a TLS slot for the default heap, but the mi_prim_tls_slot primitives are not defined" # endif static inline mi_heap_t* mi_prim_get_default_heap(void) { mi_heap_t* heap = (mi_heap_t*)mi_prim_tls_slot(MI_TLS_SLOT); - #if MI_TLS_SLOT == 1 // check if the TLS slot is initialized + #if MI_HAS_TLS_SLOT == 1 // check if the TLS slot is initialized if mi_unlikely(heap == NULL) { #ifdef __GNUC__ __asm(""); // prevent conditional load of the address of _mi_heap_empty From 7bd1d72bfba01a5551d6fac0f104055fc5bfcc56 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 30 Dec 2024 10:33:13 -0800 Subject: [PATCH 125/131] Update readme.md to fix links (issue #978) --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 11f62da4..8cb9ffff 100644 --- a/readme.md +++ b/readme.md @@ -253,7 +253,7 @@ to link with the static library. See `test\CMakeLists.txt` for an example. For best performance in C++ programs, it is also recommended to override the global `new` and `delete` operators. For convenience, mimalloc provides -[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project. +[`mimalloc-new-delete.h`](include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project. In C++, mimalloc also provides the `mi_stl_allocator` struct which implements the `std::allocator` interface. @@ -458,7 +458,7 @@ There are four requirements to make the overriding work well: For best performance on Windows with C++, it is also recommended to also override the `new`/`delete` operations (by including -[`mimalloc-new-delete.h`](../include/mimalloc-new-delete.h) +[`mimalloc-new-delete.h`](include/mimalloc-new-delete.h) a single(!) source file in your project). The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic @@ -487,7 +487,7 @@ object file. For example: Another way to override statically that works on all platforms, is to link statically to mimalloc (as shown in the introduction) and include a header file in each source file that re-defines `malloc` etc. to `mi_malloc`. -This is provided by [`mimalloc-override.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-override.h). This only works reliably though if all sources are +This is provided by [`mimalloc-override.h`](include/mimalloc-override.h). This only works reliably though if all sources are under your control or otherwise mixing of pointers from different heaps may occur! From 9561ae428612d8fa5d2d7683d2c5f2276e982175 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:00:54 -0800 Subject: [PATCH 126/131] rename segment_map_destroy to segment_map_unsafe_destroy --- include/mimalloc/atomic.h | 3 +++ include/mimalloc/internal.h | 2 +- src/init.c | 2 +- src/segment-map.c | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index c4fac766..5725bfbf 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -72,6 +72,7 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_atomic_load_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) #define mi_atomic_store_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) #define mi_atomic_store_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_exchange_relaxed(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(relaxed)) #define mi_atomic_exchange_release(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(release)) #define mi_atomic_exchange_acq_rel(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(acq_rel)) #define mi_atomic_cas_weak_release(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) @@ -110,6 +111,7 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); #define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,(tp*)des) #define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,(tp*)des) #define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,(tp*)des) +#define mi_atomic_exchange_ptr_relaxed(tp,p,x) mi_atomic_exchange_relaxed(p,(tp*)x) #define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,(tp*)x) #define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,(tp*)x) #else @@ -118,6 +120,7 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); #define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,des) #define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,des) #define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,des) +#define mi_atomic_exchange_ptr_relaxed(tp,p,x) mi_atomic_exchange_relaxed(p,x) #define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,x) #define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,x) #endif diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 6f6e9dc3..0ede8f8c 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -167,7 +167,7 @@ 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_destroy(void); +void _mi_segment_map_unsafe_destroy(void); // "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); diff --git a/src/init.c b/src/init.c index ab99a8f8..b8c01e51 100644 --- a/src/init.c +++ b/src/init.c @@ -682,7 +682,7 @@ void mi_cdecl _mi_process_done(void) { 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_segment_map_destroy(); + _mi_segment_map_unsafe_destroy(); } if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { diff --git a/src/segment-map.c b/src/segment-map.c index f6dff96d..ce754e98 100644 --- a/src/segment-map.c +++ b/src/segment-map.c @@ -126,9 +126,9 @@ mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_att return mi_is_valid_pointer(p); } -void _mi_segment_map_destroy(void) { +void _mi_segment_map_unsafe_destroy(void) { for (size_t i = 0; i < MI_SEGMENT_MAP_MAX_PARTS; i++) { - mi_segmap_part_t* part = mi_segment_map[i]; + mi_segmap_part_t* part = mi_atomic_exchange_ptr_relaxed(mi_segmap_part_t, &mi_segment_map[i], NULL); if (part != NULL) { _mi_os_free(part, sizeof(mi_segmap_part_t), part->memid); } From 485b69976f3227e19de699e0d280319921b1a995 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:04:30 -0800 Subject: [PATCH 127/131] add filters for vs projects --- .gitignore | 1 - ide/vs2022/mimalloc-lib.vcxproj.filters | 105 ++++++++++++++++++ .../mimalloc-override-dll.vcxproj.filters | 3 + 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 ide/vs2022/mimalloc-lib.vcxproj.filters create mode 100644 ide/vs2022/mimalloc-override-dll.vcxproj.filters diff --git a/.gitignore b/.gitignore index df1d58eb..b2439f94 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ ide/vs20??/*.db ide/vs20??/*.opendb ide/vs20??/*.user -ide/vs20??/*.vcxproj.filters ide/vs20??/.vs ide/vs20??/VTune* out/ diff --git a/ide/vs2022/mimalloc-lib.vcxproj.filters b/ide/vs2022/mimalloc-lib.vcxproj.filters new file mode 100644 index 00000000..90703da8 --- /dev/null +++ b/ide/vs2022/mimalloc-lib.vcxproj.filters @@ -0,0 +1,105 @@ + + + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + + + {1430490c-e711-4ace-a1b8-36f4d5105873} + + + {461c78ef-04b0-44d1-a0ca-7d488abaa592} + + + \ No newline at end of file diff --git a/ide/vs2022/mimalloc-override-dll.vcxproj.filters b/ide/vs2022/mimalloc-override-dll.vcxproj.filters new file mode 100644 index 00000000..0b07de1b --- /dev/null +++ b/ide/vs2022/mimalloc-override-dll.vcxproj.filters @@ -0,0 +1,3 @@ + + + \ No newline at end of file From d29372fda49313c9927cfdf5a917f3f9b84de34b Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:15:57 -0800 Subject: [PATCH 128/131] remove older vs projects as they became stale --- ide/vs2017/mimalloc-override-test.vcxproj | 190 ------------- .../mimalloc-override-test.vcxproj.filters | 22 -- ide/vs2017/mimalloc-override.vcxproj | 260 ------------------ ide/vs2017/mimalloc-override.vcxproj.filters | 98 ------- ide/vs2017/mimalloc-test-stress.vcxproj | 159 ----------- .../mimalloc-test-stress.vcxproj.filters | 22 -- ide/vs2017/mimalloc-test.vcxproj | 158 ----------- ide/vs2017/mimalloc-test.vcxproj.filters | 22 -- ide/vs2017/mimalloc.sln | 71 ----- ide/vs2017/mimalloc.vcxproj | 260 ------------------ ide/vs2017/mimalloc.vcxproj.filters | 98 ------- ide/vs2019/mimalloc-override-test.vcxproj | 190 ------------- ide/vs2019/mimalloc-override.vcxproj | 260 ------------------ ide/vs2019/mimalloc-override.vcxproj.filters | 96 ------- ide/vs2019/mimalloc-test-api.vcxproj | 155 ----------- ide/vs2019/mimalloc-test-stress.vcxproj | 159 ----------- ide/vs2019/mimalloc-test.vcxproj | 158 ----------- ide/vs2019/mimalloc.sln | 81 ------ ide/vs2019/mimalloc.vcxproj | 258 ----------------- ide/vs2019/mimalloc.vcxproj.filters | 99 ------- 20 files changed, 2816 deletions(-) delete mode 100644 ide/vs2017/mimalloc-override-test.vcxproj delete mode 100644 ide/vs2017/mimalloc-override-test.vcxproj.filters delete mode 100644 ide/vs2017/mimalloc-override.vcxproj delete mode 100644 ide/vs2017/mimalloc-override.vcxproj.filters delete mode 100644 ide/vs2017/mimalloc-test-stress.vcxproj delete mode 100644 ide/vs2017/mimalloc-test-stress.vcxproj.filters delete mode 100644 ide/vs2017/mimalloc-test.vcxproj delete mode 100644 ide/vs2017/mimalloc-test.vcxproj.filters delete mode 100644 ide/vs2017/mimalloc.sln delete mode 100644 ide/vs2017/mimalloc.vcxproj delete mode 100644 ide/vs2017/mimalloc.vcxproj.filters delete mode 100644 ide/vs2019/mimalloc-override-test.vcxproj delete mode 100644 ide/vs2019/mimalloc-override.vcxproj delete mode 100644 ide/vs2019/mimalloc-override.vcxproj.filters delete mode 100644 ide/vs2019/mimalloc-test-api.vcxproj delete mode 100644 ide/vs2019/mimalloc-test-stress.vcxproj delete mode 100644 ide/vs2019/mimalloc-test.vcxproj delete mode 100644 ide/vs2019/mimalloc.sln delete mode 100644 ide/vs2019/mimalloc.vcxproj delete mode 100644 ide/vs2019/mimalloc.vcxproj.filters diff --git a/ide/vs2017/mimalloc-override-test.vcxproj b/ide/vs2017/mimalloc-override-test.vcxproj deleted file mode 100644 index 04c16a9f..00000000 --- a/ide/vs2017/mimalloc-override-test.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7868F-750E-4C21-A04D-22707CC66879} - mimalloc-override-test - mimalloc-override-test - 10.0.19041.0 - - - - Application - true - v141 - - - Application - false - v141 - true - - - Application - true - v141 - - - Application - false - v141 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - MultiThreadedDebugDLL - false - Default - false - - - Console - kernel32.lib;%(AdditionalDependencies) - - - - - - - - - - Level3 - Disabled - true - true - ..\..\include - MultiThreadedDebugDLL - Sync - Default - false - - - Console - - - kernel32.lib;%(AdditionalDependencies) - - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - MultiThreadedDLL - - - true - true - Console - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - MultiThreadedDLL - - - true - true - Console - - - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - - - {abb5eae7-b3e6-432e-b636-333449892ea7} - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-override-test.vcxproj.filters b/ide/vs2017/mimalloc-override-test.vcxproj.filters deleted file mode 100644 index eb5e70b7..00000000 --- a/ide/vs2017/mimalloc-override-test.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-override.vcxproj b/ide/vs2017/mimalloc-override.vcxproj deleted file mode 100644 index 6d20eb57..00000000 --- a/ide/vs2017/mimalloc-override.vcxproj +++ /dev/null @@ -1,260 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {ABB5EAE7-B3E6-432E-B636-333449892EA7} - mimalloc-override - mimalloc-override - 10.0.19041.0 - - - - DynamicLibrary - true - v141 - - - DynamicLibrary - false - v141 - - - DynamicLibrary - true - v141 - - - DynamicLibrary - false - v141 - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - - Level3 - Disabled - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); - MultiThreadedDebugDLL - false - Default - - - $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) - - - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect32.dll" "$(OutputPath)" - - - Copy mimalloc-redirect32.dll to the output directory - - - - - Level3 - Disabled - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); - MultiThreadedDebugDLL - false - Default - - - $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies) - - - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect.dll" "$(OutputPath)" - - - copy mimalloc-redirect.dll to the output directory - - - - - Level3 - MaxSpeed - true - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - MultiThreadedDLL - Default - false - - - true - true - $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect32.dll" "$(OutputPath)" - - - Copy mimalloc-redirect32.dll to the output directory - - - - - Level3 - MaxSpeed - true - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - MultiThreadedDLL - Default - false - - - true - true - $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies) - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect.dll" "$(OutputPath)" - - - copy mimalloc-redirect.dll to the output directory - - - - - - - - - - - - - - - - false - false - false - false - - - true - true - true - true - - - - - - - - - - - - - true - true - true - true - - - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-override.vcxproj.filters b/ide/vs2017/mimalloc-override.vcxproj.filters deleted file mode 100644 index 1adafcfa..00000000 --- a/ide/vs2017/mimalloc-override.vcxproj.filters +++ /dev/null @@ -1,98 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-test-stress.vcxproj b/ide/vs2017/mimalloc-test-stress.vcxproj deleted file mode 100644 index 061b8605..00000000 --- a/ide/vs2017/mimalloc-test-stress.vcxproj +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7958F-750E-4C21-A04D-22707CC66878} - mimalloc-test-stress - mimalloc-test-stress - 10.0.19041.0 - - - - Application - true - v141 - - - Application - false - v141 - true - - - Application - true - v141 - - - Application - false - v141 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - false - false - false - false - - - - - {abb5eae7-b3e6-432e-b636-333449892ea6} - - - - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-test-stress.vcxproj.filters b/ide/vs2017/mimalloc-test-stress.vcxproj.filters deleted file mode 100644 index 7c5239e8..00000000 --- a/ide/vs2017/mimalloc-test-stress.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-test.vcxproj b/ide/vs2017/mimalloc-test.vcxproj deleted file mode 100644 index 04bd6537..00000000 --- a/ide/vs2017/mimalloc-test.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7858F-750E-4C21-A04D-22707CC66878} - mimalloctest - mimalloc-test - 10.0.19041.0 - - - - Application - true - v141 - - - Application - false - v141 - true - - - Application - true - v141 - - - Application - false - v141 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - stdcpp17 - - - Console - - - - - Level3 - Disabled - true - true - ..\..\include - stdcpp14 - - - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - stdcpp17 - - - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - stdcpp17 - - - true - true - Console - - - - - {abb5eae7-b3e6-432e-b636-333449892ea6} - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc-test.vcxproj.filters b/ide/vs2017/mimalloc-test.vcxproj.filters deleted file mode 100644 index fca75e1c..00000000 --- a/ide/vs2017/mimalloc-test.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc.sln b/ide/vs2017/mimalloc.sln deleted file mode 100644 index 515c03f2..00000000 --- a/ide/vs2017/mimalloc.sln +++ /dev/null @@ -1,71 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.102 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} - EndGlobalSection -EndGlobal diff --git a/ide/vs2017/mimalloc.vcxproj b/ide/vs2017/mimalloc.vcxproj deleted file mode 100644 index ece9a14d..00000000 --- a/ide/vs2017/mimalloc.vcxproj +++ /dev/null @@ -1,260 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {ABB5EAE7-B3E6-432E-B636-333449892EA6} - mimalloc - 10.0.19041.0 - mimalloc - - - - StaticLibrary - true - v141 - - - StaticLibrary - false - v141 - true - - - StaticLibrary - true - v141 - - - StaticLibrary - false - v141 - true - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - false - - - false - - - false - - - false - - - - Level3 - Disabled - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions); - CompileAsC - false - stdcpp17 - - - - - - - - - - - Level4 - Disabled - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions); - CompileAsCpp - false - stdcpp14 - - - - - - - - - - - - - - - - - - - Level3 - MaxSpeed - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - false - Default - CompileAsC - true - - - true - true - - - - - - - - - - - Level4 - MaxSpeed - true - true - ../../include - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - false - Default - CompileAsC - true - - - true - true - - - - - - - - - - - - - - - - - false - false - false - false - - - true - true - true - true - - - - - - - - - - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2017/mimalloc.vcxproj.filters b/ide/vs2017/mimalloc.vcxproj.filters deleted file mode 100644 index 8359e0e4..00000000 --- a/ide/vs2017/mimalloc.vcxproj.filters +++ /dev/null @@ -1,98 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc-override-test.vcxproj b/ide/vs2019/mimalloc-override-test.vcxproj deleted file mode 100644 index 7a9202f1..00000000 --- a/ide/vs2019/mimalloc-override-test.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7868F-750E-4C21-A04D-22707CC66879} - mimalloc-override-test - 10.0 - mimalloc-override-test - - - - Application - true - v142 - - - Application - false - v142 - true - - - Application - true - v142 - - - Application - false - v142 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - MultiThreadedDebugDLL - Sync - Default - false - - - Console - kernel32.lib;%(AdditionalDependencies) - - - - - - - - - - Level3 - Disabled - true - true - ..\..\include - MultiThreadedDebugDLL - Sync - Default - false - - - Console - - - kernel32.lib;%(AdditionalDependencies) - - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - MultiThreadedDLL - - - true - true - Console - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - MultiThreadedDLL - - - true - true - Console - - - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - - - - - - {abb5eae7-b3e6-432e-b636-333449892ea7} - - - - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc-override.vcxproj b/ide/vs2019/mimalloc-override.vcxproj deleted file mode 100644 index a84a5178..00000000 --- a/ide/vs2019/mimalloc-override.vcxproj +++ /dev/null @@ -1,260 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {ABB5EAE7-B3E6-432E-B636-333449892EA7} - mimalloc-override - 10.0 - mimalloc-override - - - - DynamicLibrary - true - v142 - - - DynamicLibrary - false - v142 - - - DynamicLibrary - true - v142 - - - DynamicLibrary - false - v142 - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .dll - mimalloc-override - - - - Level3 - Disabled - true - true - ../../include - MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); - MultiThreadedDebugDLL - false - Default - - - $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) - - - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect32.dll" "$(OutputPath)" - - - Copy mimalloc-redirect32.dll to the output directory - - - - - Level3 - Disabled - true - true - ../../include - MI_DEBUG=3;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions); - MultiThreadedDebugDLL - false - Default - - - $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) - - - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect.dll" "$(OutputPath)" - - - copy mimalloc-redirect.dll to the output directory - - - - - Level3 - MaxSpeed - true - true - true - ../../include - MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - MultiThreadedDLL - Default - false - - - true - true - $(ProjectDir)\..\..\bin\mimalloc-redirect32.lib;%(AdditionalDependencies) - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect32.dll" "$(OutputPath)" - - - Copy mimalloc-redirect32.dll to the output directory - - - - - Level3 - MaxSpeed - true - true - true - ../../include - MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - MultiThreadedDLL - Default - false - - - true - true - $(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies) - - - Default - false - - - COPY /Y "$(ProjectDir)..\..\bin\mimalloc-redirect.dll" "$(OutputPath)" - - - copy mimalloc-redirect.dll to the output directory - - - - - - - - - - - - - - - - false - false - false - false - - - true - true - true - true - - - - - - - - - - - - - true - true - true - true - - - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc-override.vcxproj.filters b/ide/vs2019/mimalloc-override.vcxproj.filters deleted file mode 100644 index 046e5603..00000000 --- a/ide/vs2019/mimalloc-override.vcxproj.filters +++ /dev/null @@ -1,96 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Source Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {f1fccf27-17b9-42dd-ba51-6070baff85c6} - - - {39cb7e38-69d0-43fb-8406-6a0f7cefc3b4} - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc-test-api.vcxproj b/ide/vs2019/mimalloc-test-api.vcxproj deleted file mode 100644 index 812a9cb1..00000000 --- a/ide/vs2019/mimalloc-test-api.vcxproj +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FFF7958F-750E-4C21-A04D-22707CC66878} - mimalloc-test-api - 10.0 - mimalloc-test-api - - - - Application - true - v142 - - - Application - false - v142 - true - - - Application - true - v142 - - - Application - false - v142 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - - - - - {abb5eae7-b3e6-432e-b636-333449892ea6} - - - - - - diff --git a/ide/vs2019/mimalloc-test-stress.vcxproj b/ide/vs2019/mimalloc-test-stress.vcxproj deleted file mode 100644 index ef7ab357..00000000 --- a/ide/vs2019/mimalloc-test-stress.vcxproj +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7958F-750E-4C21-A04D-22707CC66878} - mimalloc-test-stress - 10.0 - mimalloc-test-stress - - - - Application - true - v142 - - - Application - false - v142 - true - - - Application - true - v142 - - - Application - false - v142 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - Disabled - true - true - ..\..\include - - - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - %(PreprocessorDefinitions);NDEBUG - - - true - true - Console - - - - - false - false - false - false - - - - - {abb5eae7-b3e6-432e-b636-333449892ea6} - - - - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc-test.vcxproj b/ide/vs2019/mimalloc-test.vcxproj deleted file mode 100644 index 13af6ab4..00000000 --- a/ide/vs2019/mimalloc-test.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {FEF7858F-750E-4C21-A04D-22707CC66878} - mimalloctest - 10.0 - mimalloc-test - - - - Application - true - v142 - - - Application - false - v142 - true - - - Application - true - v142 - - - Application - false - v142 - true - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - $(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - - - - Level3 - Disabled - true - true - ..\..\include - stdcpp17 - - - Console - - - - - Level3 - Disabled - true - true - ..\..\include - stdcpp17 - - - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - stdcpp17 - - - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - ..\..\include - _MBCS;%(PreprocessorDefinitions);NDEBUG - stdcpp17 - - - true - true - Console - - - - - {abb5eae7-b3e6-432e-b636-333449892ea6} - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc.sln b/ide/vs2019/mimalloc.sln deleted file mode 100644 index 6ff01d3b..00000000 --- a/ide/vs2019/mimalloc.sln +++ /dev/null @@ -1,81 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test", "mimalloc-test.vcxproj", "{FEF7858F-750E-4C21-A04D-22707CC66878}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override", "mimalloc-override.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "mimalloc-override-test.vcxproj", "{FEF7868F-750E-4C21-A04D-22707CC66879}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-api", "mimalloc-test-api.vcxproj", "{FFF7958F-750E-4C21-A04D-22707CC66878}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7858F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.ActiveCfg = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x64.Build.0 = Debug|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.ActiveCfg = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Debug|x86.Build.0 = Debug|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.ActiveCfg = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x64.Build.0 = Release|x64 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.ActiveCfg = Release|Win32 - {ABB5EAE7-B3E6-432E-B636-333449892EA7}.Release|x86.Build.0 = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x64.Build.0 = Debug|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Debug|x86.Build.0 = Debug|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.ActiveCfg = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x64.Build.0 = Release|x64 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.ActiveCfg = Release|Win32 - {FEF7868F-750E-4C21-A04D-22707CC66879}.Release|x86.Build.0 = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 - {FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4297F93D-486A-4243-995F-7D32F59AE82A} - EndGlobalSection -EndGlobal diff --git a/ide/vs2019/mimalloc.vcxproj b/ide/vs2019/mimalloc.vcxproj deleted file mode 100644 index 0076b1db..00000000 --- a/ide/vs2019/mimalloc.vcxproj +++ /dev/null @@ -1,258 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {ABB5EAE7-B3E6-432E-B636-333449892EA6} - mimalloc - 10.0 - mimalloc - - - - StaticLibrary - true - v142 - - - StaticLibrary - false - v142 - true - - - StaticLibrary - true - v142 - - - StaticLibrary - false - v142 - true - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - $(SolutionDir)..\..\out\msvc-$(Platform)\$(Configuration)\ - $(SolutionDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\ - .lib - mimalloc-static - - - - Level4 - Disabled - true - true - ../../include - MI_DEBUG=3;%(PreprocessorDefinitions); - CompileAsCpp - false - Default - - - - - - - - - - - Level4 - Disabled - true - Default - ../../include - MI_DEBUG=3;%(PreprocessorDefinitions); - CompileAsCpp - false - Default - - - - - - - - - - - - - - - - - - - Level4 - MaxSpeed - true - true - ../../include - %(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - false - Default - CompileAsCpp - true - Default - - - true - true - - - - - - - - - - - Level4 - MaxSpeed - true - true - ../../include - %(PreprocessorDefinitions);NDEBUG - AssemblyAndSourceCode - $(IntDir) - false - false - Default - CompileAsCpp - true - Default - - - true - true - - - - - - - - - - - - - - - - - false - false - false - false - - - true - true - true - true - - - - - - false - - - - - - - true - true - true - true - - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ide/vs2019/mimalloc.vcxproj.filters b/ide/vs2019/mimalloc.vcxproj.filters deleted file mode 100644 index 98f29289..00000000 --- a/ide/vs2019/mimalloc.vcxproj.filters +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Source Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {2b556b10-f559-4b2d-896e-142652adbf0c} - - - {852a14ae-6dde-4e95-8077-ca705e97e5af} - - - \ No newline at end of file From e183384ad052e1f05f919ce5264cda17672b2bc2 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:33:33 -0800 Subject: [PATCH 129/131] update vs project filter --- .../mimalloc-override-dll.vcxproj.filters | 112 +++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/ide/vs2022/mimalloc-override-dll.vcxproj.filters b/ide/vs2022/mimalloc-override-dll.vcxproj.filters index 0b07de1b..91bdf95c 100644 --- a/ide/vs2022/mimalloc-override-dll.vcxproj.filters +++ b/ide/vs2022/mimalloc-override-dll.vcxproj.filters @@ -1,3 +1,113 @@  - + + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + Sources + + + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + + + {262c6c21-e270-4ba6-bd63-4ac999307e4e} + + + {94b40bdc-a741-45dd-81aa-c05fabcd2970} + + + + + Sources + + \ No newline at end of file From 9f70ce5fcd5e59d0b6eeb5094566b8b7711e4d13 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:34:02 -0800 Subject: [PATCH 130/131] avoid accessing heap->tld after running thread_done (pr #974) --- include/mimalloc/internal.h | 2 +- src/heap.c | 7 ++++--- src/init.c | 11 ++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 0ede8f8c..a1791cd9 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -216,7 +216,7 @@ 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); +void _mi_heap_unsafe_destroy_all(mi_heap_t* heap); 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); diff --git a/src/heap.c b/src/heap.c index c2b5ae42..7a14c1aa 100644 --- a/src/heap.c +++ b/src/heap.c @@ -393,9 +393,10 @@ void mi_heap_destroy(mi_heap_t* heap) { } // forcefully destroy all heaps in the current thread -void _mi_heap_unsafe_destroy_all(void) { - mi_heap_t* bheap = mi_heap_get_backing(); - mi_heap_t* curr = bheap->tld->heaps; +void _mi_heap_unsafe_destroy_all(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + if (heap == NULL) return; + mi_heap_t* curr = heap->tld->heaps; while (curr != NULL) { mi_heap_t* next = curr->next; if (curr->no_reclaim) { diff --git a/src/init.c b/src/init.c index b8c01e51..734bf5de 100644 --- a/src/init.c +++ b/src/init.c @@ -663,15 +663,20 @@ void mi_cdecl _mi_process_done(void) { if (process_done) return; process_done = true; + // get the default heap so we don't need to acces thread locals anymore + mi_heap_t* heap = mi_prim_get_default_heap(); // use prim to not initialize any heap + mi_assert_internal(heap != NULL); + // release any thread specific resources and ensure _mi_thread_done is called on all but the main thread _mi_prim_thread_done_auto_done(); + #ifndef MI_SKIP_COLLECT_ON_EXIT #if (MI_DEBUG || !defined(MI_SHARED_LIB)) // free all memory if possible on process exit. This is not needed for a stand-alone process // but should be done if mimalloc is statically linked into another shared library which // is repeatedly loaded/unloaded, see issue #281. - mi_collect(true /* force */ ); + mi_heap_collect(heap, true /* force */ ); #endif #endif @@ -679,8 +684,8 @@ void mi_cdecl _mi_process_done(void) { // since after process_done there might still be other code running that calls `free` (like at_exit routines, // or C-runtime termination code. 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_heap_collect(heap, true /* force */); + _mi_heap_unsafe_destroy_all(heap); // forcefully release all memory held by all heaps (of this thread only!) _mi_arena_unsafe_destroy_all(); _mi_segment_map_unsafe_destroy(); } From 2d94df860bec9bf8379f8af773c6986faf0dd2de Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 30 Dec 2024 11:44:03 -0800 Subject: [PATCH 131/131] fix potentially warning on gcc (pr #935) --- src/heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/heap.c b/src/heap.c index 7a14c1aa..f856a426 100644 --- a/src/heap.c +++ b/src/heap.c @@ -59,7 +59,7 @@ static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_ MI_UNUSED(pq); mi_assert_internal(mi_page_heap(page) == heap); mi_segment_t* segment = _mi_page_segment(page); - mi_assert_internal(segment->thread_id == heap->thread_id); + mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id) == heap->thread_id); mi_assert_expensive(_mi_page_is_valid(page)); return true; }