mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 22:49:32 +03:00
merge from dev
This commit is contained in:
commit
17ade3fca5
5 changed files with 41 additions and 31 deletions
|
@ -16,7 +16,7 @@ option(MI_BUILD_TESTS "Build test executables" ON)
|
||||||
|
|
||||||
include("cmake/mimalloc-config-version.cmake")
|
include("cmake/mimalloc-config-version.cmake")
|
||||||
|
|
||||||
set(mi_install_dir "lib/mimalloc-${mi_version}")
|
set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}")
|
||||||
|
|
||||||
set(mi_sources
|
set(mi_sources
|
||||||
src/stats.c
|
src/stats.c
|
||||||
|
|
|
@ -241,7 +241,7 @@ static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x)
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__wasi__)
|
#elif defined(__wasi__)
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
static inline void mi_atomic_yield() {
|
static inline void mi_atomic_yield(void) {
|
||||||
sched_yield();
|
sched_yield();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -101,6 +101,7 @@ uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD i
|
||||||
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);
|
||||||
uintptr_t _mi_heap_random(mi_heap_t* heap);
|
uintptr_t _mi_heap_random(mi_heap_t* heap);
|
||||||
|
void _mi_heap_set_default_direct(mi_heap_t* heap);
|
||||||
|
|
||||||
// "stats.c"
|
// "stats.c"
|
||||||
void _mi_stats_done(mi_stats_t* stats);
|
void _mi_stats_done(mi_stats_t* stats);
|
||||||
|
|
|
@ -223,7 +223,7 @@ static void mi_heap_free(mi_heap_t* heap) {
|
||||||
|
|
||||||
// reset default
|
// reset default
|
||||||
if (mi_heap_is_default(heap)) {
|
if (mi_heap_is_default(heap)) {
|
||||||
_mi_heap_default = heap->tld->heap_backing;
|
_mi_heap_set_default_direct(heap->tld->heap_backing);
|
||||||
}
|
}
|
||||||
// and free the used memory
|
// and free the used memory
|
||||||
mi_free(heap);
|
mi_free(heap);
|
||||||
|
@ -354,8 +354,8 @@ mi_heap_t* mi_heap_set_default(mi_heap_t* heap) {
|
||||||
mi_assert(mi_heap_is_initialized(heap));
|
mi_assert(mi_heap_is_initialized(heap));
|
||||||
if (!mi_heap_is_initialized(heap)) return NULL;
|
if (!mi_heap_is_initialized(heap)) return NULL;
|
||||||
mi_assert_expensive(mi_heap_is_valid(heap));
|
mi_assert_expensive(mi_heap_is_valid(heap));
|
||||||
mi_heap_t* old = _mi_heap_default;
|
mi_heap_t* old = mi_get_default_heap();
|
||||||
_mi_heap_default = heap;
|
_mi_heap_set_default_direct(heap);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
61
src/init.c
61
src/init.c
|
@ -90,6 +90,7 @@ const mi_heap_t _mi_heap_empty = {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// the thread-local default heap for allocation
|
||||||
mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty;
|
mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty;
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,8 +203,8 @@ static bool _mi_heap_init(void) {
|
||||||
if (mi_heap_is_initialized(_mi_heap_default)) return true;
|
if (mi_heap_is_initialized(_mi_heap_default)) return true;
|
||||||
if (_mi_is_main_thread()) {
|
if (_mi_is_main_thread()) {
|
||||||
// the main heap is statically allocated
|
// the main heap is statically allocated
|
||||||
_mi_heap_default = &_mi_heap_main;
|
_mi_heap_set_default_direct(&_mi_heap_main);
|
||||||
mi_assert_internal(_mi_heap_default->tld->heap_backing == _mi_heap_default);
|
mi_assert_internal(_mi_heap_default->tld->heap_backing == mi_get_default_heap());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// use `_mi_os_alloc` to allocate directly from the OS
|
// use `_mi_os_alloc` to allocate directly from the OS
|
||||||
|
@ -228,18 +229,17 @@ static bool _mi_heap_init(void) {
|
||||||
tld->os.reset_delay = reset_delay;
|
tld->os.reset_delay = reset_delay;
|
||||||
memset(reset_delay, 0, sizeof(*reset_delay));
|
memset(reset_delay, 0, sizeof(*reset_delay));
|
||||||
reset_delay->capacity = MI_RESET_DELAY_SLOTS;
|
reset_delay->capacity = MI_RESET_DELAY_SLOTS;
|
||||||
_mi_heap_default = heap;
|
_mi_heap_set_default_direct(heap);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the thread local default heap (called from `mi_thread_done`)
|
// Free the thread local default heap (called from `mi_thread_done`)
|
||||||
static bool _mi_heap_done(void) {
|
static bool _mi_heap_done(mi_heap_t* heap) {
|
||||||
mi_heap_t* heap = _mi_heap_default;
|
|
||||||
if (!mi_heap_is_initialized(heap)) return true;
|
if (!mi_heap_is_initialized(heap)) return true;
|
||||||
|
|
||||||
// reset default heap
|
// reset default heap
|
||||||
_mi_heap_default = (_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty);
|
_mi_heap_set_default_direct(_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty);
|
||||||
|
|
||||||
// todo: delete all non-backing heaps?
|
// todo: delete all non-backing heaps?
|
||||||
|
|
||||||
|
@ -286,6 +286,8 @@ static bool _mi_heap_done(void) {
|
||||||
// to set up the thread local keys.
|
// to set up the thread local keys.
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
static void _mi_thread_done(mi_heap_t* default_heap);
|
||||||
|
|
||||||
#ifdef __wasi__
|
#ifdef __wasi__
|
||||||
// no pthreads in the WebAssembly Standard Interface
|
// no pthreads in the WebAssembly Standard Interface
|
||||||
#elif !defined(_WIN32)
|
#elif !defined(_WIN32)
|
||||||
|
@ -300,14 +302,14 @@ static bool _mi_heap_done(void) {
|
||||||
#include <fibersapi.h>
|
#include <fibersapi.h>
|
||||||
static DWORD mi_fls_key;
|
static DWORD mi_fls_key;
|
||||||
static void NTAPI mi_fls_done(PVOID value) {
|
static void NTAPI mi_fls_done(PVOID value) {
|
||||||
if (value!=NULL) mi_thread_done();
|
if (value!=NULL) _mi_thread_done((mi_heap_t*)value);
|
||||||
}
|
}
|
||||||
#elif defined(MI_USE_PTHREADS)
|
#elif defined(MI_USE_PTHREADS)
|
||||||
// use pthread locol storage keys to detect thread ending
|
// use pthread locol storage keys to detect thread ending
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
static pthread_key_t mi_pthread_key;
|
static pthread_key_t mi_pthread_key;
|
||||||
static void mi_pthread_done(void* value) {
|
static void mi_pthread_done(void* value) {
|
||||||
if (value!=NULL) mi_thread_done();
|
if (value!=NULL) _mi_thread_done((mi_heap_t*)value);
|
||||||
}
|
}
|
||||||
#elif defined(__wasi__)
|
#elif defined(__wasi__)
|
||||||
// no pthreads in the WebAssembly Standard Interface
|
// no pthreads in the WebAssembly Standard Interface
|
||||||
|
@ -341,6 +343,8 @@ void mi_thread_init(void) mi_attr_noexcept
|
||||||
mi_process_init();
|
mi_process_init();
|
||||||
|
|
||||||
// initialize the thread local default heap
|
// initialize the thread local default heap
|
||||||
|
// (this will call `_mi_heap_set_default_direct` and thus set the
|
||||||
|
// fiber/pthread key to a non-zero value, ensuring `_mi_thread_done` is called)
|
||||||
if (_mi_heap_init()) return; // returns true if already initialized
|
if (_mi_heap_init()) return; // returns true if already initialized
|
||||||
|
|
||||||
// don't further initialize for the main thread
|
// don't further initialize for the main thread
|
||||||
|
@ -348,33 +352,38 @@ void mi_thread_init(void) mi_attr_noexcept
|
||||||
|
|
||||||
_mi_stat_increase(&mi_get_default_heap()->tld->stats.threads, 1);
|
_mi_stat_increase(&mi_get_default_heap()->tld->stats.threads, 1);
|
||||||
|
|
||||||
// set hooks so our mi_thread_done() will be called
|
|
||||||
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
|
||||||
// nothing to do as it is done in DllMain
|
|
||||||
#elif defined(_WIN32) && !defined(MI_SHARED_LIB)
|
|
||||||
FlsSetValue(mi_fls_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_fls_done` is called
|
|
||||||
#elif defined(MI_USE_PTHREADS)
|
|
||||||
pthread_setspecific(mi_pthread_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_pthread_done` is called
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
//_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void mi_thread_done(void) mi_attr_noexcept {
|
void mi_thread_done(void) mi_attr_noexcept {
|
||||||
|
_mi_thread_done(mi_get_default_heap());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _mi_thread_done(mi_heap_t* heap) {
|
||||||
// stats
|
// stats
|
||||||
mi_heap_t* heap = mi_get_default_heap();
|
|
||||||
if (!_mi_is_main_thread() && mi_heap_is_initialized(heap)) {
|
if (!_mi_is_main_thread() && mi_heap_is_initialized(heap)) {
|
||||||
_mi_stat_decrease(&heap->tld->stats.threads, 1);
|
_mi_stat_decrease(&heap->tld->stats.threads, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// abandon the thread local heap
|
// abandon the thread local heap
|
||||||
if (_mi_heap_done()) return; // returns true if already ran
|
if (_mi_heap_done(heap)) return; // returns true if already ran
|
||||||
|
|
||||||
//if (!_mi_is_main_thread()) {
|
|
||||||
// _mi_verbose_message("thread done: 0x%zx\n", _mi_thread_id());
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _mi_heap_set_default_direct(mi_heap_t* heap) {
|
||||||
|
mi_assert_internal(heap != NULL);
|
||||||
|
_mi_heap_default = heap;
|
||||||
|
|
||||||
|
// ensure the default heap is passed to `_mi_thread_done`
|
||||||
|
// setting to a non-NULL value also ensures `mi_thread_done` is called.
|
||||||
|
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
||||||
|
// nothing to do as it is done in DllMain
|
||||||
|
#elif defined(_WIN32) && !defined(MI_SHARED_LIB)
|
||||||
|
FlsSetValue(mi_fls_key, heap);
|
||||||
|
#elif defined(MI_USE_PTHREADS)
|
||||||
|
pthread_setspecific(mi_pthread_key, heap);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Run functions on process init/done, and thread init/done
|
// Run functions on process init/done, and thread init/done
|
||||||
|
@ -449,7 +458,7 @@ void mi_process_init(void) mi_attr_noexcept {
|
||||||
// access _mi_heap_default before setting _mi_process_is_initialized to ensure
|
// access _mi_heap_default before setting _mi_process_is_initialized to ensure
|
||||||
// that the TLS slot is allocated without getting into recursion on macOS
|
// that the TLS slot is allocated without getting into recursion on macOS
|
||||||
// when using dynamic linking with interpose.
|
// when using dynamic linking with interpose.
|
||||||
mi_heap_t* h = _mi_heap_default;
|
mi_heap_t* h = mi_get_default_heap();
|
||||||
_mi_process_is_initialized = true;
|
_mi_process_is_initialized = true;
|
||||||
|
|
||||||
_mi_heap_main.thread_id = _mi_thread_id();
|
_mi_heap_main.thread_id = _mi_thread_id();
|
||||||
|
@ -466,7 +475,7 @@ void mi_process_init(void) mi_attr_noexcept {
|
||||||
#endif
|
#endif
|
||||||
mi_thread_init();
|
mi_thread_init();
|
||||||
mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL)
|
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)) {
|
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(mi_option_reserve_huge_os_pages);
|
||||||
mi_reserve_huge_os_pages_interleave(pages, 0, pages*500);
|
mi_reserve_huge_os_pages_interleave(pages, 0, pages*500);
|
||||||
|
|
Loading…
Add table
Reference in a new issue