Skip to content

Commit 88b9c27

Browse files
aykevldeadprogram
authored andcommitted
unix: check for mmap error and act accordingly
At startup, a large chunk of virtual memory is used up by the heap. This works fine in emulation (qemu-arm), but doesn't work so well on an actual Raspberry Pi. Therefore, this commit reduces the requested amount until a heap size is found that works on the system. This can certainly be improved, but for now it's an important fix because it allows TinyGo built binaries to actually run on a Raspberry Pi with just 1GB RAM.
1 parent 37ee4be commit 88b9c27

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

src/runtime/runtime_unix.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ func usleep(usec uint) int
1616
//export malloc
1717
func malloc(size uintptr) unsafe.Pointer
1818

19+
// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
1920
//export mmap
20-
func mmap(addr unsafe.Pointer, length, prot, flags, fd int, offset int) unsafe.Pointer
21+
func mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int, offset int) unsafe.Pointer
2122

2223
//export abort
2324
func abort()

src/runtime/runtime_unix_heap.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,32 @@
55

66
package runtime
77

8-
var heapSize uintptr = 128 * 1024 // small amount to start
9-
const heapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap
8+
import "unsafe"
9+
10+
var heapSize uintptr = 128 * 1024 // small amount to start
11+
var heapMaxSize uintptr
1012

1113
var heapStart, heapEnd uintptr
1214

1315
func preinit() {
1416
// Allocate a large chunk of virtual memory. Because it is virtual, it won't
1517
// really be allocated in RAM. Memory will only be allocated when it is
1618
// first touched.
17-
addr := mmap(nil, heapMaxSize, flag_PROT_READ|flag_PROT_WRITE, flag_MAP_PRIVATE|flag_MAP_ANONYMOUS, -1, 0)
18-
heapStart = uintptr(addr)
19-
heapEnd = heapStart + heapSize
19+
heapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap
20+
for {
21+
addr := mmap(nil, heapMaxSize, flag_PROT_READ|flag_PROT_WRITE, flag_MAP_PRIVATE|flag_MAP_ANONYMOUS, -1, 0)
22+
if addr == unsafe.Pointer(^uintptr(0)) {
23+
// Heap was too big to be mapped by mmap. Reduce the maximum size.
24+
// We might want to make this a bit smarter than simply halving the
25+
// heap size.
26+
// This can happen on 32-bit systems.
27+
heapMaxSize /= 2
28+
continue
29+
}
30+
heapStart = uintptr(addr)
31+
heapEnd = heapStart + heapSize
32+
break
33+
}
2034
}
2135

2236
// growHeap tries to grow the heap size. It returns true if it succeeds, false

0 commit comments

Comments
 (0)