type timer … // init initializes a newly allocated timer t. // Any code that allocates a timer must call t.init before using it. // The arg and f can be set during init, or they can be nil in init // and set by a future call to t.modify. func (t *timer) init(f func(arg any, seq uintptr, delay int64), arg any) { … } type timers … type timerWhen … func (ts *timers) lock() { … } func (ts *timers) unlock() { … } const timerHeaped … const timerModified … const timerZombie … const timerDebug … func (t *timer) trace(op string) { … } func (t *timer) trace1(op string) { … } func (ts *timers) trace(op string) { … } // lock locks the timer, allowing reading or writing any of the timer fields. func (t *timer) lock() { … } // unlock updates t.astate and unlocks the timer. func (t *timer) unlock() { … } // hchan returns the channel in t.arg. // t must be a timer with a channel. func (t *timer) hchan() *hchan { … } // updateHeap updates t as directed by t.state, updating t.state // and returning a bool indicating whether the state (and ts.heap[0].when) changed. // The caller must hold t's lock, or the world can be stopped instead. // The timer set t.ts must be non-nil and locked, t must be t.ts.heap[0], and updateHeap // takes care of moving t within the timers heap to preserve the heap invariants. // If ts == nil, then t must not be in a heap (or is in a heap that is // temporarily not maintaining its invariant, such as during timers.adjust). func (t *timer) updateHeap() (updated bool) { … } const maxWhen … const verifyTimers … // timeSleep puts the current goroutine to sleep for at least ns nanoseconds. // //go:linkname timeSleep time.Sleep func timeSleep(ns int64) { … } // resetForSleep is called after the goroutine is parked for timeSleep. // We can't call timer.reset in timeSleep itself because if this is a short // sleep and there are many goroutines then the P can wind up running the // timer function, goroutineReady, before the goroutine has been parked. func resetForSleep(gp *g, _ unsafe.Pointer) bool { … } type timeTimer … // newTimer allocates and returns a new time.Timer or time.Ticker (same layout) // with the given parameters. // //go:linkname newTimer time.newTimer func newTimer(when, period int64, f func(arg any, seq uintptr, delay int64), arg any, c *hchan) *timeTimer { … } // stopTimer stops a timer. // It reports whether t was stopped before being run. // //go:linkname stopTimer time.stopTimer func stopTimer(t *timeTimer) bool { … } // resetTimer resets an inactive timer, adding it to the timer heap. // // Reports whether the timer was modified before it was run. // //go:linkname resetTimer time.resetTimer func resetTimer(t *timeTimer, when, period int64) bool { … } // Ready the goroutine arg. func goroutineReady(arg any, _ uintptr, _ int64) { … } // addHeap adds t to the timers heap. // The caller must hold ts.lock or the world must be stopped. // The caller must also have checked that t belongs in the heap. // Callers that are not sure can call t.maybeAdd instead, // but note that maybeAdd has different locking requirements. func (ts *timers) addHeap(t *timer) { … } // maybeRunAsync checks whether t needs to be triggered and runs it if so. // The caller is responsible for locking the timer and for checking that we // are running timers in async mode. If the timer needs to be run, // maybeRunAsync will unlock and re-lock it. // The timer is always locked on return. func (t *timer) maybeRunAsync() { … } // stop stops the timer t. It may be on some other P, so we can't // actually remove it from the timers heap. We can only mark it as stopped. // It will be removed in due course by the P whose heap it is on. // Reports whether the timer was stopped before it was run. func (t *timer) stop() bool { … } // deleteMin removes timer 0 from ts. // ts must be locked. func (ts *timers) deleteMin() { … } // modify modifies an existing timer. // This is called by the netpoll code or time.Ticker.Reset or time.Timer.Reset. // Reports whether the timer was modified before it was run. // If f == nil, then t.f, t.arg, and t.seq are not modified. func (t *timer) modify(when, period int64, f func(arg any, seq uintptr, delay int64), arg any, seq uintptr) bool { … } // needsAdd reports whether t needs to be added to a timers heap. // t must be locked. func (t *timer) needsAdd() bool { … } // maybeAdd adds t to the local timers heap if it needs to be in a heap. // The caller must not hold t's lock nor any timers heap lock. // The caller probably just unlocked t, but that lock must be dropped // in order to acquire a ts.lock, to avoid lock inversions. // (timers.adjust holds ts.lock while acquiring each t's lock, // so we cannot hold any t's lock while acquiring ts.lock). // // Strictly speaking it *might* be okay to hold t.lock and // acquire ts.lock at the same time, because we know that // t is not in any ts.heap, so nothing holding a ts.lock would // be acquiring the t.lock at the same time, meaning there // isn't a possible deadlock. But it is easier and safer not to be // too clever and respect the static ordering. // (If we don't, we have to change the static lock checking of t and ts.) // // Concurrent calls to time.Timer.Reset or blockTimerChan // may result in concurrent calls to t.maybeAdd, // so we cannot assume that t is not in a heap on entry to t.maybeAdd. func (t *timer) maybeAdd() { … } // reset resets the time when a timer should fire. // If used for an inactive timer, the timer will become active. // Reports whether the timer was active and was stopped. func (t *timer) reset(when, period int64) bool { … } // cleanHead cleans up the head of the timer queue. This speeds up // programs that create and delete timers; leaving them in the heap // slows down heap operations. // The caller must have locked ts. func (ts *timers) cleanHead() { … } // take moves any timers from src into ts // and then clears the timer state from src, // because src is being destroyed. // The caller must not have locked either timers. // For now this is only called when the world is stopped. func (ts *timers) take(src *timers) { … } // adjust looks through the timers in ts.heap for // any timers that have been modified to run earlier, and puts them in // the correct place in the heap. While looking for those timers, // it also moves timers that have been modified to run later, // and removes deleted timers. The caller must have locked ts. func (ts *timers) adjust(now int64, force bool) { … } // wakeTime looks at ts's timers and returns the time when we // should wake up the netpoller. It returns 0 if there are no timers. // This function is invoked when dropping a P, so it must run without // any write barriers. // //go:nowritebarrierrec func (ts *timers) wakeTime() int64 { … } // check runs any timers in ts that are ready. // If now is not 0 it is the current time. // It returns the passed time or the current time if now was passed as 0. // and the time when the next timer should run or 0 if there is no next timer, // and reports whether it ran any timers. // If the time when the next timer should run is not 0, // it is always larger than the returned time. // We pass now in and out to avoid extra calls of nanotime. // //go:yeswritebarrierrec func (ts *timers) check(now int64) (rnow, pollUntil int64, ran bool) { … } // run examines the first timer in ts. If it is ready based on now, // it runs the timer and removes or updates it. // Returns 0 if it ran a timer, -1 if there are no more timers, or the time // when the first timer should run. // The caller must have locked ts. // If a timer is run, this will temporarily unlock ts. // //go:systemstack func (ts *timers) run(now int64) int64 { … } // unlockAndRun unlocks and runs the timer t (which must be locked). // If t is in a timer set (t.ts != nil), the caller must also have locked the timer set, // and this call will temporarily unlock the timer set while running the timer function. // unlockAndRun returns with t unlocked and t.ts (re-)locked. // //go:systemstack func (t *timer) unlockAndRun(now int64) { … } // verifyTimerHeap verifies that the timers is in a valid state. // This is only for debugging, and is only called if verifyTimers is true. // The caller must have locked ts. func (ts *timers) verify() { … } // updateMinWhenHeap sets ts.minWhenHeap to ts.heap[0].when. // The caller must have locked ts or the world must be stopped. func (ts *timers) updateMinWhenHeap() { … } // updateMinWhenModified updates ts.minWhenModified to be <= when. // ts need not be (and usually is not) locked. func (ts *timers) updateMinWhenModified(when int64) { … } // timeSleepUntil returns the time when the next timer should fire. Returns // maxWhen if there are no timers. // This is only called by sysmon and checkdead. func timeSleepUntil() int64 { … } const timerHeapN … // siftUp puts the timer at position i in the right place // in the heap by moving it up toward the top of the heap. func (ts *timers) siftUp(i int) { … } // siftDown puts the timer at position i in the right place // in the heap by moving it down toward the bottom of the heap. func (ts *timers) siftDown(i int) { … } // initHeap reestablishes the heap order in the slice ts.heap. // It takes O(n) time for n=len(ts.heap), not the O(n log n) of n repeated add operations. func (ts *timers) initHeap() { … } // badTimer is called if the timer data structures have been corrupted, // presumably due to racy use by the program. We panic here rather than // panicking due to invalid slice access while holding locks. // See issue #25686. func badTimer() { … } // maybeRunChan checks whether the timer needs to run // to send a value to its associated channel. If so, it does. // The timer must not be locked. func (t *timer) maybeRunChan() { … } // blockTimerChan is called when a channel op has decided to block on c. // The caller holds the channel lock for c and possibly other channels. // blockTimerChan makes sure that c is in a timer heap, // adding it if needed. func blockTimerChan(c *hchan) { … } // unblockTimerChan is called when a channel op that was blocked on c // is no longer blocked. Every call to blockTimerChan must be paired with // a call to unblockTimerChan. // The caller holds the channel lock for c and possibly other channels. // unblockTimerChan removes c from the timer heap when nothing is // blocked on it anymore. func unblockTimerChan(c *hchan) { … }