diff options
Diffstat (limited to 'src/pkg/runtime/time.goc')
-rw-r--r-- | src/pkg/runtime/time.goc | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc deleted file mode 100644 index 712e03e83..000000000 --- a/src/pkg/runtime/time.goc +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Time-related runtime and pieces of package time. - -package time - -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "arch_GOARCH.h" -#include "malloc.h" -#include "race.h" - -enum { - debug = 0, -}; - -static Timers timers; -static void addtimer(Timer*); -static void dumptimers(int8*); - -// nacl fake time support. -int64 runtime·timens; - -// Package time APIs. -// Godoc uses the comments in package time, not these. - -// time.now is implemented in assembly. - -// runtimeNano returns the current value of the runtime clock in nanoseconds. -func runtimeNano() (ns int64) { - ns = runtime·nanotime(); -} - -// Sleep puts the current goroutine to sleep for at least ns nanoseconds. -func Sleep(ns int64) { - runtime·tsleep(ns, "sleep"); -} - -// startTimer adds t to the timer heap. -func startTimer(t *Timer) { - if(raceenabled) - runtime·racerelease(t); - runtime·addtimer(t); -} - -// stopTimer removes t from the timer heap if it is there. -// It returns true if t was removed, false if t wasn't even there. -func stopTimer(t *Timer) (stopped bool) { - stopped = runtime·deltimer(t); -} - -// C runtime. - -void runtime·gc_unixnanotime(int64 *now); - -int64 runtime·unixnanotime(void) -{ - int64 now; - - runtime·gc_unixnanotime(&now); - return now; -} - -static void timerproc(void); -static void siftup(int32); -static void siftdown(int32); - -// Ready the goroutine e.data. -static void -ready(int64 now, Eface e) -{ - USED(now); - - runtime·ready(e.data); -} - -static FuncVal readyv = {(void(*)(void))ready}; - -// Put the current goroutine to sleep for ns nanoseconds. -void -runtime·tsleep(int64 ns, int8 *reason) -{ - Timer t; - - if(ns <= 0) - return; - - t.when = runtime·nanotime() + ns; - t.period = 0; - t.fv = &readyv; - t.arg.data = g; - runtime·lock(&timers); - addtimer(&t); - runtime·parkunlock(&timers, reason); -} - -static FuncVal timerprocv = {timerproc}; - -void -runtime·addtimer(Timer *t) -{ - runtime·lock(&timers); - addtimer(t); - runtime·unlock(&timers); -} - -// Add a timer to the heap and start or kick the timer proc -// if the new timer is earlier than any of the others. -static void -addtimer(Timer *t) -{ - int32 n; - Timer **nt; - - // when must never be negative; otherwise timerproc will overflow - // during its delta calculation and never expire other timers. - if(t->when < 0) - t->when = (1LL<<63)-1; - - if(timers.len >= timers.cap) { - // Grow slice. - n = 16; - if(n <= timers.cap) - n = timers.cap*3 / 2; - nt = runtime·malloc(n*sizeof nt[0]); - runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]); - runtime·free(timers.t); - timers.t = nt; - timers.cap = n; - } - t->i = timers.len++; - timers.t[t->i] = t; - siftup(t->i); - if(t->i == 0) { - // siftup moved to top: new earliest deadline. - if(timers.sleeping) { - timers.sleeping = false; - runtime·notewakeup(&timers.waitnote); - } - if(timers.rescheduling) { - timers.rescheduling = false; - runtime·ready(timers.timerproc); - } - } - if(timers.timerproc == nil) { - timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addtimer); - timers.timerproc->issystem = true; - } - if(debug) - dumptimers("addtimer"); -} - -// Delete timer t from the heap. -// Do not need to update the timerproc: -// if it wakes up early, no big deal. -bool -runtime·deltimer(Timer *t) -{ - int32 i; - - // Dereference t so that any panic happens before the lock is held. - // Discard result, because t might be moving in the heap. - i = t->i; - USED(i); - - runtime·lock(&timers); - - // t may not be registered anymore and may have - // a bogus i (typically 0, if generated by Go). - // Verify it before proceeding. - i = t->i; - if(i < 0 || i >= timers.len || timers.t[i] != t) { - runtime·unlock(&timers); - return false; - } - - timers.len--; - if(i == timers.len) { - timers.t[i] = nil; - } else { - timers.t[i] = timers.t[timers.len]; - timers.t[timers.len] = nil; - timers.t[i]->i = i; - siftup(i); - siftdown(i); - } - if(debug) - dumptimers("deltimer"); - runtime·unlock(&timers); - return true; -} - -// Timerproc runs the time-driven events. -// It sleeps until the next event in the timers heap. -// If addtimer inserts a new earlier event, addtimer -// wakes timerproc early. -static void -timerproc(void) -{ - int64 delta, now; - Timer *t; - void (*f)(int64, Eface); - Eface arg; - - for(;;) { - runtime·lock(&timers); - timers.sleeping = false; - now = runtime·nanotime(); - for(;;) { - if(timers.len == 0) { - delta = -1; - break; - } - t = timers.t[0]; - delta = t->when - now; - if(delta > 0) - break; - if(t->period > 0) { - // leave in heap but adjust next time to fire - t->when += t->period * (1 + -delta/t->period); - siftdown(0); - } else { - // remove from heap - timers.t[0] = timers.t[--timers.len]; - timers.t[0]->i = 0; - siftdown(0); - t->i = -1; // mark as removed - } - f = (void*)t->fv->fn; - arg = t->arg; - runtime·unlock(&timers); - if(raceenabled) - runtime·raceacquire(t); - f(now, arg); - - // clear f and arg to avoid leak while sleeping for next timer - f = nil; - USED(f); - arg.type = nil; - arg.data = nil; - USED(&arg); - - runtime·lock(&timers); - } - if(delta < 0) { - // No timers left - put goroutine to sleep. - timers.rescheduling = true; - g->isbackground = true; - runtime·parkunlock(&timers, "timer goroutine (idle)"); - g->isbackground = false; - continue; - } - // At least one timer pending. Sleep until then. - timers.sleeping = true; - runtime·noteclear(&timers.waitnote); - runtime·unlock(&timers); - runtime·notetsleepg(&timers.waitnote, delta); - } -} - -// heap maintenance algorithms. - -static void -siftup(int32 i) -{ - int32 p; - int64 when; - Timer **t, *tmp; - - t = timers.t; - when = t[i]->when; - tmp = t[i]; - while(i > 0) { - p = (i-1)/4; // parent - if(when >= t[p]->when) - break; - t[i] = t[p]; - t[i]->i = i; - t[p] = tmp; - tmp->i = p; - i = p; - } -} - -static void -siftdown(int32 i) -{ - int32 c, c3, len; - int64 when, w, w3; - Timer **t, *tmp; - - t = timers.t; - len = timers.len; - when = t[i]->when; - tmp = t[i]; - for(;;) { - c = i*4 + 1; // left child - c3 = c + 2; // mid child - if(c >= len) { - break; - } - w = t[c]->when; - if(c+1 < len && t[c+1]->when < w) { - w = t[c+1]->when; - c++; - } - if(c3 < len) { - w3 = t[c3]->when; - if(c3+1 < len && t[c3+1]->when < w3) { - w3 = t[c3+1]->when; - c3++; - } - if(w3 < w) { - w = w3; - c = c3; - } - } - if(w >= when) - break; - t[i] = t[c]; - t[i]->i = i; - t[c] = tmp; - tmp->i = c; - i = c; - } -} - -static void -dumptimers(int8 *msg) -{ - Timer *t; - int32 i; - - runtime·printf("timers: %s\n", msg); - for(i = 0; i < timers.len; i++) { - t = timers.t[i]; - runtime·printf("\t%d\t%p:\ti %d when %D period %D fn %p\n", - i, t, t->i, t->when, t->period, t->fv->fn); - } - runtime·printf("\n"); -} |