Commit 08dac128 authored by Rusty Russell's avatar Rusty Russell

timer: fix two corruption bugs.

We fill the upper buckets after we've moved on from the first bucket
in this layer.  This means two things:
1) If we have to look at an upper layer, we need to look at the next bucket,
   unless offset is 0.
2) We need to keep looking up layers in the corner case, too.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent bd9a48e7
#define CCAN_TIMER_DEBUG 1
#include <ccan/timer/timer.h>
/* Include the C files directly. */
#include <ccan/timer/timer.c>
#include <ccan/tap/tap.h>
static void new_timer(struct timers *timers, unsigned long nsec)
{
struct timer *timer;
struct timeabs when;
timer = malloc(sizeof(*timer));
timer_init(timer);
when.ts.tv_sec = 0; when.ts.tv_nsec = nsec;
timer_add(timers, timer, when);
}
static void update_and_expire(struct timers *timers)
{
struct timeabs when;
timer_earliest(timers, &when);
free(timers_expire(timers, when));
}
int main(int argc, char *argv[])
{
struct timeabs when;
struct timers timers;
plan_tests(7);
when.ts.tv_sec = 0; when.ts.tv_nsec = 0;
timers_init(&timers, when);
/* Add these */
new_timer(&timers, 35000000);
new_timer(&timers, 38000000);
new_timer(&timers, 59000000);
new_timer(&timers, 65000000);
new_timer(&timers, 88000000);
new_timer(&timers, 125000000);
new_timer(&timers, 130000000);
new_timer(&timers, 152000000);
new_timer(&timers, 168000000);
/* Expire all but the last one. */
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
update_and_expire(&timers);
/* Add a new one. */
new_timer(&timers, 169000000);
ok1(timers_check(&timers, NULL));
/* Used to get the wrong one... */
timers_dump(&timers, stdout);
ok1(timer_earliest(&timers, &when));
ok1(when.ts.tv_nsec == 168000000);
free(timers_expire(&timers, when));
ok1(timer_earliest(&timers, &when));
ok1(when.ts.tv_nsec == 169000000);
free(timers_expire(&timers, when));
ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &when));
timers_cleanup(&timers);
return exit_status();
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -180,6 +180,10 @@ next: ...@@ -180,6 +180,10 @@ next:
if (i == PER_LEVEL) { if (i == PER_LEVEL) {
level++; level++;
base >>= TIMER_LEVEL_BITS; base >>= TIMER_LEVEL_BITS;
if (off != 0)
/* We need *next* bucket: we've started reusing the
* one above */
base++;
goto next; goto next;
} }
...@@ -189,16 +193,25 @@ next: ...@@ -189,16 +193,25 @@ next:
else else
found = find_first(h, NULL); found = find_first(h, NULL);
if (need_next) { while (need_next) {
need_next = false;
if (!timers->level[level+1]) { if (!timers->level[level+1]) {
found = find_first(&timers->far, found); found = find_first(&timers->far, found);
} else { } else {
/* Current upper bucket has emptied into this
* bucket; we want *next* one. */
base >>= TIMER_LEVEL_BITS; base >>= TIMER_LEVEL_BITS;
base++;
off = base % PER_LEVEL; off = base % PER_LEVEL;
if (off == 0) {
need_next = true;
} else {
h = &timers->level[level+1]->list[off]; h = &timers->level[level+1]->list[off];
found = find_first(h, found); found = find_first(h, found);
} }
} }
}
return found; return found;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment