]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: implement timeSleepUntil for new timers
authorIan Lance Taylor <iant@golang.org>
Thu, 11 Apr 2019 16:02:37 +0000 (09:02 -0700)
committerIan Lance Taylor <iant@golang.org>
Wed, 23 Oct 2019 07:02:10 +0000 (07:02 +0000)
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>
src/runtime/time.go

index c0f2d0287dd64953089602091bd7b35bb959433a..4bc819f023617eb3d7158cdf73d408ea084929b9 100644 (file)
@@ -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.