Skip to content

Commit 53f88dc

Browse files
committed
add physical memory detection on macOS/freeBSD
1 parent cfff6bf commit 53f88dc

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed

src/prim/unix/prim.c

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ terms of the MIT license. A copy of the license can be found in the file
4949
#if !defined(MAC_OS_X_VERSION_10_7)
5050
#define MAC_OS_X_VERSION_10_7 1070
5151
#endif
52+
#include <sys/sysctl.h>
5253
#elif defined(__FreeBSD__) || defined(__DragonFly__)
5354
#include <sys/param.h>
5455
#if __FreeBSD_version >= 1200000
@@ -119,43 +120,64 @@ static inline int mi_prim_access(const char *fpath, int mode) {
119120

120121
static bool unix_detect_overcommit(void) {
121122
bool os_overcommit = true;
122-
#if defined(__linux__)
123-
int fd = mi_prim_open("/proc/sys/vm/overcommit_memory", O_RDONLY);
124-
if (fd >= 0) {
125-
char buf[32];
126-
ssize_t nread = mi_prim_read(fd, &buf, sizeof(buf));
127-
mi_prim_close(fd);
128-
// <https://www.kernel.org/doc/Documentation/vm/overcommit-accounting>
129-
// 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE)
130-
if (nread >= 1) {
131-
os_overcommit = (buf[0] == '0' || buf[0] == '1');
123+
#if defined(__linux__)
124+
int fd = mi_prim_open("/proc/sys/vm/overcommit_memory", O_RDONLY);
125+
if (fd >= 0) {
126+
char buf[32];
127+
ssize_t nread = mi_prim_read(fd, &buf, sizeof(buf));
128+
mi_prim_close(fd);
129+
// <https://www.kernel.org/doc/Documentation/vm/overcommit-accounting>
130+
// 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE)
131+
if (nread >= 1) {
132+
os_overcommit = (buf[0] == '0' || buf[0] == '1');
133+
}
132134
}
133-
}
134-
#elif defined(__FreeBSD__)
135-
int val = 0;
136-
size_t olen = sizeof(val);
137-
if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) {
138-
os_overcommit = (val != 0);
139-
}
140-
#else
141-
// default: overcommit is true
142-
#endif
135+
#elif defined(__FreeBSD__)
136+
int val = 0;
137+
size_t olen = sizeof(val);
138+
if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) {
139+
os_overcommit = (val != 0);
140+
}
141+
#else
142+
// default: overcommit is true
143+
#endif
143144
return os_overcommit;
144145
}
145146

147+
// try to detect the physical memory dynamically (if possible)
148+
static void unix_detect_physical_memory( size_t page_size, size_t* physical_memory_in_kib ) {
149+
#if defined(CTL_HW) && (defined(HW_PHYSMEM64) || defined(HW_MEMSIZE)) // freeBSD, macOS
150+
MI_UNUSED(page_size);
151+
int64_t physical_memory = 0;
152+
size_t length = sizeof(int64_t);
153+
#if defined(HW_PHYSMEM64)
154+
int mib[2] = { CTL_HW, HW_PHYSMEM64 };
155+
#else
156+
int mib[2] = { CTL_HW, HW_MEMSIZE };
157+
#endif
158+
const int err = sysctl(mib, 2, &physical_memory, &length, NULL, 0);
159+
if (err == 0 && physical_memory > 0) {
160+
const int64_t phys_in_kib = physical_memory / MI_KiB;
161+
if (phys_in_kib > 0 && (uint64_t)phys_in_kib <= SIZE_MAX) {
162+
*physical_memory_in_kib = (size_t)phys_in_kib;
163+
}
164+
}
165+
#elif defined(_SC_PHYS_PAGES) // linux
166+
const long pphys = sysconf(_SC_PHYS_PAGES);
167+
const size_t psize_in_kib = page_size / MI_KiB;
168+
if (psize_in_kib > 0 && pphys > 0 && (unsigned long)pphys < SIZE_MAX && (size_t)pphys <= (SIZE_MAX/psize_in_kib)) {
169+
*physical_memory_in_kib = (size_t)pphys * psize_in_kib;
170+
}
171+
#endif
172+
}
173+
146174
void _mi_prim_mem_init( mi_os_mem_config_t* config )
147175
{
148176
long psize = sysconf(_SC_PAGESIZE);
149-
if (psize > 0) {
177+
if (psize > 0 && (unsigned long)psize < SIZE_MAX) {
150178
config->page_size = (size_t)psize;
151179
config->alloc_granularity = (size_t)psize;
152-
#if defined(_SC_PHYS_PAGES)
153-
long pphys = sysconf(_SC_PHYS_PAGES);
154-
const size_t psize_in_kib = (size_t)psize / MI_KiB;
155-
if (psize_in_kib > 0 && pphys > 0 && (size_t)pphys <= (SIZE_MAX/psize_in_kib)) {
156-
config->physical_memory_in_kib = (size_t)pphys * psize_in_kib;
157-
}
158-
#endif
180+
unix_detect_physical_memory(config->page_size, &config->physical_memory_in_kib);
159181
}
160182
config->large_page_size = MI_UNIX_LARGE_PAGE_SIZE;
161183
config->has_overcommit = unix_detect_overcommit();

0 commit comments

Comments
 (0)