// queue adds s to the blocked goroutines in semaRoot. func(root *semaRoot)queue(addr *uint32, s *sudog, lifo bool) { s.g = getg() //当前的G s.elem = unsafe.Pointer(addr) s.next = nil s.prev = nil
var last *sudog pt := &root.treap for t := *pt; t != nil; t = *pt { //bst搜索 if t.elem == unsafe.Pointer(addr) { // Already have addr in list. //lifo:插到head if lifo { // Substitute s in t's place in treap. //old: t->t1->t2 //new s->t->t1 *pt = s s.ticket = t.ticket s.acquiretime = t.acquiretime s.parent = t.parent s.prev = t.prev s.next = t.next if s.prev != nil { s.prev.parent = s } if s.next != nil { s.next.parent = s } // Add t first in s's wait list. s.waitlink = t s.waittail = t.waittail if s.waittail == nil { s.waittail = t } t.parent = nil t.prev = nil t.next = nil t.waittail = nil //fifo:插到tail } else { // Add s to end of t's wait list. if t.waittail == nil { t.waitlink = s } else { t.waittail.waitlink = s } //只更新了链表第一个元素指向的tail,其他元素的tail指针好像没有同步 t.waittail = s s.waitlink = nil } return } last = t ifuintptr(unsafe.Pointer(addr)) < uintptr(t.elem) { pt = &t.prev } else { pt = &t.next } }
// Add s as new leaf in tree of unique addrs. // The balanced tree is a treap using ticket as the random heap priority. // That is, it is a binary tree ordered according to the elem addresses, // but then among the space of possible binary trees respecting those // addresses, it is kept balanced on average by maintaining a heap ordering // on the ticket: s.ticket <= both s.prev.ticket and s.next.ticket. // https://en.wikipedia.org/wiki/Treap // https://faculty.washington.edu/aragon/pubs/rst89.pdf // // s.ticket compared with zero in couple of places, therefore set lowest bit. // It will not affect treap's quality noticeably. //更新s的优先级,平衡整棵树 s.ticket = fastrand() | 1 s.parent = last *pt = s
// Rotate up into tree according to ticket (priority). for s.parent != nil && s.parent.ticket > s.ticket { //当前节点是左节点就右旋,右节点则左旋 //这里看样子用的是小顶堆 if s.parent.prev == s { root.rotateRight(s.parent) } else { if s.parent.next != s { panic("semaRoot queue") } root.rotateLeft(s.parent) } } }
// dequeue searches for and finds the first goroutine // in semaRoot blocked on addr. // If the sudog was being profiled, dequeue returns the time // at which it was woken up as now. Otherwise now is 0. func(root *semaRoot)dequeue(addr *uint32)(found *sudog, now int64) { ps := &root.treap s := *ps for ; s != nil; s = *ps { if s.elem == unsafe.Pointer(addr) { goto Found } //bst搜索 ifuintptr(unsafe.Pointer(addr)) < uintptr(s.elem) { ps = &s.prev } else { ps = &s.next } } returnnil, 0
Found: //s:对应addr的节点 now = int64(0) if s.acquiretime != 0 { now = cputicks() } if t := s.waitlink; t != nil { // Substitute t, also waiting on addr, for s in root tree of unique addrs. //链表有2个以上元素,把第2个元素挪到treap下,删掉s *ps = t t.ticket = s.ticket t.parent = s.parent t.prev = s.prev if t.prev != nil { t.prev.parent = t } t.next = s.next if t.next != nil { t.next.parent = t } if t.waitlink != nil { t.waittail = s.waittail } else { t.waittail = nil } t.acquiretime = now s.waitlink = nil s.waittail = nil } else { //链表只有1个元素,这个元素s有子节点才考虑旋转,将这个元素删掉 // Rotate s down to be leaf of tree for removal, respecting priorities. for s.next != nil || s.prev != nil { //只有右节点,或者有2个节点但是右节点大于左节点,都右旋 if s.next == nil || s.prev != nil && s.prev.ticket < s.next.ticket { root.rotateRight(s) } else { root.rotateLeft(s) } } // Remove s, now a leaf. if s.parent != nil { if s.parent.prev == s { s.parent.prev = nil } else { s.parent.next = nil } } else { root.treap = nil } } s.parent = nil s.elem = nil s.next = nil s.prev = nil s.ticket = 0 return s, now }
// rotateLeft rotates the tree rooted at node x. // turning (x a (y b c)) into (y (x a b) c). func(root *semaRoot)rotateLeft(x *sudog) { // p -> (x a (y b c)) p := x.parent y := x.next b := y.prev
y.prev = x x.parent = y x.next = b if b != nil { b.parent = x }
y.parent = p if p == nil { root.treap = y } elseif p.prev == x { p.prev = y } else { if p.next != x { throw("semaRoot rotateLeft") } p.next = y } }
// rotateRight rotates the tree rooted at node y. // turning (y (x a b) c) into (x a (y b c)). func(root *semaRoot)rotateRight(y *sudog) { // p -> (y (x a b) c) p := y.parent x := y.prev b := x.next
x.next = y y.parent = x y.prev = b if b != nil { b.parent = y }
x.parent = p if p == nil { root.treap = x } elseif p.prev == y { p.prev = x } else { if p.next != y { throw("semaRoot rotateRight") } p.next = x } }