aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/proc.go')
-rw-r--r--src/runtime/proc.go30
1 files 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