Current Path : /usr/src/contrib/ntp/ntpd/ |
FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64 |
Current File : //usr/src/contrib/ntp/ntpd/ntp_timer.c |
/* * ntp_timer.c - event timer support routines */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "ntp_machine.h" #include "ntpd.h" #include "ntp_stdlib.h" #include <stdio.h> #include <signal.h> #ifdef HAVE_SYS_SIGNAL_H # include <sys/signal.h> #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #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. */ volatile int interface_interval = 300; /* update interface every 5 minutes as default */ /* * 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 stats_timer; /* stats timer */ static u_long huffpuff_timer; /* huff-n'-puff timer */ static u_long interface_timer; /* interface update timer */ #ifdef OPENSSL static u_long revoke_timer; /* keys revoke timer */ u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */ #endif /* OPENSSL */ /* * 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 */ #if !defined(VMS) # if !defined SYS_WINNT || defined(SYS_CYGWIN32) # ifndef HAVE_TIMER_SETTIME struct itimerval itimer; # else static timer_t ntpd_timerid; struct itimerspec itimer; # endif /* HAVE_TIMER_SETTIME */ # endif /* SYS_WINNT */ #endif /* VMS */ /* * reinit_timer - reinitialize interval timer. */ void reinit_timer(void) { #if !defined(SYS_WINNT) && !defined(VMS) # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) timer_gettime(ntpd_timerid, &itimer); if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) { itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT); } if (itimer.it_value.tv_nsec < 0 ) { itimer.it_value.tv_nsec = 0; } if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_nsec == 0) { itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT); itimer.it_value.tv_nsec = 0; } itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT); itimer.it_interval.tv_nsec = 0; timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL); # else getitimer(ITIMER_REAL, &itimer); if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) { itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT); } if (itimer.it_value.tv_usec < 0 ) { itimer.it_value.tv_usec = 0; } if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_usec == 0) { itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT); itimer.it_value.tv_usec = 0; } itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT); itimer.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); # endif # endif /* VMS */ } /* * init_timer - initialize the timer data structures */ void init_timer(void) { # if defined SYS_WINNT & !defined(SYS_CYGWIN32) HANDLE hToken = INVALID_HANDLE_VALUE; TOKEN_PRIVILEGES tkp; # endif /* SYS_WINNT */ /* * Initialize... */ alarm_flag = 0; alarm_overflow = 0; adjust_timer = 1; stats_timer = 0; huffpuff_timer = 0; interface_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<<EVENT_TIMEOUT); itimer.it_interval.tv_nsec = itimer.it_value.tv_nsec = 0; timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL); # else (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); # endif # else /* VMS */ vmsinc[0] = 10000000; /* 1 sec */ vmsinc[1] = 0; lib$emul(&(1<<EVENT_TIMEOUT), &vmsinc, &0, &vmsinc); sys$gettim(&vmstimer); /* that's "now" as abstime */ lib$addx(&vmsinc, &vmstimer, &vmstimer); sys$setimr(0, &vmstimer, alarming, alarming, 0); # endif /* VMS */ #else /* SYS_WINNT */ _tzset(); /* * Get privileges needed for fiddling with the clock */ /* get the current process token handle */ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { msyslog(LOG_ERR, "OpenProcessToken failed: %m"); exit(1); } /* get the LUID for system-time privilege. */ LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; /* one privilege to set */ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* get set-time privilege for this process. */ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); /* cannot test return value of AdjustTokenPrivileges. */ if (GetLastError() != ERROR_SUCCESS) { msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); } /* * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds * Under Windows/NT, */ WaitableTimerHandle = CreateWaitableTimer(NULL, FALSE, NULL); if (WaitableTimerHandle == NULL) { msyslog(LOG_ERR, "CreateWaitableTimer failed: %m"); exit(1); } else { DWORD Period = (1<<EVENT_TIMEOUT) * 1000; LARGE_INTEGER DueTime; DueTime.QuadPart = Period * 10000i64; if (!SetWaitableTimer(WaitableTimerHandle, &DueTime, Period, NULL, NULL, FALSE) != NO_ERROR) { msyslog(LOG_ERR, "SetWaitableTimer failed: %m"); exit(1); } } #endif /* SYS_WINNT */ } #if defined(SYS_WINNT) extern HANDLE get_timer_handle(void) { return WaitableTimerHandle; } #endif /* * timer - dispatch anyone who needs to be */ void timer(void) { register struct peer *peer, *next_peer; #ifdef OPENSSL char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ #endif /* OPENSSL */ u_int n; current_time += (1<<EVENT_TIMEOUT); /* * Adjustment timeout first. */ if (adjust_timer <= current_time) { adjust_timer += 1; adj_host_clock(); kod_proto(); #ifdef REFCLOCK for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->next; if (peer->flags & FLAG_REFCLOCK) refclock_timer(peer); } } #endif /* REFCLOCK */ } /* * Now dispatch any peers whose event timer has expired. Be careful * here, since the peer structure might go away as the result of * the call. */ for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->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 OPENSSL /* * Garbage collect old keys and generate new private value */ if (revoke_timer <= current_time) { revoke_timer += RANDPOLL(sys_revoke); expire_all(); sprintf(statstr, "refresh ts %u", ntohl(hostval.tstamp)); record_crypto_stats(NULL, statstr); #ifdef DEBUG if (debug) printf("timer: %s\n", statstr); #endif } #endif /* OPENSSL */ /* * interface update timer */ if (interface_interval && interface_timer <= current_time) { timer_interfacetimeout(current_time + interface_interval); DPRINTF(1, ("timer: interface update\n")); interface_update(NULL, NULL); } /* * Finally, periodically write stats. */ if (stats_timer <= current_time) { if (stats_timer != 0) write_stats(); stats_timer += stats_write_period; } } #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 */ void timer_interfacetimeout(u_long timeout) { interface_timer = timeout; } /* * timer_clr_stats - clear timer module stat counters */ void timer_clr_stats(void) { timer_overflows = 0; timer_xmtcalls = 0; timer_timereset = current_time; }