aboutsummaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2017-06-23 16:05:44 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-06-23 16:05:44 +0000
commitbb96aa6726d1fac7e2500ef37d1193eed00b03f1 (patch)
treef9c9927c7f70e3dd316f3234661634304e55c10a /libgo/go
parent5f0b897b2ee47bf3845d924dd5bc3beb949bc78b (diff)
downloadgcc-bb96aa6726d1fac7e2500ef37d1193eed00b03f1.zip
gcc-bb96aa6726d1fac7e2500ef37d1193eed00b03f1.tar.gz
gcc-bb96aa6726d1fac7e2500ef37d1193eed00b03f1.tar.bz2
runtime: don't crash if no p in kickoff
The kickoff function for g0 can be invoked without a p, for example from mcall(exitsyscall0) in exitsyscall after exitsyscall has cleared the p field. The assignment gp.param = nil will invoke a write barrier. If gp.param is not already nil, this will require a p. Avoid the problem for a specific case that is known to be OK: when the value in gp.param is a *g. Reviewed-on: https://go-review.googlesource.com/46512 From-SVN: r249595
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/runtime/proc.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index 77b624b..6b6f9c9 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1097,7 +1097,25 @@ func kickoff() {
fv := gp.entry
param := gp.param
gp.entry = nil
+
+ // When running on the g0 stack we can wind up here without a p,
+ // for example from mcall(exitsyscall0) in exitsyscall.
+ // Setting gp.param = nil will call a write barrier, and if
+ // there is no p that write barrier will crash. When called from
+ // mcall the gp.param value will be a *g, which we don't need to
+ // shade since we know it will be kept alive elsewhere. In that
+ // case clear the field using uintptr so that the write barrier
+ // does nothing.
+ if gp.m.p == 0 {
+ if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) {
+ *(*uintptr)(unsafe.Pointer(&gp.param)) = 0
+ } else {
+ throw("no p in kickoff")
+ }
+ }
+
gp.param = nil
+
fv(param)
goexit1()
}