From eff3c1e426559660993d47eba569a4060f0bb69b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 10 Apr 2019 21:16:09 -0700 Subject: [PATCH] runtime: add new resettimer function Updates #27707 Change-Id: I02f97ec7869ec8a3fb2dfc94cff246badc7ea0fa Reviewed-on: https://go-review.googlesource.com/c/go/+/171833 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Michael Knyszek --- src/runtime/time.go | 55 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index 54cbb0b6e4..4e3511eb11 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -141,6 +141,16 @@ type timersBucket struct { // timerRemoving -> wait until status changes // timerDeleted -> panic: concurrent modtimer/deltimer calls // timerModifying -> panic: concurrent modtimer calls +// resettimer: +// timerNoStatus -> timerWaiting +// timerRemoved -> timerWaiting +// timerDeleted -> timerModifying -> timerModifiedXX +// timerRemoving -> wait until status changes +// timerRunning -> wait until status changes +// timerWaiting -> panic: resettimer called on active timer +// timerMoving -> panic: resettimer called on active timer +// timerModifiedXX -> panic: resettimer called on active timer +// timerModifying -> panic: resettimer called on active timer // Values for the timer status field. const ( @@ -573,7 +583,50 @@ func resettimer(t *timer, when int64) { resettimerOld(t, when) return } - throw("new resettimer not yet implemented") + + if when < 0 { + when = maxWhen + } + + for { + switch s := atomic.Load(&t.status); s { + case timerNoStatus, timerRemoved: + atomic.Store(&t.status, timerWaiting) + t.when = when + addInitializedTimer(t) + return + case timerDeleted: + if atomic.Cas(&t.status, s, timerModifying) { + t.nextwhen = when + newStatus := uint32(timerModifiedLater) + if when < t.when { + newStatus = timerModifiedEarlier + atomic.Xadd(&t.pp.ptr().adjustTimers, 1) + } + if !atomic.Cas(&t.status, timerModifying, newStatus) { + badTimer() + } + if newStatus == timerModifiedEarlier { + wakeNetPoller(when) + } + return + } + case timerRemoving: + // Wait for the removal to complete. + osyield() + case timerRunning: + // Even though the timer should not be active, + // we can see timerRunning if the timer function + // permits some other goroutine to call resettimer. + // Wait until the run is complete. + osyield() + case timerWaiting, timerModifying, timerModifiedEarlier, timerModifiedLater, timerMoving: + // Called resettimer on active timer. + badTimer() + default: + badTimer() + } + } } func resettimerOld(t *timer, when int64) { -- 2.50.0