1 module rt.sys.posix.osmemory; 2 3 version (Posix): 4 5 import core.sys.posix.sys.mman; 6 import core.stdc.stdlib; 7 8 import rt.sys.config; 9 10 void *os_mem_map(size_t nbytes, bool share = false) nothrow @nogc 11 { void *p; 12 13 auto map_f = share ? MAP_SHARED : MAP_PRIVATE; 14 p = mmap(null, nbytes, PROT_READ | PROT_WRITE, map_f | MAP_ANON, -1, 0); 15 return (p == MAP_FAILED) ? null : p; 16 } 17 18 19 int os_mem_unmap(void *base, size_t nbytes) nothrow @nogc 20 { 21 return munmap(base, nbytes); 22 } 23 24 /** 25 Check for any kind of memory pressure. 26 27 Params: 28 mapped = the amount of memory mapped by the GC in bytes 29 Returns: 30 true if memory is scarce 31 */ 32 // TODO: get virtual mem sizes and current usage from OS 33 // TODO: compare current RSS and avail. physical memory 34 static if(usePosix_osmemory_isLowOnMem) 35 { 36 bool isLowOnMem(size_t mapped) nothrow @nogc 37 { 38 enum GB = 2 ^^ 30; 39 version (D_LP64) 40 return false; 41 42 // be conservative and assume 3GB 43 enum size_t limit = 3UL * GB * 8 / 10; 44 return mapped > limit; 45 } 46 } 47 48 49 /** 50 Get the size of available physical memory 51 52 Returns: 53 size of installed physical RAM 54 */ 55 static if(usePosix_osmemory_os_physical_mem) 56 { 57 ulong os_physical_mem() nothrow @nogc 58 { 59 import core.sys.posix.unistd : sysconf, _SC_PAGESIZE, _SC_PHYS_PAGES; 60 const pageSize = sysconf(_SC_PAGESIZE); 61 const pages = sysconf(_SC_PHYS_PAGES); 62 return pageSize * pages; 63 } 64 } 65 66 67 /** 68 Get get the page size of OS 69 70 Returns: 71 OS page size in bytes 72 */ 73 size_t getPageSize() 74 { 75 import core.sys.posix.unistd : sysconf, _SC_PAGESIZE; 76 77 return cast(size_t) sysconf(_SC_PAGESIZE); 78 } 79 80 81 // wait_pid is used in conservative GC 82 /// Possible results for the wait_pid() function. 83 enum ChildStatus 84 { 85 done, /// The process has finished successfully 86 running, /// The process is still running 87 error /// There was an error waiting for the process 88 } 89 90 /** 91 * Wait for a process with PID pid to finish. 92 * 93 * If block is false, this function will not block, and return ChildStatus.running if 94 * the process is still running. Otherwise it will return always ChildStatus.done 95 * (unless there is an error, in which case ChildStatus.error is returned). 96 */ 97 ChildStatus wait_pid(pid_t pid, bool block = true) nothrow @nogc @system 98 { 99 import core.exception : onForkError; 100 101 int status = void; 102 pid_t waited_pid = void; 103 // In the case where we are blocking, we need to consider signals 104 // arriving while we wait, and resume the waiting if EINTR is returned 105 do { 106 errno = 0; 107 waited_pid = waitpid(pid, &status, block ? 0 : WNOHANG); 108 } 109 while (waited_pid == -1 && errno == EINTR); 110 if (waited_pid == 0) 111 return ChildStatus.running; 112 else if (errno == ECHILD) 113 return ChildStatus.done; // someone called posix.syswait 114 else if (waited_pid != pid || status != 0) 115 onForkError(); 116 return ChildStatus.done; 117 } 118 119 public import core.sys.posix.unistd: pid_t, fork; 120 import core.sys.posix.sys.wait: waitpid, WNOHANG; 121 import core.stdc.errno: errno, EINTR, ECHILD;