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)
add_level(&timers, i);
i = 0;
timer_init(&t);
for (diff = 0; diff < (1ULL << MAX_ORD)+2; diff = next(diff)) {
i++;
for (timers.base = 0;
......
......@@ -13,6 +13,7 @@ int main(void)
timers_init(&timers, grains_to_time(1364984760903400ULL));
ok1(timers.base == 1364984760903400ULL);
timer_init(&t);
timer_add(&timers, &t, grains_to_time(1364984761003398ULL));
ok1(t.time == 1364984761003398ULL);
ok1(timers.first == 1364984761003398ULL);
......
......@@ -18,6 +18,7 @@ int main(void)
plan_tests(3);
timers_init(&timers, timeabs_from_usec(1364726722653919ULL));
timer_init(&t);
timer_add(&timers, &t, timeabs_from_usec(1364726722703919ULL));
ok1(!timers_expire(&timers, timeabs_from_usec(1364726722653920ULL)));
expired = timers_expire(&timers, timeabs_from_usec(1364726725454187ULL));
......
......@@ -24,6 +24,10 @@ int main(void)
ok1(timers_check(&timers, NULL));
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));
ok1(timers_check(&timers, NULL));
ok1(timer_earliest(&timers, &earliest));
......@@ -32,10 +36,15 @@ int main(void)
ok1(timers_check(&timers, NULL));
ok1(!timer_earliest(&timers, &earliest));
/* timer_del can be called twice, no problems. */
timer_del(&timers, &t[0]);
/* Check timer ordering. */
for (i = 0; i < 32; i++) {
timer_init(&t[i*2]);
timer_add(&timers, &t[i*2], timeabs_from_nsec(1ULL << i));
ok1(timers_check(&timers, NULL));
timer_init(&t[i*2+1]);
timer_add(&timers, &t[i*2+1], timeabs_from_nsec((1ULL << i) + 1));
ok1(timers_check(&timers, NULL));
}
......
......@@ -63,8 +63,20 @@ static void timer_add_raw(struct timers *timers, struct timer *t)
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)
{
assert(list_node_initted(&t->list));
t->time = time_to_grains(when);
/* Added in the past? Treat it as imminent. */
......@@ -79,7 +91,7 @@ void timer_add(struct timers *timers, struct timer *t, struct timeabs when)
/* FIXME: inline */
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,
......@@ -285,6 +297,8 @@ struct timer *timers_expire(struct timers *timers, struct timeabs expire)
/* This *may* be NULL, if we deleted the first timer */
t = list_pop(&timers->level[0]->list[off], struct timer, list);
if (t)
list_node_init(&t->list);
} while (!t && update_first(timers));
return t;
......
......@@ -44,29 +44,40 @@ void timers_init(struct timers *timers, struct timeabs start);
*/
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.
* @timers: the struct timers
* @timer: the (uninitialized) timer to add
* @timer: the (initialized or timer_del'd) timer to add
* @when: when @timer expires.
*
* This efficiently adds @timer to @timers, to expire @when (rounded to
* TIMER_GRANULARITY nanoseconds).
*
* Example:
* struct timer t;
*
* // Timeout in 100ms.
* timer_add(&timeouts, &t, timeabs_add(time_now(), time_from_msec(100)));
*/
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
* @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:
* 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