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(now, arg) in the timer goroutine, so f must be
20 // a well-behaved function and not block.
23 f
func(interface{}, uintptr)
38 // nacl fake time support - time in nanoseconds since 1970
42 // Godoc uses the comments in package time, not these.
44 // time.now is implemented in assembly.
46 // Sleep puts the current goroutine to sleep for at least ns nanoseconds.
47 func timeSleep(ns
int64) {
53 t
.when
= nanotime() + ns
58 goparkunlock(&timers
.lock
, "sleep")
61 // startTimer adds t to the timer heap.
62 func startTimer(t
*timer
) {
64 racerelease(unsafe
.Pointer(t
))
69 // stopTimer removes t from the timer heap if it is there.
70 // It returns true if t was removed, false if t wasn't even there.
71 func stopTimer(t
*timer
) bool {
77 // Ready the goroutine arg.
78 func goroutineReady(arg
interface{}, seq
uintptr) {
82 func addtimer(t
*timer
) {
88 // Add a timer to the heap and start or kick the timer proc.
89 // If the new timer is earlier than any of the others.
91 func addtimerLocked(t
*timer
) {
92 // when must never be negative; otherwise timerproc will overflow
93 // during its delta calculation and never expire other runtime·timers.
98 timers
.t
= append(timers
.t
, t
)
101 // siftup moved to top: new earliest deadline.
103 timers
.sleeping
= false
104 notewakeup(&timers
.waitnote
)
106 if timers
.rescheduling
{
107 timers
.rescheduling
= false
112 timers
.created
= true
117 // Delete timer t from the heap.
118 // Do not need to update the timerproc: if it wakes up early, no big deal.
119 func deltimer(t
*timer
) bool {
120 // Dereference t so that any panic happens before the lock is held.
121 // Discard result, because t might be moving in the heap.
125 // t may not be registered anymore and may have
126 // a bogus i (typically 0, if generated by Go).
127 // Verify it before proceeding.
129 last
:= len(timers
.t
) - 1
130 if i
< 0 || i
> last || timers
.t
[i
] != t
{
135 timers
.t
[i
] = timers
.t
[last
]
139 timers
.t
= timers
.t
[:last
]
148 // Timerproc runs the time-driven events.
149 // It sleeps until the next event in the timers heap.
150 // If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
153 timers
.gp
.issystem
= true
156 timers
.sleeping
= false
160 if len(timers
.t
) == 0 {
170 // leave in heap but adjust next time to fire
171 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
175 last
:= len(timers
.t
) - 1
177 timers
.t
[0] = timers
.t
[last
]
181 timers
.t
= timers
.t
[:last
]
185 t
.i
= -1 // mark as removed
192 raceacquire(unsafe
.Pointer(t
))
197 if delta
< 0 || faketime
> 0 {
198 // No timers left - put goroutine to sleep.
199 timers
.rescheduling
= true
200 goparkunlock(&timers
.lock
, "timer goroutine (idle)")
203 // At least one timer pending. Sleep until then.
204 timers
.sleeping
= true
205 noteclear(&timers
.waitnote
)
207 notetsleepg(&timers
.waitnote
, delta
)
217 if !timers
.created ||
len(timers
.t
) == 0 {
223 if faketime
< timers
.t
[0].when
{
224 faketime
= timers
.t
[0].when
225 if timers
.rescheduling
{
226 timers
.rescheduling
= false
234 // Heap maintenance algorithms.
236 func siftupTimer(i
int) {
241 p
:= (i
- 1) / 4 // parent
242 if when
>= t
[p
].when
{
253 func siftdownTimer(i
int) {
259 c
:= i
*4 + 1 // left child
260 c3
:= c
+ 2 // mid child
265 if c
+1 < n
&& t
[c
+1].when
< w
{
271 if c3
+1 < n
&& t
[c3
+1].when
< w3
{