1
0
mirror of https://github.com/golang/go synced 2024-11-17 01:44:52 -07:00

runtime: merge timerNoStatus into timerRemoved

For historical reasons, we have to treat a zero timer as
the same as an initialized timer that was stopped (removed).
The two states are already treated mostly identically.
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: I9c3aeb8f92bafb18c47489c1ec20a7b87ac5cd9c
Reviewed-on: https://go-review.googlesource.com/c/go/+/564122
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:
Russ Cox 2024-02-14 11:56:59 -05:00
parent 3be36e9b20
commit ed0ad591d3

View File

@ -73,7 +73,6 @@ type timer struct {
// deltimer: // deltimer:
// timerWaiting -> timerModifying -> timerDeleted // timerWaiting -> timerModifying -> timerDeleted
// timerModified -> timerModifying -> timerDeleted // timerModified -> timerModifying -> timerDeleted
// timerNoStatus -> do nothing
// timerDeleted -> do nothing // timerDeleted -> do nothing
// timerRemoved -> do nothing // timerRemoved -> do nothing
// timerRunning -> wait until status changes // timerRunning -> wait until status changes
@ -81,7 +80,6 @@ type timer struct {
// modtimer: // modtimer:
// timerWaiting -> timerModifying -> timerModified // timerWaiting -> timerModifying -> timerModified
// timerModified -> timerModifying -> timerModified // timerModified -> timerModifying -> timerModified
// timerNoStatus -> timerModifying -> timerWaiting
// timerRemoved -> timerModifying -> timerWaiting // timerRemoved -> timerModifying -> timerWaiting
// timerDeleted -> timerModifying -> timerModified // timerDeleted -> timerModifying -> timerModified
// timerRunning -> wait until status changes // timerRunning -> wait until status changes
@ -90,9 +88,9 @@ type timer struct {
// timerDeleted -> timerModifying -> timerRemoved // timerDeleted -> timerModifying -> timerRemoved
// timerModified -> timerModifying -> timerWaiting // timerModified -> timerModifying -> timerWaiting
// runtimer (looks in P's timer heap): // runtimer (looks in P's timer heap):
// timerNoStatus -> panic: uninitialized timer // timerRemoved -> panic: uninitialized timer
// timerWaiting -> timerWaiting or // timerWaiting -> timerWaiting or
// timerWaiting -> timerRunning -> timerNoStatus or // timerWaiting -> timerRunning -> timerRemoved or
// timerWaiting -> timerRunning -> timerWaiting // timerWaiting -> timerRunning -> timerWaiting
// timerModifying -> wait until status changes // timerModifying -> wait until status changes
// timerModified -> timerModifying -> timerWaiting // timerModified -> timerModifying -> timerWaiting
@ -101,8 +99,9 @@ type timer struct {
// Values for the timer status field. // Values for the timer status field.
const ( const (
// Timer has no status set yet. // Timer has no status set yet or is removed from the heap.
timerNoStatus = iota // Must be zero value; see issue 21874.
timerRemoved = iota
// Waiting for timer to fire. // Waiting for timer to fire.
// The timer is in some P's heap. // The timer is in some P's heap.
@ -116,10 +115,6 @@ const (
// It should not be run, but it is still in some P's heap. // It should not be run, but it is still in some P's heap.
timerDeleted timerDeleted
// The timer has been stopped.
// It is not in any P's heap.
timerRemoved
// The timer is being modified. // The timer is being modified.
// The timer will only have this status briefly. // The timer will only have this status briefly.
timerModifying timerModifying
@ -183,7 +178,7 @@ func startTimer(t *timer) {
if raceenabled { if raceenabled {
racerelease(unsafe.Pointer(t)) racerelease(unsafe.Pointer(t))
} }
if t.status.Load() != timerNoStatus { if t.status.Load() != 0 {
throw("startTimer called with initialized timer") throw("startTimer called with initialized timer")
} }
resettimer(t, t.when) resettimer(t, t.when)
@ -278,10 +273,6 @@ func deltimer(t *timer) bool {
// The timer is being run or modified, by a different P. // The timer is being run or modified, by a different P.
// Wait for it to complete. // Wait for it to complete.
osyield() osyield()
case timerNoStatus:
// Removing timer that was never added or
// has already been run. Also see issue 21874.
return false
default: default:
badTimer() badTimer()
} }
@ -326,7 +317,7 @@ func modtimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq u
throw("timer period must be non-negative") throw("timer period must be non-negative")
} }
status := uint32(timerNoStatus) status := uint32(timerRemoved)
wasRemoved := false wasRemoved := false
var pending bool var pending bool
var mp *m var mp *m
@ -342,7 +333,7 @@ loop:
break loop break loop
} }
releasem(mp) releasem(mp)
case timerNoStatus, timerRemoved: case timerRemoved:
// Prevent preemption while the timer is in timerModifying. // Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070. // This could lead to a self-deadlock. See #38070.
mp = acquirem() mp = acquirem()
@ -536,7 +527,7 @@ func moveTimers(pp *p, timers []*timer) {
case timerModifying: case timerModifying:
// Loop until the modification is complete. // Loop until the modification is complete.
osyield() osyield()
case timerNoStatus, timerRemoved: case timerRemoved:
// We should not see these status values in a timers heap. // We should not see these status values in a timers heap.
badTimer() badTimer()
case timerRunning: case timerRunning:
@ -604,7 +595,7 @@ func adjusttimers(pp *p, now int64, force bool) {
badTimer() badTimer()
} }
} }
case timerNoStatus, timerRunning, timerRemoved: case timerRunning, timerRemoved:
badTimer() badTimer()
case timerWaiting: case timerWaiting:
// OK, nothing to do. // OK, nothing to do.
@ -762,7 +753,7 @@ func runtimer(pp *p, now int64) int64 {
// Wait for modification to complete. // Wait for modification to complete.
osyield() osyield()
case timerNoStatus, timerRemoved: case timerRemoved:
// Should not see a new or inactive timer on the heap. // Should not see a new or inactive timer on the heap.
badTimer() badTimer()
case timerRunning: case timerRunning:
@ -808,7 +799,7 @@ func runOneTimer(pp *p, t *timer, now int64) {
} else { } else {
// Remove from heap. // Remove from heap.
dodeltimer0(pp) dodeltimer0(pp)
if !t.status.CompareAndSwap(timerRunning, timerNoStatus) { if !t.status.CompareAndSwap(timerRunning, timerRemoved) {
badTimer() badTimer()
} }
} }