]> Cypherpunks repositories - gostls13.git/commitdiff
runtime, syscall, time: add and use resettimer
authorIan Lance Taylor <iant@golang.org>
Thu, 11 Apr 2019 00:23:05 +0000 (17:23 -0700)
committerIan Lance Taylor <iant@golang.org>
Mon, 21 Oct 2019 17:06:22 +0000 (17:06 +0000)
As a small step toward speeding up timers, restrict modification
of the timer.when field to the timer code itself. Other code that
wants to change the when field of an existing timer must now call
resettimer rather than changing the when field and calling addtimer.
The new resettimer function also works for a new timer.

This is just a refactoring in preparation for later code.

Updates #27707

Change-Id: Iccd5dcad415ffbeac4c2a3cf015e91f82692acf8
Reviewed-on: https://go-review.googlesource.com/c/go/+/171825
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/mgcscavenge.go
src/runtime/netpoll.go
src/runtime/time.go
src/time/internal_test.go
src/time/sleep.go

index 0273c8d234abf86a9cecc13b8e67bfc8fb07eada..0a67f74150f2391394c3c05ff6dbfa2cf81e8c02 100644 (file)
@@ -268,8 +268,7 @@ func scavengeSleep(ns int64) bool {
        // because we can't close over any variables without
        // failing escape analysis.
        now := nanotime()
-       scavenge.timer.when = now + ns
-       startTimer(scavenge.timer)
+       resetTimer(scavenge.timer, now+ns)
 
        // Mark ourself as asleep and go to sleep.
        scavenge.parked = true
index 7d18dcaeeab3b1b70e210b02b15be5abda5e978c..536dae3d4f1b228b2314003a5ec5812ec12fc464 100644 (file)
@@ -239,13 +239,12 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
        if pd.rt.f == nil {
                if pd.rd > 0 {
                        pd.rt.f = rtf
-                       pd.rt.when = pd.rd
                        // Copy current seq into the timer arg.
                        // Timer func will check the seq against current descriptor seq,
                        // if they differ the descriptor was reused or timers were reset.
                        pd.rt.arg = pd
                        pd.rt.seq = pd.rseq
-                       addtimer(&pd.rt)
+                       resettimer(&pd.rt, pd.rd)
                }
        } else if pd.rd != rd0 || combo != combo0 {
                pd.rseq++ // invalidate current timers
@@ -259,10 +258,9 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
        if pd.wt.f == nil {
                if pd.wd > 0 && !combo {
                        pd.wt.f = netpollWriteDeadline
-                       pd.wt.when = pd.wd
                        pd.wt.arg = pd
                        pd.wt.seq = pd.wseq
-                       addtimer(&pd.wt)
+                       resettimer(&pd.wt, pd.wd)
                }
        } else if pd.wd != wd0 || combo != combo0 {
                pd.wseq++ // invalidate current timers
index d667d11244ecfa769cb0c844fb7798d219310ac5..5521b8a807e4dd023b3e35aa253e0a6705427ced 100644 (file)
@@ -116,6 +116,15 @@ func stopTimer(t *timer) bool {
        return deltimer(t)
 }
 
+// resetTimer resets an inactive timer, adding it to the heap.
+//go:linkname resetTimer time.resetTimer
+func resetTimer(t *timer, when int64) {
+       if raceenabled {
+               racerelease(unsafe.Pointer(t))
+       }
+       resettimer(t, when)
+}
+
 // Go runtime.
 
 // Ready the goroutine arg.
@@ -236,6 +245,15 @@ func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg in
        }
 }
 
+// resettimer resets an existing inactive timer to turn it into an active timer,
+// with a new time for when the timer should fire.
+// This should be called instead of addtimer if the timer value has been,
+// or may have been, used previously.
+func resettimer(t *timer, when int64) {
+       t.when = when
+       addtimer(t)
+}
+
 // Timerproc runs the time-driven events.
 // It sleeps until the next event in the tb heap.
 // If addtimer inserts a new earlier event, it wakes timerproc early.
index 336deb921122294f6819fe9448fcb5668e94fed4..3bca88e2b994cd4fa693614a6af408cb22871dac 100644 (file)
@@ -64,8 +64,7 @@ func CheckRuntimeTimerOverflow() {
                // once more.
                stopTimer(r)
                t.Stop()
-               r.when = 0
-               startTimer(r)
+               resetTimer(r, 0)
        }()
 
        // If the test fails, we will hang here until the timeout in the testing package
index 2cc908da55e4fa767e37be542a857207ee4fcdbe..b381a1f73bf558b1d8b49480d1bb73fa6a105ab8 100644 (file)
@@ -38,6 +38,7 @@ func when(d Duration) int64 {
 
 func startTimer(*runtimeTimer)
 func stopTimer(*runtimeTimer) bool
+func resetTimer(*runtimeTimer, int64)
 
 // The Timer type represents a single event.
 // When the Timer expires, the current time will be sent on C,
@@ -122,8 +123,7 @@ func (t *Timer) Reset(d Duration) bool {
        }
        w := when(d)
        active := stopTimer(&t.r)
-       t.r.when = w
-       startTimer(&t.r)
+       resetTimer(&t.r, w)
        return active
 }