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 // Export temporarily for gccgo's C code to call:
12 //go:linkname addtimer runtime.addtimer
13 //go:linkname deltimer runtime.deltimer
15 // Package time knows the layout of this structure.
16 // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
17 // For GOOS=nacl, package syscall knows the layout of this structure.
18 // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
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)
42 // nacl fake time support - time in nanoseconds since 1970
46 // Godoc uses the comments in package time, not these.
48 // time.now is implemented in assembly.
50 // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
51 //go:linkname timeSleep time.Sleep
52 func timeSleep(ns
int64) {
58 t
.when
= nanotime() + ns
63 goparkunlock(&timers
.lock
, "sleep", traceEvGoSleep
, 2)
66 // startTimer adds t to the timer heap.
67 //go:linkname startTimer time.startTimer
68 func startTimer(t
*timer
) {
70 racerelease(unsafe
.Pointer(t
))
75 // stopTimer removes t from the timer heap if it is there.
76 // It returns true if t was removed, false if t wasn't even there.
77 //go:linkname stopTimer time.stopTimer
78 func stopTimer(t
*timer
) bool {
84 // Ready the goroutine arg.
85 func goroutineReady(arg
interface{}, seq
uintptr) {
89 func addtimer(t
*timer
) {
95 // Add a timer to the heap and start or kick the timer proc.
96 // If the new timer is earlier than any of the others.
98 func addtimerLocked(t
*timer
) {
99 // when must never be negative; otherwise timerproc will overflow
100 // during its delta calculation and never expire other runtime·timers.
105 timers
.t
= append(timers
.t
, t
)
108 // siftup moved to top: new earliest deadline.
110 timers
.sleeping
= false
111 notewakeup(&timers
.waitnote
)
113 if timers
.rescheduling
{
114 timers
.rescheduling
= false
115 goready(timers
.gp
, 0)
119 timers
.created
= true
124 // Delete timer t from the heap.
125 // Do not need to update the timerproc: if it wakes up early, no big deal.
126 func deltimer(t
*timer
) bool {
127 // Dereference t so that any panic happens before the lock is held.
128 // Discard result, because t might be moving in the heap.
132 // t may not be registered anymore and may have
133 // a bogus i (typically 0, if generated by Go).
134 // Verify it before proceeding.
136 last
:= len(timers
.t
) - 1
137 if i
< 0 || i
> last || timers
.t
[i
] != t
{
142 timers
.t
[i
] = timers
.t
[last
]
146 timers
.t
= timers
.t
[:last
]
155 // Timerproc runs the time-driven events.
156 // It sleeps until the next event in the timers heap.
157 // If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
162 timers
.sleeping
= false
166 if len(timers
.t
) == 0 {
176 // leave in heap but adjust next time to fire
177 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
181 last
:= len(timers
.t
) - 1
183 timers
.t
[0] = timers
.t
[last
]
187 timers
.t
= timers
.t
[:last
]
191 t
.i
= -1 // mark as removed
198 raceacquire(unsafe
.Pointer(t
))
203 if delta
< 0 || faketime
> 0 {
204 // No timers left - put goroutine to sleep.
205 timers
.rescheduling
= true
206 goparkunlock(&timers
.lock
, "timer goroutine (idle)", traceEvGoBlock
, 1)
209 // At least one timer pending. Sleep until then.
210 timers
.sleeping
= true
211 noteclear(&timers
.waitnote
)
213 notetsleepg(&timers
.waitnote
, delta
)
223 if !timers
.created ||
len(timers
.t
) == 0 {
229 if faketime
< timers
.t
[0].when
{
230 faketime
= timers
.t
[0].when
231 if timers
.rescheduling
{
232 timers
.rescheduling
= false
240 // Heap maintenance algorithms.
242 func siftupTimer(i
int) {
247 p
:= (i
- 1) / 4 // parent
248 if when
>= t
[p
].when
{
259 func siftdownTimer(i
int) {
265 c
:= i
*4 + 1 // left child
266 c3
:= c
+ 2 // mid child
271 if c
+1 < n
&& t
[c
+1].when
< w
{
277 if c3
+1 < n
&& t
[c3
+1].when
< w3
{
297 // Entry points for net, time to call nanotime.
299 //go:linkname net_runtimeNano net.runtimeNano
300 func net_runtimeNano() int64 {
304 //go:linkname time_runtimeNano time.runtimeNano
305 func time_runtimeNano() int64 {