mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 01:31:55 +00:00
Sysdep: Remove old timer code
This commit is contained in:
parent
3e405fb188
commit
6b5cd7c05f
18
lib/timer.c
18
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>
|
||||
|
283
sysdep/unix/io.c
283
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
|
||||
|
Loading…
Reference in New Issue
Block a user