From 55ccc947077ac4cfee808d17463253cfcbd0856b Mon Sep 17 00:00:00 2001 From: daan Date: Wed, 15 Dec 2021 19:28:34 -0800 Subject: [PATCH] wip: fix zero init for sbrk; add lock around sbrk --- include/mimalloc-internal.h | 7 +++- src/init.c | 7 ---- src/os.c | 73 +++++++++++++++++++++---------------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 44631f8b..68239573 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -42,6 +42,11 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_decl_externc #endif +#if !defined(_WIN32) && !defined(__wasi__) +#define MI_USE_PTHREADS +#include +#endif + // "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, ...); @@ -326,7 +331,6 @@ mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing hea #if defined(MI_TLS_SLOT) static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept; // forward declaration #elif defined(MI_TLS_PTHREAD_SLOT_OFS) -#include static inline mi_heap_t** mi_tls_pthread_heap_slot(void) { pthread_t self = pthread_self(); #if defined(__DragonFly__) @@ -338,7 +342,6 @@ static inline mi_heap_t** mi_tls_pthread_heap_slot(void) { return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS); } #elif defined(MI_TLS_PTHREAD) -#include extern pthread_key_t _mi_heap_default_key; #endif diff --git a/src/init.c b/src/init.c index f2619000..e06fa6b9 100644 --- a/src/init.c +++ b/src/init.c @@ -275,12 +275,6 @@ static bool _mi_heap_done(mi_heap_t* heap) { static void _mi_thread_done(mi_heap_t* default_heap); -#ifdef __wasi__ -// no pthreads in the WebAssembly Standard Interface -#elif !defined(_WIN32) -#define MI_USE_PTHREADS -#endif - #if defined(_WIN32) && defined(MI_SHARED_LIB) // nothing to do as it is done in DllMain #elif defined(_WIN32) && !defined(MI_SHARED_LIB) @@ -300,7 +294,6 @@ static void _mi_thread_done(mi_heap_t* default_heap); #elif defined(MI_USE_PTHREADS) // use pthread local storage keys to detect thread ending // (and used with MI_TLS_PTHREADS for the default heap) - #include pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1); static void mi_pthread_done(void* value) { if (value!=NULL) _mi_thread_done((mi_heap_t*)value); diff --git a/src/os.c b/src/os.c index dc2afc78..afa94a1c 100644 --- a/src/os.c +++ b/src/os.c @@ -231,7 +231,7 @@ void _mi_os_init(void) #elif defined(__wasi__) void _mi_os_init() { os_overcommit = false; - os_page_size = 0x10000; // WebAssembly has a fixed page size: 64KiB + os_page_size = 64*MI_KiB; // WebAssembly has a fixed page size: 64KiB os_alloc_granularity = 16; } @@ -283,7 +283,7 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats bool err = false; #if defined(_WIN32) err = (VirtualFree(addr, 0, MEM_RELEASE) == 0); -#elif defined(MI_USE_SBRK) +#elif defined(MI_USE_SBRK) || defined(__wasi__) err = 0; // sbrk heap cannot be shrunk #else err = (munmap(addr, size) == -1); @@ -376,38 +376,47 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, } #elif defined(MI_USE_SBRK) || defined(__wasi__) - #if defined(MI_USE_SBRK) -#define MI_SBRK_FAIL ((void*)(-1)) -static void* mi_memory_grow( size_t size ) { - void* p = sbrk(size); - if (p == MI_SBRK_FAIL) { - _mi_warning_message("unable to allocate sbrk() OS memory (%zu bytes)\n", size); - errno = ENOMEM; - return NULL; +// unfortunately sbrk is usually not safe to call from multiple threads +#if defined(MI_USE_PTHREADS) + static pthread_mutex_t mi_sbrk_mutex = PTHREAD_MUTEX_INITIALIZER; + static void* mi_sbrk(size_t size) { + pthread_mutex_lock(&mi_sbrk_mutex); + void* p = sbrk(size); + pthread_mutex_unlock(&mi_sbrk_mutex); + return p; + } + #else + static void* mi_sbrk(size_t size) { + return sbrk(size); + } + #endif + static void* mi_memory_grow( size_t size ) { + void* p = mi_sbrk(size); + if (p == (void*)(-1)) { + _mi_warning_message("unable to allocate sbrk() OS memory (%zu bytes)\n", size); + errno = ENOMEM; + return NULL; + } + if (size > 0) { memset(p,0,size); } + return p; } - return p; -} #elif defined(__wasi__) -static void* mi_memory_grow( size_t size ) { - if (size > 0) { - size_t base = __builtin_wasm_memory_grow( 0, _mi_divide_up(size, _mi_os_page_size()) ); + static void* mi_memory_grow( size_t size ) { + size_t base; + if (size > 0) { + base = __builtin_wasm_memory_grow( 0, _mi_divide_up(size, _mi_os_page_size()) ); + } + else { + base = __builtin_wasm_memory_size(0); + } if (base == SIZE_MAX) { _mi_warning_message("unable to allocate wasm_memory_grow OS memory (%zu bytes)\n", size); errno = ENOMEM; return NULL; } - return (void*)(base * _mi_os_page_size()); + return (void*)(base * _mi_os_page_size()); } - else { - size_t base = __builtin_wasm_memory_size(0); - if (base == SIZE_MAX) { - errno = ENOMEM; - return NULL; - } - return (void*)(base * _mi_os_page_size()); - } -} #endif static void* mi_heap_grow(size_t size, size_t try_alignment) { @@ -432,17 +441,19 @@ static void* mi_heap_grow(size_t size, size_t try_alignment) { errno = 0; void* pbase2 = mi_memory_grow( alloc_size ); if (pbase2 == NULL) { return NULL; } + base = (uintptr_t)pbase2; aligned_base = _mi_align_up(base, try_alignment); - mi_assert_internal(aligned_base + size <= (uintptr_t)pbase2 + alloc_size); } - } - else { - mi_assert_internal(aligned_base + size <= (uintptr_t)pbase1 + alloc_size); - } + else { + // it still fits + mi_assert_internal(aligned_base + size <= base + alloc_size); + } + } + mi_assert_internal(aligned_base + size <= base + alloc_size); return (void*)aligned_base; } -#else +#else #define MI_OS_USE_MMAP static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) { MI_UNUSED(try_alignment);