OSDN Git Service

libgo: Update to weekly 2011-11-09.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / mem.c
1 #include <errno.h>
2 #include <unistd.h>
3
4 #include "runtime.h"
5 #include "arch.h"
6 #include "malloc.h"
7
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
16
17 #ifdef USE_DEV_ZERO
18 static int dev_zero = -1;
19 #endif
20
21 static _Bool
22 addrspace_free(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused)))
23 {
24 #ifdef HAVE_MINCORE
25         size_t page_size = getpagesize();
26         size_t off;
27         char one_byte;
28
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;
36 }
37
38 void*
39 runtime_SysAlloc(uintptr n)
40 {
41         void *p;
42         int fd = -1;
43
44         mstats.sys += n;
45
46 #ifdef USE_DEV_ZERO
47         if (dev_zero == -1) {
48                 dev_zero = open("/dev/zero", O_RDONLY);
49                 if (dev_zero < 0) {
50                         printf("open /dev/zero: errno=%d\n", errno);
51                         exit(2);
52                 }
53         }
54         fd = dev_zero;
55 #endif
56
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                         printf("runtime: mmap: access denied\n");
61                         printf("if you're running SELinux, enable execmem for this process.\n");
62                         exit(2);
63                 }
64                 return nil;
65         }
66         return p;
67 }
68
69 void
70 runtime_SysUnused(void *v, uintptr n)
71 {
72         USED(v);
73         USED(n);
74         // TODO(rsc): call madvise MADV_DONTNEED
75 }
76
77 void
78 runtime_SysFree(void *v, uintptr n)
79 {
80         mstats.sys -= n;
81         runtime_munmap(v, n);
82 }
83
84 void*
85 runtime_SysReserve(void *v, uintptr n)
86 {
87         int fd = -1;
88         void *p;
89
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;
95         
96 #ifdef USE_DEV_ZERO
97         if (dev_zero == -1) {
98                 dev_zero = open("/dev/zero", O_RDONLY);
99                 if (dev_zero < 0) {
100                         printf("open /dev/zero: errno=%d\n", errno);
101                         exit(2);
102                 }
103         }
104         fd = dev_zero;
105 #endif
106
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;
110         }
111         return p;
112 }
113
114 void
115 runtime_SysMap(void *v, uintptr n)
116 {
117         void *p;
118         int fd = -1;
119         
120         mstats.sys += n;
121
122 #ifdef USE_DEV_ZERO
123         if (dev_zero == -1) {
124                 dev_zero = open("/dev/zero", O_RDONLY);
125                 if (dev_zero < 0) {
126                         printf("open /dev/zero: errno=%d\n", errno);
127                         exit(2);
128                 }
129         }
130         fd = dev_zero;
131 #endif
132
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);
140                 }
141                 if(p != v) {
142                         runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p);
143                         runtime_throw("runtime: address space conflict");
144                 }
145                 return;
146         }
147
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");
151 }