Skip to content

Commit 7416315

Browse files
runtime: add new deltimer function
Updates #27707 Change-Id: I720e8af9e183c75abcb63ccc30466734c8dba74f Reviewed-on: https://go-review.googlesource.com/c/go/+/171831 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 2e0aa58 commit 7416315

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

src/runtime/time.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package runtime
88

99
import (
1010
"internal/cpu"
11+
"runtime/internal/atomic"
1112
"unsafe"
1213
)
1314

@@ -120,6 +121,16 @@ type timersBucket struct {
120121
// addtimer:
121122
// timerNoStatus -> timerWaiting
122123
// anything else -> panic: invalid value
124+
// deltimer:
125+
// timerWaiting -> timerDeleted
126+
// timerModifiedXX -> timerDeleted
127+
// timerNoStatus -> do nothing
128+
// timerDeleted -> do nothing
129+
// timerRemoving -> do nothing
130+
// timerRemoved -> do nothing
131+
// timerRunning -> wait until status changes
132+
// timerMoving -> wait until status changes
133+
// timerModifying -> panic: concurrent deltimer/modtimer calls
123134

124135
// Values for the timer status field.
125136
const (
@@ -216,8 +227,8 @@ func startTimer(t *timer) {
216227
addtimer(t)
217228
}
218229

219-
// stopTimer removes t from the timer heap if it is there.
220-
// It returns true if t was removed, false if t wasn't even there.
230+
// stopTimer stops a timer.
231+
// It reports whether t was stopped before being run.
221232
//go:linkname stopTimer time.stopTimer
222233
func stopTimer(t *timer) bool {
223234
return deltimer(t)
@@ -335,14 +346,48 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool {
335346
return true
336347
}
337348

338-
// Delete timer t from the heap.
339-
// Do not need to update the timerproc: if it wakes up early, no big deal.
349+
// deltimer deletes the timer t. It may be on some other P, so we can't
350+
// actually remove it from the timers heap. We can only mark it as deleted.
351+
// It will be removed in due course by the P whose heap it is on.
352+
// Reports whether the timer was removed before it was run.
340353
func deltimer(t *timer) bool {
341354
if oldTimers {
342355
return deltimerOld(t)
343356
}
344-
throw("no deltimer not yet implemented")
345-
return false
357+
358+
for {
359+
switch s := atomic.Load(&t.status); s {
360+
case timerWaiting, timerModifiedLater:
361+
if atomic.Cas(&t.status, s, timerDeleted) {
362+
// Timer was not yet run.
363+
return true
364+
}
365+
case timerModifiedEarlier:
366+
if atomic.Cas(&t.status, s, timerModifying) {
367+
if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
368+
badTimer()
369+
}
370+
// Timer was not yet run.
371+
return true
372+
}
373+
case timerDeleted, timerRemoving, timerRemoved:
374+
// Timer was already run.
375+
return false
376+
case timerRunning, timerMoving:
377+
// The timer is being run or moved, by a different P.
378+
// Wait for it to complete.
379+
osyield()
380+
case timerNoStatus:
381+
// Removing timer that was never added or
382+
// has already been run. Also see issue 21874.
383+
return false
384+
case timerModifying:
385+
// Simultaneous calls to deltimer and modtimer.
386+
badTimer()
387+
default:
388+
badTimer()
389+
}
390+
}
346391
}
347392

348393
func deltimerOld(t *timer) bool {

0 commit comments

Comments
 (0)