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.
21 static void addtimer(Timer*);
22 static void dumptimers(const char*);
24 // nacl fake time support.
28 // Godoc uses the comments in package time, not these.
30 // time.now is implemented in assembly.
32 // runtimeNano returns the current value of the runtime clock in nanoseconds.
33 func runtimeNano() (ns int64) {
34 ns = runtime_nanotime();
37 // Sleep puts the current goroutine to sleep for at least ns nanoseconds.
38 func Sleep(ns int64) {
39 runtime_tsleep(ns, "sleep");
42 // startTimer adds t to the timer heap.
43 func startTimer(t *Timer) {
47 // stopTimer removes t from the timer heap if it is there.
48 // It returns true if t was removed, false if t wasn't even there.
49 func stopTimer(t *Timer) (stopped bool) {
50 stopped = runtime_deltimer(t);
55 int64 runtime_unixnanotime(void)
57 struct time_now_ret r;
60 return r.sec*1000000000 + r.nsec;
63 static void timerproc(void*);
64 static void siftup(int32);
65 static void siftdown(int32);
67 // Ready the goroutine e.data.
69 ready(Eface e, uintptr seq)
73 runtime_ready(e.__object);
76 static FuncVal readyv = {(void(*)(void))ready};
78 // Put the current goroutine to sleep for ns nanoseconds.
80 runtime_tsleep(int64 ns, const char *reason)
90 t.when = runtime_nanotime() + ns;
95 runtime_lock(&timers);
97 runtime_parkunlock(&timers, reason);
101 runtime_addtimer(Timer *t)
103 runtime_lock(&timers);
105 runtime_unlock(&timers);
108 // Add a timer to the heap and start or kick the timer proc
109 // if the new timer is earlier than any of the others.
116 // when must never be negative; otherwise timerproc will overflow
117 // during its delta calculation and never expire other timers.
119 t->when = (int64)((1ULL<<63)-1);
121 if(timers.len >= timers.cap) {
125 n = timers.cap*3 / 2;
126 nt = runtime_malloc(n*sizeof nt[0]);
127 runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]);
128 runtime_free(timers.t);
136 // siftup moved to top: new earliest deadline.
137 if(timers.sleeping) {
138 timers.sleeping = false;
139 runtime_notewakeup(&timers.waitnote);
141 if(timers.rescheduling) {
142 timers.rescheduling = false;
143 runtime_ready(timers.timerproc);
146 if(timers.timerproc == nil) {
147 timers.timerproc = __go_go(timerproc, nil);
148 timers.timerproc->issystem = true;
151 dumptimers("addtimer");
154 // Used to force a dereference before the lock is acquired.
157 // Delete timer t from the heap.
158 // Do not need to update the timerproc:
159 // if it wakes up early, no big deal.
161 runtime_deltimer(Timer *t)
165 // Dereference t so that any panic happens before the lock is held.
166 // Discard result, because t might be moving in the heap.
170 runtime_lock(&timers);
172 // t may not be registered anymore and may have
173 // a bogus i (typically 0, if generated by Go).
174 // Verify it before proceeding.
176 if(i < 0 || i >= timers.len || timers.t[i] != t) {
177 runtime_unlock(&timers);
182 if(i == timers.len) {
185 timers.t[i] = timers.t[timers.len];
186 timers.t[timers.len] = nil;
192 dumptimers("deltimer");
193 runtime_unlock(&timers);
197 // Timerproc runs the time-driven events.
198 // It sleeps until the next event in the timers heap.
199 // If addtimer inserts a new earlier event, addtimer
200 // wakes timerproc early.
202 timerproc(void* dummy __attribute__ ((unused)))
207 void (*f)(Eface, uintptr);
212 runtime_lock(&timers);
213 timers.sleeping = false;
214 now = runtime_nanotime();
216 if(timers.len == 0) {
221 delta = t->when - now;
225 // leave in heap but adjust next time to fire
226 t->when += t->period * (1 + -delta/t->period);
230 timers.t[0] = timers.t[--timers.len];
233 t->i = -1; // mark as removed
236 f = (void*)t->fv->fn;
239 runtime_unlock(&timers);
240 __builtin_call_with_static_chain(f(arg, seq), fv);
242 // clear f and arg to avoid leak while sleeping for next timer
245 arg.__type_descriptor = nil;
249 runtime_lock(&timers);
252 // No timers left - put goroutine to sleep.
253 timers.rescheduling = true;
254 runtime_g()->isbackground = true;
255 runtime_parkunlock(&timers, "timer goroutine (idle)");
256 runtime_g()->isbackground = false;
259 // At least one timer pending. Sleep until then.
260 timers.sleeping = true;
261 runtime_noteclear(&timers.waitnote);
262 runtime_unlock(&timers);
263 runtime_notetsleepg(&timers.waitnote, delta);
267 // heap maintenance algorithms.
280 p = (i-1)/4; // parent
281 if(when >= t[p]->when)
303 c = i*4 + 1; // left child
304 c3 = c + 2; // mid child
309 if(c+1 < len && t[c+1]->when < w) {
315 if(c3+1 < len && t[c3+1]->when < w3) {
335 dumptimers(const char *msg)
340 runtime_printf("timers: %s\n", msg);
341 for(i = 0; i < timers.len; i++) {
343 runtime_printf("\t%d\t%p:\ti %d when %D period %D fn %p\n",
344 i, t, t->i, t->when, t->period, t->fv->fn);
346 runtime_printf("\n");
350 runtime_time_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
352 enqueue1(wbufp, (Obj){(byte*)&timers, sizeof timers, 0});