summaryrefslogtreecommitdiff
path: root/ptimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ptimer.c')
-rw-r--r--ptimer.c223
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);
-}
-