mirror of
https://github.com/golang/go.git
synced 2025-05-18 13:54:40 +00:00
runtime: use timer.lock in runtimer
Continue using timer.lock to simplify timer operations. [This is one CL in a refactoring stack making very small changes in each step, so that any subtle bugs that we miss can be more easily pinpointed to a small change.] Change-Id: I504335a010d6eb4d7d627145b64a896582158406 Reviewed-on: https://go-review.googlesource.com/c/go/+/564129 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
58911599e8
commit
d1e8dc25ff
@ -657,67 +657,57 @@ func checkTimers(pp *p, now int64) (rnow, pollUntil int64, ran bool) {
|
|||||||
//
|
//
|
||||||
//go:systemstack
|
//go:systemstack
|
||||||
func runtimer(pp *p, now int64) int64 {
|
func runtimer(pp *p, now int64) int64 {
|
||||||
for {
|
Redo:
|
||||||
t := pp.timers[0]
|
if len(pp.timers) == 0 {
|
||||||
if t.pp.ptr() != pp {
|
return -1
|
||||||
throw("runtimer: bad p")
|
|
||||||
}
|
|
||||||
switch s := t.status.Load(); s {
|
|
||||||
case timerWaiting:
|
|
||||||
if t.when > now {
|
|
||||||
// Not ready to run.
|
|
||||||
return t.when
|
|
||||||
}
|
|
||||||
|
|
||||||
if !t.status.CompareAndSwap(s, timerLocked) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Note that runOneTimer may temporarily unlock
|
|
||||||
// pp.timersLock.
|
|
||||||
runOneTimer(pp, t, now)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
case timerModified:
|
|
||||||
if !t.status.CompareAndSwap(s, timerLocked) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if t.nextwhen == 0 {
|
|
||||||
dodeltimer0(pp)
|
|
||||||
if !t.status.CompareAndSwap(timerLocked, timerRemoved) {
|
|
||||||
badTimer()
|
|
||||||
}
|
|
||||||
pp.deletedTimers.Add(-1)
|
|
||||||
if len(pp.timers) == 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.when = t.nextwhen
|
|
||||||
dodeltimer0(pp)
|
|
||||||
doaddtimer(pp, t)
|
|
||||||
if !t.status.CompareAndSwap(timerLocked, timerWaiting) {
|
|
||||||
badTimer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case timerLocked:
|
|
||||||
// Wait for modification to complete.
|
|
||||||
osyield()
|
|
||||||
|
|
||||||
case timerRemoved:
|
|
||||||
// Should not see a new or inactive timer on the heap.
|
|
||||||
badTimer()
|
|
||||||
default:
|
|
||||||
badTimer()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
t := pp.timers[0]
|
||||||
|
if t.pp.ptr() != pp {
|
||||||
|
throw("runtimer: bad p")
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.status.Load() == timerWaiting && t.when > now {
|
||||||
|
// Fast path: not ready to run.
|
||||||
|
// The access of t.when is protected by the caller holding
|
||||||
|
// pp.timersLock, even though t itself is unlocked.
|
||||||
|
return t.when
|
||||||
|
}
|
||||||
|
|
||||||
|
status, mp := t.lock()
|
||||||
|
if status == timerModified {
|
||||||
|
dodeltimer0(pp)
|
||||||
|
if t.nextwhen == 0 {
|
||||||
|
status = timerRemoved
|
||||||
|
pp.deletedTimers.Add(-1)
|
||||||
|
} else {
|
||||||
|
t.when = t.nextwhen
|
||||||
|
doaddtimer(pp, t)
|
||||||
|
status = timerWaiting
|
||||||
|
}
|
||||||
|
t.unlock(status, mp)
|
||||||
|
goto Redo
|
||||||
|
}
|
||||||
|
|
||||||
|
if status != timerWaiting {
|
||||||
|
badTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.when > now {
|
||||||
|
// Not ready to run.
|
||||||
|
t.unlock(status, mp)
|
||||||
|
return t.when
|
||||||
|
}
|
||||||
|
|
||||||
|
unlockAndRunTimer(pp, t, now, status, mp)
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// runOneTimer runs a single timer.
|
// unlockAndRunTimer unlocks and runs a single timer.
|
||||||
// The caller must have locked the timers for pp.
|
// The caller must have locked the timers for pp.
|
||||||
// This will temporarily unlock the timers while running the timer function.
|
// This will temporarily unlock the timers while running the timer function.
|
||||||
//
|
//
|
||||||
//go:systemstack
|
//go:systemstack
|
||||||
func runOneTimer(pp *p, t *timer, now int64) {
|
func unlockAndRunTimer(pp *p, t *timer, now int64, status uint32, mp *m) {
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
ppcur := getg().m.p.ptr()
|
ppcur := getg().m.p.ptr()
|
||||||
if ppcur.timerRaceCtx == 0 {
|
if ppcur.timerRaceCtx == 0 {
|
||||||
@ -738,17 +728,14 @@ func runOneTimer(pp *p, t *timer, now int64) {
|
|||||||
t.when = maxWhen
|
t.when = maxWhen
|
||||||
}
|
}
|
||||||
siftdownTimer(pp.timers, 0)
|
siftdownTimer(pp.timers, 0)
|
||||||
if !t.status.CompareAndSwap(timerLocked, timerWaiting) {
|
status = timerWaiting
|
||||||
badTimer()
|
|
||||||
}
|
|
||||||
updateTimer0When(pp)
|
updateTimer0When(pp)
|
||||||
} else {
|
} else {
|
||||||
// Remove from heap.
|
// Remove from heap.
|
||||||
dodeltimer0(pp)
|
dodeltimer0(pp)
|
||||||
if !t.status.CompareAndSwap(timerLocked, timerRemoved) {
|
status = timerRemoved
|
||||||
badTimer()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
t.unlock(status, mp)
|
||||||
|
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
// Temporarily use the current P's racectx for g0.
|
// Temporarily use the current P's racectx for g0.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user