type g struct { stack stack //棧,兩個能容納任何變量地址的變量 stackguard0 uintptr // offset known to liblink stackguard1 uintptr // offset known to liblink _panic *_panic // innermost panic - offset known to liblink _defer *_defer // innermost defer m *m // current m; offset known to arm liblink sched gobuf //存放g上下文信息,g被中止調度時,會將上線文信息存在這裏,喚醒後可繼續調度 syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc stktopsp uintptr // expected sp at top of stack, to check in traceback param unsafe.Pointer // passed parameter on wakeup atomicstatus uint32 stackLock uint32 // sigprof/scang lock; TODO: fold in to atomicstatus goid int64 //就像線程有id,g也有id waitsince int64 // approx time when the g become blocked waitreason string // if status==Gwaiting schedlink guintptr //指向另外一個G,全局G就是經過這個字段連在一塊兒的 preempt bool // preemption signal, duplicates stackguard0 = stackpreempt paniconfault bool // panic (instead of crash) on unexpected fault address preemptscan bool // preempted g does scan for gc gcscandone bool // g has scanned stack; protected by _Gscan bit in status gcscanvalid bool // false at start of gc cycle, true if G has not run since last scan; TODO: remove? throwsplit bool // must not split stack raceignore int8 // ignore race detection events sysblocktraced bool // StartTrace has emitted EvGoInSyscall about this goroutine sysexitticks int64 // cputicks when syscall has returned (for tracing) traceseq uint64 // trace event sequencer tracelastp puintptr // last P emitted an event for this goroutine lockedm *m sig uint32 writebuf []byte sigcode0 uintptr sigcode1 uintptr sigpc uintptr gopc uintptr // pc of go statement that created this goroutine startpc uintptr // 被執行的函數 racectx uintptr waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order cgoCtxt []uintptr // cgo traceback context labels unsafe.Pointer // profiler labels timer *timer // cached timer for time.Sleep gcAssistBytes int64 }
type p struct { lock mutex id int32 status uint32 // one of pidle/prunning/... link puintptr schedtick uint32 // incremented on every scheduler call syscalltick uint32 // incremented on every system call sysmontick sysmontick // last tick observed by sysmon m muintptr // back-link to associated m (nil if idle) mcache *mcache //方便小對象的分配,一個p一個,不須要加鎖 racectx uintptr deferpool [5][]*_defer // pool of available defer structs of different sizes (see panic.go) deferpoolbuf [5][32]*_defer // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen. goidcache uint64 goidcacheend uint64 // Queue of runnable goroutines. Accessed without lock. runqhead uint32 //隊頭 runqtail uint32 //隊尾 runq [256]guintptr //G循環隊列 runnext guintptr //高優先級的G,會先執行 // Available G's (status == Gdead) gfree *g //空閒G列表 gfreecnt int32 //空閒G數量 sudogcache []*sudog sudogbuf [128]*sudog tracebuf traceBufPtr // traceSweep indicates the sweep events should be traced. // This is used to defer the sweep start event until a span // has actually been swept. traceSweep bool // traceSwept and traceReclaimed track the number of bytes // swept and reclaimed by sweeping in the current sweep loop. traceSwept, traceReclaimed uintptr palloc persistentAlloc // per-P to avoid mutex // Per-P GC state gcAssistTime int64 // Nanoseconds in assistAlloc gcBgMarkWorker guintptr gcMarkWorkerMode gcMarkWorkerMode gcw gcWork runSafePointFn uint32 // if 1, run sched.safePointFn at next safe point pad [sys.CacheLineSize]byte }
// goexit continuation on g0. func goexit0(gp *g) { _g_ := getg() casgstatus(gp, _Grunning, _Gdead) dropg() _g_.m.locked = 0 gfput(_g_.m.p.ptr(), gp) schedule() }
TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8 LEAQ 8(SP), SI // argv MOVQ 0(SP), DI // argc MOVQ $main(SB), AX JMP AX TEXT main(SB),NOSPLIT,$-8 MOVQ $runtime·rt0_go(SB), AX JMP AX TEXT runtime·rt0_go(SB),NOSPLIT,$0 LEAQ runtime·g0(SB), CX MOVQ CX, g(BX) LEAQ runtime·m0(SB), AX // save m->g0 = g0 MOVQ CX, m_g0(AX) // save m0 to g0->m MOVQ AX, g_m(CX) CALL runtime·args(SB) CALL runtime·osinit(SB) //獲取cpu數量,頁大小 CALL runtime·schedinit(SB) //調度初始化 // create a new goroutine to start program MOVQ $runtime·mainPC(SB), AX // entry,執行runtime.main CALL runtime·newproc(SB) // start this M CALL runtime·mstart(SB) MOVL $0xf1, 0xf1 // crash RET DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) GLOBL runtime·mainPC(SB),RODATA,$8 package runtime // The main goroutine. func main() { // Allow newproc to start new Ms. mainStarted = true gcenable() fn := main_init // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime fn() fn = main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime fn() exit(0) }