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)
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 // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
47 //go:linkname timeSleep time.Sleep
48 func timeSleep(ns
int64) {
54 t
.when
= nanotime() + ns
59 goparkunlock(&timers
.lock
, "sleep", traceEvGoSleep
, 2)
62 // startTimer adds t to the timer heap.
63 //go:linkname startTimer time.startTimer
64 func startTimer(t
*timer
) {
66 racerelease(unsafe
.Pointer(t
))
71 // stopTimer removes t from the timer heap if it is there.
72 // It returns true if t was removed, false if t wasn't even there.
73 //go:linkname stopTimer time.stopTimer
74 func stopTimer(t
*timer
) bool {
80 // Ready the goroutine arg.
81 func goroutineReady(arg
interface{}, seq
uintptr) {
85 func addtimer(t
*timer
) {
91 // Add a timer to the heap and start or kick timerproc if the new timer is
92 // earlier than any of the others.
94 func addtimerLocked(t
*timer
) {
95 // when must never be negative; otherwise timerproc will overflow
96 // during its delta calculation and never expire other runtime timers.
101 timers
.t
= append(timers
.t
, t
)
104 // siftup moved to top: new earliest deadline.
106 timers
.sleeping
= false
107 notewakeup(&timers
.waitnote
)
109 if timers
.rescheduling
{
110 timers
.rescheduling
= false
111 goready(timers
.gp
, 0)
115 timers
.created
= true
120 // Delete timer t from the heap.
121 // Do not need to update the timerproc: if it wakes up early, no big deal.
122 func deltimer(t
*timer
) bool {
123 // Dereference t so that any panic happens before the lock is held.
124 // Discard result, because t might be moving in the heap.
128 // t may not be registered anymore and may have
129 // a bogus i (typically 0, if generated by Go).
130 // Verify it before proceeding.
132 last
:= len(timers
.t
) - 1
133 if i
< 0 || i
> last || timers
.t
[i
] != t
{
138 timers
.t
[i
] = timers
.t
[last
]
142 timers
.t
= timers
.t
[:last
]
151 // Timerproc runs the time-driven events.
152 // It sleeps until the next event in the timers heap.
153 // If addtimer inserts a new earlier event, it wakes timerproc early.
160 timers
.sleeping
= false
164 if len(timers
.t
) == 0 {
174 // leave in heap but adjust next time to fire
175 t
.when
+= t
.period
* (1 + -delta
/t
.period
)
179 last
:= len(timers
.t
) - 1
181 timers
.t
[0] = timers
.t
[last
]
185 timers
.t
= timers
.t
[:last
]
189 t
.i
= -1 // mark as removed
196 raceacquire(unsafe
.Pointer(t
))
201 if delta
< 0 || faketime
> 0 {
202 // No timers left - put goroutine to sleep.
203 timers
.rescheduling
= true
204 goparkunlock(&timers
.lock
, "timer goroutine (idle)", traceEvGoBlock
, 1)
207 // At least one timer pending. Sleep until then.
208 timers
.sleeping
= true
209 noteclear(&timers
.waitnote
)
211 notetsleepg(&timers
.waitnote
, delta
)
221 if !timers
.created ||
len(timers
.t
) == 0 {
227 if faketime
< timers
.t
[0].when
{
228 faketime
= timers
.t
[0].when
229 if timers
.rescheduling
{
230 timers
.rescheduling
= false
238 // Heap maintenance algorithms.
240 func siftupTimer(i
int) {
245 p
:= (i
- 1) / 4 // parent
246 if when
>= t
[p
].when
{
257 func siftdownTimer(i
int) {
263 c
:= i
*4 + 1 // left child
264 c3
:= c
+ 2 // mid child
269 if c
+1 < n
&& t
[c
+1].when
< w
{
275 if c3
+1 < n
&& t
[c3
+1].when
< w3
{
295 // Entry points for net, time to call nanotime.
297 //go:linkname net_runtimeNano net.runtimeNano
298 func net_runtimeNano() int64 {
302 //go:linkname time_runtimeNano time.runtimeNano
303 func time_runtimeNano() int64 {