summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/time.goc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/time.goc')
-rw-r--r--src/pkg/runtime/time.goc45
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();
}