summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/timer.c18
-rw-r--r--sysdep/unix/io.c283
2 files changed, 18 insertions, 283 deletions
diff --git a/lib/timer.c b/lib/timer.c
index 3136a56b..338b0a1a 100644
--- a/lib/timer.c
+++ b/lib/timer.c
@@ -7,6 +7,24 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
+/**
+ * DOC: Timers
+ *
+ * Timers are resources which represent a wish of a module to call a function at
+ * the specified time. The timer code does not guarantee exact timing, only that
+ * a timer function will not be called before the requested time.
+ *
+ * In BIRD, time is represented by values of the &btime type which is signed
+ * 64-bit integer interpreted as a relative number of microseconds since some
+ * fixed time point in past. The current time can be obtained by current_time()
+ * function with reasonable accuracy and is monotonic. There is also a current
+ * 'wall-clock' real time obtainable by current_real_time() reported by OS.
+ *
+ * Each timer is described by a &timer structure containing a pointer to the
+ * handler function (@hook), data private to this function (@data), time the
+ * function should be called at (@expires, 0 for inactive timers), for the other
+ * fields see |timer.h|.
+ */
#include <stdio.h>
#include <stdlib.h>
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 25121d74..3e56a32d 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -103,289 +103,6 @@ tracked_fopen(pool *p, char *name, char *mode)
return f;
}
-/**
- * DOC: Timers
- *
- * Timers are resources which represent a wish of a module to call
- * a function at the specified time. The platform dependent code
- * doesn't guarantee exact timing, only that a timer function
- * won't be called before the requested time.
- *
- * In BIRD, time is represented by values of the &bird_clock_t type
- * which are integral numbers interpreted as a relative number of seconds since
- * some fixed time point in past. The current time can be read
- * from variable @now with reasonable accuracy and is monotonic. There is also
- * a current 'absolute' time in variable @now_real reported by OS.
- *
- * Each timer is described by a &timer structure containing a pointer
- * to the handler function (@hook), data private to this function (@data),
- * time the function should be called at (@expires, 0 for inactive timers),
- * for the other fields see |timer.h|.
- */
-
-#if 0
-#define NEAR_TIMER_LIMIT 4
-
-static list near_timers, far_timers;
-static bird_clock_t first_far_timer = TIME_INFINITY;
-
-
-/* now must be different from 0, because 0 is a special value in timer->expires */
-bird_clock_t now = 1, now_real, boot_time;
-
-static void
-update_times_plain(void)
-{
- bird_clock_t new_time = time(NULL);
- int delta = new_time - now_real;
-
- if ((delta >= 0) && (delta < 60))
- now += delta;
- else if (now_real != 0)
- log(L_WARN "Time jump, delta %d s", delta);
-
- now_real = new_time;
-}
-
-static void
-update_times_gettime(void)
-{
- struct timespec ts;
- int rv;
-
- rv = clock_gettime(CLOCK_MONOTONIC, &ts);
- if (rv != 0)
- die("clock_gettime: %m");
-
- if (ts.tv_sec != now) {
- if (ts.tv_sec < now)
- log(L_ERR "Monotonic timer is broken");
-
- now = ts.tv_sec;
- now_real = time(NULL);
- }
-}
-
-static int clock_monotonic_available;
-
-static inline void
-update_times(void)
-{
- if (clock_monotonic_available)
- update_times_gettime();
- else
- update_times_plain();
-}
-
-static inline void
-init_times(void)
-{
- struct timespec ts;
- clock_monotonic_available = (clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
- if (!clock_monotonic_available)
- log(L_WARN "Monotonic timer is missing");
-}
-
-static void
-tm_free(resource *r)
-{
- timer *t = (timer *) r;
-
- tm_stop(t);
-}
-
-static void
-tm_dump(resource *r)
-{
- timer *t = (timer *) r;
-
- debug("(code %p, data %p, ", t->hook, t->data);
- if (t->randomize)
- debug("rand %d, ", t->randomize);
- if (t->recurrent)
- debug("recur %d, ", t->recurrent);
- if (t->expires)
- debug("expires in %d sec)\n", t->expires - now);
- else
- debug("inactive)\n");
-}
-
-static struct resclass tm_class = {
- "Timer",
- sizeof(timer),
- tm_free,
- tm_dump,
- NULL,
- NULL
-};
-
-/**
- * tm_new - create a timer
- * @p: pool
- *
- * This function creates a new timer resource and returns
- * a pointer to it. To use the timer, you need to fill in
- * the structure fields and call tm_start() to start timing.
- */
-timer *
-tm_new(pool *p)
-{
- timer *t = ralloc(p, &tm_class);
- return t;
-}
-
-static inline void
-tm_insert_near(timer *t)
-{
- node *n = HEAD(near_timers);
-
- while (n->next && (SKIP_BACK(timer, n, n)->expires < t->expires))
- n = n->next;
- insert_node(&t->n, n->prev);
-}
-
-/**
- * tm_start - start a timer
- * @t: timer
- * @after: number of seconds the timer should be run after
- *
- * This function schedules the hook function of the timer to
- * be called after @after seconds. If the timer has been already
- * started, it's @expire time is replaced by the new value.
- *
- * You can have set the @randomize field of @t, the timeout
- * will be increased by a random number of seconds chosen
- * uniformly from range 0 .. @randomize.
- *
- * You can call tm_start() from the handler function of the timer
- * to request another run of the timer. Also, you can set the @recurrent
- * field to have the timer re-added automatically with the same timeout.
- */
-void
-tm_start(timer *t, unsigned after)
-{
- bird_clock_t when;
-
- if (t->randomize)
- after += random() % (t->randomize + 1);
- when = now + after;
- if (t->expires == when)
- return;
- if (t->expires)
- rem_node(&t->n);
- t->expires = when;
- if (after <= NEAR_TIMER_LIMIT)
- tm_insert_near(t);
- else
- {
- if (!first_far_timer || first_far_timer > when)
- first_far_timer = when;
- add_tail(&far_timers, &t->n);
- }
-}
-
-/**
- * tm_stop - stop a timer
- * @t: timer
- *
- * This function stops a timer. If the timer is already stopped,
- * nothing happens.
- */
-void
-tm_stop(timer *t)
-{
- if (t->expires)
- {
- rem_node(&t->n);
- t->expires = 0;
- }
-}
-
-static void
-tm_dump_them(char *name, list *l)
-{
- node *n;
- timer *t;
-
- debug("%s timers:\n", name);
- WALK_LIST(n, *l)
- {
- t = SKIP_BACK(timer, n, n);
- debug("%p ", t);
- tm_dump(&t->r);
- }
- debug("\n");
-}
-
-void
-tm_dump_all(void)
-{
- tm_dump_them("Near", &near_timers);
- tm_dump_them("Far", &far_timers);
-}
-
-static inline time_t
-tm_first_shot(void)
-{
- time_t x = first_far_timer;
-
- if (!EMPTY_LIST(near_timers))
- {
- timer *t = SKIP_BACK(timer, n, HEAD(near_timers));
- if (t->expires < x)
- x = t->expires;
- }
- return x;
-}
-
-void io_log_event(void *hook, void *data);
-
-static void
-tm_shot(void)
-{
- timer *t;
- node *n, *m;
-
- if (first_far_timer <= now)
- {
- bird_clock_t limit = now + NEAR_TIMER_LIMIT;
- first_far_timer = TIME_INFINITY;
- n = HEAD(far_timers);
- while (m = n->next)
- {
- t = SKIP_BACK(timer, n, n);
- if (t->expires <= limit)
- {
- rem_node(n);
- tm_insert_near(t);
- }
- else if (t->expires < first_far_timer)
- first_far_timer = t->expires;
- n = m;
- }
- }
- while ((n = HEAD(near_timers)) -> next)
- {
- int delay;
- t = SKIP_BACK(timer, n, n);
- if (t->expires > now)
- break;
- rem_node(n);
- delay = t->expires - now;
- t->expires = 0;
- if (t->recurrent)
- {
- int i = t->recurrent - delay;
- if (i < 0)
- i = 0;
- tm_start(t, i);
- }
- io_log_event(t->hook, t->data);
- t->hook(t);
- }
-}
-#endif
-
/*
* Time clock