From 898a23ec2b4c7974d9381312f5ff01b78747a8d5 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 22 Oct 2021 08:12:14 +0100 Subject: [PATCH 1/8] fixes malloc_usable_size signature on FreeBSD. --- src/alloc-override.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/alloc-override.c b/src/alloc-override.c index f97b6e78..af9035dd 100644 --- a/src/alloc-override.c +++ b/src/alloc-override.c @@ -173,7 +173,7 @@ extern "C" { void cfree(void* p) MI_FORWARD0(mi_free, p) void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize) size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p) -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__FreeBSD__) size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p) #else size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p) From fc7777ee8c7538fa181ae52c621c09edc11d46b7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 22 Oct 2021 10:08:16 +0100 Subject: [PATCH 2/8] NUMA base detection on FreeBSD. --- src/os.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/os.c b/src/os.c index 3066dad5..f15a2197 100644 --- a/src/os.c +++ b/src/os.c @@ -51,6 +51,14 @@ terms of the MIT license. A copy of the license can be found in the file #include #endif #endif +#if defined(__FreeBSD__) +#include +#if __FreeBSD_version >= 1200000 +#include +#include +#include +#endif +#endif #endif /* ----------------------------------------------------------- @@ -1236,6 +1244,29 @@ static size_t mi_os_numa_node_countx(void) { } return (node+1); } +#elif defined(__FreeBSD__) && __FreeBSD_version >= 1200000 +static size_t mi_os_numa_nodex(void) { + domainset_t dom; + size_t node; + int policy; + + if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul; + + for (node = 0; node < MAXMEMDOM; node++) { + if (DOMAINSET_ISSET(node, &dom)) return node; + } + + return 0ul; +} + +static size_t mi_os_numa_node_countx(void) { + size_t ndomains = 0; + size_t len = sizeof(ndomains); + + if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul; + + return ndomains; +} #else static size_t mi_os_numa_nodex(void) { return 0; From 2d2d9af5c6e2473b8aa6b651b0dad7d67b8957f8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 24 Oct 2021 10:57:40 +0100 Subject: [PATCH 3/8] while at it, doing dragonflybsd too --- src/os.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/os.c b/src/os.c index f15a2197..a4b9602f 100644 --- a/src/os.c +++ b/src/os.c @@ -51,13 +51,13 @@ terms of the MIT license. A copy of the license can be found in the file #include #endif #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__DragonFly__) #include #if __FreeBSD_version >= 1200000 #include #include -#include #endif +#include #endif #endif @@ -1267,6 +1267,24 @@ static size_t mi_os_numa_node_countx(void) { return ndomains; } +#elif defined(__DragonFly__) +static size_t mi_os_numa_nodex(void) { + // TODO DragonFlyBSD does not seem to provide any userland mean to + // check this information, even less the possibility to control + // the allocation to a logical core level's granularity, only the kernel + // is fully NUMA aware at the moment. + return 0ul; +} + +static size_t mi_os_numa_node_countx(void) { + size_t ncpus = 0, nvirtcoresperphys = 0; + size_t len = sizeof(size_t); + + if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul; + if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul; + + return nvirtcoresperphys * ncpus; +} #else static size_t mi_os_numa_nodex(void) { return 0; From 00edd9201bad722eabc5066c9b8ee8622c0f0d8c Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 24 Oct 2021 19:49:11 +0100 Subject: [PATCH 4/8] proposal to not overcommit page unconditionally on Linux and FreeBSD, respecting userland settings. --- src/os.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/os.c b/src/os.c index 3066dad5..e40d57a9 100644 --- a/src/os.c +++ b/src/os.c @@ -39,6 +39,8 @@ terms of the MIT license. A copy of the license can be found in the file #include // sysconf #if defined(__linux__) #include +#include +#include #if defined(__GLIBC__) #include // linux mmap flags #else @@ -51,6 +53,9 @@ terms of the MIT license. A copy of the license can be found in the file #include #endif #endif +#if defined(__FreeBSD__) +#include +#endif #endif /* ----------------------------------------------------------- @@ -88,6 +93,9 @@ static size_t os_alloc_granularity = 4096; // if non-zero, use large page allocation static size_t large_os_page_size = 0; +// if non-zero, enable page overcommit +static int os_overcommit = 0; + // OS (small) page size size_t _mi_os_page_size() { return os_page_size; @@ -223,6 +231,31 @@ void _mi_os_init() { os_alloc_granularity = os_page_size; } large_os_page_size = 2*MiB; // TODO: can we query the OS for this? +#if defined(__linux__) + int fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd != -1) { + char buf[1] = {0}; + if (read(fd, buf, sizeof(buf)) == sizeof(buf)) { + switch (buf[0]) { + case '0': // heuristic mode + case '1': // always + os_overcommit = 1; + break; + default: // never regardless + os_overcommit = 0; + } + } + close(fd); + } +#elif defined(__FreeBSD__) + int val = 0; + size_t olen = sizeof(val); + if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) { + os_overcommit = val; + } +#elif defined(__NetBSD__) || defined(__HAIKU__) + os_overcommit = 1; +#endif } #endif @@ -398,8 +431,11 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro #if !defined(MAP_NORESERVE) #define MAP_NORESERVE 0 #endif - int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; int fd = -1; + if (os_overcommit) { + flags |= MAP_NORESERVE; + } #if defined(MAP_ALIGNED) // BSD if (try_alignment > 0) { size_t n = mi_bsr(try_alignment); From f38956568c07d0fe31111f141652954ccbb3635c Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 27 Oct 2021 17:01:12 -0700 Subject: [PATCH 5/8] only set visibility attribute when compiling for a shared library --- include/mimalloc.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 7ebf3e60..fe0fd746 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -58,8 +58,12 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_attr_alloc_size2(s1,s2) #define mi_attr_alloc_align(p) #elif defined(__GNUC__) // includes clang and icc + #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __attribute__((visibility("default"))) + #else + #define mi_decl_export + #endif #define mi_cdecl // leads to warnings... __attribute__((cdecl)) - #define mi_decl_export __attribute__((visibility("default"))) #define mi_decl_restrict #define mi_attr_malloc __attribute__((malloc)) #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5) From 6ccf7e87c0aa62154f63054a905842bb93d52e3f Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 27 Oct 2021 17:06:10 -0700 Subject: [PATCH 6/8] minor edits --- src/os.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/os.c b/src/os.c index a4b9602f..73ef462e 100644 --- a/src/os.c +++ b/src/os.c @@ -1249,40 +1249,28 @@ static size_t mi_os_numa_nodex(void) { domainset_t dom; size_t node; int policy; - if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul; - for (node = 0; node < MAXMEMDOM; node++) { - if (DOMAINSET_ISSET(node, &dom)) return node; + if (DOMAINSET_ISSET(node, &dom)) return node; } - return 0ul; } - static size_t mi_os_numa_node_countx(void) { size_t ndomains = 0; size_t len = sizeof(ndomains); - if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul; - return ndomains; } #elif defined(__DragonFly__) static size_t mi_os_numa_nodex(void) { - // TODO DragonFlyBSD does not seem to provide any userland mean to - // check this information, even less the possibility to control - // the allocation to a logical core level's granularity, only the kernel - // is fully NUMA aware at the moment. + // TODO: DragonFly does not seem to provide any userland means to get this information. return 0ul; } - static size_t mi_os_numa_node_countx(void) { size_t ncpus = 0, nvirtcoresperphys = 0; size_t len = sizeof(size_t); - if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul; if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul; - return nvirtcoresperphys * ncpus; } #else From fdcdc4cf2aadefce1f7e768cc933508ac88420c4 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 27 Oct 2021 17:01:12 -0700 Subject: [PATCH 7/8] only set visibility attribute when compiling for a shared library (issue #475) --- include/mimalloc.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 7ebf3e60..fe0fd746 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -58,8 +58,12 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_attr_alloc_size2(s1,s2) #define mi_attr_alloc_align(p) #elif defined(__GNUC__) // includes clang and icc + #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __attribute__((visibility("default"))) + #else + #define mi_decl_export + #endif #define mi_cdecl // leads to warnings... __attribute__((cdecl)) - #define mi_decl_export __attribute__((visibility("default"))) #define mi_decl_restrict #define mi_attr_malloc __attribute__((malloc)) #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5) From 5fd77aa1986305a30680f6b62a27b58940dfbfd0 Mon Sep 17 00:00:00 2001 From: Daan Date: Wed, 27 Oct 2021 17:39:11 -0700 Subject: [PATCH 8/8] refactor os_overcommit detection --- src/os.c | 62 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/os.c b/src/os.c index b8c3f603..507d9971 100644 --- a/src/os.c +++ b/src/os.c @@ -40,7 +40,6 @@ terms of the MIT license. A copy of the license can be found in the file #if defined(__linux__) #include #include -#include #if defined(__GLIBC__) #include // linux mmap flags #else @@ -98,8 +97,9 @@ static size_t os_alloc_granularity = 4096; // if non-zero, use large page allocation static size_t large_os_page_size = 0; -// if non-zero, enable page overcommit -static int os_overcommit = 0; +// is memory overcommit allowed? +// set dynamically in _mi_os_init (and if true we use MAP_NORESERVE) +static bool os_overcommit = true; // OS (small) page size size_t _mi_os_page_size() { @@ -189,7 +189,9 @@ static bool mi_win_enable_large_os_pages() return (ok!=0); } -void _mi_os_init(void) { +void _mi_os_init(void) +{ + os_overcommit = false; // get the page size SYSTEM_INFO si; GetSystemInfo(&si); @@ -224,10 +226,36 @@ 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_alloc_granularity = 16; } + +#else // generic unix + +static void os_detect_overcommit(void) { +#if defined(__linux__) + int fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd < 0) return; + char buf[128]; + ssize_t nread = read(fd, &buf, sizeof(buf)); + close(fd); + // + // 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE) + if (nread >= 1) { + os_overcommit = (buf[0] == '0' || buf[0] == '1'); + } +#elif defined(__FreeBSD__) + int val = 0; + size_t olen = sizeof(val); + if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) { + os_overcommit = (val != 0); + } #else + // default: overcommit is true +#endif +} + void _mi_os_init() { // get the page size long result = sysconf(_SC_PAGESIZE); @@ -236,31 +264,7 @@ void _mi_os_init() { os_alloc_granularity = os_page_size; } large_os_page_size = 2*MiB; // TODO: can we query the OS for this? -#if defined(__linux__) - int fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY); - if (fd != -1) { - char buf[1] = {0}; - if (read(fd, buf, sizeof(buf)) == sizeof(buf)) { - switch (buf[0]) { - case '0': // heuristic mode - case '1': // always - os_overcommit = 1; - break; - default: // never regardless - os_overcommit = 0; - } - } - close(fd); - } -#elif defined(__FreeBSD__) - int val = 0; - size_t olen = sizeof(val); - if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) { - os_overcommit = val; - } -#elif defined(__NetBSD__) || defined(__HAIKU__) - os_overcommit = 1; -#endif + os_detect_overcommit(); } #endif