From: Ian Lance Taylor Date: Thu, 11 Apr 2019 01:13:24 +0000 (-0700) Subject: runtime: add new deltimer function X-Git-Tag: go1.14beta1~637 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7416315e3358b0bc2774c92f39d8f7c4b33790ad;p=gostls13.git runtime: add new deltimer function Updates #27707 Change-Id: I720e8af9e183c75abcb63ccc30466734c8dba74f Reviewed-on: https://go-review.googlesource.com/c/go/+/171831 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Michael Knyszek --- diff --git a/src/runtime/time.go b/src/runtime/time.go index b4f1c0205e..f2dd40e6b4 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -8,6 +8,7 @@ package runtime import ( "internal/cpu" + "runtime/internal/atomic" "unsafe" ) @@ -120,6 +121,16 @@ type timersBucket struct { // addtimer: // timerNoStatus -> timerWaiting // anything else -> panic: invalid value +// deltimer: +// timerWaiting -> timerDeleted +// timerModifiedXX -> timerDeleted +// timerNoStatus -> do nothing +// timerDeleted -> do nothing +// timerRemoving -> do nothing +// timerRemoved -> do nothing +// timerRunning -> wait until status changes +// timerMoving -> wait until status changes +// timerModifying -> panic: concurrent deltimer/modtimer calls // Values for the timer status field. const ( @@ -216,8 +227,8 @@ func startTimer(t *timer) { addtimer(t) } -// stopTimer removes t from the timer heap if it is there. -// It returns true if t was removed, false if t wasn't even there. +// stopTimer stops a timer. +// It reports whether t was stopped before being run. //go:linkname stopTimer time.stopTimer func stopTimer(t *timer) bool { return deltimer(t) @@ -335,14 +346,48 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool { return true } -// Delete timer t from the heap. -// Do not need to update the timerproc: if it wakes up early, no big deal. +// deltimer deletes the timer t. It may be on some other P, so we can't +// actually remove it from the timers heap. We can only mark it as deleted. +// It will be removed in due course by the P whose heap it is on. +// Reports whether the timer was removed before it was run. func deltimer(t *timer) bool { if oldTimers { return deltimerOld(t) } - throw("no deltimer not yet implemented") - return false + + for { + switch s := atomic.Load(&t.status); s { + case timerWaiting, timerModifiedLater: + if atomic.Cas(&t.status, s, timerDeleted) { + // Timer was not yet run. + return true + } + case timerModifiedEarlier: + if atomic.Cas(&t.status, s, timerModifying) { + if !atomic.Cas(&t.status, timerModifying, timerDeleted) { + badTimer() + } + // Timer was not yet run. + return true + } + case timerDeleted, timerRemoving, timerRemoved: + // Timer was already run. + return false + case timerRunning, timerMoving: + // The timer is being run or moved, 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 + case timerModifying: + // Simultaneous calls to deltimer and modtimer. + badTimer() + default: + badTimer() + } + } } func deltimerOld(t *timer) bool {