experimental destroy_on_exit option for statically linked mimalloc in a dynamically unloaded DLL

This commit is contained in:
Daan Leijen 2022-11-18 11:00:23 -08:00
parent 18cf94dff6
commit 35d332141d
6 changed files with 25 additions and 4 deletions

View File

@ -139,6 +139,7 @@ uint8_t _mi_bin(size_t size); // for stats
void _mi_heap_destroy_pages(mi_heap_t* heap); void _mi_heap_destroy_pages(mi_heap_t* heap);
void _mi_heap_collect_abandon(mi_heap_t* heap); void _mi_heap_collect_abandon(mi_heap_t* heap);
void _mi_heap_set_default_direct(mi_heap_t* heap); void _mi_heap_set_default_direct(mi_heap_t* heap);
void _mi_heap_destroy_all(void);
// "stats.c" // "stats.c"
void _mi_stats_done(mi_stats_t* stats); void _mi_stats_done(mi_stats_t* stats);

View File

@ -335,6 +335,7 @@ typedef enum mi_option_e {
mi_option_max_errors, mi_option_max_errors,
mi_option_max_warnings, mi_option_max_warnings,
mi_option_max_segment_reclaim, mi_option_max_segment_reclaim,
mi_option_destroy_on_exit,
_mi_option_last _mi_option_last
} mi_option_t; } mi_option_t;

View File

@ -327,7 +327,20 @@ void mi_heap_destroy(mi_heap_t* heap) {
} }
} }
void _mi_heap_destroy_all(void) {
mi_heap_t* bheap = mi_heap_get_backing();
mi_heap_t* curr = bheap->tld->heaps;
while (curr != NULL) {
mi_heap_t* next = curr->next;
if (curr->no_reclaim) {
mi_heap_destroy(curr);
}
else {
_mi_heap_destroy_pages(curr);
}
curr = next;
}
}
/* ----------------------------------------------------------- /* -----------------------------------------------------------
Safe Heap delete Safe Heap delete

View File

@ -598,7 +598,7 @@ static void mi_cdecl mi_process_done(void) {
#if defined(_WIN32) && !defined(MI_SHARED_LIB) #if defined(_WIN32) && !defined(MI_SHARED_LIB)
FlsFree(mi_fls_key); // 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); // call thread-done on all threads (except the main thread) to prevent dangling callback pointer if statically linked with a DLL; Issue #208
#endif #endif
#ifndef MI_SKIP_COLLECT_ON_EXIT #ifndef MI_SKIP_COLLECT_ON_EXIT
#if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB) #if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB)
// free all memory if possible on process exit. This is not needed for a stand-alone process // free all memory if possible on process exit. This is not needed for a stand-alone process
@ -608,6 +608,11 @@ static void mi_cdecl mi_process_done(void) {
#endif #endif
#endif #endif
if (mi_option_is_enabled(mi_option_destroy_on_exit)) {
_mi_heap_destroy_all(); // forcefully release all memory held by all heaps (of this thread only!)
_mi_mem_collect(&_mi_heap_main_get()->tld->os); // release all regions
}
if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) {
mi_stats_print(NULL); mi_stats_print(NULL);
} }

View File

@ -93,7 +93,8 @@ static mi_option_desc_t options[_mi_option_last] =
{ 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose { 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_errors) }, // maximum errors that are output
{ 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output { 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output
{ 8, UNINIT, MI_OPTION(max_segment_reclaim)} // max. number of segment reclaims from the abandoned segments per try. { 8, UNINIT, MI_OPTION(max_segment_reclaim)},// max. number of segment reclaims from the abandoned segments per try.
{ 0, UNINIT, MI_OPTION(destroy_on_exit)} // release all OS memory on process exit; careful with dangling pointer or after-exit frees!
}; };
static void mi_option_init(mi_option_desc_t* desc); static void mi_option_init(mi_option_desc_t* desc);

View File

@ -32,7 +32,7 @@ int main() {
// invalid_free(); // invalid_free();
// test_reserved(); // test_reserved();
// negative_stat(); // negative_stat();
test_heap_walk(); // test_heap_walk();
// alloc_huge(); // alloc_huge();
void* p1 = malloc(78); void* p1 = malloc(78);