Sysdep: Remove old timer code
This commit is contained in:
parent
3e405fb188
commit
6b5cd7c05f
2 changed files with 18 additions and 283 deletions
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.
|
* 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 <stdio.h>
|
||||||
#include <stdlib.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;
|
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
|
* Time clock
|
||||||
|
|
Loading…
Reference in a new issue