The OpenD Programming Language

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;