]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix stack-move sensitivity in some tests
authorAustin Clements <austin@google.com>
Mon, 25 Apr 2022 16:25:59 +0000 (12:25 -0400)
committerAustin Clements <austin@google.com>
Mon, 25 Apr 2022 18:06:52 +0000 (18:06 +0000)
There are a few tests of the scheduler run queue API that allocate a
local []g and test using those G's. However, the run queue API
frequently converts between *g and guintptr, which is safe for "real"
Gs because they're heap-allocated and hence don't move, but if these
tests get a stack movement while holding one of these local *g's as a
guintptr, it won't get updated and the test will fail.

Updates #48297.

Change-Id: Ifd424147ce1a1b53732ff0cf55a81df1a9beeb3b
Reviewed-on: https://go-review.googlesource.com/c/go/+/402157
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/runtime/export_test.go

index 8a81f42ca09d6f8c12d10729d52df0430c276f2b..0a00801a1144484e1622dcbf32e0b681cd0e6452 100644 (file)
@@ -85,6 +85,7 @@ func GCMask(x any) (ret []byte) {
 func RunSchedLocalQueueTest() {
        _p_ := new(p)
        gs := make([]g, len(_p_.runq))
+       escape(gs) // Ensure gs doesn't move, since we use guintptrs
        for i := 0; i < len(_p_.runq); i++ {
                if g, _ := runqget(_p_); g != nil {
                        throw("runq is not empty initially")
@@ -108,6 +109,7 @@ func RunSchedLocalQueueStealTest() {
        p1 := new(p)
        p2 := new(p)
        gs := make([]g, len(p1.runq))
+       escape(gs) // Ensure gs doesn't move, since we use guintptrs
        for i := 0; i < len(p1.runq); i++ {
                for j := 0; j < i; j++ {
                        gs[j].sig = 0
@@ -155,6 +157,7 @@ func RunSchedLocalQueueEmptyTest(iters int) {
        done := make(chan bool, 1)
        p := new(p)
        gs := make([]g, 2)
+       escape(gs) // Ensure gs doesn't move, since we use guintptrs
        ready := new(uint32)
        for i := 0; i < iters; i++ {
                *ready = 0
@@ -1257,7 +1260,7 @@ func NewGCController(gcPercent int) *GCController {
        // do 64-bit atomics on it, and if it gets stack-allocated
        // on a 32-bit architecture, it may get allocated unaligned
        // space.
-       g := escape(new(GCController)).(*GCController)
+       g := escape(new(GCController))
        g.gcControllerState.test = true // Mark it as a test copy.
        g.init(int32(gcPercent))
        return g
@@ -1318,7 +1321,8 @@ func (c *GCController) EndCycle(bytesMarked uint64, assistTime, elapsed int64, g
 var escapeSink any
 
 //go:noinline
-func escape(x any) any {
+//go:norace
+func escape[T any](x T) T {
        escapeSink = x
        escapeSink = nil
        return x