Skip to content

Commit a8ad859

Browse files
committed
runtime: more flexible heap memory mapping on 64-bits
Fixes golang#5641. R=golang-dev, dave, daniel.morsing, iant CC=golang-dev, kcc https://golang.org/cl/10126044
1 parent dbcfed9 commit a8ad859

3 files changed

Lines changed: 68 additions & 5 deletions

File tree

misc/cgo/testasan/main.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2013 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
/*
8+
#include <sys/mman.h>
9+
#include <pthread.h>
10+
#include <unistd.h>
11+
12+
void ctor(void) __attribute__((constructor));
13+
static void* thread(void*);
14+
15+
void
16+
ctor(void)
17+
{
18+
// occupy memory where Go runtime would normally map heap
19+
mmap((void*)0x00c000000000, 64<<10, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
20+
21+
// allocate 4K every 10us
22+
pthread_t t;
23+
pthread_create(&t, 0, thread, 0);
24+
}
25+
26+
static void*
27+
thread(void *p)
28+
{
29+
for(;;) {
30+
usleep(10000);
31+
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
32+
}
33+
return 0;
34+
}
35+
*/
36+
import "C"
37+
38+
import (
39+
"time"
40+
)
41+
42+
func main() {
43+
// ensure that we can function normally
44+
var v [][]byte
45+
for i := 0; i < 1000; i++ {
46+
time.Sleep(10 * time.Microsecond)
47+
v = append(v, make([]byte, 64<<10))
48+
}
49+
}

src/pkg/runtime/malloc.goc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ runtime·mallocinit(void)
303303
extern byte end[];
304304
byte *want;
305305
uintptr limit;
306+
uint64 i;
306307

307308
p = nil;
308309
arena_size = 0;
@@ -330,15 +331,17 @@ runtime·mallocinit(void)
330331
// 128 GB (MaxMem) should be big enough for now.
331332
//
332333
// The code will work with the reservation at any address, but ask
333-
// SysReserve to use 0x000000c000000000 if possible.
334+
// SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
334335
// Allocating a 128 GB region takes away 37 bits, and the amd64
335336
// doesn't let us choose the top 17 bits, so that leaves the 11 bits
336337
// in the middle of 0x00c0 for us to choose. Choosing 0x00c0 means
337-
// that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x0x00df.
338+
// that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
338339
// In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
339340
// UTF-8 sequences, and they are otherwise as far away from
340-
// ff (likely a common byte) as possible. An earlier attempt to use 0x11f8
341-
// caused out of memory errors on OS X during thread allocations.
341+
// ff (likely a common byte) as possible. If that fails, we try other 0xXXc0
342+
// addresses. An earlier attempt to use 0x11f8 caused out of memory errors
343+
// on OS X during thread allocations. 0x00c0 causes conflicts with
344+
// AddressSanitizer which reserves all memory up to 0x0100.
342345
// These choices are both for debuggability and to reduce the
343346
// odds of the conservative garbage collector not collecting memory
344347
// because some non-pointer block of memory had a bit pattern
@@ -353,7 +356,12 @@ runtime·mallocinit(void)
353356
spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
354357
// round spans_size to pages
355358
spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
356-
p = runtime·SysReserve((void*)(0x00c0ULL<<32), bitmap_size + spans_size + arena_size);
359+
for(i = 0; i <= 0x7f; i++) {
360+
p = (void*)(i<<40 | 0x00c0ULL<<32);
361+
p = runtime·SysReserve(p, bitmap_size + spans_size + arena_size);
362+
if(p != nil)
363+
break;
364+
}
357365
}
358366
if (p == nil) {
359367
// On a 32-bit machine, we can't typically get away

src/run.bash

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ esac
108108
./test.bash
109109
) || exit $?
110110

111+
[ "$CGO_ENABLED" != 1 ] ||
112+
[ "$GOHOSTOS-$GOARCH" != linux-amd64 ] ||
113+
(xcd ../misc/cgo/testasan
114+
go run main.go
115+
) || exit $?
116+
111117
(xcd ../doc/progs
112118
time ./run
113119
) || exit $?

0 commit comments

Comments
 (0)