diff options
Diffstat (limited to 'ptimer.c')
-rw-r--r-- | ptimer.c | 223 |
1 files changed, 0 insertions, 223 deletions
diff --git a/ptimer.c b/ptimer.c deleted file mode 100644 index 5f9cf5d..0000000 --- a/ptimer.c +++ /dev/null @@ -1,223 +0,0 @@ -#include <inttypes.h> -#include <sys/timerfd.h> -#include <string.h> -#include <unistd.h> -#include <time.h> - -#include "main.h" -#include "uring.h" -#include "ptimer.h" - -struct ptimer { - uint64_t value; - time_t previous_time; - struct uring_task task; - unsigned task_count; - struct list_head ptasks; -}; - -static void -ptimer_set(unsigned value, unsigned interval) -{ - struct itimerspec tspec = { - .it_interval = { - .tv_sec = interval, - .tv_nsec = 0 - }, - .it_value = { - .tv_sec = value, - .tv_nsec = 0 - } - }; - - assert_return(cfg->ptimer && cfg->ptimer->task.fd >= 0); - - if (timerfd_settime(cfg->ptimer->task.fd, 0, &tspec, NULL) != 0) - error("timerfd_settime: %m"); -} - -static unsigned -gcd(unsigned a, unsigned b) -{ - if (a == 0) - return b; - return gcd(b % a, a); -} - -static unsigned -array_gcd(unsigned arr[], unsigned n) -{ - unsigned result = arr[0]; - - for (unsigned i = 1; i < n; i++) - result = gcd(arr[i], result); - - return result; -} - -static void -ptimer_tick(struct ptimer *ptimer) -{ - time_t now = time(NULL); - unsigned diff = (unsigned)(now - ptimer->previous_time); - struct ptimer_task *ptask, *ptmp; - - debug(DBG_TIMER, "got a tick of %u secs", diff); - list_for_each_entry_safe(ptask, ptmp, &ptimer->ptasks, list) { - if (ptask->remain > diff) { - ptask->remain -= diff; - continue; - } - - debug(DBG_TIMER, "triggering ptask %p (times %u)", - ptask, ptask->times); - - ptask->cb(ptask); - ptask->remain = ptask->interval; - - if (ptask->times == 0) - continue; - - ptask->times--; - if (ptask->times == 0) { - ptask->active = false; - list_del(&ptask->list); - } - } - - ptimer->previous_time = now; -} - -static void -ptimer_reconfig(struct ptimer *ptimer) -{ - struct ptimer_task *ptask; - unsigned i = 0; - unsigned lowest = ~0; - unsigned interval; - - if (list_empty(&ptimer->ptasks)) { - debug(DBG_TIMER, "no tasks"); - ptimer_set(0, 0); - return; - } - - unsigned intervals[ptimer->task_count]; - - list_for_each_entry(ptask, &ptimer->ptasks, list) { - if (ptask->remain < lowest) - lowest = ptask->remain; - intervals[i++] = ptask->interval; - } - - interval = array_gcd(intervals, i); - - debug(DBG_TIMER, "lowest: %u, gcd: %u\n", lowest, interval); - ptimer_set(lowest, interval); -} - -void -ptimer_del_task(struct ptimer_task *ptask) -{ - struct ptimer *ptimer = cfg->ptimer; - - assert_return(ptask && ptimer); - assert_return_silent(ptask->active); - assert_return(ptimer->task_count > 0); - - list_del(&ptask->list); - ptask->active = false; - ptimer->task_count--; - ptimer_tick(ptimer); - ptimer_reconfig(ptimer); - uring_task_put(&ptimer->task); -} - -void -ptimer_add_task(struct ptimer_task *ptask) -{ - struct ptimer *ptimer = cfg->ptimer; - - assert_return(ptask && ptask->interval > 0 && ptask->cb && ptimer); - assert_return_silent(!ptask->active); - - uring_task_get(&ptimer->task); - ptask->active = true; - ptask->remain = ptask->interval; - ptimer_tick(ptimer); - list_add(&ptask->list, &ptimer->ptasks); - ptimer->task_count++; - ptimer_reconfig(ptimer); -} - -void -ptimer_refdump() -{ - assert_return(cfg->ptimer); - - uring_task_refdump(&cfg->ptimer->task); -} - -static void -ptimer_free(struct uring_task *task) -{ - struct ptimer *ptimer = container_of(task, struct ptimer, task); - - assert_return(task); - - debug(DBG_TIMER, "task %p, ptimer %p", task, ptimer); - xfree(ptimer); - cfg->ptimer = NULL; -} - -void -ptimer_delete() -{ - assert_return(cfg->ptimer); - - debug(DBG_TIMER, "closing fd %i", cfg->ptimer->task.fd); - uring_task_destroy(&cfg->ptimer->task); -} - -static void -ptimer_cb(struct uring_task *task, int res) -{ - struct ptimer *ptimer = container_of(task, struct ptimer, task); - - assert_return(task); - assert_task_alive(DBG_IGMP, task); - - if (res != sizeof(ptimer->value)) { - error("timerfd_read: res: %i, %m", res); - return; - } - - ptimer_tick(ptimer); - uring_read(&ptimer->task, &ptimer->value, sizeof(ptimer->value), ptimer_cb); -} - -void -ptimer_init() -{ - struct ptimer *ptimer; - int tfd; - - assert_return(!cfg->ptimer); - - ptimer = zmalloc(sizeof(*ptimer)); - if (!ptimer) - die("malloc: %m"); - - tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); - if (tfd < 0) - die("timerfd_create: %m"); - - ptimer->task_count = 0; - ptimer->previous_time = time(NULL); - list_init(&ptimer->ptasks); - uring_task_init(&ptimer->task, "ptimer", uring_parent(), ptimer_free); - uring_task_set_fd(&ptimer->task, tfd); - cfg->ptimer = ptimer; - uring_read(&ptimer->task, &ptimer->value, sizeof(ptimer->value), ptimer_cb); -} - |