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)
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;
out:
pthread_mutex_unlock(&timer_lock);
- return pending;
+ return idx >= 0;
}
+static bool timer_thread_stop = false;
+
static int timer_thread(void *arg)
{
struct pending_timer *p;
pthread_mutex_lock(&timer_lock);
- while (1) {
+ while (!timer_thread_stop) {
now = jiffies;
p = heap_peek(&pending_timers);
BUG_ON(!timer_running());
pthread_mutex_unlock(&timer_lock);
- timer->function(timer->data);
+ timer->function(timer);
pthread_mutex_lock(&timer_lock);
timer_seq++;
return 0;
}
+struct task_struct *timer_task;
+
__attribute__((constructor(103)))
static void timers_init(void)
{
- struct task_struct *p;
-
heap_init(&pending_timers, 64);
BUG_ON(!pending_timers.data);
- p = kthread_run(timer_thread, NULL, "timers");
- BUG_ON(IS_ERR(p));
+ timer_task = kthread_run(timer_thread, NULL, "timers");
+ BUG_ON(IS_ERR(timer_task));
+}
+
+__attribute__((destructor(103)))
+static void timers_cleanup(void)
+{
+ get_task_struct(timer_task);
+
+ pthread_mutex_lock(&timer_lock);
+ timer_thread_stop = true;
+ pthread_cond_signal(&timer_cond);
+ pthread_mutex_unlock(&timer_lock);
+
+ int ret = kthread_stop(timer_task);
+ BUG_ON(ret);
+
+ put_task_struct(timer_task);
+ timer_task = NULL;
}