mirror of https://github.com/golang/go.git
runtime: merge timerModifiedEarlier and timerModifierLater
Nothing actually needs to know the difference between these two states, so merge them. This is part of a larger simplification of the state set. [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: Ia30699ac92e66467773942e7df1fb21470a6e51a Reviewed-on: https://go-review.googlesource.com/c/go/+/564119 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
4a3c3ec996
commit
b2bd7ebafc
|
|
@ -72,8 +72,7 @@ type timer struct {
|
|||
//
|
||||
// deltimer:
|
||||
// timerWaiting -> timerModifying -> timerDeleted
|
||||
// timerModifiedEarlier -> timerModifying -> timerDeleted
|
||||
// timerModifiedLater -> timerModifying -> timerDeleted
|
||||
// timerModified -> timerModifying -> timerDeleted
|
||||
// timerNoStatus -> do nothing
|
||||
// timerDeleted -> do nothing
|
||||
// timerRemoving -> do nothing
|
||||
|
|
@ -82,25 +81,25 @@ type timer struct {
|
|||
// timerMoving -> wait until status changes
|
||||
// timerModifying -> wait until status changes
|
||||
// modtimer:
|
||||
// timerWaiting -> timerModifying -> timerModifiedXX
|
||||
// timerModifiedXX -> timerModifying -> timerModifiedYY
|
||||
// timerWaiting -> timerModifying -> timerModified
|
||||
// timerModified -> timerModifying -> timerModified
|
||||
// timerNoStatus -> timerModifying -> timerWaiting
|
||||
// timerRemoved -> timerModifying -> timerWaiting
|
||||
// timerDeleted -> timerModifying -> timerModifiedXX
|
||||
// timerDeleted -> timerModifying -> timerModified
|
||||
// timerRunning -> wait until status changes
|
||||
// timerMoving -> wait until status changes
|
||||
// timerRemoving -> wait until status changes
|
||||
// timerModifying -> wait until status changes
|
||||
// adjusttimers (looks in P's timer heap):
|
||||
// timerDeleted -> timerRemoving -> timerRemoved
|
||||
// timerModifiedXX -> timerMoving -> timerWaiting
|
||||
// timerModified -> timerMoving -> timerWaiting
|
||||
// runtimer (looks in P's timer heap):
|
||||
// timerNoStatus -> panic: uninitialized timer
|
||||
// timerWaiting -> timerWaiting or
|
||||
// timerWaiting -> timerRunning -> timerNoStatus or
|
||||
// timerWaiting -> timerRunning -> timerWaiting
|
||||
// timerModifying -> wait until status changes
|
||||
// timerModifiedXX -> timerMoving -> timerWaiting
|
||||
// timerModified -> timerMoving -> timerWaiting
|
||||
// timerDeleted -> timerRemoving -> timerRemoved
|
||||
// timerRunning -> panic: concurrent runtimer calls
|
||||
// timerRemoved -> panic: inconsistent timer heap
|
||||
|
|
@ -136,15 +135,11 @@ const (
|
|||
// The timer will only have this status briefly.
|
||||
timerModifying
|
||||
|
||||
// The timer has been modified to an earlier time.
|
||||
// The timer has been modified to a different time.
|
||||
// The new when value is in the nextwhen field.
|
||||
// The timer is in some P's heap, possibly in the wrong place.
|
||||
timerModifiedEarlier
|
||||
|
||||
// The timer has been modified to the same or a later time.
|
||||
// The new when value is in the nextwhen field.
|
||||
// The timer is in some P's heap, possibly in the wrong place.
|
||||
timerModifiedLater
|
||||
// The timer is in some P's heap, possibly in the wrong place
|
||||
// (the right place by .when; the wrong place by .nextwhen).
|
||||
timerModified
|
||||
|
||||
// The timer has been modified and is being moved.
|
||||
// The timer will only have this status briefly.
|
||||
|
|
@ -272,7 +267,7 @@ func doaddtimer(pp *p, t *timer) {
|
|||
func deltimer(t *timer) bool {
|
||||
for {
|
||||
switch s := t.status.Load(); s {
|
||||
case timerWaiting, timerModifiedLater:
|
||||
case timerWaiting, timerModified:
|
||||
// Prevent preemption while the timer is in timerModifying.
|
||||
// This could lead to a self-deadlock. See #38070.
|
||||
mp := acquirem()
|
||||
|
|
@ -291,24 +286,6 @@ func deltimer(t *timer) bool {
|
|||
} else {
|
||||
releasem(mp)
|
||||
}
|
||||
case timerModifiedEarlier:
|
||||
// Prevent preemption while the timer is in timerModifying.
|
||||
// This could lead to a self-deadlock. See #38070.
|
||||
mp := acquirem()
|
||||
if t.status.CompareAndSwap(s, timerModifying) {
|
||||
// Must fetch t.pp before setting status
|
||||
// to timerDeleted.
|
||||
tpp := t.pp.ptr()
|
||||
if !t.status.CompareAndSwap(timerModifying, timerDeleted) {
|
||||
badTimer()
|
||||
}
|
||||
releasem(mp)
|
||||
tpp.deletedTimers.Add(1)
|
||||
// Timer was not yet run.
|
||||
return true
|
||||
} else {
|
||||
releasem(mp)
|
||||
}
|
||||
case timerDeleted, timerRemoving, timerRemoved:
|
||||
// Timer was already run.
|
||||
return false
|
||||
|
|
@ -375,7 +352,7 @@ func modtimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq u
|
|||
loop:
|
||||
for {
|
||||
switch status = t.status.Load(); status {
|
||||
case timerWaiting, timerModifiedEarlier, timerModifiedLater:
|
||||
case timerWaiting, timerModified:
|
||||
// Prevent preemption while the timer is in timerModifying.
|
||||
// This could lead to a self-deadlock. See #38070.
|
||||
mp = acquirem()
|
||||
|
|
@ -442,26 +419,19 @@ loop:
|
|||
// nextwhen field, and let the other P set the when field
|
||||
// when it is prepared to resort the heap.
|
||||
t.nextwhen = when
|
||||
|
||||
newStatus := uint32(timerModifiedLater)
|
||||
if when < t.when {
|
||||
newStatus = timerModifiedEarlier
|
||||
}
|
||||
|
||||
tpp := t.pp.ptr()
|
||||
|
||||
if newStatus == timerModifiedEarlier {
|
||||
updateTimerModifiedEarliest(tpp, when)
|
||||
earlier := when < t.when
|
||||
if earlier {
|
||||
updateTimerModifiedEarliest(t.pp.ptr(), when)
|
||||
}
|
||||
|
||||
// Set the new status of the timer.
|
||||
if !t.status.CompareAndSwap(timerModifying, newStatus) {
|
||||
if !t.status.CompareAndSwap(timerModifying, timerModified) {
|
||||
badTimer()
|
||||
}
|
||||
releasem(mp)
|
||||
|
||||
// If the new status is earlier, wake up the poller.
|
||||
if newStatus == timerModifiedEarlier {
|
||||
if earlier {
|
||||
wakeNetPoller(when)
|
||||
}
|
||||
}
|
||||
|
|
@ -509,7 +479,7 @@ func cleantimers(pp *p) {
|
|||
badTimer()
|
||||
}
|
||||
pp.deletedTimers.Add(-1)
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
case timerModified:
|
||||
if !t.status.CompareAndSwap(s, timerMoving) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -568,7 +538,7 @@ func moveTimers(pp *p, timers []*timer) {
|
|||
badTimer()
|
||||
}
|
||||
break loop
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
case timerModified:
|
||||
if !t.status.CompareAndSwap(s, timerMoving) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -609,7 +579,7 @@ func moveTimers(pp *p, timers []*timer) {
|
|||
// it also moves timers that have been modified to run later,
|
||||
// and removes deleted timers. The caller must have locked the timers for pp.
|
||||
func adjusttimers(pp *p, now int64, force bool) {
|
||||
// If we haven't yet reached the time of the first timerModifiedEarlier
|
||||
// If we haven't yet reached the time of the earliest timerModified
|
||||
// timer, don't do anything. This speeds up programs that adjust
|
||||
// a lot of timers back and forth if the timers rarely expire.
|
||||
// We'll postpone looking through all the adjusted timers until
|
||||
|
|
@ -624,7 +594,7 @@ func adjusttimers(pp *p, now int64, force bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// We are going to clear all timerModifiedEarlier timers.
|
||||
// We are going to clear all timerModified timers.
|
||||
pp.timerModifiedEarliest.Store(0)
|
||||
|
||||
changed := false
|
||||
|
|
@ -648,7 +618,7 @@ func adjusttimers(pp *p, now int64, force bool) {
|
|||
i--
|
||||
changed = true
|
||||
}
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
case timerModified:
|
||||
if t.status.CompareAndSwap(s, timerMoving) {
|
||||
// Now we can change the when field.
|
||||
t.when = t.nextwhen
|
||||
|
|
@ -800,7 +770,7 @@ func runtimer(pp *p, now int64) int64 {
|
|||
return -1
|
||||
}
|
||||
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
case timerModified:
|
||||
if !t.status.CompareAndSwap(s, timerMoving) {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue