/* * ntp_timer.c - event timer support routines */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "ntp_machine.h" #include "ntpd.h" #include "ntp_stdlib.h" #if defined(HAVE_IO_COMPLETION_PORT) # include "ntp_iocompletionport.h" # include "ntp_timer.h" #endif /* * 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. */ volatile int alarm_flag; /* * The counters */ static u_long adjust_timer; /* second timer */ static u_long keys_timer; /* minute timer */ static u_long hourly_timer; /* hour timer */ static u_long revoke_timer; /* keys revoke timer */ u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout */ /* * Statistics counter for the interested. */ volatile u_long alarm_overflow; #define MINUTE 60 #define HOUR (60*60) u_long current_time; /* * Stats. Number of overflows and number of calls to transmit(). */ u_long timer_timereset; u_long timer_overflows; u_long timer_xmtcalls; #if defined(VMS) static int vmstimer[2]; /* time for next timer AST */ static int vmsinc[2]; /* timer increment */ #endif /* VMS */ #if defined SYS_WINNT static HANDLE WaitableTimerHandle = NULL; #else static RETSIGTYPE alarming P((int)); #endif /* SYS_WINNT */ /* * init_timer - initialize the timer data structures */ void init_timer(void) { #if !defined(VMS) # if !defined SYS_WINNT || defined(SYS_CYGWIN32) # ifndef HAVE_TIMER_SETTIME struct itimerval itimer; # else static timer_t ntpd_timerid; /* should be global if we ever want */ /* to kill timer without rebooting ... */ struct itimerspec itimer; # endif /* HAVE_TIMER_SETTIME */ # else /* SYS_WINNT */ HANDLE hToken; TOKEN_PRIVILEGES tkp; # endif /* SYS_WINNT */ #endif /* !VMS */ /* * Initialize... */ alarm_flag = 0; alarm_overflow = 0; adjust_timer = 1; hourly_timer = HOUR; current_time = 0; timer_overflows = 0; timer_xmtcalls = 0; timer_timereset = 0; #if !defined(SYS_WINNT) /* * Set up the alarm interrupt. The first comes 2**EVENT_TIMEOUT * seconds from now and they continue on every 2**EVENT_TIMEOUT * seconds. */ # if !defined(VMS) # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) if (timer_create (CLOCK_REALTIME, NULL, &ntpd_timerid) == # ifdef SYS_VXWORKS ERROR # else -1 # endif ) { fprintf (stderr, "timer create FAILED\n"); exit (0); } (void) signal_no_reset(SIGALRM, alarming); itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<next; if (peer->action && peer->nextaction <= current_time) peer->action(peer); if (peer->nextdate <= current_time) { #ifdef REFCLOCK if (peer->flags & FLAG_REFCLOCK) refclock_transmit(peer); else transmit(peer); #else /* REFCLOCK */ transmit(peer); #endif /* REFCLOCK */ } } } /* * Garbage collect expired keys. */ if (keys_timer <= current_time) { keys_timer += MINUTE; auth_agekeys(); } /* * Garbage collect revoked keys */ if (revoke_timer <= current_time) { revoke_timer += RANDPOLL(sys_revoke); key_expire_all(); } /* * Finally, call the hourly routine. */ if (hourly_timer <= current_time) { hourly_timer += HOUR; hourly_stats(); } } #ifndef SYS_WINNT /* * alarming - tell the world we've been alarmed */ static RETSIGTYPE alarming( int sig ) { #if !defined(VMS) if (initializing) return; if (alarm_flag) alarm_overflow++; else alarm_flag++; #else /* VMS AST routine */ if (!initializing) { if (alarm_flag) alarm_overflow++; else alarm_flag = 1; /* increment is no good */ } lib$addx(&vmsinc,&vmstimer,&vmstimer); sys$setimr(0,&vmstimer,alarming,alarming,0); #endif /* VMS */ } #endif /* SYS_WINNT */ /* * timer_clr_stats - clear timer module stat counters */ void timer_clr_stats(void) { timer_overflows = 0; timer_xmtcalls = 0; timer_timereset = current_time; }