From ed0ad591d31daf911092487ceafb7b440d0ed8ea Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 14 Feb 2024 11:56:59 -0500 Subject: [PATCH] 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 Reviewed-by: Ian Lance Taylor --- src/runtime/time.go | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index 3ecfb90bfbc..679a155bece 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -73,7 +73,6 @@ type timer struct { // deltimer: // timerWaiting -> timerModifying -> timerDeleted // timerModified -> timerModifying -> timerDeleted -// timerNoStatus -> do nothing // timerDeleted -> do nothing // timerRemoved -> do nothing // timerRunning -> wait until status changes @@ -81,7 +80,6 @@ type timer struct { // modtimer: // timerWaiting -> timerModifying -> timerModified // timerModified -> timerModifying -> timerModified -// timerNoStatus -> timerModifying -> timerWaiting // timerRemoved -> timerModifying -> timerWaiting // timerDeleted -> timerModifying -> timerModified // timerRunning -> wait until status changes @@ -90,9 +88,9 @@ type timer struct { // 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 @@ -101,8 +99,9 @@ type timer struct { // 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. @@ -116,10 +115,6 @@ const ( // 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 @@ -183,7 +178,7 @@ func startTimer(t *timer) { 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) @@ -278,10 +273,6 @@ func deltimer(t *timer) bool { // 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() } @@ -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") } - status := uint32(timerNoStatus) + status := uint32(timerRemoved) wasRemoved := false var pending bool var mp *m @@ -342,7 +333,7 @@ loop: 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() @@ -536,7 +527,7 @@ func moveTimers(pp *p, timers []*timer) { 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: @@ -604,7 +595,7 @@ func adjusttimers(pp *p, now int64, force bool) { badTimer() } } - case timerNoStatus, timerRunning, timerRemoved: + case timerRunning, timerRemoved: badTimer() case timerWaiting: // OK, nothing to do. @@ -762,7 +753,7 @@ func runtimer(pp *p, now int64) int64 { // 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: @@ -808,7 +799,7 @@ func runOneTimer(pp *p, t *timer, now int64) { } else { // Remove from heap. dodeltimer0(pp) - if !t.status.CompareAndSwap(timerRunning, timerNoStatus) { + if !t.status.CompareAndSwap(timerRunning, timerRemoved) { badTimer() } }