1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/* ----------------------------------------------------------
% (C)1995 Institute for New Generation Computer Technology
% (Read COPYRIGHT for detailed information.)
% (C)1996, 1997, 1998, 1999 Japan Information Processing Development Center
% (Read COPYRIGHT-JIPDEC for detailed information.)
----------------------------------------------------------- */
#include <klic/basic.h>
#ifdef USETIMER
#include <signal.h>
#include <sys/time.h>
#include <klic/timer.h>
extern char *malloc_check();
static struct klic_timer_wait_rec * Volatile
timer_wait_root = 0;
static struct klic_timer_wait_rec * Volatile
timer_wait_free = 0;
static Inline void
insert_timer_queue(newtwr)
struct klic_timer_wait_rec *newtwr;
{
struct klic_timer_wait_rec * Volatile *twr;
for (twr = &timer_wait_root;
*twr != 0 && NotLaterThan((*twr)->on_at, newtwr->on_at);
twr = &(*twr)->next) {
}
newtwr->next = *twr;
*twr = newtwr;
}
static void restart_timer(now)
struct timeval *now;
{
struct itimerval itmp;
struct timeval margin;
TimeSub(timer_wait_root->on_at, *now, itmp.it_value);
TimeSet(itmp.it_interval, 0, 0);
if (setitimer(ITIMER_REAL, &itmp, 0) != 0) {
fatalp("setitimer", "Error in restarting timer");
}
}
void klic_gettod(now)
struct timeval *now;
{
if (gettimeofday(now, 0) != 0) {
fatalp("gettimeofday", "Error in getting date and time");
}
}
static void
process_time_expired_events()
{
struct timeval now;
klic_gettod(&now);
while (timer_wait_root != 0 &&
NotLaterThan(timer_wait_root->on_at, now)) {
struct klic_timer_wait_rec *tmp;
timer_wait_root->func();
tmp = timer_wait_root;
timer_wait_root = tmp->next;
if (TimeIsZero(tmp->interval)) {
tmp->next = timer_wait_free;
timer_wait_free = tmp;
} else {
TimeAdd(tmp->on_at, tmp->interval, tmp->on_at);
insert_timer_queue(tmp);
}
}
if (timer_wait_root != 0) {
restart_timer(&now);
}
}
static void timer_expiration_handler()
{
process_time_expired_events();
}
static void
schedule_timer_interrupt(on_at, interval, func)
struct timeval *on_at, *interval;
void (*func)();
{
struct timeval now;
struct timeval at;
sigset_t original, blocking;
struct klic_timer_wait_rec *tmp;
at = *on_at;
sigemptyset(&blocking);
sigaddset(&blocking, SIGALRM);
if (sigprocmask(SIG_BLOCK, &blocking, &original) != 0) {
fatalp("sigprocmask", "Error in setting signal mask");
}
if (timer_wait_free == 0) {
tmp = (struct klic_timer_wait_rec *)
malloc_check(sizeof(struct klic_timer_wait_rec));
} else {
tmp = timer_wait_free;
timer_wait_free = timer_wait_free->next;
}
tmp->on_at = at;
tmp->func = func;
tmp->interval = *interval;
insert_timer_queue(tmp);
process_time_expired_events();
if (sigprocmask(SIG_SETMASK, &original, (sigset_t *)0) != 0) {
fatalp("sigprocmask", "Error in restoring signal mask");
}
}
void
call_at_specified_time(sec, usec, func)
long sec, usec;
void (*func)();
{
struct timeval at, interval;
TimeSet(at, sec, usec);
TimeSet(interval, 0, 0);
schedule_timer_interrupt(&at, &interval, func);
}
void
call_after_specified_interval(sec, usec, func)
long sec, usec;
void (*func)();
{
struct timeval now, at, interval;
klic_gettod(&now);
TimeSet(at, sec, usec);
TimeAdd(at, now, at);
TimeSet(interval, 0, 0);
schedule_timer_interrupt(&at, &interval, func);
}
void
call_at_time_intervals(sec, usec, func)
long sec, usec;
void (*func)();
{
struct timeval now, at, interval;
klic_gettod(&now);
TimeSet(at, sec, usec);
TimeAdd(at, now, at);
TimeSet(interval, sec, usec);
schedule_timer_interrupt(&at, &interval, func);
}
void
init_virtualized_timer()
{
struct sigaction act;
act.sa_handler = timer_expiration_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGALRM);
act.sa_flags = 0;
if (sigaction(SIGALRM, &act, (struct sigaction *)0) != 0) {
fatalp("sigation", "Error in initiating handler for SIGALRM");
}
}
#endif
|