runtime: mark mstart as nowritebarrierrec

mstart is the entry point for new threads, so it certainly can't
interact with GC enough to have write barriers. We move the one small
piece that is allowed to have write barriers out into its own
function.

Change-Id: Id9c31d6ffac31d0051fab7db15eb428c11cadbad
Reviewed-on: https://go-review.googlesource.com/46035
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2017-06-15 15:02:32 -04:00
parent 8f7f46f5a6
commit a212083eea

View file

@ -1137,7 +1137,15 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
} }
// Called to start an M. // Called to start an M.
//
// This must not split the stack because we may not even have stack
// bounds set up yet.
//
// May run during STW (because it doesn't have a P yet), so write
// barriers are not allowed.
//
//go:nosplit //go:nosplit
//go:nowritebarrierrec
func mstart() { func mstart() {
_g_ := getg() _g_ := getg()
@ -1176,12 +1184,7 @@ func mstart1() {
// Install signal handlers; after minit so that minit can // Install signal handlers; after minit so that minit can
// prepare the thread to be able to handle the signals. // prepare the thread to be able to handle the signals.
if _g_.m == &m0 { if _g_.m == &m0 {
// Create an extra M for callbacks on threads not created by Go. mstartm0()
if iscgo && !cgoHasExtraM {
cgoHasExtraM = true
newextram()
}
initsig(false)
} }
if fn := _g_.m.mstartfn; fn != nil { if fn := _g_.m.mstartfn; fn != nil {
@ -1198,6 +1201,21 @@ func mstart1() {
schedule() schedule()
} }
// mstartm0 implements part of mstart1 that only runs on the m0.
//
// Write barriers are allowed here because we know the GC can't be
// running yet, so they'll be no-ops.
//
//go:yeswritebarrierrec
func mstartm0() {
// Create an extra M for callbacks on threads not created by Go.
if iscgo && !cgoHasExtraM {
cgoHasExtraM = true
newextram()
}
initsig(false)
}
// forEachP calls fn(p) for every P p when p reaches a GC safe point. // forEachP calls fn(p) for every P p when p reaches a GC safe point.
// If a P is currently executing code, this will bring the P to a GC // If a P is currently executing code, this will bring the P to a GC
// safe point and execute fn on that P. If the P is not executing code // safe point and execute fn on that P. If the P is not executing code