3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
|
func goschedImpl(gp *g) {
// readgstatus(gp) -> atomic.Load(&gp.atomicstatus)
// 原子获取 user goroutine 的状态
status := readgstatus(gp)
// 判断 user goroutine 状态
if status&^_Gscan != _Grunning {
dumpgstatus(gp)
throw("bad g status")
}
// 当前 user goroutine 即将被挂起,需要修改状态
// _Grunning: goroutine可能正在运行用户代码,它的栈归自己所有。
// _Grunnable:goroutine应该在某个runq中,当前并没有在运行用户代码,它的栈不归自己所有。
casgstatus(gp, _Grunning, _Grunnable)
// 设置当前m.curg = nil, gp.m = nil 解除m与g之前的绑定关系
dropg()
lock(&sched.lock)
// 把gp放入sched的全局运行队列runq
globrunqput(gp)
unlock(&sched.lock)
// 在schedule函数中会判断 m.locks != 0 判断
// 因此当前M还存在锁情况下不要让出
schedule() // 进入新一轮调度
}
|