recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
- lock mutex
+
+ // lock protects all fields in hchan, as well as several
+ // fields in sudogs blocked on this channel.
+ lock mutex
}
type waitq struct {
c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
}
}
- unlockf()
if sg.elem != nil {
sendDirect(c.elemtype, sg, ep)
sg.elem = nil
}
gp := sg.g
+ unlockf()
gp.param = unsafe.Pointer(sg)
if sg.releasetime != 0 {
sg.releasetime = cputicks()
if raceenabled {
racesync(c, sg)
}
- unlockf()
if ep != nil {
// copy data from sender
// ep points to our own stack or heap, so nothing
c.recvx = 0
}
c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
- unlockf()
}
sg.elem = nil
gp := sg.g
+ unlockf()
gp.param = unsafe.Pointer(sg)
if sg.releasetime != 0 {
sg.releasetime = cputicks()
// Changes here must also be made in src/cmd/compile/internal/gc/select.go's
// selecttype.
type sudog struct {
- g *g
- selectdone *uint32 // CAS to 1 to win select race (may point to stack)
- next *sudog
- prev *sudog
- elem unsafe.Pointer // data element (may point to stack)
+ // The following fields are protected by the hchan.lock of the
+ // channel this sudog is blocking on.
+
+ g *g
+ selectdone *uint32 // CAS to 1 to win select race (may point to stack)
+ next *sudog
+ prev *sudog
+ elem unsafe.Pointer // data element (may point to stack)
+
+ // The following fields are never accessed concurrently.
+ // waitlink is only accessed by g.
+
releasetime int64
ticket uint32
waitlink *sudog // g.waiting list