Commit c7c7c703 authored by Austin Clements's avatar Austin Clements

runtime: fix, simplify, and improve scan state in goroutine header

Currently goroutineheader goes through some convolutions to *almost*
print the scan state of a G. However, the code path that would print
the scan state of the G refers to gStatusStrings where it almost
certainly meant to refer to gScanStatusStrings (which is unused), so
it winds up printing the regular status string without the scan state
either way. Furthermore, if the G is in _Gwaiting, we override the
status string and lose where this would indicate the scan state if it
worked.

This commit fixes this so the runtime prints the scan state. However,
rather than using a parallel list of status strings, this simply adds
a conditional print if the scan bit is set. This lets us remove the
string list, prints the scan state even in _Gwaiting, and lets us
strip off the scan bit at the beginning of the function, which
simplifies the rest of it.

Change-Id: Ic0adbe5c05abf4adda93da59f93b578172b28e3d
Reviewed-on: https://go-review.googlesource.com/18092Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 0f3c2290
...@@ -645,41 +645,34 @@ var gStatusStrings = [...]string{ ...@@ -645,41 +645,34 @@ var gStatusStrings = [...]string{
_Gcopystack: "copystack", _Gcopystack: "copystack",
} }
var gScanStatusStrings = [...]string{
0: "scan",
_Grunnable: "scanrunnable",
_Grunning: "scanrunning",
_Gsyscall: "scansyscall",
_Gwaiting: "scanwaiting",
_Gdead: "scandead",
_Genqueue: "scanenqueue",
}
func goroutineheader(gp *g) { func goroutineheader(gp *g) {
gpstatus := readgstatus(gp) gpstatus := readgstatus(gp)
isScan := gpstatus&_Gscan != 0
gpstatus &^= _Gscan // drop the scan bit
// Basic string status // Basic string status
var status string var status string
if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) { if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
status = gStatusStrings[gpstatus] status = gStatusStrings[gpstatus]
} else if gpstatus&_Gscan != 0 && 0 <= gpstatus&^_Gscan && gpstatus&^_Gscan < uint32(len(gStatusStrings)) {
status = gStatusStrings[gpstatus&^_Gscan]
} else { } else {
status = "???" status = "???"
} }
// Override. // Override.
if (gpstatus == _Gwaiting || gpstatus == _Gscanwaiting) && gp.waitreason != "" { if gpstatus == _Gwaiting && gp.waitreason != "" {
status = gp.waitreason status = gp.waitreason
} }
// approx time the G is blocked, in minutes // approx time the G is blocked, in minutes
var waitfor int64 var waitfor int64
gpstatus &^= _Gscan // drop the scan bit
if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 { if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
waitfor = (nanotime() - gp.waitsince) / 60e9 waitfor = (nanotime() - gp.waitsince) / 60e9
} }
print("goroutine ", gp.goid, " [", status) print("goroutine ", gp.goid, " [", status)
if isScan {
print(" (scan)")
}
if waitfor >= 1 { if waitfor >= 1 {
print(", ", waitfor, " minutes") print(", ", waitfor, " minutes")
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment