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.goc77
1 files changed, 62 insertions, 15 deletions
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
index be0c1f83d..b575696f7 100644
--- a/src/pkg/runtime/time.goc
+++ b/src/pkg/runtime/time.goc
@@ -13,8 +13,13 @@ package time
#include "malloc.h"
#include "race.h"
+enum {
+ debug = 0,
+};
+
static Timers timers;
static void addtimer(Timer*);
+static void dumptimers(int8*);
// Package time APIs.
// Godoc uses the comments in package time, not these.
@@ -92,6 +97,11 @@ 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;
@@ -121,6 +131,8 @@ addtimer(Timer *t)
timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addtimer);
timers.timerproc->issystem = true;
}
+ if(debug)
+ dumptimers("addtimer");
}
// Delete timer t from the heap.
@@ -157,6 +169,8 @@ runtime·deltimer(Timer *t)
siftup(i);
siftdown(i);
}
+ if(debug)
+ dumptimers("deltimer");
runtime·unlock(&timers);
return true;
}
@@ -175,6 +189,7 @@ timerproc(void)
for(;;) {
runtime·lock(&timers);
+ timers.sleeping = false;
now = runtime·nanotime();
for(;;) {
if(timers.len == 0) {
@@ -214,9 +229,7 @@ timerproc(void)
timers.sleeping = true;
runtime·noteclear(&timers.waitnote);
runtime·unlock(&timers);
- runtime·entersyscallblock();
- runtime·notetsleep(&timers.waitnote, delta);
- runtime·exitsyscall();
+ runtime·notetsleepg(&timers.waitnote, delta);
}
}
@@ -226,18 +239,20 @@ 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)/2; // parent
- if(t[i]->when >= t[p]->when)
+ p = (i-1)/4; // parent
+ if(when >= t[p]->when)
break;
- tmp = t[i];
t[i] = t[p];
- t[p] = tmp;
t[i]->i = i;
- t[p]->i = p;
+ t[p] = tmp;
+ tmp->i = p;
i = p;
}
}
@@ -245,25 +260,57 @@ siftup(int32 i)
static void
siftdown(int32 i)
{
- int32 c, len;
+ 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*2 + 1; // left child
+ c = i*4 + 1; // left child
+ c3 = c + 2; // mid child
if(c >= len) {
break;
}
- if(c+1 < len && t[c+1]->when < t[c]->when)
+ w = t[c]->when;
+ if(c+1 < len && t[c+1]->when < w) {
+ w = t[c+1]->when;
c++;
- if(t[c]->when >= t[i]->when)
+ }
+ 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;
- tmp = t[i];
t[i] = t[c];
- t[c] = tmp;
t[i]->i = i;
- t[c]->i = c;
+ 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");
+}