Commit a7ce2ca5 authored by Ian Lance Taylor's avatar Ian Lance Taylor

runtime, syscall, time: add and use resettimer

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: default avatarMichael Knyszek <mknyszek@google.com>
Reviewed-by: default avatarEmmanuel Odeke <emm.odeke@gmail.com>
parent 7a6da218
...@@ -268,8 +268,7 @@ func scavengeSleep(ns int64) bool { ...@@ -268,8 +268,7 @@ func scavengeSleep(ns int64) bool {
// because we can't close over any variables without // because we can't close over any variables without
// failing escape analysis. // failing escape analysis.
now := nanotime() now := nanotime()
scavenge.timer.when = now + ns resetTimer(scavenge.timer, now+ns)
startTimer(scavenge.timer)
// Mark ourself as asleep and go to sleep. // Mark ourself as asleep and go to sleep.
scavenge.parked = true scavenge.parked = true
......
...@@ -239,13 +239,12 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { ...@@ -239,13 +239,12 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
if pd.rt.f == nil { if pd.rt.f == nil {
if pd.rd > 0 { if pd.rd > 0 {
pd.rt.f = rtf pd.rt.f = rtf
pd.rt.when = pd.rd
// Copy current seq into the timer arg. // Copy current seq into the timer arg.
// Timer func will check the seq against current descriptor seq, // Timer func will check the seq against current descriptor seq,
// if they differ the descriptor was reused or timers were reset. // if they differ the descriptor was reused or timers were reset.
pd.rt.arg = pd pd.rt.arg = pd
pd.rt.seq = pd.rseq pd.rt.seq = pd.rseq
addtimer(&pd.rt) resettimer(&pd.rt, pd.rd)
} }
} else if pd.rd != rd0 || combo != combo0 { } else if pd.rd != rd0 || combo != combo0 {
pd.rseq++ // invalidate current timers pd.rseq++ // invalidate current timers
...@@ -259,10 +258,9 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { ...@@ -259,10 +258,9 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
if pd.wt.f == nil { if pd.wt.f == nil {
if pd.wd > 0 && !combo { if pd.wd > 0 && !combo {
pd.wt.f = netpollWriteDeadline pd.wt.f = netpollWriteDeadline
pd.wt.when = pd.wd
pd.wt.arg = pd pd.wt.arg = pd
pd.wt.seq = pd.wseq pd.wt.seq = pd.wseq
addtimer(&pd.wt) resettimer(&pd.wt, pd.wd)
} }
} else if pd.wd != wd0 || combo != combo0 { } else if pd.wd != wd0 || combo != combo0 {
pd.wseq++ // invalidate current timers pd.wseq++ // invalidate current timers
......
...@@ -116,6 +116,15 @@ func stopTimer(t *timer) bool { ...@@ -116,6 +116,15 @@ func stopTimer(t *timer) bool {
return deltimer(t) 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. // Go runtime.
// Ready the goroutine arg. // Ready the goroutine arg.
...@@ -236,6 +245,15 @@ func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg in ...@@ -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. // Timerproc runs the time-driven events.
// It sleeps until the next event in the tb heap. // It sleeps until the next event in the tb heap.
// If addtimer inserts a new earlier event, it wakes timerproc early. // If addtimer inserts a new earlier event, it wakes timerproc early.
......
...@@ -64,8 +64,7 @@ func CheckRuntimeTimerOverflow() { ...@@ -64,8 +64,7 @@ func CheckRuntimeTimerOverflow() {
// once more. // once more.
stopTimer(r) stopTimer(r)
t.Stop() t.Stop()
r.when = 0 resetTimer(r, 0)
startTimer(r)
}() }()
// If the test fails, we will hang here until the timeout in the testing package // If the test fails, we will hang here until the timeout in the testing package
......
...@@ -38,6 +38,7 @@ func when(d Duration) int64 { ...@@ -38,6 +38,7 @@ func when(d Duration) int64 {
func startTimer(*runtimeTimer) func startTimer(*runtimeTimer)
func stopTimer(*runtimeTimer) bool func stopTimer(*runtimeTimer) bool
func resetTimer(*runtimeTimer, int64)
// The Timer type represents a single event. // The Timer type represents a single event.
// When the Timer expires, the current time will be sent on C, // When the Timer expires, the current time will be sent on C,
...@@ -122,8 +123,7 @@ func (t *Timer) Reset(d Duration) bool { ...@@ -122,8 +123,7 @@ func (t *Timer) Reset(d Duration) bool {
} }
w := when(d) w := when(d)
active := stopTimer(&t.r) active := stopTimer(&t.r)
t.r.when = w resetTimer(&t.r, w)
startTimer(&t.r)
return active return active
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment