/* * ntp_timer.c - event timer support routines */ #ifdef HAVE_CONFIG_H # include #endif #include "ntp_machine.h" #include "ntpd.h" #include "ntp_stdlib.h" #include #include #ifdef HAVE_SYS_SIGNAL_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #if defined(HAVE_IO_COMPLETION_PORT) # include "ntp_iocompletionport.h" # include "ntp_timer.h" #endif #ifdef PUBKEY #include "ntp_crypto.h" #endif /* PUBKEY */ /* * 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 huffpuff_timer; /* huff-n'-puff timer */ #ifdef AUTOKEY static u_long revoke_timer; /* keys revoke timer */ u_long sys_revoke = 1 << KEY_REVOKE; /* keys revoke timeout */ #endif /* AUTOKEY */ /* * 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; huffpuff_timer = 0; 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(); } /* * Huff-n'-puff filter */ if (huffpuff_timer <= current_time) { huffpuff_timer += HUFFPUFF; huffpuff(); } #ifdef AUTOKEY /* * Garbage collect old keys and generate new private value */ if (revoke_timer <= current_time) { revoke_timer += sys_revoke; expire_all(); #ifdef DEBUG if (debug) printf("key expire: at %lu next %lu\n", current_time, revoke_timer); #endif } #endif /* AUTOKEY */ /* * 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; }