Open gh-liu opened 5 months ago
go version go1.22.2 linux/amd64
G 是被调度的对象,有状态、栈
src/runtime/runtime2.go:18
// _Grunnable: 创建一个可运行的 G func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g {} // _Grunnable -> _Grunning: 将G调度在M上运行 func execute(gp *g, inheritTime bool) {} // _Grunning -> _Grunnable: 当前 G 让出当前 CPU,允许其他 G 使用 func goyield() {} // 调用 goyield_m func goyield_m(gp *g) {} // _Grunning -> _Gdead: G 表示的任务已经完成 // // 每个 G 的调用栈都构造得像是 goexit 调用了该 G 的入口函数, // 因此当入口函数返回时,它会返回到 goexit, // goexit 会调用 goexit1 来执行实际的退出操作 func goexit(neverCallThisFunction) func goexit1() {} // 调用 goexit0 func goexit0(gp *g) {} // 调用 gdestroy func gdestroy(gp *g) {} // _Grunning -> _Gdead // _Grunning -> _Gsyscall: 执行 G 的时候,进入系统调用状态 // // 此时 G 不在使用 CPU 资源 func entersyscall() {} // 调用 reentersyscall func reentersyscall(pc, sp uintptr) {} // func entersyscallblock() {} // 同上,但是进入了一个阻塞的系统调用 // _Gsyscall -> _Grunning: // _Gsyscall -> _Grunnable: // // 退出系统调用状态: // 调用 exitsyscallfast 为true,则 _Gsyscall -> _Grunning // 否则调用 exitsyscall0,则 _Gsyscall -> _Grunnable func exitsyscall() {} // _Grunning -> _Gwaiting: 将 G 设置为等待状态 func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason waitReason, traceReason traceBlockReason, traceskip int) {} // 调用 park_m func park_m(gp *g) {} // _Grunning -> _Gwaiting // _Gwaiting -> _Grunnable: 将 G 设置为可运行状态 func goready(gp *g, traceskip int) {} // 调用 ready func ready(gp *g, traceskip int, next bool) {}
--- title: G status --- stateDiagram-v2 direction LR gidle : _Gidle grunable: _Grunnable grunning: _Grunning gsyscall: _Gsyscall gwaiting: _Gwaiting gdead : _Gdead [*] --> gidle gdead --> [*] gidle --> grunable: newproc1 grunable --> grunning: execute grunning --> grunable: goyield grunning --> gsyscall: entersyscall/entersyscallblock state gsyscall_state <<choice>> gsyscall --> gsyscall_state gsyscall_state --> grunning: exitsyscall,exitsyscallfast gsyscall_state --> grunable: exitsyscall,exitsyscall0 grunning --> gwaiting: gopark gwaiting --> grunable: goready grunning --> gdead: goexit
P是逻辑CPU,主要保存着可执行的G队列
src/runtime/runtime2.go:110
// _Pidle: // // 所有的 P 被设置为 _Pidle 状态 func procresize(nprocs int32) *p {}
// _Pidle -> _Prunning: // // 将 P 和 M 绑定,运行 G 或调度器 func acquirep(pp p) {} // 调用 wirep func wirep(pp p) {} // pp.status = _Prunning
// _Prunning -> _Pidle: // // 将 P 和 M 解绑 func releasep() p {} // 调用 releasepNoTrace func releasepNoTrace() p {} // pp.status = _Pidle
// _Pdead func procresize(nprocs int32) p {} // 重新设置 P 数量时,如果少于原 P 的数量,多余的 P 调用 destroy func (pp p) destroy() {} // pp.status = _Pdead
// _Psyscall // // P 关联了一个进行系统调用的M,也就是没有在运行G,此时可能被其他M窃取的 func entersyscall() {} // atomic.Store(&pp.status, _Psyscall)
```mermaid --- title: P status --- stateDiagram-v2 pidle : _Pidle prunning: _Prunning psyscall: _Psyscall pdead : _Pdead pidle --> prunning prunning --> pidle prunning --> psyscall
M 是OS线程,执行代码,必须绑定一个P才能获取到G进行执行
running/spinning: 运行状态或自旋状态
// 运行M: 新建M或唤醒M // 新建M func startm(pp *p, spinning, lockheld bool) {} func newm(fn func(), pp *p, id int64) {} // 调用 newosproc, 不同`OS`不同实现 func newosproc(mp *m) {} // 唤醒M func wakep() {} // 调用 startm func startm(pp *p, spinning, lockheld bool) {} // 调用 mget func mget() *m {} // 自旋M func (mp *m) becomeSpinning() {} // 从自旋中恢复 func resetspinning() {} // 休眠 M // M 没有 G 可以执行,也不是自旋状态,进入休眠状态 func stopm() {} // 调用 mput func mput(mp *m) {} TODO 状态图
GMP
G
status
P
status
// _Pidle: // // 所有的 P 被设置为 _Pidle 状态 func procresize(nprocs int32) *p {}
// _Pidle -> _Prunning: // // 将 P 和 M 绑定,运行 G 或调度器 func acquirep(pp p) {} // 调用 wirep func wirep(pp p) {} // pp.status = _Prunning
// _Prunning -> _Pidle: // // 将 P 和 M 解绑 func releasep() p {} // 调用 releasepNoTrace func releasepNoTrace() p {} // pp.status = _Pidle
// _Pdead func procresize(nprocs int32) p {} // 重新设置 P 数量时,如果少于原 P 的数量,多余的 P 调用 destroy func (pp p) destroy() {} // pp.status = _Pdead
// _Psyscall // // P 关联了一个进行系统调用的M,也就是没有在运行G,此时可能被其他M窃取的 func entersyscall() {} // atomic.Store(&pp.status, _Psyscall)
M
status