Commit 29b21ec4 authored by Austin Clements's avatar Austin Clements

runtime: add a more stable isSystemGoroutine mode

Currently, isSystemGoroutine varies on whether it considers the
finalizer goroutine a user goroutine or a system goroutine. For the
next CL, we're going to want to always consider the finalier goroutine
a user goroutine, so add a flag that indicates that.

Updates #26903. This is preparation for unifying STW GC and concurrent
GC.

Change-Id: Iafc92e519c13d9f8d879332cb5f0d12164104c33
Reviewed-on: https://go-review.googlesource.com/c/134778
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRick Hudson <rlh@golang.org>
parent 198440cc
...@@ -346,7 +346,7 @@ func dumpgoroutine(gp *g) { ...@@ -346,7 +346,7 @@ func dumpgoroutine(gp *g) {
dumpint(uint64(gp.goid)) dumpint(uint64(gp.goid))
dumpint(uint64(gp.gopc)) dumpint(uint64(gp.gopc))
dumpint(uint64(readgstatus(gp))) dumpint(uint64(readgstatus(gp)))
dumpbool(isSystemGoroutine(gp)) dumpbool(isSystemGoroutine(gp, false))
dumpbool(false) // isbackground dumpbool(false) // isbackground
dumpint(uint64(gp.waitsince)) dumpint(uint64(gp.waitsince))
dumpstr(gp.waitreason.String()) dumpstr(gp.waitreason.String())
......
...@@ -723,7 +723,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) { ...@@ -723,7 +723,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
isOK := func(gp1 *g) bool { isOK := func(gp1 *g) bool {
// Checking isSystemGoroutine here makes GoroutineProfile // Checking isSystemGoroutine here makes GoroutineProfile
// consistent with both NumGoroutine and Stack. // consistent with both NumGoroutine and Stack.
return gp1 != gp && readgstatus(gp1) != _Gdead && !isSystemGoroutine(gp1) return gp1 != gp && readgstatus(gp1) != _Gdead && !isSystemGoroutine(gp1, false)
} }
stopTheWorld("profile") stopTheWorld("profile")
......
...@@ -2730,7 +2730,7 @@ func goexit0(gp *g) { ...@@ -2730,7 +2730,7 @@ func goexit0(gp *g) {
_g_ := getg() _g_ := getg()
casgstatus(gp, _Grunning, _Gdead) casgstatus(gp, _Grunning, _Gdead)
if isSystemGoroutine(gp) { if isSystemGoroutine(gp, false) {
atomic.Xadd(&sched.ngsys, -1) atomic.Xadd(&sched.ngsys, -1)
} }
gp.m = nil gp.m = nil
...@@ -3381,7 +3381,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, callergp *g, callerpc uintpt ...@@ -3381,7 +3381,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, callergp *g, callerpc uintpt
if _g_.m.curg != nil { if _g_.m.curg != nil {
newg.labels = _g_.m.curg.labels newg.labels = _g_.m.curg.labels
} }
if isSystemGoroutine(newg) { if isSystemGoroutine(newg, false) {
atomic.Xadd(&sched.ngsys, +1) atomic.Xadd(&sched.ngsys, +1)
} }
newg.gcscanvalid = false newg.gcscanvalid = false
...@@ -4244,7 +4244,7 @@ func checkdead() { ...@@ -4244,7 +4244,7 @@ func checkdead() {
lock(&allglock) lock(&allglock)
for i := 0; i < len(allgs); i++ { for i := 0; i < len(allgs); i++ {
gp := allgs[i] gp := allgs[i]
if isSystemGoroutine(gp) { if isSystemGoroutine(gp, false) {
continue continue
} }
s := readgstatus(gp) s := readgstatus(gp)
......
...@@ -945,7 +945,7 @@ func tracebackothers(me *g) { ...@@ -945,7 +945,7 @@ func tracebackothers(me *g) {
lock(&allglock) lock(&allglock)
for _, gp := range allgs { for _, gp := range allgs {
if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp) && level < 2 { if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp, false) && level < 2 {
continue continue
} }
print("\n") print("\n")
...@@ -1031,7 +1031,11 @@ func topofstack(f funcInfo, g0 bool) bool { ...@@ -1031,7 +1031,11 @@ func topofstack(f funcInfo, g0 bool) bool {
// in stack dumps and deadlock detector. This is any goroutine that // in stack dumps and deadlock detector. This is any goroutine that
// starts at a runtime.* entry point, except for runtime.main and // starts at a runtime.* entry point, except for runtime.main and
// sometimes runtime.runfinq. // sometimes runtime.runfinq.
func isSystemGoroutine(gp *g) bool { //
// If fixed is true, any goroutine that can vary between user and
// system (that is, the finalizer goroutine) is considered a user
// goroutine.
func isSystemGoroutine(gp *g, fixed bool) bool {
// Keep this in sync with cmd/trace/trace.go:isSystemGoroutine. // Keep this in sync with cmd/trace/trace.go:isSystemGoroutine.
f := findfunc(gp.startpc) f := findfunc(gp.startpc)
if !f.valid() { if !f.valid() {
...@@ -1043,6 +1047,11 @@ func isSystemGoroutine(gp *g) bool { ...@@ -1043,6 +1047,11 @@ func isSystemGoroutine(gp *g) bool {
if f.funcID == funcID_runfinq { if f.funcID == funcID_runfinq {
// We include the finalizer goroutine if it's calling // We include the finalizer goroutine if it's calling
// back into user code. // back into user code.
if fixed {
// This goroutine can vary. In fixed mode,
// always consider it a user goroutine.
return false
}
return !fingRunning return !fingRunning
} }
return hasPrefix(funcname(f), "runtime.") return hasPrefix(funcname(f), "runtime.")
......
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