mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: put g.waiting list in lock order
Currently the g.waiting list created by a select is in poll order. However, nothing depends on this, and we're going to need access to the channel lock order in other places shortly, so modify select to put the waiting list in channel lock order. For #12967. Change-Id: If0d38816216ecbb37a36624d9b25dd96e0a775ec Reviewed-on: https://go-review.googlesource.com/20037 Reviewed-by: Rick Hudson <rlh@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Austin Clements <austin@google.com>
This commit is contained in:
parent
26594c3dfd
commit
005140a77e
2 changed files with 12 additions and 9 deletions
|
|
@ -314,7 +314,7 @@ type g struct {
|
||||||
gopc uintptr // pc of go statement that created this goroutine
|
gopc uintptr // pc of go statement that created this goroutine
|
||||||
startpc uintptr // pc of goroutine function
|
startpc uintptr // pc of goroutine function
|
||||||
racectx uintptr
|
racectx uintptr
|
||||||
waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr)
|
waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
|
||||||
|
|
||||||
// Per-G gcController state
|
// Per-G gcController state
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,7 @@ func selectgoImpl(sel *hselect) (uintptr, uint16) {
|
||||||
sglist *sudog
|
sglist *sudog
|
||||||
sgnext *sudog
|
sgnext *sudog
|
||||||
qp unsafe.Pointer
|
qp unsafe.Pointer
|
||||||
|
nextp **sudog
|
||||||
)
|
)
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
|
|
@ -374,8 +375,9 @@ loop:
|
||||||
if gp.waiting != nil {
|
if gp.waiting != nil {
|
||||||
throw("gp.waiting != nil")
|
throw("gp.waiting != nil")
|
||||||
}
|
}
|
||||||
for i := 0; i < int(sel.ncase); i++ {
|
nextp = &gp.waiting
|
||||||
cas = &scases[pollorder[i]]
|
for _, casei := range lockorder {
|
||||||
|
cas = &scases[casei]
|
||||||
c = cas.c
|
c = cas.c
|
||||||
sg := acquireSudog()
|
sg := acquireSudog()
|
||||||
sg.g = gp
|
sg.g = gp
|
||||||
|
|
@ -388,9 +390,10 @@ loop:
|
||||||
if t0 != 0 {
|
if t0 != 0 {
|
||||||
sg.releasetime = -1
|
sg.releasetime = -1
|
||||||
}
|
}
|
||||||
sg.waitlink = gp.waiting
|
|
||||||
sg.c = c
|
sg.c = c
|
||||||
gp.waiting = sg
|
// Construct waiting list in lock order.
|
||||||
|
*nextp = sg
|
||||||
|
nextp = &sg.waitlink
|
||||||
|
|
||||||
switch cas.kind {
|
switch cas.kind {
|
||||||
case caseRecv:
|
case caseRecv:
|
||||||
|
|
@ -413,8 +416,7 @@ loop:
|
||||||
// pass 3 - dequeue from unsuccessful chans
|
// pass 3 - dequeue from unsuccessful chans
|
||||||
// otherwise they stack up on quiet channels
|
// otherwise they stack up on quiet channels
|
||||||
// record the successful case, if any.
|
// record the successful case, if any.
|
||||||
// We singly-linked up the SudoGs in case order, so when
|
// We singly-linked up the SudoGs in lock order.
|
||||||
// iterating through the linked list they are in reverse order.
|
|
||||||
cas = nil
|
cas = nil
|
||||||
sglist = gp.waiting
|
sglist = gp.waiting
|
||||||
// Clear all elem before unlinking from gp.waiting.
|
// Clear all elem before unlinking from gp.waiting.
|
||||||
|
|
@ -424,8 +426,9 @@ loop:
|
||||||
sg1.c = nil
|
sg1.c = nil
|
||||||
}
|
}
|
||||||
gp.waiting = nil
|
gp.waiting = nil
|
||||||
for i := int(sel.ncase) - 1; i >= 0; i-- {
|
|
||||||
k = &scases[pollorder[i]]
|
for _, casei := range lockorder {
|
||||||
|
k = &scases[casei]
|
||||||
if sglist.releasetime > 0 {
|
if sglist.releasetime > 0 {
|
||||||
k.releasetime = sglist.releasetime
|
k.releasetime = sglist.releasetime
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue