From b2bd7ebafcd8588fadef6b73755ee98bc8889233 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 14 Feb 2024 11:56:57 -0500 Subject: [PATCH] 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 Reviewed-by: Ian Lance Taylor --- src/runtime/time.go | 76 ++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 53 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index d75cab0ba8..cd4d214c79 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -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 } -- 2.48.1