1 /* Defining _XOPEN_SOURCE hides the declaration of madvise() on Solaris <
2 11 and the MADV_DONTNEED definition on IRIX 6.5. */
14 #define MAP_ANON MAP_ANONYMOUS
22 #define MAP_NORESERVE 0
26 static int dev_zero
= -1;
30 addrspace_free(void *v
__attribute__ ((unused
)), uintptr n
__attribute__ ((unused
)))
33 size_t page_size
= getpagesize();
38 // NOTE: vec must be just 1 byte long here.
39 // Mincore returns ENOMEM if any of the pages are unmapped,
40 // but we want to know that all of the pages are unmapped.
41 // To make these the same, we can only ask about one page
42 // at a time. See golang.org/issue/7476.
46 for(off
= 0; off
< n
; off
+= chunk
) {
47 chunk
= page_size
* sizeof vec
;
50 errval
= mincore((char*)v
+ off
, chunk
, (void*)vec
);
51 // ENOMEM means unmapped, which is what we want.
52 // Anything else we assume means the pages are mapped.
53 if(errval
== 0 || errno
!= ENOMEM
)
61 mmap_fixed(byte
*v
, uintptr n
, int32 prot
, int32 flags
, int32 fd
, uint32 offset
)
65 p
= runtime_mmap((void *)v
, n
, prot
, flags
, fd
, offset
);
66 if(p
!= v
&& addrspace_free(v
, n
)) {
67 // On some systems, mmap ignores v without
68 // MAP_FIXED, so retry if the address space is free.
71 p
= runtime_mmap((void *)v
, n
, prot
, flags
|MAP_FIXED
, fd
, offset
);
77 runtime_SysAlloc(uintptr n
, uint64
*stat
)
84 dev_zero
= open("/dev/zero", O_RDONLY
);
86 runtime_printf("open /dev/zero: errno=%d\n", errno
);
93 p
= runtime_mmap(nil
, n
, PROT_READ
|PROT_WRITE
, MAP_ANON
|MAP_PRIVATE
, fd
, 0);
94 if (p
== MAP_FAILED
) {
96 runtime_printf("runtime: mmap: access denied\n");
97 runtime_printf("if you're running SELinux, enable execmem for this process.\n");
100 if(errno
== EAGAIN
) {
101 runtime_printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n");
106 runtime_xadd64(stat
, n
);
111 runtime_SysUnused(void *v
__attribute__ ((unused
)), uintptr n
__attribute__ ((unused
)))
114 runtime_madvise(v
, n
, MADV_DONTNEED
);
119 runtime_SysUsed(void *v
, uintptr n
)
126 runtime_SysFree(void *v
, uintptr n
, uint64
*stat
)
128 runtime_xadd64(stat
, -(uint64
)n
);
129 runtime_munmap(v
, n
);
133 runtime_SysFault(void *v
, uintptr n
)
138 if (dev_zero
== -1) {
139 dev_zero
= open("/dev/zero", O_RDONLY
);
141 runtime_printf("open /dev/zero: errno=%d\n", errno
);
148 runtime_mmap(v
, n
, PROT_NONE
, MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
, fd
, 0);
152 runtime_SysReserve(void *v
, uintptr n
, bool *reserved
)
158 if (dev_zero
== -1) {
159 dev_zero
= open("/dev/zero", O_RDONLY
);
161 runtime_printf("open /dev/zero: errno=%d\n", errno
);
168 // On 64-bit, people with ulimit -v set complain if we reserve too
169 // much address space. Instead, assume that the reservation is okay
170 // if we can reserve at least 64K and check the assumption in SysMap.
171 // Only user-mode Linux (UML) rejects these requests.
172 if(sizeof(void*) == 8 && (n
>> 16) > 1LLU<<16) {
173 p
= mmap_fixed(v
, 64<<10, PROT_NONE
, MAP_ANON
|MAP_PRIVATE
, fd
, 0);
175 runtime_munmap(p
, 64<<10);
178 runtime_munmap(p
, 64<<10);
183 // Use the MAP_NORESERVE mmap() flag here because typically most of
184 // this reservation will never be used. It does not make sense
185 // reserve a huge amount of unneeded swap space. This is important on
186 // systems which do not overcommit memory by default.
187 p
= runtime_mmap(v
, n
, PROT_NONE
, MAP_ANON
|MAP_PRIVATE
|MAP_NORESERVE
, fd
, 0);
195 runtime_SysMap(void *v
, uintptr n
, bool reserved
, uint64
*stat
)
200 runtime_xadd64(stat
, n
);
203 if (dev_zero
== -1) {
204 dev_zero
= open("/dev/zero", O_RDONLY
);
206 runtime_printf("open /dev/zero: errno=%d\n", errno
);
213 // On 64-bit, we don't actually have v reserved, so tread carefully.
215 p
= mmap_fixed(v
, n
, PROT_READ
|PROT_WRITE
, MAP_ANON
|MAP_PRIVATE
, fd
, 0);
216 if(p
== MAP_FAILED
&& errno
== ENOMEM
)
217 runtime_throw("runtime: out of memory");
219 runtime_printf("runtime: address space conflict: map(%p) = %p\n", v
, p
);
220 runtime_throw("runtime: address space conflict");
225 p
= runtime_mmap(v
, n
, PROT_READ
|PROT_WRITE
, MAP_ANON
|MAP_FIXED
|MAP_PRIVATE
, fd
, 0);
226 if(p
== MAP_FAILED
&& errno
== ENOMEM
)
227 runtime_throw("runtime: out of memory");
229 runtime_throw("runtime: cannot map pages in arena address space");