Given a G, there's currently no way to find the channel it's blocking
on. We'll need this information to fix a (probably theoretical) bug in
select and to implement concurrent stack shrinking, so record the
channel in the sudog.
For #12967.
Change-Id: If8fb63a140f1d07175818824d08c0ebeec2bdf66
Reviewed-on: https://go-review.googlesource.com/20035
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
sudog.List.Append(Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
sudog.List.Append(Nod(ODCLFIELD, newname(Lookup("ticket")), typenod(Types[TUINT32])))
sudog.List.Append(Nod(ODCLFIELD, newname(Lookup("waitlink")), typenod(Ptrto(Types[TUINT8]))))
+ sudog.List.Append(Nod(ODCLFIELD, newname(Lookup("c")), typenod(Ptrto(Types[TUINT8]))))
typecheck(&sudog, Etype)
sudog.Type.Noalg = true
sudog.Type.Local = true
mysg.waitlink = nil
mysg.g = gp
mysg.selectdone = nil
+ mysg.c = c
gp.waiting = mysg
gp.param = nil
c.sendq.enqueue(mysg)
if mysg.releasetime > 0 {
blockevent(mysg.releasetime-t0, 2)
}
+ mysg.c = nil
releaseSudog(mysg)
return true
}
gp.waiting = mysg
mysg.g = gp
mysg.selectdone = nil
+ mysg.c = c
gp.param = nil
c.recvq.enqueue(mysg)
goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, 3)
}
closed := gp.param == nil
gp.param = nil
+ mysg.c = nil
releaseSudog(mysg)
return true, !closed
}
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")
// selecttype.
type sudog struct {
g *g
- selectdone *uint32
+ selectdone *uint32 // CAS to 1 to win select race (may point to stack)
next *sudog
prev *sudog
- elem unsafe.Pointer // data element
+ elem unsafe.Pointer // data element (may point to stack)
releasetime int64
ticket uint32
waitlink *sudog // g.waiting list
+ c *hchan // channel
}
type gcstats struct {
sg.releasetime = -1
}
sg.waitlink = gp.waiting
+ sg.c = c
gp.waiting = sg
switch cas.kind {
for sg1 := gp.waiting; sg1 != nil; sg1 = sg1.waitlink {
sg1.selectdone = nil
sg1.elem = nil
+ sg1.c = nil
}
gp.waiting = nil
for i := int(sel.ncase) - 1; i >= 0; i-- {