// The bootstrap sequence is:
//
// call osinit
// call schedinit
// make & queue new G to run runtime·main(put g in a runnable queue)
// call runtime·mstart (this calls shedule() and The new G get scheduled and calls runtime·main.)
/usr/local/go/src/runtime/asm_amd64.s (golang.design/go-question…)
TEXT runtime·rt0_go(SB),NOSPLIT,$0
//关联m0和g0
m0.g0 = &g0
g0.m = &m0
// 初始化系统核心数
CALL runtime·osinit(SB)
// 调度器初始化
CALL runtime·schedinit(SB)
// create a new goroutine to start program
MOVQ $runtime·mainPC(SB), AX // entry
//mainPC is a function value for runtime.main, to be passed to newproc.
PUSHQ AX
CALL runtime·newproc(SB)
//newproc:Create a new g running fn. put g on the local runnable queue.
//所以这儿是创建了一个g来运行runtime.main
POPQ AX
// start this M
CALL runtime·mstart(SB)
CALL runtime·abort(SB) // mstart should never return
RET
osint
ncpu = getproccount()
physHugePageSize = getHugePageSize()
schedinit
--->各种lockInit
--->sched.maxmcount = 10000
--->stackinit()//stackpool,stackLarge 的 mSpanList 初始化
--->mallocinit()
--->goargs()、goenvs()、parsedebugvars()
--->gcinit()//初始化 gcPercent , GC pacer state
--->procresize(procs)//创建 GOMAXPROCS or ncpu 个 p
runtime·mstart
mstart0
--->Initialize stack bounds (if osStack)//8192 byte
--->Initialize stack guard
--->调用mstart1()
--->mexit(osStack)
mstart1
--->minit(), Called to initialize a new m ,including the bootstrap m,主要调用 minitSignalStack.
--->mstartm0(),Install signal handlers (if g.m == &m0)
--->执行 g.m.mstartfn,mstartfn有sysmon和templateThread
--->acquirep(g.m.nextp.ptr()),Associate p and the current m.(if g.m != &m0)
--->schedule() //One round of scheduler: find a runnable goroutine and execute it. Never returns.
runtime·main
--->设置maxstacksize,maxstackceiling//Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
--->newm(sysmon, nil, -1)// 在systemstack中创建监控线程
--->doInit(&runtime_inittask)//runtime 包初始化
--->gcenable()//go bgsweep(c), go bgscavenge(c)
--->doInit(&main_inittask)//main 包初始化
--->调用main.mian
--->exit(0)//退出进程
sysmon
在for循环里面执行:
--->sleep 20us - 10ms
--->poll network if not polled for more than 10ms, non-blocking // netpoll checks for ready network connections. // Returns list of goroutines that become runnable. // add these goroutines to some run queue
--->scavenge.sysmonWake!=0时 wakeScavenger //add scavenge.g to some run queue
--->Preempt G if it's running for too long && Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
--->check if we need to force a GC //add forcegc.g to some run queue, 由 runtime.forcegcperiod 变量控制,默认为2 分钟
preemptone
// Every call in a goroutine checks for stack overflow by
// comparing the current stack pointer to gp->stackguard0.
// Setting gp->stackguard0 to StackPreempt folds
// preemption into the normal stack overflow check.
gp.stackguard0 = stackPreempt
handoffp
retake 调用 handoffp // Hands off P from syscall or locked M.
handoffp 里面主要调用 startm
startm(_p_, false)//`Schedules some M to run the p (creates an M if necessary).
injectglist
// injectglist adds each runnable G on the list to some run queue,
// and clears glist. If there is no current P, they are added to the
// global queue, and up to npidle M's are started to run them.
// Otherwise, for each idle P, this adds a G to the global queue
// and starts an M. Any remaining G's are added to the current P's
// local run queue.
// This may temporarily acquire sched.lock.
// Can run concurrently with GC.
func injectglist(glist *gList) {
...
}