This change was adapted from gccgo's libgo/runtime/mem.c at
Ian Taylor's suggestion. It fixes all.bash failing with
"address space conflict: map() =" on amd64 Linux with kernel
version 2.6.32.8-grsec-2.1.14-modsign-xeon-64.
With this change, SysMap will use MAP_FIXED to allocate its desired
address space, after first calling mincore to check that there is
nothing else mapped there.
R=iant, dave, n13m3y3r, rsc
CC=golang-dev
https://golang.org/cl/
4438091
INT $0x80
RET
+TEXT runtime·mincore(SB),7,$0-24
+ MOVL $218, AX // syscall - mincore
+ MOVL 4(SP), BX
+ MOVL 8(SP), CX
+ MOVL 12(SP), DX
+ INT $0x80
+ RET
+
TEXT runtime·gettime(SB), 7, $32
MOVL $78, AX // syscall - gettimeofday
LEAL 8(SP), BX
SYSCALL
RET
+TEXT runtime·mincore(SB),7,$0-24
+ MOVQ 8(SP), DI
+ MOVQ 16(SP), SI
+ MOVQ 24(SP), DX
+ MOVL $27, AX // syscall entry
+ SYSCALL
+ RET
+
TEXT runtime·gettime(SB), 7, $32
LEAQ 8(SP), DI
MOVQ $0, SI
#define SYS_exit_group (SYS_BASE + 248)
#define SYS_munmap (SYS_BASE + 91)
#define SYS_setitimer (SYS_BASE + 104)
+#define SYS_mincore (SYS_BASE + 219)
#define SYS_gettid (SYS_BASE + 224)
#define SYS_tkill (SYS_BASE + 238)
SWI $0
RET
+TEXT runtime·mincore(SB),7,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ MOVW $SYS_mincore, R7
+ SWI $0
+ RET
+
TEXT runtime·gettime(SB),7,$32
/* dummy version - return 0,0 */
MOVW $0, R1
#include "os.h"
#include "malloc.h"
+enum
+{
+ ENOMEM = 12,
+};
+
+static int32
+addrspace_free(void *v, uintptr n)
+{
+ uintptr page_size = 4096;
+ uintptr off;
+ int8 one_byte;
+
+ for(off = 0; off < n; off += page_size) {
+ int32 errval = runtime·mincore((int8 *)v + off, page_size, (void *)&one_byte);
+ // errval is 0 if success, or -(error_code) if error.
+ if (errval == 0 || errval != -ENOMEM)
+ return 0;
+ }
+ USED(v);
+ USED(n);
+ return 1;
+}
+
+
void*
runtime·SysAlloc(uintptr n)
{
return p;
}
-enum
-{
- ENOMEM = 12,
-};
-
void
runtime·SysMap(void *v, uintptr n)
{
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(sizeof(void*) == 8) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+ if(p != v && addrspace_free(v, n)) {
+ // On some systems, mmap ignores v without
+ // MAP_FIXED, so retry if the address space is free.
+ p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+ }
if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
void runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp);
void runtime·tracebackothers(G*);
int32 runtime·write(int32, void*, int32);
+int32 runtime·mincore(void*, uintptr, byte*);
bool runtime·cas(uint32*, uint32, uint32);
bool runtime·casp(void**, void*, void*);
uint32 runtime·xadd(uint32 volatile*, int32);