]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - c_src/linux/timer.c
Move c_src dirs back to toplevel
[bcachefs-tools-debian] / c_src / linux / timer.c
diff --git a/c_src/linux/timer.c b/c_src/linux/timer.c
deleted file mode 100644 (file)
index 7d519a4..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-
-#include <pthread.h>
-#include <signal.h>
-#include <time.h>
-
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/timer.h>
-
-/**
- * timespec_add_ns - Adds nanoseconds to a timespec
- * @a:         pointer to timespec to be incremented
- * @ns:                unsigned nanoseconds value to be added
- *
- * This must always be inlined because its used from the x86-64 vdso,
- * which cannot call other kernel functions.
- */
-static struct timespec timespec_add_ns(struct timespec a, u64 ns)
-{
-       a.tv_nsec       += ns;
-       a.tv_sec        += a.tv_nsec / NSEC_PER_SEC;
-       a.tv_nsec       %= NSEC_PER_SEC;
-       return a;
-}
-
-#define DECLARE_HEAP(type)                                             \
-struct {                                                               \
-       size_t size, used;                                              \
-       type *data;                                                     \
-}
-
-#define heap_init(heap, _size)                                         \
-({                                                                     \
-       size_t _bytes;                                                  \
-       (heap)->used = 0;                                               \
-       (heap)->size = (_size);                                         \
-       _bytes = (heap)->size * sizeof(*(heap)->data);                  \
-       (heap)->data = malloc(_bytes);                                  \
-       (heap)->data;                                                   \
-})
-
-#define heap_free(heap)                                                        \
-do {                                                                   \
-       kvfree((heap)->data);                                           \
-       (heap)->data = NULL;                                            \
-} while (0)
-
-#define heap_swap(h, i, j)     swap((h)->data[i], (h)->data[j])
-
-#define heap_sift(h, i, cmp)                                           \
-do {                                                                   \
-       size_t _r, _j = i;                                              \
-                                                                       \
-       for (; _j * 2 + 1 < (h)->used; _j = _r) {                       \
-               _r = _j * 2 + 1;                                        \
-               if (_r + 1 < (h)->used &&                               \
-                   cmp((h)->data[_r], (h)->data[_r + 1]))              \
-                       _r++;                                           \
-                                                                       \
-               if (cmp((h)->data[_r], (h)->data[_j]))                  \
-                       break;                                          \
-               heap_swap(h, _r, _j);                                   \
-       }                                                               \
-} while (0)
-
-#define heap_sift_down(h, i, cmp)                                      \
-do {                                                                   \
-       while (i) {                                                     \
-               size_t p = (i - 1) / 2;                                 \
-               if (cmp((h)->data[i], (h)->data[p]))                    \
-                       break;                                          \
-               heap_swap(h, i, p);                                     \
-               i = p;                                                  \
-       }                                                               \
-} while (0)
-
-#define heap_add(h, d, cmp)                                            \
-({                                                                     \
-       bool _r = !heap_full(h);                                        \
-       if (_r) {                                                       \
-               size_t _i = (h)->used++;                                \
-               (h)->data[_i] = d;                                      \
-                                                                       \
-               heap_sift_down(h, _i, cmp);                             \
-               heap_sift(h, _i, cmp);                                  \
-       }                                                               \
-       _r;                                                             \
-})
-
-#define heap_del(h, i, cmp)                                            \
-do {                                                                   \
-       size_t _i = (i);                                                \
-                                                                       \
-       BUG_ON(_i >= (h)->used);                                        \
-       (h)->used--;                                                    \
-       if ((_i) < (h)->used) {                                         \
-               heap_swap(h, _i, (h)->used);                            \
-               heap_sift_down(h, _i, cmp);                             \
-               heap_sift(h, _i, cmp);                                  \
-       }                                                               \
-} while (0)
-
-#define heap_pop(h, d, cmp)                                            \
-({                                                                     \
-       bool _r = (h)->used;                                            \
-       if (_r) {                                                       \
-               (d) = (h)->data[0];                                     \
-               heap_del(h, 0, cmp);                                    \
-       }                                                               \
-       _r;                                                             \
-})
-
-#define heap_peek(h)   ((h)->used ? &(h)->data[0] : NULL)
-#define heap_full(h)   ((h)->used == (h)->size)
-#define heap_empty(h)  ((h)->used == 0)
-
-#define heap_resort(heap, cmp)                                         \
-do {                                                                   \
-       ssize_t _i;                                                     \
-       for (_i = (ssize_t) (heap)->used / 2 -  1; _i >= 0; --_i)       \
-               heap_sift(heap, _i, cmp);                               \
-} while (0)
-
-struct pending_timer {
-       struct timer_list       *timer;
-       unsigned long           expires;
-};
-
-static inline bool pending_timer_cmp(struct pending_timer a,
-                                    struct pending_timer b)
-{
-       return a.expires < b.expires;
-}
-
-static DECLARE_HEAP(struct pending_timer) pending_timers;
-
-static pthread_mutex_t timer_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t  timer_cond = PTHREAD_COND_INITIALIZER;
-static pthread_cond_t  timer_running_cond = PTHREAD_COND_INITIALIZER;
-static unsigned long   timer_seq;
-
-static inline bool timer_running(void)
-{
-       return timer_seq & 1;
-}
-
-static ssize_t timer_idx(struct timer_list *timer)
-{
-       size_t i;
-
-       for (i = 0; i < pending_timers.used; i++)
-               if (pending_timers.data[i].timer == timer)
-                       return i;
-
-       return -1;
-}
-
-int del_timer(struct timer_list *timer)
-{
-       ssize_t idx;
-
-       pthread_mutex_lock(&timer_lock);
-       idx = timer_idx(timer);
-       if (idx >= 0)
-               heap_del(&pending_timers, idx, pending_timer_cmp);
-
-       timer->pending = false;
-       pthread_mutex_unlock(&timer_lock);
-
-       return idx >= 0;
-}
-
-void flush_timers(void)
-{
-       unsigned long seq;
-
-       pthread_mutex_lock(&timer_lock);
-       seq = timer_seq;
-       while (timer_running() && seq == timer_seq)
-               pthread_cond_wait(&timer_running_cond, &timer_lock);
-
-       pthread_mutex_unlock(&timer_lock);
-}
-
-int del_timer_sync(struct timer_list *timer)
-{
-       unsigned long seq;
-       ssize_t idx;
-
-       pthread_mutex_lock(&timer_lock);
-       idx = timer_idx(timer);
-       if (idx >= 0)
-               heap_del(&pending_timers, idx, 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 idx >= 0;
-}
-
-int mod_timer(struct timer_list *timer, unsigned long expires)
-{
-       ssize_t idx;
-
-       pthread_mutex_lock(&timer_lock);
-       timer->expires = expires;
-       timer->pending = true;
-       idx = timer_idx(timer);
-
-       if (idx >= 0 &&
-           pending_timers.data[idx].expires == expires)
-               goto out;
-
-       if (idx >= 0) {
-               pending_timers.data[idx].expires = expires;
-
-               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;
-                       pending_timers.data =
-                               realloc(pending_timers.data,
-                                       pending_timers.size *
-                                       sizeof(struct pending_timer));
-
-                       BUG_ON(!pending_timers.data);
-               }
-
-               heap_add(&pending_timers,
-                        ((struct pending_timer) {
-                               .timer = timer,
-                               .expires = expires,
-                        }),
-                        pending_timer_cmp);
-       }
-
-       pthread_cond_signal(&timer_cond);
-out:
-       pthread_mutex_unlock(&timer_lock);
-
-       return idx >= 0;
-}
-
-static bool timer_thread_stop = false;
-
-static int timer_thread(void *arg)
-{
-       struct pending_timer *p;
-       struct timespec ts;
-       unsigned long now;
-       int ret;
-
-       pthread_mutex_lock(&timer_lock);
-
-       while (!timer_thread_stop) {
-               now = jiffies;
-               p = heap_peek(&pending_timers);
-
-               if (!p) {
-                       pthread_cond_wait(&timer_cond, &timer_lock);
-                       continue;
-               }
-
-               if (time_after_eq(now, p->expires)) {
-                       struct timer_list *timer = p->timer;
-
-                       heap_del(&pending_timers, 0, pending_timer_cmp);
-                       BUG_ON(!timer_pending(timer));
-                       timer->pending = false;
-
-                       timer_seq++;
-                       BUG_ON(!timer_running());
-
-                       pthread_mutex_unlock(&timer_lock);
-                       timer->function(timer);
-                       pthread_mutex_lock(&timer_lock);
-
-                       timer_seq++;
-                       pthread_cond_broadcast(&timer_running_cond);
-                       continue;
-               }
-
-
-               ret = clock_gettime(CLOCK_REALTIME, &ts);
-               BUG_ON(ret);
-
-               ts = timespec_add_ns(ts, jiffies_to_nsecs(p->expires - now));
-
-               pthread_cond_timedwait(&timer_cond, &timer_lock, &ts);
-       }
-
-       pthread_mutex_unlock(&timer_lock);
-
-       return 0;
-}
-
-struct task_struct *timer_task;
-
-__attribute__((constructor(103)))
-static void timers_init(void)
-{
-       heap_init(&pending_timers, 64);
-       BUG_ON(!pending_timers.data);
-
-       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;
-}