diff options
Diffstat (limited to 'src/pkg/runtime/time.goc')
-rw-r--r-- | src/pkg/runtime/time.goc | 77 |
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"); +} |