Commit a9d42b8d authored by Rusty Russell's avatar Rusty Russell

timer: make timer_del() idempotent, add timer_init().

This catches duplicate timer_add() calls, as well as meaning we don't
need to track if the timer is active before calling timer_del().
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent fe6bc8c5
...@@ -32,6 +32,7 @@ int main(void) ...@@ -32,6 +32,7 @@ int main(void)
add_level(&timers, i); add_level(&timers, i);
i = 0; i = 0;
timer_init(&t);
for (diff = 0; diff < (1ULL << MAX_ORD)+2; diff = next(diff)) { for (diff = 0; diff < (1ULL << MAX_ORD)+2; diff = next(diff)) {
i++; i++;
for (timers.base = 0; for (timers.base = 0;
......
...@@ -13,6 +13,7 @@ int main(void) ...@@ -13,6 +13,7 @@ int main(void)
timers_init(&timers, grains_to_time(1364984760903400ULL)); timers_init(&timers, grains_to_time(1364984760903400ULL));
ok1(timers.base == 1364984760903400ULL); ok1(timers.base == 1364984760903400ULL);
timer_init(&t);
timer_add(&timers, &t, grains_to_time(1364984761003398ULL)); timer_add(&timers, &t, grains_to_time(1364984761003398ULL));
ok1(t.time == 1364984761003398ULL); ok1(t.time == 1364984761003398ULL);
ok1(timers.first == 1364984761003398ULL); ok1(timers.first == 1364984761003398ULL);
......
...@@ -18,6 +18,7 @@ int main(void) ...@@ -18,6 +18,7 @@ int main(void)
plan_tests(3); plan_tests(3);
timers_init(&timers, timeabs_from_usec(1364726722653919ULL)); timers_init(&timers, timeabs_from_usec(1364726722653919ULL));
timer_init(&t);
timer_add(&timers, &t, timeabs_from_usec(1364726722703919ULL)); timer_add(&timers, &t, timeabs_from_usec(1364726722703919ULL));
ok1(!timers_expire(&timers, timeabs_from_usec(1364726722653920ULL))); ok1(!timers_expire(&timers, timeabs_from_usec(1364726722653920ULL)));
expired = timers_expire(&timers, timeabs_from_usec(1364726725454187ULL)); expired = timers_expire(&timers, timeabs_from_usec(1364726725454187ULL));
......
...@@ -24,6 +24,10 @@ int main(void) ...@@ -24,6 +24,10 @@ int main(void)
ok1(timers_check(&timers, NULL)); ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &earliest)); ok1(!timer_earliest(&timers, &earliest));
timer_init(&t[0]);
/* timer_del can be called immediately after init. */
timer_del(&timers, &t[0]);
timer_add(&timers, &t[0], timeabs_from_nsec(1)); timer_add(&timers, &t[0], timeabs_from_nsec(1));
ok1(timers_check(&timers, NULL)); ok1(timers_check(&timers, NULL));
ok1(timer_earliest(&timers, &earliest)); ok1(timer_earliest(&timers, &earliest));
...@@ -32,10 +36,15 @@ int main(void) ...@@ -32,10 +36,15 @@ int main(void)
ok1(timers_check(&timers, NULL)); ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &earliest)); ok1(!timer_earliest(&timers, &earliest));
/* timer_del can be called twice, no problems. */
timer_del(&timers, &t[0]);
/* Check timer ordering. */ /* Check timer ordering. */
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
timer_init(&t[i*2]);
timer_add(&timers, &t[i*2], timeabs_from_nsec(1ULL << i)); timer_add(&timers, &t[i*2], timeabs_from_nsec(1ULL << i));
ok1(timers_check(&timers, NULL)); ok1(timers_check(&timers, NULL));
timer_init(&t[i*2+1]);
timer_add(&timers, &t[i*2+1], timeabs_from_nsec((1ULL << i) + 1)); timer_add(&timers, &t[i*2+1], timeabs_from_nsec((1ULL << i) + 1));
ok1(timers_check(&timers, NULL)); ok1(timers_check(&timers, NULL));
} }
......
...@@ -63,8 +63,20 @@ static void timer_add_raw(struct timers *timers, struct timer *t) ...@@ -63,8 +63,20 @@ static void timer_add_raw(struct timers *timers, struct timer *t)
list_add_tail(l, &t->list); list_add_tail(l, &t->list);
} }
void timer_init(struct timer *t)
{
list_node_init(&t->list);
}
static bool list_node_initted(const struct list_node *n)
{
return n->prev == n;
}
void timer_add(struct timers *timers, struct timer *t, struct timeabs when) void timer_add(struct timers *timers, struct timer *t, struct timeabs when)
{ {
assert(list_node_initted(&t->list));
t->time = time_to_grains(when); t->time = time_to_grains(when);
/* Added in the past? Treat it as imminent. */ /* Added in the past? Treat it as imminent. */
...@@ -79,7 +91,7 @@ void timer_add(struct timers *timers, struct timer *t, struct timeabs when) ...@@ -79,7 +91,7 @@ void timer_add(struct timers *timers, struct timer *t, struct timeabs when)
/* FIXME: inline */ /* FIXME: inline */
void timer_del(struct timers *timers, struct timer *t) void timer_del(struct timers *timers, struct timer *t)
{ {
list_del(&t->list); list_del_init(&t->list);
} }
static void timers_far_get(struct timers *timers, static void timers_far_get(struct timers *timers,
...@@ -285,6 +297,8 @@ struct timer *timers_expire(struct timers *timers, struct timeabs expire) ...@@ -285,6 +297,8 @@ struct timer *timers_expire(struct timers *timers, struct timeabs expire)
/* This *may* be NULL, if we deleted the first timer */ /* This *may* be NULL, if we deleted the first timer */
t = list_pop(&timers->level[0]->list[off], struct timer, list); t = list_pop(&timers->level[0]->list[off], struct timer, list);
if (t)
list_node_init(&t->list);
} while (!t && update_first(timers)); } while (!t && update_first(timers));
return t; return t;
......
...@@ -44,29 +44,40 @@ void timers_init(struct timers *timers, struct timeabs start); ...@@ -44,29 +44,40 @@ void timers_init(struct timers *timers, struct timeabs start);
*/ */
void timers_cleanup(struct timers *timers); void timers_cleanup(struct timers *timers);
/**
* timer_init - initialize a timer.
* @timer: the timer to initialize
*
* Example:
* struct timer t;
*
* timer_init(&t);
*/
void timer_init(struct timer *t);
/** /**
* timer_add - insert a timer. * timer_add - insert a timer.
* @timers: the struct timers * @timers: the struct timers
* @timer: the (uninitialized) timer to add * @timer: the (initialized or timer_del'd) timer to add
* @when: when @timer expires. * @when: when @timer expires.
* *
* This efficiently adds @timer to @timers, to expire @when (rounded to * This efficiently adds @timer to @timers, to expire @when (rounded to
* TIMER_GRANULARITY nanoseconds). * TIMER_GRANULARITY nanoseconds).
* *
* Example: * Example:
* struct timer t;
*
* // Timeout in 100ms. * // Timeout in 100ms.
* timer_add(&timeouts, &t, timeabs_add(time_now(), time_from_msec(100))); * timer_add(&timeouts, &t, timeabs_add(time_now(), time_from_msec(100)));
*/ */
void timer_add(struct timers *timers, struct timer *timer, struct timeabs when); void timer_add(struct timers *timers, struct timer *timer, struct timeabs when);
/** /**
* timer_del - remove an unexpired timer. * timer_del - remove a timer.
* @timers: the struct timers * @timers: the struct timers
* @timer: the timer previously added with timer_add() * @timer: the timer
* *
* This efficiently removes @timer from @timers. * This efficiently removes @timer from @timers, if timer_add() was
* called. It can be called multiple times without bad effect, and
* can be called any time after timer_init().
* *
* Example: * Example:
* timer_del(&timeouts, &t); * timer_del(&timeouts, &t);
......
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