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.
16 static void addtimer(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) {
25 runtime_tsleep(ns, "sleep");
28 // startTimer adds t to the timer heap.
29 func startTimer(t *Timer) {
31 runtime_racerelease(t);
35 // stopTimer removes t from the timer heap if it is there.
36 // It returns true if t was removed, false if t wasn't even there.
37 func stopTimer(t *Timer) (stopped bool) {
38 stopped = runtime_deltimer(t);
43 static void timerproc(void*);
44 static void siftup(int32);
45 static void siftdown(int32);
47 // Ready the goroutine e.data.
49 ready(int64 now, Eface e)
53 runtime_ready(e.__object);
56 static FuncVal readyv = {(void(*)(void))ready};
58 // Put the current goroutine to sleep for ns nanoseconds.
60 runtime_tsleep(int64 ns, const char *reason)
70 t.when = runtime_nanotime() + ns;
74 runtime_lock(&timers);
76 runtime_park(runtime_unlock, &timers, reason);
80 runtime_addtimer(Timer *t)
82 runtime_lock(&timers);
84 runtime_unlock(&timers);
87 // Add a timer to the heap and start or kick the timer proc
88 // if the new timer is earlier than any of the others.
95 if(timers.len >= timers.cap) {
100 nt = runtime_malloc(n*sizeof nt[0]);
101 runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]);
102 runtime_free(timers.t);
110 // siftup moved to top: new earliest deadline.
111 if(timers.sleeping) {
112 timers.sleeping = false;
113 runtime_notewakeup(&timers.waitnote);
115 if(timers.rescheduling) {
116 timers.rescheduling = false;
117 runtime_ready(timers.timerproc);
120 if(timers.timerproc == nil) {
121 timers.timerproc = __go_go(timerproc, nil);
122 timers.timerproc->issystem = true;
126 // Delete timer t from the heap.
127 // Do not need to update the timerproc:
128 // if it wakes up early, no big deal.
130 runtime_deltimer(Timer *t)
134 runtime_lock(&timers);
136 // t may not be registered anymore and may have
137 // a bogus i (typically 0, if generated by Go).
138 // Verify it before proceeding.
140 if(i < 0 || i >= timers.len || timers.t[i] != t) {
141 runtime_unlock(&timers);
146 if(i == timers.len) {
149 timers.t[i] = timers.t[timers.len];
150 timers.t[timers.len] = nil;
155 runtime_unlock(&timers);
159 // Timerproc runs the time-driven events.
160 // It sleeps until the next event in the timers heap.
161 // If addtimer inserts a new earlier event, addtimer
162 // wakes timerproc early.
164 timerproc(void* dummy __attribute__ ((unused)))
168 void (*f)(int64, Eface);
172 runtime_lock(&timers);
173 now = runtime_nanotime();
175 if(timers.len == 0) {
180 delta = t->when - now;
184 // leave in heap but adjust next time to fire
185 t->when += t->period * (1 + -delta/t->period);
189 timers.t[0] = timers.t[--timers.len];
192 t->i = -1; // mark as removed
194 f = (void*)t->fv->fn;
196 runtime_unlock(&timers);
198 runtime_raceacquire(t);
199 __go_set_closure(t->fv);
201 runtime_lock(&timers);
204 // No timers left - put goroutine to sleep.
205 timers.rescheduling = true;
206 runtime_park(runtime_unlock, &timers, "timer goroutine (idle)");
209 // At least one timer pending. Sleep until then.
210 timers.sleeping = true;
211 runtime_noteclear(&timers.waitnote);
212 runtime_unlock(&timers);
213 runtime_entersyscallblock();
214 runtime_notetsleep(&timers.waitnote, delta);
215 runtime_exitsyscall();
219 // heap maintenance algorithms.
229 p = (i-1)/2; // parent
230 if(t[i]->when >= t[p]->when)
250 c = i*2 + 1; // left child
254 if(c+1 < len && t[c+1]->when < t[c]->when)
256 if(t[c]->when >= t[i]->when)
268 runtime_time_scan(void (*addroot)(Obj))
270 addroot((Obj){(byte*)&timers, sizeof timers, 0});