1212#include <sys/sysinfo.h>
1313#include <sys/resource.h>
1414#endif
15+ #ifdef __APPLE__
16+ #include <sys/sysctl.h>
17+ #include <sys/resource.h>
18+ #include <mach/mach.h>
19+ #endif
1520
1621#include "common.h"
1722#include "epoch.h"
@@ -59,14 +64,12 @@ void sysmon() {
5964 int64_t currentMs = currentTick * SYSMON_TICK_MS ;
6065
6166 // First: check that we have a reasonable amount of free RAM.
62- #ifdef __linux__
6367 // TODO: move this check to userspace.
6468 if (currentTick % 1000 == 0 ) {
6569 // assuming that ticks happen every 2ms, this should happen
6670 // every 2s.
6771 checkRam ();
6872 }
69- #endif
7073
7174 // Second: deal with any remove-later statements that we should
7275 // remove.
@@ -221,10 +224,10 @@ static void checkRam() {
221224 // detect leaks (I think system RAM is good for killing but
222225 // process RAM use is better for leak diagnosis).
223226 struct rusage ru ; getrusage (RUSAGE_SELF , & ru );
224- /* fprintf(stderr, "Check avail system RAM: %d MB / %d MB\n" */
225- /* "Check self RAM usage: %ld MB\n", */
226- /* freeRamMb, totalRamMb, */
227- /* ru.ru_maxrss / 1024); */
227+ fprintf (stderr , "Check avail system RAM: %d MB / %d MB\n"
228+ "Check self RAM usage: %ld MB\n" ,
229+ freeRamMb , totalRamMb ,
230+ ru .ru_maxrss / 1024 );
228231 // TODO: Report this result as a statement.
229232 if (freeRamMb < 200 ) {
230233 // Hard die if we are likely to run out of RAM, because
@@ -236,6 +239,50 @@ static void checkRam() {
236239 exit (1 );
237240 }
238241#endif
242+ #ifdef __APPLE__
243+ // Get total physical memory
244+ int64_t totalRamBytes = 0 ;
245+ size_t len = sizeof (totalRamBytes );
246+ if (sysctlbyname ("hw.memsize" , & totalRamBytes , & len , NULL , 0 ) != 0 ) {
247+ totalRamBytes = 0 ;
248+ }
249+ int totalRamMb = totalRamBytes / (1024 * 1024 );
250+
251+ // Get VM statistics for free/available memory
252+ vm_size_t page_size ;
253+ mach_port_t mach_port = mach_host_self ();
254+ mach_msg_type_number_t count = sizeof (vm_statistics64_data_t ) / sizeof (integer_t );
255+ vm_statistics64_data_t vm_stats ;
256+
257+ int freeRamMb = 0 ;
258+ if (host_page_size (mach_port , & page_size ) == KERN_SUCCESS &&
259+ host_statistics64 (mach_port , HOST_VM_INFO64 , (host_info64_t )& vm_stats , & count ) == KERN_SUCCESS ) {
260+ // Calculate available memory (free + inactive + purgeable)
261+ int64_t free_pages = vm_stats .free_count ;
262+ int64_t inactive_pages = vm_stats .inactive_count ;
263+ int64_t purgeable_pages = vm_stats .purgeable_count ;
264+ int64_t available_bytes = (free_pages + inactive_pages + purgeable_pages ) * page_size ;
265+ freeRamMb = available_bytes / (1024 * 1024 );
266+ }
267+
268+ // Check process's own RAM usage
269+ struct rusage ru ;
270+ getrusage (RUSAGE_SELF , & ru );
271+ // Note: On macOS, ru_maxrss is in bytes, not kilobytes like Linux
272+ fprintf (stderr , "Check avail system RAM: %d MB / %d MB\n"
273+ "Check self RAM usage: %ld MB\n" ,
274+ freeRamMb , totalRamMb ,
275+ ru .ru_maxrss / (1024 * 1024 ));
276+
277+ // TODO: Report this result as a statement.
278+ if (freeRamMb < 200 ) {
279+ // Hard die if we are likely to run out of RAM
280+ fprintf (stderr , "--------------------\n"
281+ "OUT OF RAM, EXITING.\n"
282+ "--------------------\n" );
283+ exit (1 );
284+ }
285+ #endif
239286}
240287
241288void * sysmonMain (void * ptr ) {
0 commit comments