aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/time.go
diff options
context:
space:
mode:
authorGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-22 17:43:43 -0300
committerGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-22 17:43:43 -0300
commita926878ddbd5a98b272c22171ce58663fc04c3e0 (patch)
tree86af256e5d9a9c06263c00adc90e5fe348008c43 /libgo/go/runtime/time.go
parent542730f087133690b47e036dfd43eb0db8a650ce (diff)
parent07cbaed8ba7d1b6e4ab3a9f44175502a4e1ecdb1 (diff)
downloadgcc-devel/autopar_devel.zip
gcc-devel/autopar_devel.tar.gz
gcc-devel/autopar_devel.tar.bz2
Merge branch 'autopar_rebase2' into autopar_develdevel/autopar_devel
Quickly commit changes in the rebase branch.
Diffstat (limited to 'libgo/go/runtime/time.go')
-rw-r--r--libgo/go/runtime/time.go37
1 files changed, 31 insertions, 6 deletions
diff --git a/libgo/go/runtime/time.go b/libgo/go/runtime/time.go
index 27d88d4..3cf13f1 100644
--- a/libgo/go/runtime/time.go
+++ b/libgo/go/runtime/time.go
@@ -215,11 +215,18 @@ func stopTimer(t *timer) bool {
// resetTimer resets an inactive timer, adding it to the heap.
//go:linkname resetTimer time.resetTimer
-func resetTimer(t *timer, when int64) {
+// Reports whether the timer was modified before it was run.
+func resetTimer(t *timer, when int64) bool {
if raceenabled {
racerelease(unsafe.Pointer(t))
}
- resettimer(t, when)
+ return resettimer(t, when)
+}
+
+// modTimer modifies an existing timer.
+//go:linkname modTimer time.modTimer
+func modTimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
+ modtimer(t, when, period, f, arg, seq)
}
// Go runtime.
@@ -395,14 +402,16 @@ func dodeltimer0(pp *p) {
}
// modtimer modifies an existing timer.
-// This is called by the netpoll code.
-func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
+// This is called by the netpoll code or time.Ticker.Reset.
+// Reports whether the timer was modified before it was run.
+func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) bool {
if when < 0 {
when = maxWhen
}
status := uint32(timerNoStatus)
wasRemoved := false
+ var pending bool
var mp *m
loop:
for {
@@ -412,6 +421,7 @@ loop:
// This could lead to a self-deadlock. See #38070.
mp = acquirem()
if atomic.Cas(&t.status, status, timerModifying) {
+ pending = true // timer not yet run
break loop
}
releasem(mp)
@@ -424,6 +434,7 @@ loop:
// Act like addtimer.
if atomic.Cas(&t.status, status, timerModifying) {
wasRemoved = true
+ pending = false // timer already run or stopped
break loop
}
releasem(mp)
@@ -433,6 +444,7 @@ loop:
mp = acquirem()
if atomic.Cas(&t.status, status, timerModifying) {
atomic.Xadd(&t.pp.ptr().deletedTimers, -1)
+ pending = false // timer already stopped
break loop
}
releasem(mp)
@@ -503,14 +515,17 @@ loop:
wakeNetPoller(when)
}
}
+
+ return pending
}
// resettimer resets the time when a timer should fire.
// If used for an inactive timer, the timer will become active.
// 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) {
- modtimer(t, when, t.period, t.f, t.arg, t.seq)
+// Reports whether the timer was modified before it was run.
+func resettimer(t *timer, when int64) bool {
+ return modtimer(t, when, t.period, t.f, t.arg, t.seq)
}
// cleantimers cleans up the head of the timer queue. This speeds up
@@ -518,10 +533,20 @@ func resettimer(t *timer, when int64) {
// slows down addtimer. Reports whether no timer problems were found.
// The caller must have locked the timers for pp.
func cleantimers(pp *p) {
+ gp := getg()
for {
if len(pp.timers) == 0 {
return
}
+
+ // This loop can theoretically run for a while, and because
+ // it is holding timersLock it cannot be preempted.
+ // If someone is trying to preempt us, just return.
+ // We can clean the timers later.
+ if gp.preemptStop {
+ return
+ }
+
t := pp.timers[0]
if t.pp.ptr() != pp {
throw("cleantimers: bad p")