Skip to content

Commit 5b15510

Browse files
committed
runtime: align allocations harder in GODEBUG=sbrk=1 mode
Currently, GODEBUG=sbrk=1 mode aligns allocations by their type's alignment. You would think this would be the right thing to do, but because 64-bit fields are only 4-byte aligned right now (see #599), this can cause a 64-bit field of an allocated object to be 4-byte aligned, but not 8-byte aligned. If there is an atomic access to that unaligned 64-bit field, it will crash. This doesn't happen in normal allocation mode because the size-segregated allocation and the current size classes will cause any types larger than 8 bytes to be 8 byte aligned. We fix this by making sbrk=1 mode use alignment based on the type's size rather than its declared alignment. This matches how the tiny allocator aligns allocations. This was tested with GOARCH=386 GODEBUG=sbrk=1 go test sync/atomic This crashes with an unaligned access before this change, and passes with this change. This should be reverted when/if we fix #599. Fixes #33159. Change-Id: Ifc52c72c6b99c5d370476685271baa43ad907565 Reviewed-on: https://go-review.googlesource.com/c/go/+/186919 Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent ba31496 commit 5b15510

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/runtime/malloc.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,22 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
866866
if debug.sbrk != 0 {
867867
align := uintptr(16)
868868
if typ != nil {
869-
align = uintptr(typ.align)
869+
// TODO(austin): This should be just
870+
// align = uintptr(typ.align)
871+
// but that's only 4 on 32-bit platforms,
872+
// even if there's a uint64 field in typ (see #599).
873+
// This causes 64-bit atomic accesses to panic.
874+
// Hence, we use stricter alignment that matches
875+
// the normal allocator better.
876+
if size&7 == 0 {
877+
align = 8
878+
} else if size&3 == 0 {
879+
align = 4
880+
} else if size&1 == 0 {
881+
align = 2
882+
} else {
883+
align = 1
884+
}
870885
}
871886
return persistentalloc(size, align, &memstats.other_sys)
872887
}

0 commit comments

Comments
 (0)