From 1dde0b484489653136a54df9932cc8d1c0fb6d1b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 23 Dec 2024 17:21:07 +0000 Subject: [PATCH] [release-branch.go1.23] runtime: hold traceAcquire across casgstatus in injectglist Currently injectglist emits all the trace events before actually calling casgstatus on each goroutine. This is a problem, since tracing can observe an inconsistent state (gstatus does not match tracer's 'emitted an event' state). This change fixes the problem by having injectglist do what every other scheduler function does, and that's wrap each call to casgstatus in traceAcquire/traceRelease. For #70883. Fixes #71147. Change-Id: I857e96cec01688013597e8efc0c4c3d0b72d3a70 Reviewed-on: https://go-review.googlesource.com/c/go/+/638558 Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI (cherry picked from commit f025d19e7b3f0c66242760c213cc2b54cb100f69) Reviewed-on: https://go-review.googlesource.com/c/go/+/641378 Auto-Submit: Michael Pratt --- src/runtime/proc.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index d5cfaa3916..e3cdf71911 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3873,23 +3873,23 @@ func injectglist(glist *gList) { if glist.empty() { return } - trace := traceAcquire() - if trace.ok() { - for gp := glist.head.ptr(); gp != nil; gp = gp.schedlink.ptr() { - trace.GoUnpark(gp, 0) - } - traceRelease(trace) - } // Mark all the goroutines as runnable before we put them // on the run queues. head := glist.head.ptr() var tail *g qsize := 0 + trace := traceAcquire() for gp := head; gp != nil; gp = gp.schedlink.ptr() { tail = gp qsize++ casgstatus(gp, _Gwaiting, _Grunnable) + if trace.ok() { + trace.GoUnpark(gp, 0) + } + } + if trace.ok() { + traceRelease(trace) } // Turn the gList into a gQueue. -- 2.48.1