From ae9996f96510b105f478a426cd83cfac7b83c4e3 Mon Sep 17 00:00:00 2001
From: Michael Anthony Knyszek <mknyszek@google.com>
Date: Mon, 23 Dec 2024 17:21:07 +0000
Subject: [PATCH] [release-branch.go1.22] 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 #71146.

Change-Id: I857e96cec01688013597e8efc0c4c3d0b72d3a70
Reviewed-on: https://go-review.googlesource.com/c/go/+/638558
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit f025d19e7b3f0c66242760c213cc2b54cb100f69)
Reviewed-on: https://go-review.googlesource.com/c/go/+/641356
Auto-Submit: Michael Pratt <mpratt@google.com>
---
 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 061673150f5..f9803d514b0 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -3762,23 +3762,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.
-- 
GitLab