From 48849e0866f64a40d04a9151e44e5a73acdfc17b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 14 Oct 2024 11:46:17 -0700 Subject: runtime: don't frob isSending for tickers The Ticker Stop and Reset methods don't report a value, so we don't need to track whether they are interrupting a send. This includes a test that used to fail about 2% of the time on my laptop when run under x/tools/cmd/stress. Change-Id: Ic6d14b344594149dd3c24b37bbe4e42e83f9a9ad Reviewed-on: https://go-review.googlesource.com/c/go/+/620136 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Auto-Submit: Michael Knyszek Auto-Submit: Ian Lance Taylor Reviewed-by: Michael Knyszek --- src/runtime/time.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/runtime') diff --git a/src/runtime/time.go b/src/runtime/time.go index 3353502fc4..af19a6435d 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -33,6 +33,7 @@ type timer struct { // isSending is used to handle races between running a // channel timer and stopping or resetting the timer. // It is used only for channel timers (t.isChan == true). + // It is not used for tickers. // The lowest zero bit is set when about to send a value on the channel, // and cleared after sending the value. // The stop/reset code uses this to detect whether it @@ -467,7 +468,7 @@ func (t *timer) stop() bool { // send from actually happening. That means // that we should return true: the timer was // stopped, even though t.when may be zero. - if t.isSending.Load() > 0 { + if t.period == 0 && t.isSending.Load() > 0 { pending = true } } @@ -529,6 +530,7 @@ func (t *timer) modify(when, period int64, f func(arg any, seq uintptr, delay in t.maybeRunAsync() } t.trace("modify") + oldPeriod := t.period t.period = period if f != nil { t.f = f @@ -570,7 +572,7 @@ func (t *timer) modify(when, period int64, f func(arg any, seq uintptr, delay in // send from actually happening. That means // that we should return true: the timer was // stopped, even though t.when may be zero. - if t.isSending.Load() > 0 { + if oldPeriod == 0 && t.isSending.Load() > 0 { pending = true } } @@ -1064,7 +1066,7 @@ func (t *timer) unlockAndRun(now int64) { async := debug.asynctimerchan.Load() != 0 var isSendingClear uint8 - if !async && t.isChan { + if !async && t.isChan && t.period == 0 { // Tell Stop/Reset that we are sending a value. // Set the lowest zero bit. // We do this awkward step because atomic.Uint8 @@ -1115,9 +1117,12 @@ func (t *timer) unlockAndRun(now int64) { // true meaning that no value was sent. lock(&t.sendLock) - // We are committed to possibly sending a value based on seq, - // so no need to keep telling stop/modify that we are sending. - t.isSending.And(^isSendingClear) + if t.period == 0 { + // We are committed to possibly sending a value + // based on seq, so no need to keep telling + // stop/modify that we are sending. + t.isSending.And(^isSendingClear) + } if t.seq != seq { f = func(any, uintptr, int64) {} -- cgit v1.3-5-g9baa