From c824420d4744bd3e11128c000d88c24859602d46 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 11 Apr 2019 09:02:37 -0700 Subject: [PATCH] runtime: implement timeSleepUntil for new timers Updates #27707 Change-Id: Id4b37594511895f404ee3c09a85263b2b35f835d Reviewed-on: https://go-review.googlesource.com/c/go/+/171881 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Michael Knyszek Reviewed-by: Emmanuel Odeke --- src/runtime/time.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/runtime/time.go b/src/runtime/time.go index c0f2d0287d..4bc819f023 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -1227,6 +1227,52 @@ func timejumpLocked() *g { } func timeSleepUntil() int64 { + if oldTimers { + return timeSleepUntilOld() + } + + next := int64(maxWhen) + + for _, pp := range allp { + lock(&pp.timersLock) + c := atomic.Load(&pp.adjustTimers) + for _, t := range pp.timers { + switch s := atomic.Load(&t.status); s { + case timerWaiting: + if t.when < next { + next = t.when + } + case timerModifiedEarlier, timerModifiedLater: + if t.nextwhen < next { + next = t.nextwhen + } + if s == timerModifiedEarlier { + c-- + } + } + // The timers are sorted, so we only have to check + // the first timer for each P, unless there are + // some timerModifiedEarlier timers. The number + // of timerModifiedEarlier timers is in the adjustTimers + // field, used to initialize c, above. + // + // We don't worry about cases like timerModifying. + // New timers can show up at any time, + // so this function is necessarily imprecise. + // Do a signed check here since we aren't + // synchronizing the read of pp.adjustTimers + // with the check of a timer status. + if int32(c) <= 0 { + break + } + } + unlock(&pp.timersLock) + } + + return next +} + +func timeSleepUntilOld() int64 { next := int64(1<<63 - 1) // Determine minimum sleepUntil across all the timer buckets.