diff --git a/CMakeLists.txt b/CMakeLists.txt index 968ace73..79d297df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set(mi_sources src/page.c src/alloc.c src/alloc-aligned.c + src/alloc-posix.c src/heap.c src/options.c src/init.c) diff --git a/ide/vs2017/mimalloc-override.vcxproj b/ide/vs2017/mimalloc-override.vcxproj index d82bce8c..98429052 100644 --- a/ide/vs2017/mimalloc-override.vcxproj +++ b/ide/vs2017/mimalloc-override.vcxproj @@ -218,6 +218,7 @@ true + diff --git a/ide/vs2017/mimalloc-override.vcxproj.filters b/ide/vs2017/mimalloc-override.vcxproj.filters index 7a8abd74..c3c9675c 100644 --- a/ide/vs2017/mimalloc-override.vcxproj.filters +++ b/ide/vs2017/mimalloc-override.vcxproj.filters @@ -58,5 +58,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/ide/vs2017/mimalloc.vcxproj b/ide/vs2017/mimalloc.vcxproj index 05cf745c..98a3a230 100644 --- a/ide/vs2017/mimalloc.vcxproj +++ b/ide/vs2017/mimalloc.vcxproj @@ -217,6 +217,7 @@ true true + diff --git a/ide/vs2017/mimalloc.vcxproj.filters b/ide/vs2017/mimalloc.vcxproj.filters index 9b1e0971..2f54485b 100644 --- a/ide/vs2017/mimalloc.vcxproj.filters +++ b/ide/vs2017/mimalloc.vcxproj.filters @@ -50,6 +50,9 @@ Source Files + + Source Files + diff --git a/include/mimalloc.h b/include/mimalloc.h index efb1f381..192a0cfb 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -232,6 +232,26 @@ mi_decl_export long mi_option_get(mi_option_t option); mi_decl_export void mi_option_set(mi_option_t option, long value); mi_decl_export void mi_option_set_default(mi_option_t option, long value); + +// ------------------------------------------------------ +// mi prefixed implementations of various posix, unix, +// and C++ allocation functions. +// ------------------------------------------------------ + +mi_decl_export size_t mi_malloc_size(void* p) mi_attr_noexcept; +mi_decl_export size_t mi_malloc_usable_size(void *p) mi_attr_noexcept; +mi_decl_export void mi_cfree(void* p) mi_attr_noexcept; + +mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; +mi_decl_export int mi__posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; +mi_decl_export mi_decl_allocator void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_export mi_decl_allocator void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); + +mi_decl_export mi_decl_allocator void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_export mi_decl_allocator void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_export mi_decl_allocator void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); + + #ifdef __cplusplus } #endif diff --git a/src/alloc-override.c b/src/alloc-override.c index 7c052690..1cae7cfb 100644 --- a/src/alloc-override.c +++ b/src/alloc-override.c @@ -25,15 +25,17 @@ terms of the MIT license. A copy of the license can be found in the file #if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) // use aliasing to alias the exported function to one of our `mi_` functions - #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"))) - #define MI_FORWARD1(fun,x) MI_FORWARD(fun) - #define MI_FORWARD2(fun,x,y) MI_FORWARD(fun) - #define MI_FORWARD0(fun,x) MI_FORWARD(fun) + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"))) + #define MI_FORWARD1(fun,x) MI_FORWARD(fun) + #define MI_FORWARD2(fun,x,y) MI_FORWARD(fun) + #define MI_FORWARD3(fun,x,y,z) MI_FORWARD(fun) + #define MI_FORWARD0(fun,x) MI_FORWARD(fun) #else // use forwarding by calling our `mi_` function - #define MI_FORWARD1(fun,x) { return fun(x); } - #define MI_FORWARD2(fun,x,y) { return fun(x,y); } - #define MI_FORWARD0(fun,x) { fun(x); } + #define MI_FORWARD1(fun,x) { return fun(x); } + #define MI_FORWARD2(fun,x,y) { return fun(x,y); } + #define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); } + #define MI_FORWARD0(fun,x) { fun(x); } #endif #if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE) @@ -59,9 +61,7 @@ terms of the MIT license. A copy of the license can be found in the file void* malloc(size_t size) mi_attr_noexcept MI_FORWARD1(mi_malloc, size); void* calloc(size_t size, size_t n) mi_attr_noexcept MI_FORWARD2(mi_calloc, size, n); void* realloc(void* p, size_t newsize) mi_attr_noexcept MI_FORWARD2(mi_realloc, p, newsize); - void free(void* p) mi_attr_noexcept MI_FORWARD0(mi_free, p); - //char* strdup(const char* s) MI_FORWARD1(mi_strdup, s); - //char* strndup(const char* s, size_t n) MI_FORWARD2(mi_strndup, s, n); + void free(void* p) mi_attr_noexcept MI_FORWARD0(mi_free, p); #endif #if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) @@ -121,57 +121,18 @@ extern "C" { // Posix & Unix functions definitions // ------------------------------------------------------ -#include - -#ifndef EINVAL -#define EINVAL 22 -#endif -#ifndef ENOMEM -#define ENOMEM 12 -#endif - void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize); size_t malloc_size(void* p) MI_FORWARD1(mi_usable_size,p); size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p); void cfree(void* p) MI_FORWARD0(mi_free, p); - -int posix_memalign(void** p, size_t alignment, size_t size) { - // TODO: the spec says we should return EINVAL also if alignment is not a power of 2. - // The spec also dictates we should not modify `*p` on an error. (issue#27) - // - if (alignment % sizeof(void*) != 0) return EINVAL; // no `p==NULL` check as it is declared as non-null - if ((alignment & (~alignment + 1)) != alignment) return EINVAL; // not a power of 2 - void* q = mi_malloc_aligned(size, alignment); - if (q==NULL && size != 0) return ENOMEM; - *p = q; - return 0; -} - -void* memalign(size_t alignment, size_t size) { - return mi_malloc_aligned(size, alignment); -} - -void* valloc(size_t size) { - return mi_malloc_aligned(size, _mi_os_page_size()); -} - -void* pvalloc(size_t size) { - size_t psize = _mi_os_page_size(); - if (size >= SIZE_MAX - psize) return NULL; // overflow - size_t asize = ((size + psize - 1) / psize) * psize; - return mi_malloc_aligned(asize, psize); -} - -void* aligned_alloc(size_t alignment, size_t size) { - return mi_malloc_aligned(size, alignment); -} - -void* reallocarray( void* p, size_t count, size_t size ) { // BSD - void* newp = mi_reallocn(p,count,size); - if (newp==NULL) errno = ENOMEM; - return newp; -} +// no forwarding here due to aliasing/name mangling issues +void* valloc(size_t size) { return mi_valloc(size); } +void* pvalloc(size_t size) { return mi_pvalloc(size); } +void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); } +void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } +void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } +int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); } #if defined(__GLIBC__) && defined(__linux__) // forward __libc interface (needed for glibc-based Linux distributions) @@ -181,18 +142,10 @@ void* reallocarray( void* p, size_t count, size_t size ) { // BSD void __libc_free(void* p) MI_FORWARD0(mi_free,p); void __libc_cfree(void* p) MI_FORWARD0(mi_free,p); - void* __libc_memalign(size_t alignment, size_t size) { - return memalign(alignment,size); - } - void* __libc_valloc(size_t size) { - return valloc(size); - } - void* __libc_pvalloc(size_t size) { - return pvalloc(size); - } - int __posix_memalign(void** p, size_t alignment, size_t size) { - return posix_memalign(p,alignment,size); - } + void* __libc_valloc(size_t size) { return mi_valloc(size); } + void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); } + void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); } + int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); } #endif #ifdef __cplusplus diff --git a/src/alloc-posix.c b/src/alloc-posix.c new file mode 100644 index 00000000..9fb2890b --- /dev/null +++ b/src/alloc-posix.c @@ -0,0 +1,82 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// ------------------------------------------------------------------------ +// mi prefixed publi definitions of various Posix, Unix, and C++ functions +// for convenience and used when overriding these functions. +// ------------------------------------------------------------------------ + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +#include + +#ifndef EINVAL +#define EINVAL 22 +#endif +#ifndef ENOMEM +#define ENOMEM 12 +#endif + + +size_t mi_malloc_size(void* p) mi_attr_noexcept { + return mi_usable_size(p); +} + +size_t mi_malloc_usable_size(void *p) mi_attr_noexcept { + return mi_usable_size(p); +} + +void mi_cfree(void* p) mi_attr_noexcept { + mi_free(p); +} + +int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { + // Note: The spec dictates we should not modify `*p` on an error. (issue#27) + // + if (p == NULL) return EINVAL; + if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment + if ((alignment & (alignment - 1)) != 0) return EINVAL; // not a power of 2 + void* q = mi_malloc_aligned(size, alignment); + if (q==NULL && size != 0) return ENOMEM; + *p = q; + return 0; +} + +int mi__posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { + return mi_posix_memalign(p, alignment, size); +} + +void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { + return mi_malloc_aligned(size, alignment); +} + +void* mi_valloc(size_t size) mi_attr_noexcept { + return mi_malloc_aligned(size, _mi_os_page_size()); +} + +void* mi_pvalloc(size_t size) mi_attr_noexcept { + size_t psize = _mi_os_page_size(); + if (size >= SIZE_MAX - psize) return NULL; // overflow + size_t asize = ((size + psize - 1) / psize) * psize; + return mi_malloc_aligned(asize, psize); +} + +void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { + return mi_malloc_aligned(size, alignment); +} + +void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD + void* newp = mi_reallocn(p,count,size); + if (newp==NULL) errno = ENOMEM; + return newp; +} + diff --git a/src/static.c b/src/static.c index b4378b43..679d1c10 100644 --- a/src/static.c +++ b/src/static.c @@ -20,5 +20,6 @@ terms of the MIT license. A copy of the license can be found in the file #include "heap.c" #include "alloc.c" #include "alloc-aligned.c" +#include "alloc-posix.c" #include "init.c" #include "options.c" diff --git a/test/main-override.cpp b/test/main-override.cpp index c42884be..4c22fbd7 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -21,7 +21,7 @@ public: }; int main() { - mi_stats_reset(); + mi_stats_reset(); atexit(free_p); void* p1 = malloc(78); void* p2 = malloc(24); @@ -36,8 +36,10 @@ int main() { free(s); Test* t = new Test(42); delete t; + int err = mi_posix_memalign(&p1,32,60); + if (!err) free(p); mi_collect(true); - // mi_stats_print(NULL); // MIMALLOC_VERBOSE env is set to 2 + mi_stats_print(NULL); // MIMALLOC_VERBOSE env is set to 2 return 0; } diff --git a/test/main.cpp b/test/main.cpp deleted file mode 100644 index 4eab4edb..00000000 --- a/test/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include - -int main() { - void* p1 = rc_malloc(16); - void* p2 = rc_malloc(16); - rc_free(p1); - rc_free(p2); - p1 = rc_malloc(16); - p2 = rc_malloc(16); - rc_free(p1); - rc_free(p2); - rc_collect(true); - rc_stats_print(); - return 0; -}