Skip to content

Commit 686b38b

Browse files
mknyszekgopherbot
authored andcommitted
runtime: set G wait reason more consistently
Currently, wait reasons are set somewhat inconsistently. In a follow-up CL, we're going to want to rely on the wait reason being there for casgstatus, so the status quo isn't really going to work for that. Plus this inconsistency means there are a whole bunch of cases where we could be more specific about the G's status but aren't. So, this change adds a new function, casGToWaiting which is like casgstatus but also sets the wait reason. The goal is that by using this API it'll be harder to forget to set a wait reason (or the lack thereof will at least be explicit). This change then updates all casgstatus(gp, ..., _Gwaiting) calls to casGToWaiting(gp, ..., waitReasonX) instead. For a number of these cases, we're missing a wait reason, and it wouldn't hurt to add a wait reason for them, so this change also adds those wait reasons. For #49881. Change-Id: Ia95e06ecb74ed17bb7bb94f1a362ebfe6bec1518 Reviewed-on: https://go-review.googlesource.com/c/go/+/427617 Reviewed-by: Michael Pratt <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> Auto-Submit: Michael Knyszek <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent a2c396c commit 686b38b

File tree

6 files changed

+27
-15
lines changed

6 files changed

+27
-15
lines changed

Diff for: src/runtime/debugcall.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,10 @@ func debugCallWrap(dispatch uintptr) {
158158
gp.schedlink = 0
159159

160160
// Park the calling goroutine.
161-
gp.waitreason = waitReasonDebugCall
162161
if trace.enabled {
163162
traceGoPark(traceEvGoBlock, 1)
164163
}
165-
casgstatus(gp, _Grunning, _Gwaiting)
164+
casGToWaiting(gp, _Grunning, waitReasonDebugCall)
166165
dropg()
167166

168167
// Directly execute the new goroutine. The debug

Diff for: src/runtime/heapdump.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -691,8 +691,7 @@ func writeheapdump_m(fd uintptr, m *MemStats) {
691691
assertWorldStopped()
692692

693693
gp := getg()
694-
casgstatus(gp.m.curg, _Grunning, _Gwaiting)
695-
gp.waitreason = waitReasonDumpingHeap
694+
casGToWaiting(gp.m.curg, _Grunning, waitReasonDumpingHeap)
696695

697696
// Set dump file.
698697
dumpfd = fd

Diff for: src/runtime/mgc.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ top:
810810
// Otherwise, our attempt to force all P's to a safepoint could
811811
// result in a deadlock as we attempt to preempt a worker that's
812812
// trying to preempt us (e.g. for a stack scan).
813-
casgstatus(gp, _Grunning, _Gwaiting)
813+
casGToWaiting(gp, _Grunning, waitReasonGCMarkTermination)
814814
forEachP(func(pp *p) {
815815
// Flush the write barrier buffer, since this may add
816816
// work to the gcWork.
@@ -931,8 +931,7 @@ func gcMarkTermination() {
931931
mp.preemptoff = "gcing"
932932
mp.traceback = 2
933933
curgp := mp.curg
934-
casgstatus(curgp, _Grunning, _Gwaiting)
935-
curgp.waitreason = waitReasonGarbageCollection
934+
casGToWaiting(curgp, _Grunning, waitReasonGarbageCollection)
936935

937936
// Run gc on the g0 stack. We do this so that the g stack
938937
// we're currently running on will no longer change. Cuts
@@ -1332,7 +1331,7 @@ func gcBgMarkWorker() {
13321331
// the G stack. However, stack shrinking is
13331332
// disabled for mark workers, so it is safe to
13341333
// read from the G stack.
1335-
casgstatus(gp, _Grunning, _Gwaiting)
1334+
casGToWaiting(gp, _Grunning, waitReasonGCWorkerActive)
13361335
switch pp.gcMarkWorkerMode {
13371336
default:
13381337
throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")

Diff for: src/runtime/mgcmark.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 {
218218
userG := getg().m.curg
219219
selfScan := gp == userG && readgstatus(userG) == _Grunning
220220
if selfScan {
221-
casgstatus(userG, _Grunning, _Gwaiting)
222-
userG.waitreason = waitReasonGarbageCollectionScan
221+
casGToWaiting(userG, _Grunning, waitReasonGarbageCollectionScan)
223222
}
224223

225224
// TODO: suspendG blocks (and spins) until gp
@@ -560,8 +559,7 @@ func gcAssistAlloc1(gp *g, scanWork int64) {
560559
}
561560

562561
// gcDrainN requires the caller to be preemptible.
563-
casgstatus(gp, _Grunning, _Gwaiting)
564-
gp.waitreason = waitReasonGCAssistMarking
562+
casGToWaiting(gp, _Grunning, waitReasonGCAssistMarking)
565563

566564
// drain own cached work first in the hopes that it
567565
// will be more cache friendly.

Diff for: src/runtime/proc.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,14 @@ func casgstatus(gp *g, oldval, newval uint32) {
10271027
}
10281028
}
10291029

1030+
// casGToWaiting transitions gp from old to _Gwaiting, and sets the wait reason.
1031+
//
1032+
// Use this over casgstatus when possible to ensure that a waitreason is set.
1033+
func casGToWaiting(gp *g, old uint32, reason waitReason) {
1034+
gp.waitreason = reason
1035+
casgstatus(gp, old, _Gwaiting)
1036+
}
1037+
10301038
// casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable.
10311039
// Returns old status. Cannot call casgstatus directly, because we are racing with an
10321040
// async wakeup that might come in from netpoll. If we see Gwaiting from the readgstatus,
@@ -1066,6 +1074,7 @@ func casGFromPreempted(gp *g, old, new uint32) bool {
10661074
if old != _Gpreempted || new != _Gwaiting {
10671075
throw("bad g transition")
10681076
}
1077+
gp.waitreason = waitReasonPreempted
10691078
return gp.atomicstatus.CompareAndSwap(_Gpreempted, _Gwaiting)
10701079
}
10711080

@@ -1098,7 +1107,8 @@ func stopTheWorld(reason string) {
10981107
// must have preempted all goroutines, including any attempting
10991108
// to scan our stack, in which case, any stack shrinking will
11001109
// have already completed by the time we exit.
1101-
casgstatus(gp, _Grunning, _Gwaiting)
1110+
// Don't provide a wait reason because we're still executing.
1111+
casGToWaiting(gp, _Grunning, waitReasonStoppingTheWorld)
11021112
stopTheWorldWithSema()
11031113
casgstatus(gp, _Gwaiting, _Grunning)
11041114
})
@@ -3395,6 +3405,8 @@ func park_m(gp *g) {
33953405
traceGoPark(mp.waittraceev, mp.waittraceskip)
33963406
}
33973407

3408+
// N.B. Not using casGToWaiting here because the waitreason is
3409+
// set by park_m's caller.
33983410
casgstatus(gp, _Grunning, _Gwaiting)
33993411
dropg()
34003412

@@ -3468,7 +3480,6 @@ func preemptPark(gp *g) {
34683480
dumpgstatus(gp)
34693481
throw("bad g status")
34703482
}
3471-
gp.waitreason = waitReasonPreempted
34723483

34733484
if gp.asyncSafePoint {
34743485
// Double-check that async preemption does not
@@ -3545,7 +3556,7 @@ func goexit0(gp *g) {
35453556
gp._defer = nil // should be true already but just in case.
35463557
gp._panic = nil // non-nil for Goexit during panic. points at stack-allocated data.
35473558
gp.writebuf = nil
3548-
gp.waitreason = 0
3559+
gp.waitreason = waitReasonZero
35493560
gp.param = nil
35503561
gp.labels = nil
35513562
gp.timer = nil

Diff for: src/runtime/runtime2.go

+6
Original file line numberDiff line numberDiff line change
@@ -1060,8 +1060,11 @@ const (
10601060
waitReasonTraceReaderBlocked // "trace reader (blocked)"
10611061
waitReasonWaitForGCCycle // "wait for GC cycle"
10621062
waitReasonGCWorkerIdle // "GC worker (idle)"
1063+
waitReasonGCWorkerActive // "GC worker (active)"
10631064
waitReasonPreempted // "preempted"
10641065
waitReasonDebugCall // "debug call"
1066+
waitReasonGCMarkTermination // "GC mark termination"
1067+
waitReasonStoppingTheWorld // "stopping the world"
10651068
)
10661069

10671070
var waitReasonStrings = [...]string{
@@ -1092,8 +1095,11 @@ var waitReasonStrings = [...]string{
10921095
waitReasonTraceReaderBlocked: "trace reader (blocked)",
10931096
waitReasonWaitForGCCycle: "wait for GC cycle",
10941097
waitReasonGCWorkerIdle: "GC worker (idle)",
1098+
waitReasonGCWorkerActive: "GC worker (active)",
10951099
waitReasonPreempted: "preempted",
10961100
waitReasonDebugCall: "debug call",
1101+
waitReasonGCMarkTermination: "GC mark termination",
1102+
waitReasonStoppingTheWorld: "stopping the world",
10971103
}
10981104

10991105
func (w waitReason) String() string {

0 commit comments

Comments
 (0)