From 0d22807e91f3bc416cb70bcb0a39b0f05bc515eb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 7 May 2024 13:22:13 -0700 Subject: [PATCH 1/4] Emscripten: Remove no-longer-needed minimum emmalloc alignment --- src/prim/emscripten/prim.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/prim/emscripten/prim.c b/src/prim/emscripten/prim.c index c0fa0f4a..8b011b4d 100644 --- a/src/prim/emscripten/prim.c +++ b/src/prim/emscripten/prim.c @@ -78,17 +78,10 @@ int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_la // That assumes no one else uses sbrk but us (they could go up, // scribble, and then down), but we could assert on that perhaps. *is_zero = false; - // emmalloc has some limitations on alignment size. - // TODO: Why does mimalloc ask for an align of 4MB? that ends up allocating - // 8, which wastes quite a lot for us in wasm. If that is unavoidable, - // we may want to improve emmalloc to support such alignment. See also - // https://github.com/emscripten-core/emscripten/issues/20645 + // emmalloc has a minimum alignment size. #define MIN_EMMALLOC_ALIGN 8 - #define MAX_EMMALLOC_ALIGN (1024*1024) if (try_alignment < MIN_EMMALLOC_ALIGN) { try_alignment = MIN_EMMALLOC_ALIGN; - } else if (try_alignment > MAX_EMMALLOC_ALIGN) { - try_alignment = MAX_EMMALLOC_ALIGN; } void* p = emmalloc_memalign(try_alignment, size); *addr = p; From bb3802801cc95fac50a969d05f554d9737429e08 Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 11 May 2024 07:53:12 -0700 Subject: [PATCH 2/4] clarify parameters for emmalloc_memalign --- src/prim/emscripten/prim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prim/emscripten/prim.c b/src/prim/emscripten/prim.c index 8b011b4d..1f60a1bb 100644 --- a/src/prim/emscripten/prim.c +++ b/src/prim/emscripten/prim.c @@ -68,7 +68,7 @@ int _mi_prim_free(void* addr, size_t size) { // Allocation //--------------------------------------------- -extern void* emmalloc_memalign(size_t, size_t); +extern void* emmalloc_memalign(size_t alignment, size_t size); // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { From 0f6d8293c74796fa913e4b5eb4361f1e4734f7c6 Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 11 May 2024 08:08:03 -0700 Subject: [PATCH 3/4] use local dynamic tls for static MUSL builds (see issue #644) --- CMakeLists.txt | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6c95dc4..2cc2fc46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,9 @@ set(mi_sources src/prim/prim.c) set(mi_cflags "") +set(mi_cflags_static "") # extra flags for a static library build +set(mi_cflags_dynamic "") # extra flags for a shared-object library build +set(mi_defines "") set(mi_libraries "") # ----------------------------------------------------------------------------- @@ -288,8 +291,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") endif() if(MI_LIBC_MUSL) - message(STATUS "Assume using musl libc (MI_LIBC_MUSL=ON) (this implies MI_LOCAL_DYNAMIC_TLS=ON)") - set(MI_LOCAL_DYNAMIC_TLS "ON") + message(STATUS "Assume using musl libc (MI_LIBC_MUSL=ON)") list(APPEND mi_defines MI_LIBC_MUSL=1) endif() @@ -318,7 +320,14 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM if(MI_LOCAL_DYNAMIC_TLS) list(APPEND mi_cflags -ftls-model=local-dynamic) else() - list(APPEND mi_cflags -ftls-model=initial-exec) + if(MI_LIBC_MUSL) + # with musl we use local-dynamic for the static build, see issue #644 + list(APPEND mi_cflags_static -ftls-model=local-dynamic) + list(APPEND mi_cflags_dynamic -ftls-model=initial-exec) + message(STATUS "Use local dynamic TLS for the static build (since MI_LIBC_MUSL=ON)") + else() + list(APPEND mi_cflags -ftls-model=initial-exec) + endif() endif() if(MI_OVERRIDE) list(APPEND mi_cflags -fno-builtin-malloc) @@ -426,7 +435,7 @@ if(MI_BUILD_SHARED) add_library(mimalloc SHARED ${mi_sources}) set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} SOVERSION ${mi_version_major} OUTPUT_NAME ${mi_basename} ) target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_SHARED_LIB MI_SHARED_LIB_EXPORT) - target_compile_options(mimalloc PRIVATE ${mi_cflags}) + target_compile_options(mimalloc PRIVATE ${mi_cflags} ${mi_cflags_dynamic}) target_link_libraries(mimalloc PRIVATE ${mi_libraries}) target_include_directories(mimalloc PUBLIC $ @@ -456,7 +465,7 @@ if (MI_BUILD_STATIC) add_library(mimalloc-static STATIC ${mi_sources}) set_property(TARGET mimalloc-static PROPERTY POSITION_INDEPENDENT_CODE ON) target_compile_definitions(mimalloc-static PRIVATE ${mi_defines} MI_STATIC_LIB) - target_compile_options(mimalloc-static PRIVATE ${mi_cflags}) + target_compile_options(mimalloc-static PRIVATE ${mi_cflags} ${mi_cflags_static}) target_link_libraries(mimalloc-static PRIVATE ${mi_libraries}) target_include_directories(mimalloc-static PUBLIC $ @@ -488,7 +497,7 @@ if (MI_BUILD_OBJECT) add_library(mimalloc-obj OBJECT src/static.c) set_property(TARGET mimalloc-obj PROPERTY POSITION_INDEPENDENT_CODE ON) target_compile_definitions(mimalloc-obj PRIVATE ${mi_defines}) - target_compile_options(mimalloc-obj PRIVATE ${mi_cflags}) + target_compile_options(mimalloc-obj PRIVATE ${mi_cflags} ${mi_cflags_static}) target_include_directories(mimalloc-obj PUBLIC $ $ From 13e519202a678a9cb698be9fd38bf28d3c3b9143 Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 13 May 2024 09:02:40 -0700 Subject: [PATCH 4/4] fix comments; nicer strdup/strndup --- include/mimalloc/prim.h | 10 +++++----- src/alloc.c | 18 ++++++++---------- src/prim/windows/prim.c | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index 4ee6d43f..4d813b7f 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -14,17 +14,17 @@ terms of the MIT license. A copy of the license can be found in the file // Each OS/host needs to implement these primitives, see `src/prim` // for implementations on Window, macOS, WASI, and Linux/Unix. // -// note: on all primitive functions, we always have result parameters != NUL, and: +// note: on all primitive functions, we always have result parameters != NULL, and: // addr != NULL and page aligned // size > 0 and page aligned -// return value is an error code an int where 0 is success. +// the return value is an error code as an `int` where 0 is success // -------------------------------------------------------------------------- // OS memory configuration typedef struct mi_os_mem_config_s { - size_t page_size; // 4KiB - size_t large_page_size; // 2MiB - size_t alloc_granularity; // smallest allocation size (on Windows 64KiB) + size_t page_size; // default to 4KiB + size_t large_page_size; // 0 if not supported, usually 2MiB (4MiB on Windows) + size_t alloc_granularity; // smallest allocation size (usually 4KiB, on Windows 64KiB) bool has_overcommit; // can we reserve more memory than can be actually committed? bool must_free_whole; // must allocated blocks be freed as a whole (false for mmap, true for VirtualAlloc) bool has_virtual_reserve; // supports virtual address space reservation? (if true we can reserve virtual address space without using commit or physical memory) diff --git a/src/alloc.c b/src/alloc.c index ce24b8ec..6c9c5baf 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -329,11 +329,11 @@ mi_decl_nodiscard void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_ // `strdup` using mi_malloc mi_decl_nodiscard mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept { if (s == NULL) return NULL; - size_t n = strlen(s); - char* t = (char*)mi_heap_malloc(heap,n+1); + size_t len = _mi_strlen(s); + char* t = (char*)mi_heap_malloc(heap,len+1); if (t == NULL) return NULL; - _mi_memcpy(t, s, n); - t[n] = 0; + _mi_memcpy(t, s, len); + t[len] = 0; return t; } @@ -344,13 +344,11 @@ mi_decl_nodiscard mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexce // `strndup` using mi_malloc mi_decl_nodiscard mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { if (s == NULL) return NULL; - const char* end = (const char*)memchr(s, 0, n); // find end of string in the first `n` characters (returns NULL if not found) - const size_t m = (end != NULL ? (size_t)(end - s) : n); // `m` is the minimum of `n` or the end-of-string - mi_assert_internal(m <= n); - char* t = (char*)mi_heap_malloc(heap, m+1); + const size_t len = _mi_strnlen(s,n); // len <= n + char* t = (char*)mi_heap_malloc(heap, len+1); if (t == NULL) return NULL; - _mi_memcpy(t, s, m); - t[m] = 0; + _mi_memcpy(t, s, len); + t[len] = 0; return t; } diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index e6b61079..2dd7c602 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -482,7 +482,7 @@ void _mi_prim_out_stderr( const char* msg ) // on windows with redirection, the C runtime cannot handle locale dependent output // after the main thread closes so we use direct console output. if (!_mi_preloading()) { - // _cputs(msg); // _cputs cannot be used at is aborts if it fails to lock the console + // _cputs(msg); // _cputs cannot be used as it aborts when failing to lock the console static HANDLE hcon = INVALID_HANDLE_VALUE; static bool hconIsConsole; if (hcon == INVALID_HANDLE_VALUE) {