sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射
type sudog struct {// 指向的goroutineg *g// 指向前后sudog的指针next *sudogprev *sudog// 指向数据elem unsafe.Pointer // data element (may point to stack)// The following fields are never accessed concurrently.// For channels, waitlink is only accessed by g.// For semaphores, all fields (including the ones above)// are only accessed when holding a semaRoot lock.// 获取时间acquiretime int64// 释放时间releasetime int64// 作为队列元素的标识ticketuint32// isSelect indicates g is participating in a select, so// g.selectDone must be CAS'd to win the wake-up race.isSelect bool// success indicates whether communication over channel c// succeeded. It is true if the goroutine was awoken because a// value was delivered over channel c, and false if awoken// because c was closed.success boolparent *sudog // semaRoot binary treewaitlink *sudog // g.waiting list or semaRootwaittail *sudog // semaRootc*hchan // channel}
acquireSudog()
func acquireSudog() *sudog {// 增加m的锁,防止垃圾回收在此期间被调用mp := acquirem()pp := mp.p.ptr() // 如果本地缓存为空if len(pp.sudogcache) == 0 {lock(&sched.sudoglock)// 从中心缓存迁移至多一半本地缓存容量的缓存项到本地缓存for len(pp.sudogcache) < cap(pp.sudogcache)/2 && sched.sudogcache != nil {s := sched.sudogcachesched.sudogcache = s.nexts.next = nilpp.sudogcache = append(pp.sudogcache, s)}unlock(&sched.sudoglock)// 若本地缓存仍为空,则新建缓存项if len(pp.sudogcache) == 0 {pp.sudogcache = append(pp.sudogcache, new(sudog))}}// 从本地缓存中取出最后一个缓存项返回n := len(pp.sudogcache)s := pp.sudogcache[n-1]pp.sudogcache[n-1] = nilpp.sudogcache = pp.sudogcache[:n-1]if s.elem != nil {throw("acquireSudog: found s.elem != nil in cache")}// 减少m的锁,允许垃圾回收调用releasem(mp)return s}
releaseSudog()
func releaseSudog(s *sudog) {// 判断sudog各项数据、状态是否正确if s.elem != nil {throw("runtime: sudog with non-nil elem")}if s.isSelect {throw("runtime: sudog with non-false isSelect")}if s.next != nil {throw("runtime: sudog with non-nil next")}if s.prev != nil {throw("runtime: sudog with non-nil prev")}if s.waitlink != nil {throw("runtime: sudog with non-nil waitlink")}if s.c != nil {throw("runtime: sudog with non-nil c")}gp := getg()if gp.param != nil {throw("runtime: releaseSudog with non-nil gp.param")}mp := acquirem() // avoid rescheduling to another Ppp := mp.p.ptr()// 如果本地缓存满了,就迁移至多一半容量缓存项到中心缓存if len(pp.sudogcache) == cap(pp.sudogcache) {// Transfer half of local cache to the central cache.var first, last *sudogfor len(pp.sudogcache) > cap(pp.sudogcache)/2 {n := len(pp.sudogcache)p := pp.sudogcache[n-1]pp.sudogcache[n-1] = nilpp.sudogcache = pp.sudogcache[:n-1]if first == nil {first = p} else {last.next = p}last = p}lock(&sched.sudoglock)// 将迁移出来的本地缓存链表直接挂到中心缓存中last.next = sched.sudogcachesched.sudogcache = firstunlock(&sched.sudoglock)}// 将释放的sudog添加到本地缓存pp.sudogcache = append(pp.sudogcache, s)releasem(mp)}