// deltimer:
// timerWaiting -> timerModifying -> timerDeleted
// timerModified -> timerModifying -> timerDeleted
-// timerNoStatus -> do nothing
// timerDeleted -> do nothing
// timerRemoved -> do nothing
// timerRunning -> wait until status changes
// modtimer:
// timerWaiting -> timerModifying -> timerModified
// timerModified -> timerModifying -> timerModified
-// timerNoStatus -> timerModifying -> timerWaiting
// timerRemoved -> timerModifying -> timerWaiting
// timerDeleted -> timerModifying -> timerModified
// timerRunning -> wait until status changes
// timerDeleted -> timerModifying -> timerRemoved
// timerModified -> timerModifying -> timerWaiting
// runtimer (looks in P's timer heap):
-// timerNoStatus -> panic: uninitialized timer
+// timerRemoved -> panic: uninitialized timer
// timerWaiting -> timerWaiting or
-// timerWaiting -> timerRunning -> timerNoStatus or
+// timerWaiting -> timerRunning -> timerRemoved or
// timerWaiting -> timerRunning -> timerWaiting
// timerModifying -> wait until status changes
// timerModified -> timerModifying -> timerWaiting
// Values for the timer status field.
const (
- // Timer has no status set yet.
- timerNoStatus = iota
+ // Timer has no status set yet or is removed from the heap.
+ // Must be zero value; see issue 21874.
+ timerRemoved = iota
// Waiting for timer to fire.
// The timer is in some P's heap.
// It should not be run, but it is still in some P's heap.
timerDeleted
- // The timer has been stopped.
- // It is not in any P's heap.
- timerRemoved
-
// The timer is being modified.
// The timer will only have this status briefly.
timerModifying
if raceenabled {
racerelease(unsafe.Pointer(t))
}
- if t.status.Load() != timerNoStatus {
+ if t.status.Load() != 0 {
throw("startTimer called with initialized timer")
}
resettimer(t, t.when)
// The timer is being run or modified, by a different P.
// Wait for it to complete.
osyield()
- case timerNoStatus:
- // Removing timer that was never added or
- // has already been run. Also see issue 21874.
- return false
default:
badTimer()
}
throw("timer period must be non-negative")
}
- status := uint32(timerNoStatus)
+ status := uint32(timerRemoved)
wasRemoved := false
var pending bool
var mp *m
break loop
}
releasem(mp)
- case timerNoStatus, timerRemoved:
+ case timerRemoved:
// Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070.
mp = acquirem()
case timerModifying:
// Loop until the modification is complete.
osyield()
- case timerNoStatus, timerRemoved:
+ case timerRemoved:
// We should not see these status values in a timers heap.
badTimer()
case timerRunning:
badTimer()
}
}
- case timerNoStatus, timerRunning, timerRemoved:
+ case timerRunning, timerRemoved:
badTimer()
case timerWaiting:
// OK, nothing to do.
// Wait for modification to complete.
osyield()
- case timerNoStatus, timerRemoved:
+ case timerRemoved:
// Should not see a new or inactive timer on the heap.
badTimer()
case timerRunning:
} else {
// Remove from heap.
dodeltimer0(pp)
- if !t.status.CompareAndSwap(timerRunning, timerNoStatus) {
+ if !t.status.CompareAndSwap(timerRunning, timerRemoved) {
badTimer()
}
}