// runqput 尝试将 g 放到本地可执行队列里。
// 如果 next 为假,runqput 将 g 添加到可运行队列的尾部
// 如果 next 为真,runqput 将 g 添加到 p.runnext 字段
// 如果 run queue 满了,runnext 将 g 放到全局队列里
// runnext 成员中的 goroutine 会被优先调度起来运行
func runqput(_p_ *p, gp *g, next bool) {
if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
// 有其它线程在操作 runnext 成员,需要重试
// 把之前的 runnext 踢到正常的 runq 中
// 原本存放在 runnext 的 gp 放入 runq 的尾部
h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
if t-h < uint32(len(_p_.runq)) {
_p_.runq[t%uint32(len(_p_.runq))].set(gp)
atomic.Store(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
if runqputslow(_p_, gp, h, t) {
// the queue is not full, now the put above must succeed
// 没有成功放入全局队列,说明本地队列没满,重试一下