diff --git a/CMakeLists.txt b/CMakeLists.txt index 21bdb001..299aec1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ option(MI_BUILD_TESTS "Build test executables" ON) option(MI_DEBUG_TSAN "Build with thread sanitizer (needs clang)" OFF) option(MI_DEBUG_UBSAN "Build with undefined-behavior sanitizer (needs clang++)" OFF) option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF) +option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF) include("cmake/mimalloc-config-version.cmake") @@ -214,12 +215,18 @@ endif() # Install and output names # ----------------------------------------------------------------------------- -set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}") +if (MI_INSTALL_TOPLEVEL) + set(mi_install_dir "${CMAKE_INSTALL_PREFIX}") +else() + set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}") +endif() + if(MI_SECURE) set(mi_basename "mimalloc-secure") else() set(mi_basename "mimalloc") endif() + string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC) if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel)$")) set(mi_basename "${mi_basename}-${CMAKE_BUILD_TYPE_LC}") #append build type (e.g. -debug) if not a release version @@ -236,6 +243,7 @@ endif() if(MI_BUILD_TESTS) list(APPEND mi_build_targets "tests") endif() + message(STATUS "") message(STATUS "Library base name: ${mi_basename}") message(STATUS "Build type : ${CMAKE_BUILD_TYPE_LC}") @@ -271,7 +279,14 @@ if(MI_BUILD_SHARED) COMMENT "Copy mimalloc-redirect.dll to output directory") endif() - install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY) + if (MI_INSTALL_TOPLEVEL MATCHES "ON") + install(TARGETS mimalloc EXPORT mimalloc LIBRARY + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) + else() + install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY) + endif() install(EXPORT mimalloc DESTINATION ${mi_install_dir}/cmake) endif() @@ -305,7 +320,7 @@ install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_dir}/includ install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_dir}/cmake) install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_dir}/cmake) -if(NOT WIN32 AND MI_BUILD_SHARED) +if(NOT WIN32 AND MI_BUILD_SHARED AND NOT MI_INSTALL_TOPLEVEL) # install a symlink in the /usr/local/lib to the versioned library set(mi_symlink "${CMAKE_SHARED_MODULE_PREFIX}${mi_basename}${CMAKE_SHARED_LIBRARY_SUFFIX}") set(mi_soname "mimalloc-${mi_version}/${mi_symlink}.${mi_version}") diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 15c1e559..574e5bde 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -50,8 +50,8 @@ uintptr_t _os_random_weak(uintptr_t extra_seed); static inline uintptr_t _mi_random_shuffle(uintptr_t x); // init.c -extern mi_stats_t _mi_stats_main; -extern const mi_page_t _mi_page_empty; +extern mi_decl_cache_align mi_stats_t _mi_stats_main; +extern mi_decl_cache_align const mi_page_t _mi_page_empty; bool _mi_is_main_thread(void); bool _mi_preloading(); // true while the C runtime is not ready @@ -180,6 +180,21 @@ bool _mi_page_is_valid(mi_page_t* page); #endif +// ----------------------------------------------------------------------------------- +// On windows x86/x64 with msvc/clang-cl, use `rep movsb` for `memcpy` (issue #201) +// ----------------------------------------------------------------------------------- + +#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) +#include +static inline void _mi_memcpy_rep_movsb(void* d, const void* s, size_t n) { + __movsb((unsigned char*)d, (const unsigned char*)s, n); +} +#define _mi_memcpy(d,s,n) _mi_memcpy_rep_movsb(d,s,n) +#else +#define _mi_memcpy(d,s,n) memcpy(d,s,n) +#endif + + /* ----------------------------------------------------------- Inlined definitions ----------------------------------------------------------- */ diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index ca16d367..10f40355 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -137,7 +137,7 @@ static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t ne memset((uint8_t*)newp + start, 0, newsize - start); } } - memcpy(newp, p, (newsize > size ? size : newsize)); + _mi_memcpy(newp, p, (newsize > size ? size : newsize)); mi_free(p); // only free if successful } return newp; diff --git a/src/alloc-posix.c b/src/alloc-posix.c index 1ba1509b..85cef389 100644 --- a/src/alloc-posix.c +++ b/src/alloc-posix.c @@ -103,7 +103,7 @@ mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noex size_t size = (len+1)*sizeof(unsigned short); unsigned short* p = (unsigned short*)mi_malloc(size); if (p != NULL) { - memcpy(p,s,size); + _mi_memcpy(p,s,size); } return p; } diff --git a/src/alloc.c b/src/alloc.c index ac71905b..370bf271 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -628,7 +628,7 @@ void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); memset((uint8_t*)newp + start, 0, newsize - start); } - memcpy(newp, p, (newsize > size ? size : newsize)); + _mi_memcpy(newp, p, (newsize > size ? size : newsize)); mi_free(p); // only free if successful } return newp; @@ -695,7 +695,7 @@ mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_no if (s == NULL) return NULL; size_t n = strlen(s); char* t = (char*)mi_heap_malloc(heap,n+1); - if (t != NULL) memcpy(t, s, n + 1); + if (t != NULL) _mi_memcpy(t, s, n + 1); return t; } @@ -711,7 +711,7 @@ mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_assert_internal(m <= n); char* t = (char*)mi_heap_malloc(heap, m+1); if (t == NULL) return NULL; - memcpy(t, s, m); + _mi_memcpy(t, s, m); t[m] = 0; return t; } diff --git a/src/heap.c b/src/heap.c index 8db809b4..c7130a90 100644 --- a/src/heap.c +++ b/src/heap.c @@ -193,7 +193,7 @@ mi_heap_t* mi_heap_new(void) { mi_heap_t* bheap = mi_heap_get_backing(); mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t); // todo: OS allocate in secure mode? if (heap==NULL) return NULL; - memcpy(heap, &_mi_heap_empty, sizeof(mi_heap_t)); + _mi_memcpy(heap, &_mi_heap_empty, sizeof(mi_heap_t)); heap->tld = bheap->tld; heap->thread_id = _mi_thread_id(); _mi_random_split(&bheap->random, &heap->random); @@ -220,7 +220,7 @@ static void mi_heap_reset_pages(mi_heap_t* heap) { #ifdef MI_MEDIUM_DIRECT memset(&heap->pages_free_medium, 0, sizeof(heap->pages_free_medium)); #endif - memcpy(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages)); + _mi_memcpy(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages)); heap->thread_delayed_free = NULL; heap->page_count = 0; } diff --git a/src/init.c b/src/init.c index 06b402ad..eec0f1ba 100644 --- a/src/init.c +++ b/src/init.c @@ -213,8 +213,8 @@ static bool _mi_heap_init(void) { // OS allocated so already zero initialized mi_tld_t* tld = &td->tld; mi_heap_t* heap = &td->heap; - memcpy(tld, &tld_empty, sizeof(*tld)); - memcpy(heap, &_mi_heap_empty, sizeof(*heap)); + _mi_memcpy(tld, &tld_empty, sizeof(*tld)); + _mi_memcpy(heap, &_mi_heap_empty, sizeof(*heap)); heap->thread_id = _mi_thread_id(); _mi_random_init(&heap->random); heap->cookie = _mi_heap_random_next(heap) | 1; diff --git a/src/options.c b/src/options.c index f36a721e..0560b937 100644 --- a/src/options.c +++ b/src/options.c @@ -197,7 +197,7 @@ static void mi_out_buf(const char* msg, void* arg) { if (start+n >= MI_MAX_DELAY_OUTPUT) { n = MI_MAX_DELAY_OUTPUT-start-1; } - memcpy(&out_buf[start], msg, n); + _mi_memcpy(&out_buf[start], msg, n); } static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) { diff --git a/src/random.c b/src/random.c index b9485ea0..b6067ecf 100644 --- a/src/random.c +++ b/src/random.c @@ -115,7 +115,7 @@ static void chacha_init(mi_random_ctx_t* ctx, const uint8_t key[32], uint64_t no static void chacha_split(mi_random_ctx_t* ctx, uint64_t nonce, mi_random_ctx_t* ctx_new) { memset(ctx_new, 0, sizeof(*ctx_new)); - memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input)); + _mi_memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input)); ctx_new->input[12] = 0; ctx_new->input[13] = 0; ctx_new->input[14] = (uint32_t)nonce;