mirror of
https://github.com/golang/go
synced 2024-09-30 08:38:40 -06:00
runtime: update timejump function for new timers
Since timers are now on a P, rather than having a G running timerproc, timejump changes to return a P rather than a G. Updates #27707 Change-Id: I3d05af2d664409a0fd906e709fdecbbcbe00b9a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/171880 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
0195a29399
commit
5f92939c90
@ -2451,9 +2451,19 @@ stop:
|
||||
if _g_.m.spinning {
|
||||
throw("findrunnable: netpoll with spinning")
|
||||
}
|
||||
if faketime != 0 {
|
||||
// When using fake time, just poll.
|
||||
delta = 0
|
||||
}
|
||||
list := netpoll(delta) // block until new work is available
|
||||
atomic.Store64(&sched.pollUntil, 0)
|
||||
atomic.Store64(&sched.lastpoll, uint64(nanotime()))
|
||||
if faketime != 0 && list.empty() {
|
||||
// Using fake time and nothing is ready; stop M.
|
||||
// When all M's stop, checkdead will call timejump.
|
||||
stopm()
|
||||
goto top
|
||||
}
|
||||
lock(&sched.lock)
|
||||
_p_ = pidleget()
|
||||
unlock(&sched.lock)
|
||||
@ -4422,7 +4432,8 @@ func checkdead() {
|
||||
}
|
||||
|
||||
// Maybe jump time forward for playground.
|
||||
gp := timejump()
|
||||
if oldTimers {
|
||||
gp := timejumpOld()
|
||||
if gp != nil {
|
||||
casgstatus(gp, _Gwaiting, _Grunnable)
|
||||
globrunqput(gp)
|
||||
@ -4440,6 +4451,26 @@ func checkdead() {
|
||||
notewakeup(&mp.park)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
_p_ := timejump()
|
||||
if _p_ != nil {
|
||||
for pp := &sched.pidle; *pp != 0; pp = &(*pp).ptr().link {
|
||||
if (*pp).ptr() == _p_ {
|
||||
*pp = _p_.link
|
||||
break
|
||||
}
|
||||
}
|
||||
mp := mget()
|
||||
if mp == nil {
|
||||
// There should always be a free M since
|
||||
// nothing is running.
|
||||
throw("checkdead: no m for timer")
|
||||
}
|
||||
mp.nextp.set(_p_)
|
||||
notewakeup(&mp.park)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// There are no goroutines running, so we can look at the P's.
|
||||
for _, _p_ := range allp {
|
||||
|
@ -1125,7 +1125,66 @@ func runOneTimer(pp *p, t *timer, now int64) {
|
||||
f(arg, seq)
|
||||
}
|
||||
|
||||
func timejump() *g {
|
||||
func timejump() *p {
|
||||
if faketime == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Nothing is running, so we can look at all the P's.
|
||||
// Determine a timer bucket with minimum when.
|
||||
var (
|
||||
minT *timer
|
||||
minWhen int64
|
||||
minP *p
|
||||
)
|
||||
for _, pp := range allp {
|
||||
if pp.status != _Pidle && pp.status != _Pdead {
|
||||
throw("non-idle P in timejump")
|
||||
}
|
||||
if len(pp.timers) == 0 {
|
||||
continue
|
||||
}
|
||||
c := pp.adjustTimers
|
||||
for _, t := range pp.timers {
|
||||
switch s := atomic.Load(&t.status); s {
|
||||
case timerWaiting:
|
||||
if minT == nil || t.when < minWhen {
|
||||
minT = t
|
||||
minWhen = t.when
|
||||
minP = pp
|
||||
}
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
if minT == nil || t.nextwhen < minWhen {
|
||||
minT = t
|
||||
minWhen = t.nextwhen
|
||||
minP = pp
|
||||
}
|
||||
if s == timerModifiedEarlier {
|
||||
c--
|
||||
}
|
||||
case timerRunning, timerModifying, timerMoving:
|
||||
badTimer()
|
||||
}
|
||||
// The timers are sorted, so we only have to check
|
||||
// the first timer for each P, unless there are
|
||||
// some timerModifiedEarlier timers. The number
|
||||
// of timerModifiedEarlier timers is in the adjustTimers
|
||||
// field, used to initialize c, above.
|
||||
if c == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if minT == nil || minWhen <= faketime {
|
||||
return nil
|
||||
}
|
||||
|
||||
faketime = minWhen
|
||||
return minP
|
||||
}
|
||||
|
||||
func timejumpOld() *g {
|
||||
if faketime == 0 {
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user