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.
10 "runtime/internal/sys"
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
[sys
.CacheLineSize
- unsafe
.Sizeof(timersBucket
{})%sys
.CacheLineSize
]byte
56 func (t
*timer
) assignBucket() *timersBucket
{
57 id
:= uint8(getg().m
.p
.ptr().id
) % timersLen
58 t
.tb
= &timers
[id
].timersBucket
62 type timersBucket
struct {
73 // nacl fake time support - time in nanoseconds since 1970
77 // Godoc uses the comments in package time, not these.
79 // time.now is implemented in assembly.
81 // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
82 //go:linkname timeSleep time.Sleep
83 func timeSleep(ns
int64) {
95 t
.when
= nanotime() + ns
98 tb
:= t
.assignBucket()
101 goparkunlock(&tb
.lock
, "sleep", traceEvGoSleep
, 2)
104 // startTimer adds t to the timer heap.
105 //go:linkname startTimer time.startTimer
106 func startTimer(t
*timer
) {
108 racerelease(unsafe
.Pointer(t
))
113 // stopTimer removes t from the timer heap if it is there.
114 // It returns true if t was removed, false if t wasn't even there.
115 //go:linkname stopTimer time.stopTimer
116 func stopTimer(t
*timer
) bool {
122 // Ready the goroutine arg.
123 func goroutineReady(arg
interface{}, seq
uintptr) {
127 func addtimer(t
*timer
) {
128 tb
:= t
.assignBucket()
134 // Add a timer to the heap and start or kick timerproc if the new timer is
135 // earlier than any of the others.
136 // Timers are locked.
137 func (tb
*timersBucket
) addtimerLocked(t
*timer
) {
138 // when must never be negative; otherwise timerproc will overflow
139 // during its delta calculation and never expire other runtime timers.
144 tb
.t
= append(tb
.t
, t
)
145 siftupTimer(tb
.t
, t
.i
)
147 // siftup moved to top: new earliest deadline.
150 notewakeup(&tb
.waitnote
)
153 tb
.rescheduling
= false
159 expectSystemGoroutine()
164 // Delete timer t from the heap.
165 // Do not need to update the timerproc: if it wakes up early, no big deal.
166 func deltimer(t
*timer
) bool {
168 // t.tb can be nil if the user created a timer
169 // directly, without invoking startTimer e.g
171 // In this case, return early without any deletion.
179 // t may not be registered anymore and may have
180 // a bogus i (typically 0, if generated by Go).
181 // Verify it before proceeding.
183 last
:= len(tb
.t
) - 1
184 if i
< 0 || i
> last || tb
.t
[i
] != t
{
196 siftdownTimer(tb
.t
, i
)
202 // Timerproc runs the time-driven events.
203 // It sleeps until the next event in the tb heap.
204 // If addtimer inserts a new earlier event, it wakes timerproc early.
205 func timerproc(tb
*timersBucket
) {
225 // leave in heap but adjust next time to fire
226 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
227 siftdownTimer(tb
.t
, 0)
230 last
:= len(tb
.t
) - 1
238 siftdownTimer(tb
.t
, 0)
240 t
.i
= -1 // mark as removed
247 raceacquire(unsafe
.Pointer(t
))
252 if delta
< 0 || faketime
> 0 {
253 // No timers left - put goroutine to sleep.
254 tb
.rescheduling
= true
255 goparkunlock(&tb
.lock
, "timer goroutine (idle)", traceEvGoBlock
, 1)
258 // At least one timer pending. Sleep until then.
260 tb
.sleepUntil
= now
+ delta
261 noteclear(&tb
.waitnote
)
263 notetsleepg(&tb
.waitnote
, delta
)
272 for i
:= range timers
{
273 lock(&timers
[i
].lock
)
275 gp
:= timejumpLocked()
276 for i
:= range timers
{
277 unlock(&timers
[i
].lock
)
283 func timejumpLocked() *g
{
284 // Determine a timer bucket with minimum when.
286 for i
:= range timers
{
288 if !tb
.created ||
len(tb
.t
) == 0 {
292 if minT
== nil || t
.when
< minT
.when
{
296 if minT
== nil || minT
.when
<= faketime
{
302 if !tb
.rescheduling
{
305 tb
.rescheduling
= false
309 func timeSleepUntil() int64 {
310 next
:= int64(1<<63 - 1)
312 // Determine minimum sleepUntil across all the timer buckets.
314 // The function can not return a precise answer,
315 // as another timer may pop in as soon as timers have been unlocked.
316 // So lock the timers one by one instead of all at once.
317 for i
:= range timers
{
321 if tb
.sleeping
&& tb
.sleepUntil
< next
{
330 // Heap maintenance algorithms.
332 func siftupTimer(t
[]*timer
, i
int) {
336 p
:= (i
- 1) / 4 // parent
337 if when
>= t
[p
].when
{
350 func siftdownTimer(t
[]*timer
, i
int) {
355 c
:= i
*4 + 1 // left child
356 c3
:= c
+ 2 // mid child
361 if c
+1 < n
&& t
[c
+1].when
< w
{
367 if c3
+1 < n
&& t
[c3
+1].when
< w3
{
389 // Entry points for net, time to call nanotime.
391 //go:linkname poll_runtimeNano internal_poll.runtimeNano
392 func poll_runtimeNano() int64 {
396 //go:linkname time_runtimeNano time.runtimeNano
397 func time_runtimeNano() int64 {
401 // Monotonic times are reported as offsets from startNano.
402 // We initialize startNano to nanotime() - 1 so that on systems where
403 // monotonic time resolution is fairly low (e.g. Windows 2008
404 // which appears to have a default resolution of 15ms),
405 // we avoid ever reporting a nanotime of 0.
406 // (Callers may want to use 0 as "time not set".)
407 var startNano
int64 = nanotime() - 1