From f1b7b2fc52947711b8e78f7078c9e0bda35320d3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 19 Sep 2022 17:26:05 -0400 Subject: [PATCH] runtime: make mSpanStateBox accessors nosplit get, at least, is called from typedmemclr which must not be interruptible. These were previously nosplit by accident before CL 424395 (the only call they had was an intrinsic, so they were leaf functions, so they had no prologue). After CL 424395 they contained a call (in noinline builds), thus had a prologue, thus had a suspension point. I have no idea how we might test this. This is another motivating use case for having a nosplitrec directive in the runtime. Fixes #55156 Fixes #54779 Fixes #54906 Fixes #54907 Change-Id: I851d733d71bda7172c4c96e027657e22b499ee00 Reviewed-on: https://go-review.googlesource.com/c/go/+/431919 Reviewed-by: Cherry Mui Run-TryBot: Keith Randall Reviewed-by: Keith Randall TryBot-Result: Gopher Robot --- src/runtime/mbarrier.go | 2 ++ src/runtime/mheap.go | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index c3b45415a95339..efe6c4f2d63461 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -311,6 +311,8 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int { // If the caller knows that typ has pointers, it can alternatively // call memclrHasPointers. // +// TODO: A "go:nosplitrec" annotation would be perfect for this. +// //go:nosplit func typedmemclr(typ *_type, ptr unsafe.Pointer) { if writeBarrier.needed && typ.ptrdata != 0 { diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index c8a6cd29362e99..995cb2ae9c2ccd 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -362,10 +362,17 @@ type mSpanStateBox struct { s atomic.Uint8 } +// It is nosplit to match get, below. + +//go:nosplit func (b *mSpanStateBox) set(s mSpanState) { b.s.Store(uint8(s)) } +// It is nosplit because it's called indirectly by typedmemclr, +// which must not be preempted. + +//go:nosplit func (b *mSpanStateBox) get() mSpanState { return mSpanState(b.s.Load()) }