mirror of
https://github.com/golang/go
synced 2024-11-18 10:04:43 -07:00
runtime: change p.runq from []*g to []guintptr
This eliminates many write barriers in the scheduler code that are unnecessary and will interfere with upcoming changes where the garbage collector will have to invoke run queue functions in contexts that must not have write barriers. Change-Id: I702d0ac99cfd00ffff406e7362917db6a43e7e55 Reviewed-on: https://go-review.googlesource.com/16556 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Austin Clements <austin@google.com>
This commit is contained in:
parent
48155f5440
commit
0ca4488cc1
@ -3064,7 +3064,7 @@ func procresize(nprocs int32) *p {
|
|||||||
for p.runqhead != p.runqtail {
|
for p.runqhead != p.runqtail {
|
||||||
// pop from tail of local queue
|
// pop from tail of local queue
|
||||||
p.runqtail--
|
p.runqtail--
|
||||||
gp := p.runq[p.runqtail%uint32(len(p.runq))]
|
gp := p.runq[p.runqtail%uint32(len(p.runq))].ptr()
|
||||||
// push onto head of global queue
|
// push onto head of global queue
|
||||||
globrunqputhead(gp)
|
globrunqputhead(gp)
|
||||||
}
|
}
|
||||||
@ -3753,7 +3753,7 @@ retry:
|
|||||||
h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
|
h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
|
||||||
t := _p_.runqtail
|
t := _p_.runqtail
|
||||||
if t-h < uint32(len(_p_.runq)) {
|
if t-h < uint32(len(_p_.runq)) {
|
||||||
_p_.runq[t%uint32(len(_p_.runq))] = gp
|
_p_.runq[t%uint32(len(_p_.runq))].set(gp)
|
||||||
atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
|
atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -3776,7 +3776,7 @@ func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
|
|||||||
throw("runqputslow: queue is not full")
|
throw("runqputslow: queue is not full")
|
||||||
}
|
}
|
||||||
for i := uint32(0); i < n; i++ {
|
for i := uint32(0); i < n; i++ {
|
||||||
batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
|
batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr()
|
||||||
}
|
}
|
||||||
if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
|
if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
|
||||||
return false
|
return false
|
||||||
@ -3824,7 +3824,7 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) {
|
|||||||
if t == h {
|
if t == h {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
gp := _p_.runq[h%uint32(len(_p_.runq))]
|
gp := _p_.runq[h%uint32(len(_p_.runq))].ptr()
|
||||||
if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
|
if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
|
||||||
return gp, false
|
return gp, false
|
||||||
}
|
}
|
||||||
@ -3835,7 +3835,7 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) {
|
|||||||
// Batch is a ring buffer starting at batchHead.
|
// Batch is a ring buffer starting at batchHead.
|
||||||
// Returns number of grabbed goroutines.
|
// Returns number of grabbed goroutines.
|
||||||
// Can be executed by any P.
|
// Can be executed by any P.
|
||||||
func runqgrab(_p_ *p, batch *[256]*g, batchHead uint32, stealRunNextG bool) uint32 {
|
func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool) uint32 {
|
||||||
for {
|
for {
|
||||||
h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
|
h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
|
||||||
t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
|
t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
|
||||||
@ -3856,7 +3856,7 @@ func runqgrab(_p_ *p, batch *[256]*g, batchHead uint32, stealRunNextG bool) uint
|
|||||||
if !_p_.runnext.cas(next, 0) {
|
if !_p_.runnext.cas(next, 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
batch[batchHead%uint32(len(batch))] = next.ptr()
|
batch[batchHead%uint32(len(batch))] = next
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3885,7 +3885,7 @@ func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
n--
|
n--
|
||||||
gp := _p_.runq[(t+n)%uint32(len(_p_.runq))]
|
gp := _p_.runq[(t+n)%uint32(len(_p_.runq))].ptr()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return gp
|
return gp
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ type p struct {
|
|||||||
// Queue of runnable goroutines. Accessed without lock.
|
// Queue of runnable goroutines. Accessed without lock.
|
||||||
runqhead uint32
|
runqhead uint32
|
||||||
runqtail uint32
|
runqtail uint32
|
||||||
runq [256]*g
|
runq [256]guintptr
|
||||||
// runnext, if non-nil, is a runnable G that was ready'd by
|
// runnext, if non-nil, is a runnable G that was ready'd by
|
||||||
// the current G and should be run next instead of what's in
|
// the current G and should be run next instead of what's in
|
||||||
// runq if there's time remaining in the running G's time
|
// runq if there's time remaining in the running G's time
|
||||||
|
Loading…
Reference in New Issue
Block a user