2012-01-13 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / runtime / mem.c
blob04fca2c65b1a680d8dae10f3530cf3328c696f32
1 #include <errno.h>
2 #include <unistd.h>
4 #include "runtime.h"
5 #include "arch.h"
6 #include "malloc.h"
8 #ifndef MAP_ANON
9 #ifdef MAP_ANONYMOUS
10 #define MAP_ANON MAP_ANONYMOUS
11 #else
12 #define USE_DEV_ZERO
13 #define MAP_ANON 0
14 #endif
15 #endif
17 #ifdef USE_DEV_ZERO
18 static int dev_zero = -1;
19 #endif
21 static _Bool
22 addrspace_free(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused)))
24 #ifdef HAVE_MINCORE
25 size_t page_size = getpagesize();
26 size_t off;
27 char one_byte;
29 errno = 0;
30 for(off = 0; off < n; off += page_size)
31 if(mincore((char *)v + off, page_size, (void *)&one_byte) != -1
32 || errno != ENOMEM)
33 return 0;
34 #endif
35 return 1;
38 void*
39 runtime_SysAlloc(uintptr n)
41 void *p;
42 int fd = -1;
44 mstats.sys += n;
46 #ifdef USE_DEV_ZERO
47 if (dev_zero == -1) {
48 dev_zero = open("/dev/zero", O_RDONLY);
49 if (dev_zero < 0) {
50 runtime_printf("open /dev/zero: errno=%d\n", errno);
51 exit(2);
54 fd = dev_zero;
55 #endif
57 p = runtime_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
58 if (p == MAP_FAILED) {
59 if(errno == EACCES) {
60 runtime_printf("runtime: mmap: access denied\n");
61 runtime_printf("if you're running SELinux, enable execmem for this process.\n");
62 exit(2);
64 return nil;
66 return p;
69 void
70 runtime_SysUnused(void *v, uintptr n)
72 #ifdef MADV_DONTNEED
73 runtime_madvise(v, n, MADV_DONTNEED);
74 #endif
77 void
78 runtime_SysFree(void *v, uintptr n)
80 mstats.sys -= n;
81 runtime_munmap(v, n);
84 void*
85 runtime_SysReserve(void *v, uintptr n)
87 int fd = -1;
88 void *p;
90 // On 64-bit, people with ulimit -v set complain if we reserve too
91 // much address space. Instead, assume that the reservation is okay
92 // and check the assumption in SysMap.
93 if(sizeof(void*) == 8)
94 return v;
96 #ifdef USE_DEV_ZERO
97 if (dev_zero == -1) {
98 dev_zero = open("/dev/zero", O_RDONLY);
99 if (dev_zero < 0) {
100 runtime_printf("open /dev/zero: errno=%d\n", errno);
101 exit(2);
104 fd = dev_zero;
105 #endif
107 p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
108 if((uintptr)p < 4096 || -(uintptr)p < 4096) {
109 return nil;
111 return p;
114 void
115 runtime_SysMap(void *v, uintptr n)
117 void *p;
118 int fd = -1;
120 mstats.sys += n;
122 #ifdef USE_DEV_ZERO
123 if (dev_zero == -1) {
124 dev_zero = open("/dev/zero", O_RDONLY);
125 if (dev_zero < 0) {
126 runtime_printf("open /dev/zero: errno=%d\n", errno);
127 exit(2);
130 fd = dev_zero;
131 #endif
133 // On 64-bit, we don't actually have v reserved, so tread carefully.
134 if(sizeof(void*) == 8) {
135 p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
136 if(p != v && addrspace_free(v, n)) {
137 // On some systems, mmap ignores v without
138 // MAP_FIXED, so retry if the address space is free.
139 p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
141 if(p != v) {
142 runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p);
143 runtime_throw("runtime: address space conflict");
145 return;
148 p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
149 if(p != v)
150 runtime_throw("runtime: cannot map pages in arena address space");