aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/time.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-04-11 09:02:37 -0700
committerIan Lance Taylor <iant@golang.org>2019-10-23 07:02:10 +0000
commitc824420d4744bd3e11128c000d88c24859602d46 (patch)
treeb7a6d9e6ce3018f2ede0c1d017b88c7955481323 /src/runtime/time.go
parent5f92939c9040c33ed19893a6b369b3dbbd3c5837 (diff)
downloadgo-c824420d4744bd3e11128c000d88c24859602d46.tar.gz
go-c824420d4744bd3e11128c000d88c24859602d46.zip
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 <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src/runtime/time.go')
-rw-r--r--src/runtime/time.go46
1 files changed, 46 insertions, 0 deletions
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.