diff --git a/include/mimalloc.h b/include/mimalloc.h index 2707bc16..1e0062c4 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -321,6 +321,7 @@ typedef enum mi_option_e { mi_option_reset_delay, mi_option_use_numa_nodes, // 0 = use available numa nodes, otherwise use at most N nodes. mi_option_limit_os_alloc, // 1 = do not use OS memory for allocation (but only reserved arenas) + mi_option_max_segment_reclaim, mi_option_os_tag, mi_option_max_errors, mi_option_max_warnings, @@ -335,6 +336,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 e8913818..1d816fa1 100644 --- a/src/init.c +++ b/src/init.c @@ -562,7 +562,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 8700fc76..a3e2ea2a 100644 --- a/src/options.c +++ b/src/options.c @@ -90,6 +90,7 @@ static mi_option_desc_t options[_mi_option_last] = { 100, UNINIT, MI_OPTION(reset_delay) }, // reset delay in milli-seconds { 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes. { 0, UNINIT, MI_OPTION(limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas) + { 8, UNINIT, MI_OPTION(max_segment_reclaim)},// max. number of segment reclaims from the abandoned segments per try. { 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose { 16, UNINIT, MI_OPTION(max_errors) }, // maximum errors that are output { 16, UNINIT, MI_OPTION(max_warnings) } // maximum warnings that are output @@ -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/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 75265073..4554eba0 100644 --- a/src/segment.c +++ b/src/segment.c @@ -1112,7 +1112,7 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, { *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 all_pages_free;