]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - linux/timer.c
Update bcachefs sources to dbee44d5ab bcachefs: add bcachefs xxhash support
[bcachefs-tools-debian] / linux / timer.c
index 557af09409729f64b04eb7da6d189031d0df9177..eb93786364eedd6282fa113b3458ecdd8c5bf9b6 100644 (file)
@@ -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,9 +241,11 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
 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;
@@ -256,7 +255,7 @@ static int timer_thread(void *arg)
 
        pthread_mutex_lock(&timer_lock);
 
-       while (1) {
+       while (!timer_thread_stop) {
                now = jiffies;
                p = heap_peek(&pending_timers);
 
@@ -276,7 +275,7 @@ static int timer_thread(void *arg)
                        BUG_ON(!timer_running());
 
                        pthread_mutex_unlock(&timer_lock);
-                       timer->function(timer->data);
+                       timer->function(timer);
                        pthread_mutex_lock(&timer_lock);
 
                        timer_seq++;
@@ -298,14 +297,31 @@ static int timer_thread(void *arg)
        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;
 }