//
// Active timers live in heaps attached to P, in the timers field.
// Inactive timers live there too temporarily, until they are removed.
+//
+// addtimer:
+// timerNoStatus -> timerWaiting
+// anything else -> panic: invalid value
// Values for the timer status field.
const (
timerMoving
)
+// maxWhen is the maximum value for timer's when field.
+const maxWhen = 1<<63 - 1
+
// Package time APIs.
// Godoc uses the comments in package time, not these.
goready(arg.(*g), 0)
}
+// 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,
+// which could cause the heap to become unsorted.
func addtimer(t *timer) {
if oldTimers {
addtimerOld(t)
return
}
- throw("new addtimer not yet implemented")
+
+ // when must never be negative; otherwise runtimer will overflow
+ // during its delta calculation and never expire other runtime timers.
+ if t.when < 0 {
+ t.when = maxWhen
+ }
+ if t.status != timerNoStatus {
+ badTimer()
+ }
+ t.status = timerWaiting
+
+ when := t.when
+
+ pp := getg().m.p.ptr()
+ lock(&pp.timersLock)
+ ok := cleantimers(pp) && doaddtimer(pp, t)
+ unlock(&pp.timersLock)
+ if !ok {
+ badTimer()
+ }
+
+ wakeNetPoller(when)
+}
+
+// doaddtimer adds t to the current P's heap.
+// It reports whether it saw no problems due to races.
+// The caller must have locked the timers for pp.
+func doaddtimer(pp *p, t *timer) bool {
+ // Timers rely on the network poller, so make sure the poller
+ // has started.
+ if netpollInited == 0 {
+ netpollGenericInit()
+ }
+
+ if t.pp != 0 {
+ throw("doaddtimer: P already set in timer")
+ }
+ t.pp.set(pp)
+ i := len(pp.timers)
+ pp.timers = append(pp.timers, t)
+ return siftupTimer(pp.timers, i)
}
func addtimerOld(t *timer) {
}
}
+// cleantimers cleans up the head of the timer queue. This speeds up
+// programs that create and delete timers; leaving them in the heap
+// slows down addtimer. Reports whether no timer problems were found.
+// The caller must have locked the timers for pp.
+func cleantimers(pp *p) bool {
+ // TODO: write this.
+ throw("cleantimers")
+ return true
+}
+
// moveTimers moves a slice of timers to pp. The slice has been taken
// from a different P.
// This is currently called when the world is stopped, but it could