// raceCtx is the race context used while executing timer functions.
raceCtx uintptr
- // timer0When is an atomic copy of of heap[0].when.
- // If len(heap) == 0, timer0When is 0.
- timer0When atomic.Int64
+ // minWhen is the minimum heap[i].when value (= heap[0].when).
+ // The wakeTime method uses minWhen and minNextWhen to determine
+ // the next wake time.
+ // If minWhen = 0, it means there are no timers in the heap.
+ minWhen atomic.Int64
- // timerModifiedEarliest holds the earliest known heap[i].nextWhen field
- // for the heap entries with a new nextWhen pending
- // (that is, with the timerNextWhen bit set in t.state).
- // Because timers can be modified multiple times,
- // timerModifiedEarliest can be set to a nextWhen that has since
- // been replaced with a later time.
- // If this is 0, it means there are no timerNextWhen timers in the heap.
- timerModifiedEarliest atomic.Int64
+ // minNextWhen is a lower bound on the minimum
+ // heap[i].nextWhen over timers with the timerNextWhen bit set.
+ // If minNextWhen = 0, it means there are no timerNextWhen timers in the heap.
+ minNextWhen atomic.Int64
}
// Timer state field.
badTimer()
}
ts.siftDown(0)
- ts.updateTimer0When()
+ ts.updateMinWhen()
}
}
return state, true
ts.heap = append(ts.heap, t)
ts.siftUp(len(ts.heap) - 1)
if t == ts.heap[0] {
- ts.timer0When.Store(t.when)
+ ts.minWhen.Store(t.when)
}
ts.len.Add(1)
}
if last > 0 {
ts.siftDown(0)
}
- ts.updateTimer0When()
+ ts.updateMinWhen()
n := ts.len.Add(-1)
if n == 0 {
// If there are no timers, then clearly none are modified.
- ts.timerModifiedEarliest.Store(0)
+ ts.minNextWhen.Store(0)
}
}
state |= timerNextWhen
earlier := when < t.when
if earlier {
- t.ts.updateTimerModifiedEarliest(when)
+ t.ts.updateMinNextWhen(when)
}
t.unlock(state, mp)
src.heap = nil
src.len.Store(0)
src.zombies.Store(0)
- src.timer0When.Store(0)
+ src.minWhen.Store(0)
unlock(&ts.lock)
unlock(&src.lock)
}
// We'll postpone looking through all the adjusted timers until
// one would actually expire.
if !force {
- first := ts.timerModifiedEarliest.Load()
+ first := ts.minNextWhen.Load()
if first == 0 || first > now {
if verifyTimers {
ts.verify()
}
// We are going to clear all timerModified timers.
- ts.timerModifiedEarliest.Store(0)
+ ts.minNextWhen.Store(0)
changed := false
for i := 0; i < len(ts.heap); i++ {
if changed {
ts.initHeap()
- ts.updateTimer0When()
+ ts.updateMinWhen()
}
if verifyTimers {
//
//go:nowritebarrierrec
func (ts *timers) wakeTime() int64 {
- next := ts.timer0When.Load()
- nextAdj := ts.timerModifiedEarliest.Load()
+ next := ts.minWhen.Load()
+ nextAdj := ts.minNextWhen.Load()
if next == 0 || (nextAdj != 0 && nextAdj < next) {
next = nextAdj
}
func (ts *timers) check(now int64) (rnow, pollUntil int64, ran bool) {
// If it's not yet time for the first timer, or the first adjusted
// timer, then there is nothing to do.
- next := ts.timer0When.Load()
- nextAdj := ts.timerModifiedEarliest.Load()
+ next := ts.minWhen.Load()
+ nextAdj := ts.minNextWhen.Load()
if next == 0 || (nextAdj != 0 && nextAdj < next) {
next = nextAdj
}
}
}
-// updateTimer0When sets ts.timer0When to ts.heap[0].when.
+// updateMinWhen sets ts.minWhen to ts.heap[0].when.
// The caller must have locked ts.
-func (ts *timers) updateTimer0When() {
+func (ts *timers) updateMinWhen() {
assertLockHeld(&ts.lock)
if len(ts.heap) == 0 {
- ts.timer0When.Store(0)
+ ts.minWhen.Store(0)
} else {
- ts.timer0When.Store(ts.heap[0].when)
+ ts.minWhen.Store(ts.heap[0].when)
}
}
-// updateTimerModifiedEarliest updates ts.timerModifiedEarliest to be <= nextwhen.
-// The timers for ts need not be locked.
-func (ts *timers) updateTimerModifiedEarliest(nextwhen int64) {
+// updateMinNextWhen updates ts.minNextWhen to be <= when.
+// ts need not be (and usually is not) locked.
+func (ts *timers) updateMinNextWhen(when int64) {
for {
- old := ts.timerModifiedEarliest.Load()
- if old != 0 && old < nextwhen {
+ old := ts.minNextWhen.Load()
+ if old != 0 && old < when {
return
}
-
- if ts.timerModifiedEarliest.CompareAndSwap(old, nextwhen) {
+ if ts.minNextWhen.CompareAndSwap(old, when) {
return
}
}
continue
}
- w := pp.timers.timer0When.Load()
+ w := pp.timers.minWhen.Load()
if w != 0 && w < next {
next = w
}
- w = pp.timers.timerModifiedEarliest.Load()
+ w = pp.timers.minNextWhen.Load()
if w != 0 && w < next {
next = w
}