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
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()
102 goparkunlock(&tb
.lock
, "sleep", traceEvGoSleep
, 2)
105 // startTimer adds t to the timer heap.
106 //go:linkname startTimer time.startTimer
107 func startTimer(t
*timer
) {
109 racerelease(unsafe
.Pointer(t
))
114 // stopTimer removes t from the timer heap if it is there.
115 // It returns true if t was removed, false if t wasn't even there.
116 //go:linkname stopTimer time.stopTimer
117 func stopTimer(t
*timer
) bool {
123 // Ready the goroutine arg.
124 func goroutineReady(arg
interface{}, seq
uintptr) {
128 func addtimer(t
*timer
) {
129 tb
:= t
.assignBucket()
135 // Add a timer to the heap and start or kick timerproc if the new timer is
136 // earlier than any of the others.
137 // Timers are locked.
138 func (tb
*timersBucket
) addtimerLocked(t
*timer
) {
139 // when must never be negative; otherwise timerproc will overflow
140 // during its delta calculation and never expire other runtime timers.
145 tb
.t
= append(tb
.t
, t
)
146 siftupTimer(tb
.t
, t
.i
)
148 // siftup moved to top: new earliest deadline.
151 notewakeup(&tb
.waitnote
)
154 tb
.rescheduling
= false
160 expectSystemGoroutine()
165 // Delete timer t from the heap.
166 // Do not need to update the timerproc: if it wakes up early, no big deal.
167 func deltimer(t
*timer
) bool {
169 // t.tb can be nil if the user created a timer
170 // directly, without invoking startTimer e.g
172 // In this case, return early without any deletion.
180 // t may not be registered anymore and may have
181 // a bogus i (typically 0, if generated by Go).
182 // Verify it before proceeding.
184 last
:= len(tb
.t
) - 1
185 if i
< 0 || i
> last || tb
.t
[i
] != t
{
197 siftdownTimer(tb
.t
, i
)
203 // Timerproc runs the time-driven events.
204 // It sleeps until the next event in the tb heap.
205 // If addtimer inserts a new earlier event, it wakes timerproc early.
206 func timerproc(tb
*timersBucket
) {
226 // leave in heap but adjust next time to fire
227 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
228 siftdownTimer(tb
.t
, 0)
231 last
:= len(tb
.t
) - 1
239 siftdownTimer(tb
.t
, 0)
241 t
.i
= -1 // mark as removed
248 raceacquire(unsafe
.Pointer(t
))
253 if delta
< 0 || faketime
> 0 {
254 // No timers left - put goroutine to sleep.
255 tb
.rescheduling
= true
256 goparkunlock(&tb
.lock
, "timer goroutine (idle)", traceEvGoBlock
, 1)
259 // At least one timer pending. Sleep until then.
261 tb
.sleepUntil
= now
+ delta
262 noteclear(&tb
.waitnote
)
264 notetsleepg(&tb
.waitnote
, delta
)
273 for i
:= range timers
{
274 lock(&timers
[i
].lock
)
276 gp
:= timejumpLocked()
277 for i
:= range timers
{
278 unlock(&timers
[i
].lock
)
284 func timejumpLocked() *g
{
285 // Determine a timer bucket with minimum when.
287 for i
:= range timers
{
289 if !tb
.created ||
len(tb
.t
) == 0 {
293 if minT
== nil || t
.when
< minT
.when
{
297 if minT
== nil || minT
.when
<= faketime
{
303 if !tb
.rescheduling
{
306 tb
.rescheduling
= false
310 func timeSleepUntil() int64 {
311 next
:= int64(1<<63 - 1)
313 // Determine minimum sleepUntil across all the timer buckets.
315 // The function can not return a precise answer,
316 // as another timer may pop in as soon as timers have been unlocked.
317 // So lock the timers one by one instead of all at once.
318 for i
:= range timers
{
322 if tb
.sleeping
&& tb
.sleepUntil
< next
{
331 // Heap maintenance algorithms.
333 func siftupTimer(t
[]*timer
, i
int) {
337 p
:= (i
- 1) / 4 // parent
338 if when
>= t
[p
].when
{
351 func siftdownTimer(t
[]*timer
, i
int) {
356 c
:= i
*4 + 1 // left child
357 c3
:= c
+ 2 // mid child
362 if c
+1 < n
&& t
[c
+1].when
< w
{
368 if c3
+1 < n
&& t
[c3
+1].when
< w3
{
390 // Entry points for net, time to call nanotime.
392 //go:linkname poll_runtimeNano internal_poll.runtimeNano
393 func poll_runtimeNano() int64 {
397 //go:linkname time_runtimeNano time.runtimeNano
398 func time_runtimeNano() int64 {
402 // Monotonic times are reported as offsets from startNano.
403 // We initialize startNano to nanotime() - 1 so that on systems where
404 // monotonic time resolution is fairly low (e.g. Windows 2008
405 // which appears to have a default resolution of 15ms),
406 // we avoid ever reporting a nanotime of 0.
407 // (Callers may want to use 0 as "time not set".)
408 var startNano
int64 = nanotime() - 1