summaryrefslogtreecommitdiff
path: root/linux/timer.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-03-19 17:21:49 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2017-03-19 17:45:29 -0800
commit2ea91f85d8a321d937fcc0127e6364ac013057e8 (patch)
tree2c177b23cc89483308298df2c7912a5f8cf220f9 /linux/timer.c
parent5ec39af8eaba49aee7bafa44c661da39e2f40dc3 (diff)
make linux shim timer code less fragile
Diffstat (limited to 'linux/timer.c')
-rw-r--r--linux/timer.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/linux/timer.c b/linux/timer.c
index 557af094..b67a54ac 100644
--- a/linux/timer.c
+++ b/linux/timer.c
@@ -142,30 +142,30 @@ static inline bool timer_running(void)
return timer_seq & 1;
}
-static size_t timer_idx(struct timer_list *timer)
+static ssize_t timer_idx(struct timer_list *timer)
{
size_t i;
- for (i = 0; i < pending_timers.size; i++)
+ for (i = 0; i < pending_timers.used; i++)
if (pending_timers.data[i].timer == timer)
return i;
- BUG();
+
+ return -1;
}
int del_timer(struct timer_list *timer)
{
- int pending;
+ ssize_t idx;
pthread_mutex_lock(&timer_lock);
- pending = timer_pending(timer);
- timer->pending = false;
-
- if (pending)
- heap_del(&pending_timers, timer_idx(timer), pending_timer_cmp);
+ idx = timer_idx(timer);
+ if (idx >= 0)
+ heap_del(&pending_timers, idx, pending_timer_cmp);
+ timer->pending = false;
pthread_mutex_unlock(&timer_lock);
- return pending;
+ return idx >= 0;
}
void flush_timers(void)
@@ -183,44 +183,41 @@ void flush_timers(void)
int del_timer_sync(struct timer_list *timer)
{
unsigned long seq;
- int pending;
+ ssize_t idx;
pthread_mutex_lock(&timer_lock);
- pending = timer_pending(timer);
- timer->pending = false;
+ idx = timer_idx(timer);
+ if (idx >= 0)
+ heap_del(&pending_timers, idx, pending_timer_cmp);
- if (pending)
- heap_del(&pending_timers, timer_idx(timer), pending_timer_cmp);
+ timer->pending = false;
seq = timer_seq;
while (timer_running() && seq == timer_seq)
pthread_cond_wait(&timer_running_cond, &timer_lock);
-
pthread_mutex_unlock(&timer_lock);
- return pending;
+ return idx >= 0;
}
int mod_timer(struct timer_list *timer, unsigned long expires)
{
- int pending;
- size_t i;
+ ssize_t idx;
pthread_mutex_lock(&timer_lock);
- pending = timer_pending(timer);
-
- if (pending && timer->expires == expires)
- goto out;
-
timer->expires = expires;
timer->pending = true;
+ idx = timer_idx(timer);
+
+ if (idx >= 0 &&
+ pending_timers.data[idx].expires == expires)
+ goto out;
- if (pending) {
- i = timer_idx(timer);
- pending_timers.data[i].expires = expires;
+ if (idx >= 0) {
+ pending_timers.data[idx].expires = expires;
- heap_sift_down(&pending_timers, i, pending_timer_cmp);
- heap_sift(&pending_timers, i, pending_timer_cmp);
+ heap_sift_down(&pending_timers, idx, pending_timer_cmp);
+ heap_sift(&pending_timers, idx, pending_timer_cmp);
} else {
if (heap_full(&pending_timers)) {
pending_timers.size *= 2;
@@ -244,7 +241,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
out:
pthread_mutex_unlock(&timer_lock);
- return pending;
+ return idx >= 0;
}
static int timer_thread(void *arg)