// mstart is the entry-point for new Ms. // // 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 funcmstart() { _g_ := getg()
//低位判断 osStack := _g_.stack.lo == 0 if osStack { // Initialize stack bounds from system stack. // Cgo may have left stack size in stack.hi. // minit may update the stack bounds. size := _g_.stack.hi if size == 0 { size = 8192 * sys.StackGuardMultiplier } //g0的stack空间是真的大 _g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size))) _g_.stack.lo = _g_.stack.hi - size + 1024 } // Initialize stack guard so that we can start calling regular // Go code. _g_.stackguard0 = _g_.stack.lo + _StackGuard // This is the g0, so we can also call go:systemstack // functions, which check stackguard1. _g_.stackguard1 = _g_.stackguard0 mstart1()
// Exit this thread. switch GOOS { case"windows", "solaris", "illumos", "plan9", "darwin", "aix": // Windows, Solaris, illumos, Darwin, AIX and Plan 9 always system-allocate // the stack, but put it in _g_.stack before mstart, // so the logic above hasn't set osStack yet. osStack = true } mexit(osStack) }
//启动非g0就崩盘了 if _g_ != _g_.m.g0 { throw("bad runtime·mstart") }
//初始化 // Record the caller for use as the top of stack in mcall and // for terminating the thread. // We're never coming back to mstart1 after we call schedule, // so other calls can reuse the current frame. save(getcallerpc(), getcallersp()) asminit() minit()
// Install signal handlers; after minit so that minit can // prepare the thread to be able to handle the signals. //m0启动 if _g_.m == &m0 { mstartm0() }
// mstart1的具体实现,仅run在m0上 // 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 funcmstartm0() { // Create an extra M for callbacks on threads not created by Go. // An extra M is also needed on Windows for callbacks created by // syscall.NewCallback. See issue #6751 for details. //windows下需要一个额外的M if (iscgo || GOOS == "windows") && !cgoHasExtraM { cgoHasExtraM = true newextram() } //初始化信号量,用于后续调度 initsig(false) }