freebsd-dev/usr.sbin/xntpd/xntpd/ntp_timer.c

188 lines
3.8 KiB
C
Raw Normal View History

1994-09-29 23:04:24 +00:00
/*
1993-12-21 18:36:48 +00:00
* ntp_event.c - event timer support routines
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/signal.h>
#include "ntpd.h"
#include "ntp_stdlib.h"
/*
* These routines provide support for the event timer. The timer is
* implemented by an interrupt routine which sets a flag once every
* 2**EVENT_TIMEOUT seconds (currently 4), and a timer routine which
* is called when the mainline code gets around to seeing the flag.
* The timer routine dispatches the clock adjustment code if its time
* has come, then searches the timer queue for expiries which are
* dispatched to the transmit procedure. Finally, we call the hourly
* procedure to do cleanup and print a message.
*/
/*
* Alarm flag. The mainline code imports this.
*/
int alarm_flag;
/*
* adjust and hourly counters
*/
1994-09-29 23:04:24 +00:00
static u_long adjust_timer;
static u_long hourly_timer;
1993-12-21 18:36:48 +00:00
/*
* Imported from the leap module. The leap timer.
*/
1994-09-29 23:04:24 +00:00
extern u_long leap_timer;
1993-12-21 18:36:48 +00:00
/*
* Statistics counter for the interested.
*/
1994-09-29 23:04:24 +00:00
u_long alarm_overflow;
1993-12-21 18:36:48 +00:00
#define HOUR (60*60)
/*
* Current_time holds the number of seconds since we started, in
* increments of 2**EVENT_TIMEOUT seconds. The timer queue is the
* hash into which we sort timer entries.
*/
1994-09-29 23:04:24 +00:00
u_long current_time;
1993-12-21 18:36:48 +00:00
struct event timerqueue[TIMER_NSLOTS];
/*
* Stats. Number of overflows and number of calls to transmit().
*/
1994-09-29 23:04:24 +00:00
u_long timer_timereset;
u_long timer_overflows;
u_long timer_xmtcalls;
1993-12-21 18:36:48 +00:00
static RETSIGTYPE alarming P((int));
/*
* init_timer - initialize the timer data structures
*/
void
init_timer()
{
register int i;
struct itimerval itimer;
/*
* Initialize...
*/
alarm_flag = 0;
alarm_overflow = 0;
adjust_timer = (1<<CLOCK_ADJ);
hourly_timer = HOUR;
current_time = 0;
timer_overflows = 0;
timer_xmtcalls = 0;
timer_timereset = 0;
for (i = 0; i < TIMER_NSLOTS; i++) {
/*
* Queue pointers should point at themselves. Event
* times must be set to 0 since this is used to
* detect the queue end.
*/
timerqueue[i].next = &timerqueue[i];
timerqueue[i].prev = &timerqueue[i];
timerqueue[i].event_time = 0;
}
/*
* Set up the alarm interrupt. The first comes 2**EVENT_TIMEOUT
* seconds from now and they continue on every 2**EVENT_TIMEOUT
* seconds.
*/
(void) signal_no_reset(SIGALRM, alarming);
itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
itimer.it_interval.tv_usec = itimer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
}
/*
* timer - dispatch anyone who needs to be
*/
void
timer()
{
register struct event *ev;
register struct event *tq;
current_time += (1<<EVENT_TIMEOUT);
/*
* Adjustment timeout first
*/
if (adjust_timer <= current_time) {
adjust_timer += (1<<CLOCK_ADJ);
adj_host_clock();
}
/*
* Leap timer next.
*/
if (leap_timer != 0 && leap_timer <= current_time)
leap_process();
/*
* Now dispatch any peers whose event timer has expired.
*/
tq = &timerqueue[TIMER_SLOT(current_time)];
ev = tq->next;
while (ev->event_time != 0
&& ev->event_time < (current_time + (1<<EVENT_TIMEOUT))) {
tq->next = ev->next;
tq->next->prev = tq;
ev->prev = ev->next = 0;
timer_xmtcalls++;
ev->event_handler(ev->peer);
ev = tq->next;
}
/*
* Finally, call the hourly routine
*/
if (hourly_timer <= current_time) {
hourly_timer += HOUR;
hourly_stats();
}
}
/*
* alarming - tell the world we've been alarmed
*/
static RETSIGTYPE
alarming(sig)
int sig;
{
extern int initializing; /* from main line code */
if (initializing)
return;
if (alarm_flag)
alarm_overflow++;
else
alarm_flag++;
}
/*
* timer_clr_stats - clear timer module stat counters
*/
void
timer_clr_stats()
{
timer_overflows = 0;
timer_xmtcalls = 0;
timer_timereset = current_time;
}