@@ -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
120121static 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+
146174void _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