OSDN Git Service

4267c55fb47c3fa27b597ac4655d54a03195cf77
[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
89         // On 64-bit, people with ulimit -v set complain if we reserve too
90         // much address space.  Instead, assume that the reservation is okay
91         // and check the assumption in SysMap.
92         if(sizeof(void*) == 8)
93                 return v;
94         
95 #ifdef USE_DEV_ZERO
96         if (dev_zero == -1) {
97                 dev_zero = open("/dev/zero", O_RDONLY);
98                 if (dev_zero < 0) {
99                         printf("open /dev/zero: errno=%d\n", errno);
100                         exit(2);
101                 }
102         }
103         fd = dev_zero;
104 #endif
105
106         return runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
107 }
108
109 void
110 runtime_SysMap(void *v, uintptr n)
111 {
112         void *p;
113         int fd = -1;
114         
115         mstats.sys += n;
116
117 #ifdef USE_DEV_ZERO
118         if (dev_zero == -1) {
119                 dev_zero = open("/dev/zero", O_RDONLY);
120                 if (dev_zero < 0) {
121                         printf("open /dev/zero: errno=%d\n", errno);
122                         exit(2);
123                 }
124         }
125         fd = dev_zero;
126 #endif
127
128         // On 64-bit, we don't actually have v reserved, so tread carefully.
129         if(sizeof(void*) == 8) {
130                 p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
131                 if(p != v && addrspace_free(v, n)) {
132                         // On some systems, mmap ignores v without
133                         // MAP_FIXED, so retry if the address space is free.
134                         p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
135                 }
136                 if(p != v) {
137                         runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p);
138                         runtime_throw("runtime: address space conflict");
139                 }
140                 return;
141         }
142
143         p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
144         if(p != v)
145                 runtime_throw("runtime: cannot map pages in arena address space");
146 }