@@ -8,6 +8,7 @@ package runtime
8
8
9
9
import (
10
10
"internal/cpu"
11
+ "runtime/internal/atomic"
11
12
"unsafe"
12
13
)
13
14
@@ -120,6 +121,16 @@ type timersBucket struct {
120
121
// addtimer:
121
122
// timerNoStatus -> timerWaiting
122
123
// 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
123
134
124
135
// Values for the timer status field.
125
136
const (
@@ -216,8 +227,8 @@ func startTimer(t *timer) {
216
227
addtimer (t )
217
228
}
218
229
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 .
221
232
//go:linkname stopTimer time.stopTimer
222
233
func stopTimer (t * timer ) bool {
223
234
return deltimer (t )
@@ -335,14 +346,48 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool {
335
346
return true
336
347
}
337
348
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.
340
353
func deltimer (t * timer ) bool {
341
354
if oldTimers {
342
355
return deltimerOld (t )
343
356
}
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
+ }
346
391
}
347
392
348
393
func deltimerOld (t * timer ) bool {
0 commit comments