diff --git a/include/mimalloc.h b/include/mimalloc.h index 58ecaa67..c752ac24 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -327,6 +327,7 @@ typedef enum mi_option_e { mi_option_os_tag, mi_option_max_errors, mi_option_max_warnings, + mi_option_max_segment_reclaim, mi_option_allow_decommit, mi_option_segment_decommit_delay, mi_option_decommit_extend_delay, @@ -341,6 +342,7 @@ mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable); mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable); mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option); +mi_decl_nodiscard mi_decl_export long mi_option_get_clamp(mi_option_t option, long min, long max); mi_decl_export void mi_option_set(mi_option_t option, long value); mi_decl_export void mi_option_set_default(mi_option_t option, long value); diff --git a/src/init.c b/src/init.c index 69bd1706..19124afe 100644 --- a/src/init.c +++ b/src/init.c @@ -589,7 +589,7 @@ void mi_process_init(void) mi_attr_noexcept { mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL) if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { - size_t pages = mi_option_get(mi_option_reserve_huge_os_pages); + size_t pages = mi_option_get_clamp(mi_option_reserve_huge_os_pages, 0, 128*1024); long reserve_at = mi_option_get(mi_option_reserve_huge_os_pages_at); if (reserve_at != -1) { mi_reserve_huge_os_pages_at(pages, reserve_at, pages*500); diff --git a/src/options.c b/src/options.c index 7eb1ebaf..80feacf3 100644 --- a/src/options.c +++ b/src/options.c @@ -93,7 +93,8 @@ static mi_option_desc_t options[_mi_option_last] = { 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output { 1, UNINIT, MI_OPTION(allow_decommit) }, // decommit slices when no longer used (after decommit_delay milli-seconds) { 500, UNINIT, MI_OPTION(segment_decommit_delay) }, // decommit delay in milli-seconds for freed segments - { 2, UNINIT, MI_OPTION(decommit_extend_delay) } + { 2, UNINIT, MI_OPTION(decommit_extend_delay) }, + { 8, UNINIT, MI_OPTION(max_segment_reclaim)},// max. number of segment reclaims from the abandoned segments per try. }; static void mi_option_init(mi_option_desc_t* desc); @@ -125,6 +126,11 @@ mi_decl_nodiscard long mi_option_get(mi_option_t option) { return desc->value; } +mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long max) { + long x = mi_option_get(option); + return (x < min ? min : (x > max ? max : x)); +} + void mi_option_set(mi_option_t option, long value) { mi_assert(option >= 0 && option < _mi_option_last); if (option < 0 || option >= _mi_option_last) return; diff --git a/src/os.c b/src/os.c index 9d3bbb1a..72959d81 100644 --- a/src/os.c +++ b/src/os.c @@ -364,7 +364,7 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats // the start of the region. MEMORY_BASIC_INFORMATION info = { 0, 0 }; VirtualQuery(addr, &info, sizeof(info)); - if (info.AllocationBase < addr) { + if (info.AllocationBase < addr && ((uint8_t*)addr - (uint8_t*)info.AllocationBase) < MI_SEGMENT_SIZE) { errcode = 0; err = (VirtualFree(info.AllocationBase, 0, MEM_RELEASE) == 0); if (err) { errcode = GetLastError(); } @@ -403,7 +403,7 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment if (hint != NULL) { void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE); if (p != NULL) return p; - _mi_warning_message("unable to allocate hinted aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), hint, try_alignment, flags); + _mi_verbose_message("warning: unable to allocate hinted aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), hint, try_alignment, flags); // fall through on error } } diff --git a/src/region.c b/src/region.c index 2d73025e..72ce8494 100644 --- a/src/region.c +++ b/src/region.c @@ -122,7 +122,7 @@ static size_t mi_good_commit_size(size_t size) { */ // Return if a pointer points into a region reserved by us. -bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { +mi_decl_nodiscard bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { if (p==NULL) return false; size_t count = mi_atomic_load_relaxed(®ions_count); for (size_t i = 0; i < count; i++) { diff --git a/src/segment.c b/src/segment.c index 470632c5..800d4fc3 100644 --- a/src/segment.c +++ b/src/segment.c @@ -1364,7 +1364,7 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t needed_slice { *reclaimed = false; mi_segment_t* segment; - int max_tries = 8; // limit the work to bound allocation times + long max_tries = mi_option_get_clamp(mi_option_max_segment_reclaim, 8, 1024); // limit the work to bound allocation times while ((max_tries-- > 0) && ((segment = mi_abandoned_pop()) != NULL)) { segment->abandoned_visits++; bool has_page = mi_segment_check_free(segment,needed_slices,block_size,tld); // try to free up pages (due to concurrent frees)