diff options
Diffstat (limited to 'src/pkg/runtime/time.goc')
-rw-r--r-- | src/pkg/runtime/time.goc | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc index b18902f00..2babb173d 100644 --- a/src/pkg/runtime/time.goc +++ b/src/pkg/runtime/time.goc @@ -11,6 +11,7 @@ package time #include "os_GOOS.h" #include "arch_GOARCH.h" #include "malloc.h" +#include "race.h" static Timers timers; static void addtimer(Timer*); @@ -23,14 +24,16 @@ static bool deltimer(Timer*); // Sleep puts the current goroutine to sleep for at least ns nanoseconds. func Sleep(ns int64) { - g->status = Gwaiting; - g->waitreason = "sleep"; - runtime·tsleep(ns); + runtime·tsleep(ns, "sleep"); } // startTimer adds t to the timer heap. func startTimer(t *Timer) { + if(raceenabled) + runtime·racerelease(t); + runtime·lock(&timers); addtimer(t); + runtime·unlock(&timers); } // stopTimer removes t from the timer heap if it is there. @@ -54,27 +57,28 @@ ready(int64 now, Eface e) runtime·ready(e.data); } +static FuncVal readyv = {(void(*)(void))ready}; + // Put the current goroutine to sleep for ns nanoseconds. -// The caller must have set g->status and g->waitreason. void -runtime·tsleep(int64 ns) +runtime·tsleep(int64 ns, int8 *reason) { Timer t; - if(ns <= 0) { - g->status = Grunning; - g->waitreason = nil; + if(ns <= 0) return; - } t.when = runtime·nanotime() + ns; t.period = 0; - t.f = ready; + t.fv = &readyv; t.arg.data = g; + runtime·lock(&timers); addtimer(&t); - runtime·gosched(); + runtime·park(runtime·unlock, &timers, reason); } +static FuncVal timerprocv = {timerproc}; + // 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 @@ -83,7 +87,6 @@ addtimer(Timer *t) int32 n; Timer **nt; - runtime·lock(&timers); if(timers.len >= timers.cap) { // Grow slice. n = 16; @@ -109,9 +112,10 @@ addtimer(Timer *t) runtime·ready(timers.timerproc); } } - if(timers.timerproc == nil) - timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0, addtimer); - runtime·unlock(&timers); + if(timers.timerproc == nil) { + timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addtimer); + timers.timerproc->issystem = true; + } } // Delete timer t from the heap. @@ -182,26 +186,25 @@ timerproc(void) siftdown(0); t->i = -1; // mark as removed } - f = t->f; + f = (void*)t->fv->fn; arg = t->arg; runtime·unlock(&timers); + if(raceenabled) + runtime·raceacquire(t); f(now, arg); runtime·lock(&timers); } if(delta < 0) { // No timers left - put goroutine to sleep. timers.rescheduling = true; - g->status = Gwaiting; - g->waitreason = "timer goroutine (idle)"; - runtime·unlock(&timers); - runtime·gosched(); + runtime·park(runtime·unlock, &timers, "timer goroutine (idle)"); continue; } // At least one timer pending. Sleep until then. timers.sleeping = true; runtime·noteclear(&timers.waitnote); runtime·unlock(&timers); - runtime·entersyscall(); + runtime·entersyscallblock(); runtime·notetsleep(&timers.waitnote, delta); runtime·exitsyscall(); } |