1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Time-related runtime and pieces of package time.
14 // Package time knows the layout of this structure.
15 // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
16 // For GOOS=nacl, package syscall knows the layout of this structure.
17 // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
19 tb *timersBucket // the bucket the timer lives in
22 // Timer wakes up at when, and then at when+period, ... (period > 0 only)
23 // each time calling f(arg, now) in the timer goroutine, so f must be
24 // a well-behaved function and not block.
27 f func(interface{}, uintptr)
32 // timersLen is the length of timers array.
34 // Ideally, this would be set to GOMAXPROCS, but that would require
35 // dynamic reallocation
37 // The current value is a compromise between memory usage and performance
38 // that should cover the majority of GOMAXPROCS values used in the wild.
41 // timers contains "per-P" timer heaps.
43 // Timers are queued into timersBucket associated with the current P,
44 // so each P may work with its own timers independently of other P instances.
46 // Each timersBucket may be associated with multiple P
47 // if GOMAXPROCS > timersLen.
48 var timers [timersLen]struct {
51 // The padding should eliminate false sharing
52 // between timersBucket values.
53 pad [cpu.CacheLinePadSize - unsafe.Sizeof(timersBucket{})%cpu.CacheLinePadSize]byte
56 func (t *timer) assignBucket() *timersBucket {
57 id := uint8(getg().m.p.ptr().id) % timersLen
58 t.tb = &timers[id].timersBucket
63 type timersBucket struct {
74 // nacl fake time support - time in nanoseconds since 1970
78 // Godoc uses the comments in package time, not these.
80 // time.now is implemented in assembly.
82 // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
83 //go:linkname timeSleep time.Sleep
84 func timeSleep(ns int64) {
96 t.when = nanotime() + ns
99 tb := t.assignBucket()
101 if !tb.addtimerLocked(t) {
105 goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 2)
108 // startTimer adds t to the timer heap.
109 //go:linkname startTimer time.startTimer
110 func startTimer(t *timer) {
112 racerelease(unsafe.Pointer(t))
117 // stopTimer removes t from the timer heap if it is there.
118 // It returns true if t was removed, false if t wasn't even there.
119 //go:linkname stopTimer time.stopTimer
120 func stopTimer(t *timer) bool {
126 // Ready the goroutine arg.
127 func goroutineReady(arg interface{}, seq uintptr) {
131 func addtimer(t *timer) {
132 tb := t.assignBucket()
134 ok := tb.addtimerLocked(t)
141 // Add a timer to the heap and start or kick timerproc if the new timer is
142 // earlier than any of the others.
143 // Timers are locked.
144 // Returns whether all is well: false if the data structure is corrupt
145 // due to user-level races.
146 func (tb *timersBucket) addtimerLocked(t *timer) bool {
147 // when must never be negative; otherwise timerproc will overflow
148 // during its delta calculation and never expire other runtime timers.
153 tb.t = append(tb.t, t)
154 if !siftupTimer(tb.t, t.i) {
158 // siftup moved to top: new earliest deadline.
159 if tb.sleeping && tb.sleepUntil > t.when {
161 notewakeup(&tb.waitnote)
164 tb.rescheduling = false
169 expectSystemGoroutine()
176 // Delete timer t from the heap.
177 // Do not need to update the timerproc: if it wakes up early, no big deal.
178 func deltimer(t *timer) bool {
180 // t.tb can be nil if the user created a timer
181 // directly, without invoking startTimer e.g
183 // In this case, return early without any deletion.
191 removed, ok := tb.deltimerLocked(t)
199 func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
200 // t may not be registered anymore and may have
201 // a bogus i (typically 0, if generated by Go).
202 // Verify it before proceeding.
204 last := len(tb.t) - 1
205 if i < 0 || i > last || tb.t[i] != t {
216 if !siftupTimer(tb.t, i) {
219 if !siftdownTimer(tb.t, i) {
226 func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
230 _, ok := tb.deltimerLocked(t)
237 ok = tb.addtimerLocked(t)
245 // Timerproc runs the time-driven events.
246 // It sleeps until the next event in the tb heap.
247 // If addtimer inserts a new earlier event, it wakes timerproc early.
248 func timerproc(tb *timersBucket) {
269 // leave in heap but adjust next time to fire
270 t.when += t.period * (1 + -delta/t.period)
271 if !siftdownTimer(tb.t, 0) {
276 last := len(tb.t) - 1
284 if !siftdownTimer(tb.t, 0) {
288 t.i = -1 // mark as removed
298 raceacquire(unsafe.Pointer(t))
303 if delta < 0 || faketime > 0 {
304 // No timers left - put goroutine to sleep.
305 tb.rescheduling = true
306 goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
309 // At least one timer pending. Sleep until then.
311 tb.sleepUntil = now + delta
312 noteclear(&tb.waitnote)
314 notetsleepg(&tb.waitnote, delta)
323 for i := range timers {
324 lock(&timers[i].lock)
326 gp := timejumpLocked()
327 for i := range timers {
328 unlock(&timers[i].lock)
334 func timejumpLocked() *g {
335 // Determine a timer bucket with minimum when.
337 for i := range timers {
339 if !tb.created || len(tb.t) == 0 {
343 if minT == nil || t.when < minT.when {
347 if minT == nil || minT.when <= faketime {
353 if !tb.rescheduling {
356 tb.rescheduling = false
360 func timeSleepUntil() int64 {
361 next := int64(1<<63 - 1)
363 // Determine minimum sleepUntil across all the timer buckets.
365 // The function can not return a precise answer,
366 // as another timer may pop in as soon as timers have been unlocked.
367 // So lock the timers one by one instead of all at once.
368 for i := range timers {
372 if tb.sleeping && tb.sleepUntil < next {
381 // Heap maintenance algorithms.
382 // These algorithms check for slice index errors manually.
383 // Slice index error can happen if the program is using racy
384 // access to timers. We don't want to panic here, because
385 // it will cause the program to crash with a mysterious
386 // "panic holding locks" message. Instead, we panic while not
388 // The races can occur despite the bucket locks because assignBucket
389 // itself is called without locks, so racy calls can cause a timer to
390 // change buckets while executing these functions.
392 func siftupTimer(t []*timer, i int) bool {
399 p := (i - 1) / 4 // parent
400 if when >= t[p].when {
414 func siftdownTimer(t []*timer, i int) bool {
422 c := i*4 + 1 // left child
423 c3 := c + 2 // mid child
428 if c+1 < n && t[c+1].when < w {
434 if c3+1 < n && t[c3+1].when < w3 {
457 // badTimer is called if the timer data structures have been corrupted,
458 // presumably due to racy use by the program. We panic here rather than
459 // panicing due to invalid slice access while holding locks.
462 panic(errorString("racy use of timers"))