diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 459a0867..e3e78e40 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -32,7 +32,6 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_decl_cache_align #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, ...); diff --git a/src/alloc-override-osx.c b/src/alloc-override-osx.c index c1c880ca..4b77f631 100644 --- a/src/alloc-override-osx.c +++ b/src/alloc-override-osx.c @@ -35,7 +35,6 @@ terms of the MIT license. A copy of the license can be found in the file extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_import)); #endif - /* ------------------------------------------------------ malloc zone members ------------------------------------------------------ */ @@ -44,7 +43,7 @@ static size_t zone_size(malloc_zone_t* zone, const void* p) { UNUSED(zone); if (!mi_is_in_heap_region(p)) return 0; // not our pointer, bail out - + return mi_usable_size(p); } @@ -190,63 +189,85 @@ static malloc_zone_t* mi_get_default_zone() } } -static void __attribute__((constructor)) _mi_macos_override_malloc() -{ - static malloc_introspection_t intro; - memset(&intro, 0, sizeof(intro)); +static malloc_introspection_t mi_introspect = { + .enumerator = &intro_enumerator, + .good_size = &intro_good_size, + .check = &intro_check, + .print = &intro_print, + .log = &intro_log, + .force_lock = &intro_force_lock, + .force_unlock = &intro_force_unlock, +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + .zone_locked = &intro_zone_locked, + .statistics = &intro_statistics, +#endif +}; - intro.enumerator = &intro_enumerator; - intro.good_size = &intro_good_size; - intro.check = &intro_check; - intro.print = &intro_print; - intro.log = &intro_log; - intro.force_lock = &intro_force_lock; - intro.force_unlock = &intro_force_unlock; +static malloc_zone_t mi_malloc_zone = { + .size = &zone_size, + .zone_name = "mimalloc", + .introspect = &mi_introspect, + .malloc = &zone_malloc, + .calloc = &zone_calloc, + .valloc = &zone_valloc, + .free = &zone_free, + .realloc = &zone_realloc, + .destroy = &zone_destroy, + .batch_malloc = &zone_batch_malloc, + .batch_free = &zone_batch_free, +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + // switch to version 9 on OSX 10.6 to support memalign. + .version = 9, + .memalign = &zone_memalign, + .free_definite_size = &zone_free_definite_size, + .pressure_relief = &zone_pressure_relief, +#else + .version = 4, +#endif +}; - static malloc_zone_t zone; - memset(&zone, 0, sizeof(zone)); - zone.version = 4; - zone.zone_name = "mimalloc"; - zone.size = &zone_size; - zone.introspect = &intro; - zone.malloc = &zone_malloc; - zone.calloc = &zone_calloc; - zone.valloc = &zone_valloc; - zone.free = &zone_free; - zone.realloc = &zone_realloc; - zone.destroy = &zone_destroy; - zone.batch_malloc = &zone_batch_malloc; - zone.batch_free = &zone_batch_free; +#if defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE) +static malloc_zone_t *mi_malloc_default_zone(void) { + return &mi_malloc_zone; +} +// TODO: should use the macros in alloc-override but they aren't available here. +__attribute__((used)) static struct { + const void *replacement; + const void *target; +} replace_malloc_default_zone[] __attribute__((section("__DATA, __interpose"))) = { + { (const void*)mi_malloc_default_zone, (const void*)malloc_default_zone }, +}; +#endif + +static void __attribute__((constructor(0))) _mi_macos_override_malloc() { malloc_zone_t* purgeable_zone = NULL; #if defined(MAC_OS_X_VERSION_10_6) && \ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - // switch to version 9 on OSX 10.6 to support memalign. - zone.version = 9; - zone.memalign = &zone_memalign; - zone.free_definite_size = &zone_free_definite_size; - zone.pressure_relief = &zone_pressure_relief; - intro.zone_locked = &intro_zone_locked; - intro.statistics = &intro_statistics; - // force the purgeable zone to exist to avoid strange bugs if (malloc_default_purgeable_zone) { purgeable_zone = malloc_default_purgeable_zone(); } #endif - // Register our zone - malloc_zone_register(&zone); - + // Register our zone. + // thomcc: I think this is still needed to put us in the zone list. + malloc_zone_register(&mi_malloc_zone); // Unregister the default zone, this makes our zone the new default // as that was the last registered. malloc_zone_t *default_zone = mi_get_default_zone(); - malloc_zone_unregister(default_zone); + // thomcc: Unsure if the next test is *always* false or just false in the + // cases I've tried. I'm also unsure if the code inside is needed. at all + if (default_zone != &mi_malloc_zone) { + malloc_zone_unregister(default_zone); - // Reregister the default zone so free and realloc in that zone keep working. - malloc_zone_register(default_zone); + // Reregister the default zone so free and realloc in that zone keep working. + malloc_zone_register(default_zone); + } // Unregister, and re-register the purgeable_zone to avoid bugs if it occurs // earlier than the default zone. @@ -257,4 +278,4 @@ static void __attribute__((constructor)) _mi_macos_override_malloc() } -#endif // MI_MALLOC_OVERRIDE +#endif // MI_MALLOC_OVERRIDE \ No newline at end of file diff --git a/src/alloc-override.c b/src/alloc-override.c index ae7ad7dd..5906bd20 100644 --- a/src/alloc-override.c +++ b/src/alloc-override.c @@ -60,6 +60,13 @@ terms of the MIT license. A copy of the license can be found in the file MI_INTERPOSE_MI(posix_memalign), MI_INTERPOSE_MI(reallocf), MI_INTERPOSE_MI(valloc), + #ifndef MI_OSX_ZONE + // some code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity ) + MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us + #else + // We interpose malloc_default_zone in alloc-override-osx.c + MI_INTERPOSE_MI(free), + #endif // some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity ) MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us }; diff --git a/src/options.c b/src/options.c index d4f3f29a..c489c65e 100644 --- a/src/options.c +++ b/src/options.c @@ -259,7 +259,7 @@ static _Atomic(uintptr_t) warning_count; // = 0; // when >= max_warning_count s static mi_decl_thread bool recurse = false; static bool mi_recurse_enter(void) { - #ifdef MI_TLS_RECURSE_GUARD + #if defined(__MACH__) || defined(MI_TLS_RECURSE_GUARD) if (_mi_preloading()) return true; #endif if (recurse) return false; @@ -268,7 +268,7 @@ static bool mi_recurse_enter(void) { } static void mi_recurse_exit(void) { - #ifdef MI_TLS_RECURSE_GUARD + #if defined(__MACH__) || defined(MI_TLS_RECURSE_GUARD) if (_mi_preloading()) return; #endif recurse = false; diff --git a/test/test-stress.c b/test/test-stress.c index ead88e37..c4247abe 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -20,7 +20,6 @@ terms of the MIT license. #include #include #include -#include // > mimalloc-test-stress [THREADS] [SCALE] [ITER] // @@ -43,6 +42,7 @@ static size_t use_one_size = 0; // use single object size of `N * s #define custom_realloc(p,s) realloc(p,s) #define custom_free(p) free(p) #else +#include #define custom_calloc(n,s) mi_calloc(n,s) #define custom_realloc(p,s) mi_realloc(p,s) #define custom_free(p) mi_free(p) @@ -251,7 +251,9 @@ int main(int argc, char** argv) { #endif // mi_collect(true); +#ifndef USE_STD_MALLOC mi_stats_print(NULL); +#endif //bench_end_program(); return 0; }