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.
15 static void addtimer(Timer*);
16 static bool deltimer(Timer*);
19 // Godoc uses the comments in package time, not these.
21 // time.now is implemented in assembly.
23 // Sleep puts the current goroutine to sleep for at least ns nanoseconds.
24 func Sleep(ns int64) {
29 g->waitreason = "sleep";
33 // startTimer adds t to the timer heap.
34 func startTimer(t *Timer) {
38 // stopTimer removes t from the timer heap if it is there.
39 // It returns true if t was removed, false if t wasn't even there.
40 func stopTimer(t *Timer) (stopped bool) {
41 stopped = deltimer(t);
46 static void timerproc(void*);
47 static void siftup(int32);
48 static void siftdown(int32);
50 // Ready the goroutine e.data.
52 ready(int64 now, Eface e)
56 runtime_ready(e.__object);
59 // Put the current goroutine to sleep for ns nanoseconds.
60 // The caller must have set g->status and g->waitreason.
62 runtime_tsleep(int64 ns)
75 t.when = runtime_nanotime() + ns;
83 // Add a timer to the heap and start or kick the timer proc
84 // if the new timer is earlier than any of the others.
91 runtime_lock(&timers);
92 if(timers.len >= timers.cap) {
97 nt = runtime_malloc(n*sizeof nt[0]);
98 runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]);
99 runtime_free(timers.t);
107 // siftup moved to top: new earliest deadline.
108 if(timers.sleeping) {
109 timers.sleeping = false;
110 runtime_notewakeup(&timers.waitnote);
112 if(timers.rescheduling) {
113 timers.rescheduling = false;
114 runtime_ready(timers.timerproc);
117 if(timers.timerproc == nil)
118 timers.timerproc = __go_go(timerproc, nil);
119 runtime_unlock(&timers);
122 // Delete timer t from the heap.
123 // Do not need to update the timerproc:
124 // if it wakes up early, no big deal.
130 runtime_lock(&timers);
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 if(i < 0 || i >= timers.len || timers.t[i] != t) {
137 runtime_unlock(&timers);
142 if(i == timers.len) {
145 timers.t[i] = timers.t[timers.len];
146 timers.t[timers.len] = nil;
151 runtime_unlock(&timers);
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, addtimer
158 // wakes timerproc early.
160 timerproc(void* dummy __attribute__ ((unused)))
165 void (*f)(int64, Eface);
170 runtime_lock(&timers);
171 now = runtime_nanotime();
173 if(timers.len == 0) {
178 delta = t->when - now;
182 // leave in heap but adjust next time to fire
183 t->when += t->period * (1 + -delta/t->period);
187 timers.t[0] = timers.t[--timers.len];
190 t->i = -1; // mark as removed
194 runtime_unlock(&timers);
196 runtime_lock(&timers);
199 // No timers left - put goroutine to sleep.
200 timers.rescheduling = true;
201 g->status = Gwaiting;
202 g->waitreason = "timer goroutine (idle)";
203 runtime_unlock(&timers);
207 // At least one timer pending. Sleep until then.
208 timers.sleeping = true;
209 runtime_noteclear(&timers.waitnote);
210 runtime_unlock(&timers);
211 runtime_entersyscall();
212 runtime_notetsleep(&timers.waitnote, delta);
213 runtime_exitsyscall();
217 // heap maintenance algorithms.
227 p = (i-1)/2; // parent
228 if(t[i]->when >= t[p]->when)
248 c = i*2 + 1; // left child
252 if(c+1 < len && t[c+1]->when < t[c]->when)
254 if(t[c]->when >= t[i]->when)
266 runtime_time_scan(void (*scan)(byte*, int64))
268 scan((byte*)&timers, sizeof timers);