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.
11 // Package time knows the layout of this structure.
12 // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
13 // For GOOS=nacl, package syscall knows the layout of this structure.
14 // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
18 // Timer wakes up at when, and then at when+period, ... (period > 0 only)
19 // each time calling f(arg, now) in the timer goroutine, so f must be
20 // a well-behaved function and not block.
23 f
func(interface{}, uintptr)
39 // nacl fake time support - time in nanoseconds since 1970
43 // Godoc uses the comments in package time, not these.
45 // time.now is implemented in assembly.
47 // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
48 //go:linkname timeSleep time.Sleep
49 func timeSleep(ns
int64) {
60 t
.when
= nanotime() + ns
65 goparkunlock(&timers
.lock
, "sleep", traceEvGoSleep
, 2)
68 // startTimer adds t to the timer heap.
69 //go:linkname startTimer time.startTimer
70 func startTimer(t
*timer
) {
72 racerelease(unsafe
.Pointer(t
))
77 // stopTimer removes t from the timer heap if it is there.
78 // It returns true if t was removed, false if t wasn't even there.
79 //go:linkname stopTimer time.stopTimer
80 func stopTimer(t
*timer
) bool {
86 // Ready the goroutine arg.
87 func goroutineReady(arg
interface{}, seq
uintptr) {
91 func addtimer(t
*timer
) {
97 // Add a timer to the heap and start or kick timerproc if the new timer is
98 // earlier than any of the others.
100 func addtimerLocked(t
*timer
) {
101 // when must never be negative; otherwise timerproc will overflow
102 // during its delta calculation and never expire other runtime timers.
107 timers
.t
= append(timers
.t
, t
)
110 // siftup moved to top: new earliest deadline.
112 timers
.sleeping
= false
113 notewakeup(&timers
.waitnote
)
115 if timers
.rescheduling
{
116 timers
.rescheduling
= false
117 goready(timers
.gp
, 0)
121 timers
.created
= true
122 expectSystemGoroutine()
127 // Delete timer t from the heap.
128 // Do not need to update the timerproc: if it wakes up early, no big deal.
129 func deltimer(t
*timer
) bool {
130 // Dereference t so that any panic happens before the lock is held.
131 // Discard result, because t might be moving in the heap.
135 // t may not be registered anymore and may have
136 // a bogus i (typically 0, if generated by Go).
137 // Verify it before proceeding.
139 last
:= len(timers
.t
) - 1
140 if i
< 0 || i
> last || timers
.t
[i
] != t
{
145 timers
.t
[i
] = timers
.t
[last
]
149 timers
.t
= timers
.t
[:last
]
158 // Timerproc runs the time-driven events.
159 // It sleeps until the next event in the timers heap.
160 // If addtimer inserts a new earlier event, it wakes timerproc early.
167 timers
.sleeping
= false
171 if len(timers
.t
) == 0 {
181 // leave in heap but adjust next time to fire
182 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
186 last
:= len(timers
.t
) - 1
188 timers
.t
[0] = timers
.t
[last
]
192 timers
.t
= timers
.t
[:last
]
196 t
.i
= -1 // mark as removed
203 raceacquire(unsafe
.Pointer(t
))
208 if delta
< 0 || faketime
> 0 {
209 // No timers left - put goroutine to sleep.
210 timers
.rescheduling
= true
211 goparkunlock(&timers
.lock
, "timer goroutine (idle)", traceEvGoBlock
, 1)
214 // At least one timer pending. Sleep until then.
215 timers
.sleeping
= true
216 timers
.sleepUntil
= now
+ delta
217 noteclear(&timers
.waitnote
)
219 notetsleepg(&timers
.waitnote
, delta
)
229 if !timers
.created ||
len(timers
.t
) == 0 {
235 if faketime
< timers
.t
[0].when
{
236 faketime
= timers
.t
[0].when
237 if timers
.rescheduling
{
238 timers
.rescheduling
= false
246 // Heap maintenance algorithms.
248 func siftupTimer(i
int) {
253 p
:= (i
- 1) / 4 // parent
254 if when
>= t
[p
].when
{
265 func siftdownTimer(i
int) {
271 c
:= i
*4 + 1 // left child
272 c3
:= c
+ 2 // mid child
277 if c
+1 < n
&& t
[c
+1].when
< w
{
283 if c3
+1 < n
&& t
[c3
+1].when
< w3
{
303 // Entry points for net, time to call nanotime.
305 //go:linkname poll_runtimeNano internal_poll.runtimeNano
306 func poll_runtimeNano() int64 {
310 //go:linkname time_runtimeNano time.runtimeNano
311 func time_runtimeNano() int64 {
315 var startNano
int64 = nanotime()