nextwhen int64
// The status field holds one of the values below.
- status uint32
+ status atomic.Uint32
}
// Code outside this file has to be careful in using a timer value.
goready(arg.(*g), 0)
}
+// Note: this changes some unsynchronized operations to synchronized operations
// addtimer adds a timer to the current P.
// This should only be called with a newly created timer.
// That avoids the risk of changing the when field of a timer in some P's heap,
if t.period < 0 {
throw("timer period must be non-negative")
}
- if t.status != timerNoStatus {
+ if t.status.Load() != timerNoStatus {
throw("addtimer called with initialized timer")
}
- t.status = timerWaiting
+ t.status.Store(timerWaiting)
when := t.when
// Reports whether the timer was removed before it was run.
func deltimer(t *timer) bool {
for {
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerWaiting, timerModifiedLater:
// Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070.
mp := acquirem()
- if atomic.Cas(&t.status, s, timerModifying) {
+ if t.status.CompareAndSwap(s, timerModifying) {
// Must fetch t.pp before changing status,
// as cleantimers in another goroutine
// can clear t.pp of a timerDeleted timer.
tpp := t.pp.ptr()
- if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
+ if !t.status.CompareAndSwap(timerModifying, timerDeleted) {
badTimer()
}
releasem(mp)
// Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070.
mp := acquirem()
- if atomic.Cas(&t.status, s, timerModifying) {
+ if t.status.CompareAndSwap(s, timerModifying) {
// Must fetch t.pp before setting status
// to timerDeleted.
tpp := t.pp.ptr()
- if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
+ if !t.status.CompareAndSwap(timerModifying, timerDeleted) {
badTimer()
}
releasem(mp)
var mp *m
loop:
for {
- switch status = atomic.Load(&t.status); status {
+ switch status = t.status.Load(); status {
case timerWaiting, timerModifiedEarlier, timerModifiedLater:
// Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070.
mp = acquirem()
- if atomic.Cas(&t.status, status, timerModifying) {
+ if t.status.CompareAndSwap(status, timerModifying) {
pending = true // timer not yet run
break loop
}
// Timer was already run and t is no longer in a heap.
// Act like addtimer.
- if atomic.Cas(&t.status, status, timerModifying) {
+ if t.status.CompareAndSwap(status, timerModifying) {
wasRemoved = true
pending = false // timer already run or stopped
break loop
// Prevent preemption while the timer is in timerModifying.
// This could lead to a self-deadlock. See #38070.
mp = acquirem()
- if atomic.Cas(&t.status, status, timerModifying) {
+ if t.status.CompareAndSwap(status, timerModifying) {
t.pp.ptr().deletedTimers.Add(-1)
pending = false // timer already stopped
break loop
lock(&pp.timersLock)
doaddtimer(pp, t)
unlock(&pp.timersLock)
- if !atomic.Cas(&t.status, timerModifying, timerWaiting) {
+ if !t.status.CompareAndSwap(timerModifying, timerWaiting) {
badTimer()
}
releasem(mp)
}
// Set the new status of the timer.
- if !atomic.Cas(&t.status, timerModifying, newStatus) {
+ if !t.status.CompareAndSwap(timerModifying, newStatus) {
badTimer()
}
releasem(mp)
if t.pp.ptr() != pp {
throw("cleantimers: bad p")
}
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerDeleted:
- if !atomic.Cas(&t.status, s, timerRemoving) {
+ if !t.status.CompareAndSwap(s, timerRemoving) {
continue
}
dodeltimer0(pp)
- if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+ if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
badTimer()
}
pp.deletedTimers.Add(-1)
case timerModifiedEarlier, timerModifiedLater:
- if !atomic.Cas(&t.status, s, timerMoving) {
+ if !t.status.CompareAndSwap(s, timerMoving) {
continue
}
// Now we can change the when field.
// Move t to the right position.
dodeltimer0(pp)
doaddtimer(pp, t)
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
default:
for _, t := range timers {
loop:
for {
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerWaiting:
- if !atomic.Cas(&t.status, s, timerMoving) {
+ if !t.status.CompareAndSwap(s, timerMoving) {
continue
}
t.pp = 0
doaddtimer(pp, t)
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
break loop
case timerModifiedEarlier, timerModifiedLater:
- if !atomic.Cas(&t.status, s, timerMoving) {
+ if !t.status.CompareAndSwap(s, timerMoving) {
continue
}
t.when = t.nextwhen
t.pp = 0
doaddtimer(pp, t)
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
break loop
case timerDeleted:
- if !atomic.Cas(&t.status, s, timerRemoved) {
+ if !t.status.CompareAndSwap(s, timerRemoved) {
continue
}
t.pp = 0
if t.pp.ptr() != pp {
throw("adjusttimers: bad p")
}
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerDeleted:
- if atomic.Cas(&t.status, s, timerRemoving) {
+ if t.status.CompareAndSwap(s, timerRemoving) {
changed := dodeltimer(pp, i)
- if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+ if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
badTimer()
}
pp.deletedTimers.Add(-1)
i = changed - 1
}
case timerModifiedEarlier, timerModifiedLater:
- if atomic.Cas(&t.status, s, timerMoving) {
+ if t.status.CompareAndSwap(s, timerMoving) {
// Now we can change the when field.
t.when = t.nextwhen
// Take t off the heap, and hold onto it.
func addAdjustedTimers(pp *p, moved []*timer) {
for _, t := range moved {
doaddtimer(pp, t)
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
}
if t.pp.ptr() != pp {
throw("runtimer: bad p")
}
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerWaiting:
if t.when > now {
// Not ready to run.
return t.when
}
- if !atomic.Cas(&t.status, s, timerRunning) {
+ if !t.status.CompareAndSwap(s, timerRunning) {
continue
}
// Note that runOneTimer may temporarily unlock
return 0
case timerDeleted:
- if !atomic.Cas(&t.status, s, timerRemoving) {
+ if !t.status.CompareAndSwap(s, timerRemoving) {
continue
}
dodeltimer0(pp)
- if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+ if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
badTimer()
}
pp.deletedTimers.Add(-1)
}
case timerModifiedEarlier, timerModifiedLater:
- if !atomic.Cas(&t.status, s, timerMoving) {
+ if !t.status.CompareAndSwap(s, timerMoving) {
continue
}
t.when = t.nextwhen
dodeltimer0(pp)
doaddtimer(pp, t)
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
t.when = maxWhen
}
siftdownTimer(pp.timers, 0)
- if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
+ if !t.status.CompareAndSwap(timerRunning, timerWaiting) {
badTimer()
}
updateTimer0When(pp)
} else {
// Remove from heap.
dodeltimer0(pp)
- if !atomic.Cas(&t.status, timerRunning, timerNoStatus) {
+ if !t.status.CompareAndSwap(timerRunning, timerNoStatus) {
badTimer()
}
}
nextTimer:
for _, t := range timers {
for {
- switch s := atomic.Load(&t.status); s {
+ switch s := t.status.Load(); s {
case timerWaiting:
if changedHeap {
timers[to] = t
to++
continue nextTimer
case timerModifiedEarlier, timerModifiedLater:
- if atomic.Cas(&t.status, s, timerMoving) {
+ if t.status.CompareAndSwap(s, timerMoving) {
t.when = t.nextwhen
timers[to] = t
siftupTimer(timers, to)
to++
changedHeap = true
- if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
badTimer()
}
continue nextTimer
}
case timerDeleted:
- if atomic.Cas(&t.status, s, timerRemoving) {
+ if t.status.CompareAndSwap(s, timerRemoving) {
t.pp = 0
cdel++
- if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+ if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
badTimer()
}
changedHeap = true