From a212083eea9ee745a3c8e7befb7bba4f4c95396c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 15 Jun 2017 15:02:32 -0400 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall Reviewed-by: Rick Hudson --- src/runtime/proc.go | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 6b96e97887..0fa0cf965e 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1137,7 +1137,15 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 { } // 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:nowritebarrierrec func mstart() { _g_ := getg() @@ -1176,12 +1184,7 @@ func mstart1() { // Install signal handlers; after minit so that minit can // prepare the thread to be able to handle the signals. if _g_.m == &m0 { - // Create an extra M for callbacks on threads not created by Go. - if iscgo && !cgoHasExtraM { - cgoHasExtraM = true - newextram() - } - initsig(false) + mstartm0() } if fn := _g_.m.mstartfn; fn != nil { @@ -1198,6 +1201,21 @@ func mstart1() { 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. // 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 -- 2.48.1