From 196492a299337f532d743556a6f6be37e9dff94f Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 28 Jul 2017 17:44:09 -0400 Subject: [PATCH] [release-branch.go1.9] runtime: map bitmap and spans during heap initialization We lazily map the bitmap and spans areas as the heap grows. However, right now we're very slightly too lazy. Specifically, the following can happen on 32-bit: 1. mallocinit fails to allocate any heap arena, so arena_used == arena_alloc == arena_end == bitmap. 2. There's less than 256MB between the end of the bitmap mapping and the next mapping. 3. On the first allocation, mheap.sysAlloc sees that there's not enough room in [arena_alloc, arena_end) because there's no room at all. It gets a 256MB mapping from somewhere *lower* in the address space than arena_used and sets arena_alloc and arena_end to this hole. 4. Since the new arena_alloc is lower than arena_used, mheap.sysAlloc doesn't bother to call mheap.setArenaUsed, so we still don't have a bitmap mapping or a spans array mapping. 5. mheap.grow, which called mheap.sysAlloc, attempts to fill in the spans array and crashes. Fix this by mapping the metadata regions for the initial arena_used when the heap is initialized, rather than trying to wait for an allocation. This maintains the intended invariant that the structures are always mapped for [arena_start, arena_used). Fixes #21044. Cherry-pick of CL 51714. Fixes #21234. Change-Id: I4422375a6e234b9f979d22135fc63ae3395946b0 Reviewed-on: https://go-review.googlesource.com/52191 Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/runtime/mheap.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index bf682ec97f..893587e5d2 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -503,6 +503,11 @@ func (h *mheap) init(spansStart, spansBytes uintptr) { sp.array = unsafe.Pointer(spansStart) sp.len = 0 sp.cap = int(spansBytes / sys.PtrSize) + + // Map metadata structures. But don't map race detector memory + // since we're not actually growing the arena here (and TSAN + // gets mad if you map 0 bytes). + h.setArenaUsed(h.arena_used, false) } // setArenaUsed extends the usable arena to address arena_used and -- 2.48.1