mirror of
https://github.com/golang/go
synced 2024-11-19 07:04:43 -07:00
runtime: record channel in sudog
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>
This commit is contained in:
parent
d7cedc4b74
commit
e4a95b6343
@ -331,6 +331,7 @@ func selecttype(size int32) *Type {
|
||||
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
|
||||
|
@ -209,6 +209,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
||||
mysg.waitlink = nil
|
||||
mysg.g = gp
|
||||
mysg.selectdone = nil
|
||||
mysg.c = c
|
||||
gp.waiting = mysg
|
||||
gp.param = nil
|
||||
c.sendq.enqueue(mysg)
|
||||
@ -229,6 +230,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
||||
if mysg.releasetime > 0 {
|
||||
blockevent(mysg.releasetime-t0, 2)
|
||||
}
|
||||
mysg.c = nil
|
||||
releaseSudog(mysg)
|
||||
return true
|
||||
}
|
||||
@ -469,6 +471,7 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
|
||||
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)
|
||||
@ -483,6 +486,7 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
|
||||
}
|
||||
closed := gp.param == nil
|
||||
gp.param = nil
|
||||
mysg.c = nil
|
||||
releaseSudog(mysg)
|
||||
return true, !closed
|
||||
}
|
||||
|
@ -329,6 +329,9 @@ func releaseSudog(s *sudog) {
|
||||
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")
|
||||
|
@ -215,13 +215,14 @@ type gobuf struct {
|
||||
// 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 {
|
||||
|
@ -385,6 +385,7 @@ loop:
|
||||
sg.releasetime = -1
|
||||
}
|
||||
sg.waitlink = gp.waiting
|
||||
sg.c = c
|
||||
gp.waiting = sg
|
||||
|
||||
switch cas.kind {
|
||||
@ -416,6 +417,7 @@ loop:
|
||||
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-- {
|
||||
|
Loading…
Reference in New Issue
Block a user