sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射
type sudog struct { // 指向的goroutine g *g // 指向前后sudog的指针 next *sudog prev *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 // 作为队列元素的标识 ticket uint32 // 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 bool parent *sudog // semaRoot binary tree waitlink *sudog // g.waiting list or semaRoot waittail *sudog // semaRoot c *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.sudogcache sched.sudogcache = s.next s.next = nil pp.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] = nil pp.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 P pp := mp.p.ptr() // 如果本地缓存满了,就迁移至多一半容量缓存项到中心缓存 if len(pp.sudogcache) == cap(pp.sudogcache) { // Transfer half of local cache to the central cache. var first, last *sudog for len(pp.sudogcache) > cap(pp.sudogcache)/2 { n := len(pp.sudogcache) p := pp.sudogcache[n-1] pp.sudogcache[n-1] = nil pp.sudogcache = pp.sudogcache[:n-1] if first == nil { first = p } else { last.next = p } last = p } lock(&sched.sudoglock) // 将迁移出来的本地缓存链表直接挂到中心缓存中 last.next = sched.sudogcache sched.sudogcache = first unlock(&sched.sudoglock) } // 将释放的sudog添加到本地缓存 pp.sudogcache = append(pp.sudogcache, s) releasem(mp) }
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)