1
0
mirror of https://github.com/golang/go synced 2024-11-26 20:31:25 -07: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:
Austin Clements 2016-02-16 11:06:00 -05:00
parent 26594c3dfd
commit 005140a77e
2 changed files with 12 additions and 9 deletions

View File

@ -314,7 +314,7 @@ type g struct {
gopc uintptr // pc of go statement that created this goroutine
startpc uintptr // pc of goroutine function
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

View File

@ -319,6 +319,7 @@ func selectgoImpl(sel *hselect) (uintptr, uint16) {
sglist *sudog
sgnext *sudog
qp unsafe.Pointer
nextp **sudog
)
loop:
@ -374,8 +375,9 @@ loop:
if gp.waiting != nil {
throw("gp.waiting != nil")
}
for i := 0; i < int(sel.ncase); i++ {
cas = &scases[pollorder[i]]
nextp = &gp.waiting
for _, casei := range lockorder {
cas = &scases[casei]
c = cas.c
sg := acquireSudog()
sg.g = gp
@ -388,9 +390,10 @@ loop:
if t0 != 0 {
sg.releasetime = -1
}
sg.waitlink = gp.waiting
sg.c = c
gp.waiting = sg
// Construct waiting list in lock order.
*nextp = sg
nextp = &sg.waitlink
switch cas.kind {
case caseRecv:
@ -413,8 +416,7 @@ loop:
// pass 3 - dequeue from unsuccessful chans
// otherwise they stack up on quiet channels
// record the successful case, if any.
// We singly-linked up the SudoGs in case order, so when
// iterating through the linked list they are in reverse order.
// We singly-linked up the SudoGs in lock order.
cas = nil
sglist = gp.waiting
// Clear all elem before unlinking from gp.waiting.
@ -424,8 +426,9 @@ loop:
sg1.c = 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 {
k.releasetime = sglist.releasetime
}