runtime: clean up canpanic

* The gp argument to canpanic is always equivalent to getg(), so no need
to pass it at all.
* gp must not be nil or _g_.m would have crashed, so no need to check
for nil.
* Use acquirem to better reason about preemption.

Change-Id: Ic7dc8dc1e56ab4c1644965f6aeba16807cdb2df4
Reviewed-on: https://go-review.googlesource.com/c/go/+/418575
Reviewed-by: Austin Clements <austin@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
This commit is contained in:
Michael Pratt 2022-07-20 11:09:14 -04:00
parent 9dbc0f3556
commit 7e952962df
5 changed files with 15 additions and 12 deletions

View file

@ -50,7 +50,7 @@ const _SIGSEGV = 0xb
func sigpanic() { func sigpanic() {
g := getg() g := getg()
if !canpanic(g) { if !canpanic() {
throw("unexpected signal during runtime execution") throw("unexpected signal during runtime execution")
} }

View file

@ -76,7 +76,7 @@ func os_sigpipe() {
func sigpanic() { func sigpanic() {
g := getg() g := getg()
if !canpanic(g) { if !canpanic() {
throw("unexpected signal during runtime execution") throw("unexpected signal during runtime execution")
} }

View file

@ -1290,29 +1290,32 @@ func dopanic_m(gp *g, pc, sp uintptr) bool {
// panicking. // panicking.
// //
//go:nosplit //go:nosplit
func canpanic(gp *g) bool { func canpanic() bool {
// Note that g is m->gsignal, different from gp. gp := getg()
// Note also that g->m can change at preemption, so m can go stale mp := acquirem()
// if this function ever makes a function call.
_g_ := getg()
mp := _g_.m
// Is it okay for gp to panic instead of crashing the program? // Is it okay for gp to panic instead of crashing the program?
// Yes, as long as it is running Go code, not runtime code, // Yes, as long as it is running Go code, not runtime code,
// and not stuck in a system call. // and not stuck in a system call.
if gp == nil || gp != mp.curg { if gp != mp.curg {
releasem(mp)
return false return false
} }
if mp.locks != 0 || mp.mallocing != 0 || mp.throwing != throwTypeNone || mp.preemptoff != "" || mp.dying != 0 { // N.B. mp.locks != 1 instead of 0 to account for acquirem.
if mp.locks != 1 || mp.mallocing != 0 || mp.throwing != throwTypeNone || mp.preemptoff != "" || mp.dying != 0 {
releasem(mp)
return false return false
} }
status := readgstatus(gp) status := readgstatus(gp)
if status&^_Gscan != _Grunning || gp.syscallsp != 0 { if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
releasem(mp)
return false return false
} }
if GOOS == "windows" && mp.libcallsp != 0 { if GOOS == "windows" && mp.libcallsp != 0 {
releasem(mp)
return false return false
} }
releasem(mp)
return true return true
} }

View file

@ -815,7 +815,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
//go:linkname sigpanic //go:linkname sigpanic
func sigpanic() { func sigpanic() {
g := getg() g := getg()
if !canpanic(g) { if !canpanic() {
throw("unexpected signal during runtime execution") throw("unexpected signal during runtime execution")
} }

View file

@ -245,7 +245,7 @@ func winthrow(info *exceptionrecord, r *context, gp *g) {
func sigpanic() { func sigpanic() {
g := getg() g := getg()
if !canpanic(g) { if !canpanic() {
throw("unexpected signal during runtime execution") throw("unexpected signal during runtime execution")
} }