#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <mat.h>#include <math.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/timex.h>#include <sys/types.h>#include <syscall.h>#include <time.h>#include <unistd.h>#include <utmp.h>#include <sys/ioctl.h>#include <linux/rtc.h>Go to the source code of this file.
Classes | |
| struct | cmos_adj |
Defines | |
| #define | _GNU_SOURCE |
| #define | LOG_PATH "/var/log/clocks.log" |
| #define | WTMP_PATH "/var/log/wtmp" |
| #define | ADJPATH "/etc/adjtime" |
| #define | RTC_JITTER .000025 |
| #define | SECONDSPERDAY 86400 |
| #define | BUFLEN 128 |
| #define | CMOS_VALID 1 |
| #define | SYS_VALID 2 |
| #define | REF_VALID 4 |
| #define | HELP 131 |
| #define | CMOS_READ(addr) ({outb(0x70,(addr)|0x80); inb(0x71);}) |
| #define | SHIFT (1<<16) |
Functions | |
| _syscall1 (int, adjtimex, struct timex *, txcp) | |
| void | compare (void) |
| void | failntpdate () |
| void | reset_time_status (void) |
| static double | compare_cmos_sys (void) |
| cmos_adj * | get_cmos_adjustment (void) |
| void | log_times (void) |
| int | valid_system_rate (double ftime_sys, double ftime_ref, double sigma_ref) |
| int | valid_cmos_rate (double ftime_cmos, double ftime_ref, double sigma_ref) |
| void | sethackent (void) |
| void | endhackent (void) |
| hack * | gethackent (void) |
| void | puthackent (struct hack *ph) |
| time_t | mkgmtime (struct tm *tp) |
| int | compare_tm (struct tm *first, struct tm *second) |
| static void * | xmalloc (int n) |
| static void * | xrealloc (void *pv, int n) |
| void | review (void) |
| void | kalman_update (double *x, int xr, double *p, double *h, double *z, int zr, double *r) |
| void | usage (void) |
| void | probe_time (int *hz, int *tick_min, int *tick_mid, int *tick_max, long *maxfreq) |
| int | main (int argc, char *argv[]) |
| static void | outb (short port, char val) |
| static unsigned char | inb (short port) |
| void | cmos_init () |
| static int | cmos_read_bcd (int addr) |
| static void | cmos_read_time (struct tm *tm) |
| static void | xusleep (long microseconds) |
Variables | |
| prev | |
| cmos_adj | ca |
| timex | txc |
| option | longopt [] |
| int | adjusting = 0 |
| int | comparing = 0 |
| int | logging = 0 |
| int | reviewing = 0 |
| int | resetting = 0 |
| int | interval = 10 |
| int | count = 8 |
| int | marked |
| int | universal = 0 |
| int | watch |
| int | undisturbed_sys = 0 |
| int | undisturbed_cmos = 0 |
| char * | timeserver |
| static FILE * | lfile |
|
|
Definition at line 13 of file adjtimex.c. |
|
|
Referenced by compare(), get_cmos_adjustment(), and valid_system_rate(). |
|
|
Referenced by log_times(), valid_cmos_rate(), and valid_system_rate(). |
|
|
Definition at line 559 of file adjtimex.c. Referenced by cmos_read_bcd(), cmos_read_time(), and compare_cmos_sys(). |
|
|
Definition at line 109 of file adjtimex.c. Referenced by review(). |
|
|
Definition at line 122 of file adjtimex.c. Referenced by main(). |
|
|
|
|
|
Definition at line 111 of file adjtimex.c. Referenced by review(). |
|
|
Referenced by review(). |
|
|
|
|
|
|
|
|
Definition at line 110 of file adjtimex.c. Referenced by review(). |
|
|
Referenced by valid_system_rate(). |
|
||||||||||||||||||||
|
Definition at line 44 of file adjtimex.c. 00075 : 00076 00077 * read RTC once any update in progress is done. The update 00078 * can take just over 2ms. We wait 10 to 20ms. There is no need to 00079 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. 00080 * If you need to know *exactly* when a second has started, enable 00081 * periodic update complete interrupts, (via ioctl) and then 00082 * immediately read /dev/rtc which will block until you get the IRQ. 00083 * Once the read clears, read the RTC time (again via ioctl). Easy. 00084 00085 However it doesn't say how to restore the interrupt setup. Until I 00086 find out about that, I'll continue to use the poll-wait. */ 00087 static int using_dev_rtc = 0; 00088 00089 struct hack { 00090 double ref; /* reference time for time hack */ 00091 double sigma_ref; /* expected error in above (or zero if 00092 no reference time available) */ 00093 time_t log; /* reference time as time_t */ 00094 double sys; /* system time */ 00095 int tick; /* "tick" system parameter */ 00096 int freq; /* "freq" system parameter */ 00097 char sys_ok; /* nonzero if system clock undisturbed 00098 during previous period */ 00099 double cmos; /* CMOS time */ 00100 char cmos_ok; /* nonzero if cmos clock undisturbed 00101 during previous period */ 00102 char valid; /* bit flags (see below) */ 00103 double sys_rate, sys_sigma; 00104 double cmos_rate, cmos_sigma; 00105 double relative_rate, relative_sigma; 00106 } prev;
|
|
|
Definition at line 522 of file adjtimex.c. Referenced by compare(), and compare_cmos_sys(). 00523 { 00524 if (using_dev_rtc < 0) 00525 { 00526 cmos_fd = open ("/dev/rtc", O_RDONLY); 00527 if (cmos_fd >= 0) 00528 { 00529 using_dev_rtc = 1; 00530 return; 00531 } 00532 using_dev_rtc = 0; 00533 } 00534 else if (using_dev_rtc > 0) 00535 return; 00536 00537 #ifdef USE_INLINE_ASM_IO 00538 if (ioperm (0x70, 2, 1)) 00539 { 00540 fprintf (stderr, "clock: unable to get I/O port access\n"); 00541 exit (1); 00542 } 00543 #else 00544 if (cmos_fd < 0) 00545 cmos_fd = open ("/dev/port", O_RDWR); 00546 if (cmos_fd < 0) 00547 { 00548 perror ("unable to open /dev/port read/write : "); 00549 exit (1); 00550 } 00551 if (lseek (cmos_fd, 0x70, 0) < 0 || lseek (cmos_fd, 0x71, 0) < 0) 00552 { 00553 perror ("unable to seek port 0x70 in /dev/port : "); 00554 exit (1); 00555 } 00556 #endif 00557 }
|
|
|
Definition at line 562 of file adjtimex.c. References CMOS_READ. Referenced by cmos_read_time(), and compare_cmos_sys(). 00563 { 00564 int b; 00565 00566 b = CMOS_READ (addr); 00567 return (b & 15) + (b >> 4) * 10; 00568 }
|
|
|
Definition at line 571 of file adjtimex.c. References CMOS_READ, and cmos_read_bcd(). Referenced by compare(). 00572 { 00573 if (using_dev_rtc > 0) 00574 ioctl (cmos_fd, RTC_RD_TIME, tm); 00575 else 00576 { 00577 long i; 00578 00579 /* read RTC exactly on falling edge of update flag */ 00580 /* Wait for rise.... (may take up to 1 second) */ 00581 00582 for (i = 0; i < 10000000; i++) 00583 if (CMOS_READ (10) & 0x80) 00584 break; 00585 00586 /* Wait for fall.... (must try at least 2.228 ms) */ 00587 00588 for (i = 0; i < 1000000; i++) 00589 if (!(CMOS_READ (10) & 0x80)) 00590 break; 00591 00592 /* The "do" loop is "low-risk programming" */ 00593 /* In theory it should never run more than once */ 00594 do 00595 { 00596 tm->tm_sec = cmos_read_bcd (0); 00597 tm->tm_min = cmos_read_bcd (2); 00598 tm->tm_hour = cmos_read_bcd (4); 00599 tm->tm_wday = cmos_read_bcd (6); 00600 tm->tm_mday = cmos_read_bcd (7); 00601 tm->tm_mon = cmos_read_bcd (8); 00602 tm->tm_year = cmos_read_bcd (9); 00603 } 00604 while (tm->tm_sec != cmos_read_bcd (0)); 00605 } 00606 }
|
|
|
Definition at line 623 of file adjtimex.c. References ADJPATH, adjusting, cmos_init(), cmos_read_time(), count, interval, logging, marked, mkgmtime(), probe_time(), puthackent(), reset_time_status(), resetting, SECONDSPERDAY, SHIFT, universal, and xusleep(). Referenced by main(). 00624 { 00625 struct timex txc; 00626 struct tm tm; 00627 time_t cmos_time; 00628 time_t last_time; 00629 double cmos_sec, system_sec, dif, dif_prev = 0.; 00630 FILE *adj; 00631 double factor; 00632 double cmos_adjustment; 00633 double not_adjusted; 00634 int loops = 0; 00635 extern char *optarg; 00636 struct timeval now; 00637 int wrote_to_log = 0; 00638 int hz, tick_min, tick_mid, tick_max; 00639 long maxfreq; 00640 00641 probe_time(&hz, &tick_min, &tick_mid, &tick_max, &maxfreq); 00642 00643 00644 /* Read adjustment parameters first */ 00645 if ((adj = fopen (ADJPATH, "r")) == NULL) 00646 { 00647 perror (ADJPATH); 00648 exit (2); 00649 } 00650 if (fscanf (adj, "%lf %ld %lf", &factor, &last_time, ¬_adjusted) < 0) 00651 { 00652 perror (ADJPATH); 00653 exit (2); 00654 } 00655 fclose (adj); 00656 #ifdef DEBUG 00657 /* 00658 cmos clock last adjusted at Tue Aug 26 11:43:57 1997 (= 872610237) 00659 current cmos time Tue Aug 26 21:27:05 1997 EDT (= 872645225) 00660 */ 00661 { 00662 struct tm bdt; 00663 if (universal) 00664 { 00665 bdt = *gmtime(&last_time); 00666 (void)mkgmtime(&bdt); /* set tzname */ 00667 } 00668 else 00669 { 00670 bdt = *localtime(&last_time); 00671 (void)mktime(&bdt); /* set tzname */ 00672 } 00673 printf ("cmos clock last adjusted %.24s %s " 00674 "(= %ld)\n", 00675 ctime(&last_time), tzname[tm.tm_isdst?1:0], (long) last_time); 00676 } 00677 #endif 00678 00679 cmos_init (); 00680 00681 while (count != 0) 00682 { 00683 if (count > 0) count--; 00684 00685 cmos_read_time (&tm); 00686 00687 /* fetch system time immediately */ 00688 gettimeofday (&now, NULL); 00689 00690 tm.tm_mon--; /* DOS uses 1 base */ 00691 tm.tm_wday -= 3; /* DOS uses 3 - 9 for week days */ 00692 tm.tm_isdst = -1; /* don't know whether it's daylight */ 00693 if ((tm.tm_year += (epoch - 1900)) <= 69) 00694 tm.tm_year += 100; 00695 00696 if (universal) 00697 cmos_time = mkgmtime(&tm); 00698 else 00699 cmos_time = mktime (&tm); 00700 /* printf ("%s", asctime (&tm)); */ 00701 00702 system_sec = now.tv_sec + .000001*now.tv_usec; 00703 00704 /* If we're adjusting time parameters, we want to make a log 00705 entry only for the first two comparisons (before we change 00706 the parameters). Otherwise, we want to log the first and last 00707 comparisons in order to maximize the duration. */ 00708 if (logging && (wrote_to_log ^ (adjusting?(loops==0):(count!=0)))) 00709 { 00710 struct hack h; 00711 00712 h.ref = 0; 00713 h.sigma_ref = 0; 00714 h.log = (time_t)system_sec; 00715 h.sys = system_sec; 00716 txc.modes = 0; 00717 adjtimex(&txc); 00718 h.tick = txc.tick; 00719 h.freq = txc.freq; 00720 h.sys_ok = wrote_to_log; 00721 h.cmos = cmos_time; 00722 h.cmos_ok = wrote_to_log; 00723 puthackent(&h); 00724 wrote_to_log = 1; 00725 } 00726 00727 #ifdef DEBUG 00728 printf (" current cmos time %.24s %s (= %ld)\n", 00729 asctime(&tm), tzname[tm.tm_isdst?1:0], (long) cmos_time); 00730 #endif 00731 cmos_adjustment = ((double) (cmos_time - last_time)) 00732 * factor / SECONDSPERDAY 00733 + not_adjusted; 00734 cmos_sec = cmos_time + cmos_adjustment; 00735 #ifdef DEBUG 00736 printf ( 00737 " time since last adjustment %10.6f days (= %9d sec)\n", 00738 (int) (cmos_time - last_time) / (double)SECONDSPERDAY, 00739 (int) (cmos_time - last_time)); 00740 printf ( 00741 " factor %10.6f sec/day\n", 00742 factor); 00743 printf ( 00744 " adjustment %10.6f + %7.6f = %7.6f sec\n", 00745 ((double) (cmos_time - last_time))*factor/SECONDSPERDAY, 00746 not_adjusted, cmos_adjustment); 00747 #endif 00748 dif = system_sec - cmos_sec; 00749 00750 txc.modes = 0; 00751 if (adjtimex (&txc) < 0) {perror ("adjtimex"); exit(1);} 00752 /* 00753 --- current --- -- suggested -- 00754 cmos time system-cmos error_ppm tick freq tick freq 00755 1094939320 -14394.974188 00756 1094939330 -14394.971203 298.5 10001 1290819 00757 1094939340 -14394.968203 300.0 10001 1290819 9998 1289097 00758 */ 00759 00760 if (! marked++ ) 00761 { 00762 if (interval) 00763 printf ( 00764 " --- current --- -- suggested --\n" 00765 "cmos time system-cmos error_ppm tick freq tick freq\n"); 00766 else 00767 printf ( 00768 "cmos time system-cmos error_ppm tick freq\n"); 00769 } 00770 printf ("%9ld %11.6f", 00771 (long) cmos_sec, 00772 dif); 00773 if (++loops > 1) 00774 { /* print difference in rates */ 00775 #define SHIFT (1<<16) 00776 double second_diff, error_ppm; 00777 second_diff = dif - dif_prev; 00778 error_ppm = second_diff/interval*1000000; 00779 printf ("%11.1f %6ld %9ld", 00780 error_ppm, 00781 txc.tick, 00782 txc.freq); 00783 if (loops > 2) 00784 { /* print suggested values */ 00785 long tick_delta = 0, freq_delta = 0; 00786 00787 tick_delta = ceil((-error_ppm + txc.freq/SHIFT - hz)/hz); 00788 error_ppm += tick_delta*hz; 00789 freq_delta = -error_ppm*SHIFT; 00790 printf(" %6ld %9ld\n", 00791 txc.tick + tick_delta, txc.freq + freq_delta); 00792 if (loops > 4 && adjusting) 00793 { 00794 txc.modes = ADJ_FREQUENCY | ADJ_TICK; 00795 txc.tick += tick_delta; 00796 txc.freq += freq_delta; 00797 if (adjtimex (&txc) < 0) 00798 { 00799 perror ("adjtimex"); 00800 exit(1); 00801 } 00802 if (resetting) 00803 reset_time_status(); 00804 loops -= 3; 00805 } 00806 } 00807 else 00808 printf("\n"); 00809 } 00810 else 00811 printf("\n"); 00812 dif_prev = dif; 00813 if (interval == 0) 00814 break; 00815 if (count) /* if it is not the last round */ 00816 xusleep (interval*1000000L - 900000); /* reading RTC takes 1 sec */ 00817 } 00818 }
|
|
|
Definition at line 1219 of file adjtimex.c. References cmos_init(), CMOS_READ, cmos_read_bcd(), mkgmtime(), and universal. Referenced by log_times(). 01220 { 01221 struct tm tm; 01222 time_t cmos_time; 01223 double system_sec; 01224 double dif; 01225 int i; 01226 extern char *optarg; 01227 struct timeval now; 01228 01229 if (geteuid() != 0) 01230 { 01231 struct tm bdt; 01232 char before[256], after[256]; 01233 int fd = open("/proc/rtc", O_RDONLY); 01234 if (fd == -1) 01235 { 01236 fprintf(stderr, "kernel lacks enhanced real time clock support, " 01237 "so only root can read RTC\n"); 01238 exit(1); 01239 } 01240 read(fd, before, sizeof(before)); 01241 close(fd); 01242 do 01243 { 01244 fd = open("/proc/rtc", O_RDONLY); 01245 read(fd, after, sizeof(after)); 01246 gettimeofday (&now, NULL); 01247 close(fd); 01248 } while (!strncmp(before, after, strlen(after))); 01249 strptime(after, "rtc_time : %H:%M:%S\nrtc_date : %Y-%m-%d", &bdt); 01250 01251 if (universal) /* also set tm_wday and tm_yday */ 01252 cmos_time = mkgmtime(&bdt); 01253 else 01254 cmos_time = mktime(&bdt); 01255 #ifdef DEBUG 01256 printf("RTC says date & time are %.24s %s\n", 01257 asctime(&bdt), tzname[bdt.tm_isdst?1:0]); 01258 #endif 01259 system_sec = now.tv_sec + .000001 * now.tv_usec; 01260 dif = (double)cmos_time - system_sec; 01261 return dif; 01262 } 01263 else /* I am superuser */ 01264 { 01265 cmos_init (); 01266 01267 /* read RTC exactly on falling edge of update flag */ 01268 /* Wait for rise.... (may take up to 1 second) */ 01269 01270 for (i = 0; i < 10000000; i++) 01271 if (CMOS_READ (10) & 0x80) 01272 break; 01273 01274 /* Wait for fall.... (must try at least 2.228 ms) */ 01275 01276 for (i = 0; i < 1000000; i++) 01277 if (!(CMOS_READ (10) & 0x80)) 01278 break; 01279 01280 /* The "do" loop is "low-risk programming" */ 01281 /* In theory it should never run more than once */ 01282 do 01283 { 01284 tm.tm_sec = cmos_read_bcd (0); 01285 tm.tm_min = cmos_read_bcd (2); 01286 tm.tm_hour = cmos_read_bcd (4); 01287 tm.tm_wday = cmos_read_bcd (6); 01288 tm.tm_mday = cmos_read_bcd (7); 01289 tm.tm_mon = cmos_read_bcd (8); 01290 tm.tm_year = cmos_read_bcd (9); 01291 } 01292 while (tm.tm_sec != cmos_read_bcd (0)); 01293 01294 /* fetch system time immediately */ 01295 gettimeofday (&now, NULL); 01296 01297 tm.tm_mon--; /* DOS uses 1 base */ 01298 tm.tm_wday -= 3; /* DOS uses 3 - 9 for week days */ 01299 tm.tm_isdst = -1; /* don't know whether it's daylight */ 01300 if ((tm.tm_year += (epoch - 1900)) <= 69) 01301 tm.tm_year += 100; 01302 #ifdef DEBUG 01303 printf (" mday=%d mon=%d wday=%d year=%d\n", 01304 tm.tm_mday, tm.tm_mon, tm.tm_wday, tm.tm_year); 01305 printf ("Cmos time %d:%02d:%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec); 01306 #endif 01307 } 01308 /* 01309 * Mktime assumes we're giving it local time. If the CMOS clock is in 01310 * GMT, we have to set up TZ so mktime knows it. Tzset gets called 01311 * implicitly by the time code, but only the first time. When 01312 * changing the environment variable, better call tzset explicitly. 01313 */ 01314 if (universal) 01315 { 01316 #ifdef ZONESWITCH 01317 zone = (char *) getenv ("TZ"); /* save original time zone */ 01318 (void) putenv ("TZ="); 01319 tzset (); 01320 cmos_time = mktime (&tm); 01321 /* now put back the original zone */ 01322 if (zone) 01323 { 01324 if ((strlen (zone) + 4) > sizeof (zonebuf)) 01325 { 01326 fprintf (stderr, "Size of TZ variable is too long\n"); 01327 exit (2); 01328 } 01329 strcpy (zonebuf, "TZ="); 01330 strcat (zonebuf, zone); 01331 putenv (zonebuf); 01332 } 01333 else 01334 { /* wasn't one, so clear it */ 01335 putenv ("TZ"); 01336 } 01337 tzset (); 01338 printf ("%s", ctime (&cmos_time)); 01339 #else /* !ZONESWITCH */ 01340 cmos_time = mkgmtime(&tm); 01341 #endif 01342 } 01343 else 01344 { 01345 cmos_time = mktime (&tm); 01346 /* printf ("%s", asctime (&tm)); */ 01347 } 01348 01349 system_sec = now.tv_sec + .000001 * now.tv_usec; 01350 #ifdef DEBUG 01351 printf ("Number of seconds since 1/1/1970 is %ld\n", 01352 (long) cmos_time); 01353 #endif 01354 01355 dif = (double)cmos_time - system_sec; 01356 01357 return dif; 01358 }
|
|
||||||||||||
|
Definition at line 1498 of file adjtimex.c. Referenced by mkgmtime(). 01499 { 01500 if (first->tm_year < second->tm_year) return -1; 01501 if (first->tm_year > second->tm_year) return 1; 01502 if (first->tm_mon < second->tm_mon) return -1; 01503 if (first->tm_mon > second->tm_mon) return 1; 01504 if (first->tm_mday < second->tm_mday) return -1; 01505 if (first->tm_mday > second->tm_mday) return 1; 01506 if (first->tm_hour < second->tm_hour) return -1; 01507 if (first->tm_hour > second->tm_hour) return 1; 01508 if (first->tm_min < second->tm_min) return -1; 01509 if (first->tm_min > second->tm_min) return 1; 01510 if (first->tm_sec < second->tm_sec) return -1; 01511 if (first->tm_sec > second->tm_sec) return 1; 01512 return 0; 01513 }
|
|
|
Definition at line 1381 of file adjtimex.c. References lfile. Referenced by review(), sethackent(), and valid_system_rate().
|
|
|
Referenced by log_times(). |
|
|
Definition at line 1193 of file adjtimex.c. References ADJPATH, cmos_adj::ca_adj_time, cmos_adj::ca_factor, and cmos_adj::ca_remainder. Referenced by review(), and valid_system_rate(). 01194 { 01195 FILE *adj; 01196 static struct cmos_adj ca; 01197 if ((adj = fopen (ADJPATH, "r")) == NULL) 01198 { 01199 perror (ADJPATH); 01200 exit (2); 01201 } 01202 if (fscanf (adj, "%lf %ld %lf", 01203 &ca.ca_factor, 01204 &ca.ca_adj_time, 01205 &ca.ca_remainder) < 0) 01206 { 01207 perror (ADJPATH); 01208 exit (2); 01209 } 01210 fclose (adj); 01211 #ifdef DEBUG 01212 printf ("CMOS clock was last adjusted %s", ctime(&ca.ca_adj_time)); 01213 #endif 01214 return &ca; 01215 }
|
|
|
Definition at line 1390 of file adjtimex.c. References lfile, and sethackent(). Referenced by review(), and valid_system_rate(). 01391 { 01392 char buf[256], sys_flag, cmos_flag, junk[26]; 01393 static struct hack h; 01394 01395 if (!lfile) sethackent(); 01396 if (!lfile) return NULL; 01397 while(fgets(buf, sizeof(buf), lfile)) 01398 { 01399 int tokens; 01400 if (buf[0] == '#') 01401 continue; 01402 tokens = sscanf(buf, "%25s %25s %lf %lf %lf %d %d %c %lf %c", 01403 junk, junk, &h.ref, &h.sigma_ref, 01404 &h.sys, &h.tick, &h.freq, &sys_flag, 01405 &h.cmos, &cmos_flag); 01406 if (tokens != 10) 01407 continue; 01408 h.sys_ok = (tolower(sys_flag) == 'y'); 01409 h.cmos_ok = (tolower(cmos_flag) == 'y'); 01410 if (h.ref) 01411 h.log = (time_t)h.ref; 01412 else if (h.sys) 01413 h.log = (time_t)h.sys; 01414 else 01415 h.log = (time_t)h.cmos; 01416 h.valid = 0; 01417 return &h; 01418 } 01419 return NULL; 01420 }
|
|
|
Definition at line 507 of file adjtimex.c. 00508 { 00509 unsigned char ret; 00510 00511 #ifdef USE_INLINE_ASM_IO 00512 __asm__ volatile ("in%B0 %1,%0":"=a" (ret):"d" (port)); 00513 00514 #else 00515 lseek (cmos_fd, port, 0); 00516 read (cmos_fd, &ret, 1); 00517 #endif 00518 return ret; 00519 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 1801 of file adjtimex.c. References mat_add(), mat_copy(), mat_mul(), mat_mul_nt(), mat_one(), mat_similarity(), mat_sub(), sym_factor(), and sym_rdiv(). Referenced by review(). 01812 { 01813 static double k[4], num[4], denom[4], v[4], w[4]; 01814 int pr=xr, pc=xr, 01815 hr=zr, hc=xr, 01816 rr=zr, rc=zr, 01817 kr=xr, kc=zr, 01818 nr=xr, nc=zr, 01819 dr=zr, dc=zr, 01820 vr=xr, vc=1, 01821 wr=zr, wc=1; 01822 01823 /* find the Kalman gain k: 01824 k = p h' /(h p h' + r) */ 01825 mat_mul_nt(p,pr,pc, h,hr,hc, num,nr,nc); 01826 mat_similarity(h,hr,hc, p,pr,pc, denom,dr,dc); 01827 mat_add(denom,dr,dc, r,rr,rc, denom,dr,dc); 01828 if (sym_factor(denom,dr,dc, denom,dr,dc)) 01829 return; /* failure - singular */ 01830 sym_rdiv(num,nr,nc, denom,dr,dc, k,kr,kc); 01831 01832 /* update the state x: 01833 x <- x + k (z - h x) */ 01834 mat_mul(h,hr,hc, x,xr,1, w,wr,wc); 01835 mat_sub(z,zr,1, w,wr,wc, w,wr,wc); 01836 mat_mul(k,kr,kc, w,wr,wc, v,vr,vc); 01837 mat_add(x,xr,1, v,vr,vc, x,xr,1); 01838 01839 /* update the covariance p: 01840 p <- (I - k h) p */ 01841 mat_one(v,xr,xr); 01842 mat_mul(k,kr,kc, h,hr,hc, w,xr,xr); 01843 mat_sub(v,xr,xr, w,xr,xr, w,xr,xr); 01844 mat_mul(w,xr,xr, p,xr,xr, v,xr,xr); 01845 mat_copy(v,xr,xr, p,xr,xr); 01846 }
|
|
|
Definition at line 843 of file adjtimex.c. References BUFLEN, compare_cmos_sys(), failntpdate(), puthackent(), timeserver, txc, valid_cmos_rate(), valid_system_rate(), and watch. Referenced by main(). 00844 { 00845 #ifdef NET_TIME_CLIENT 00846 struct protoent proto; 00847 int sockfd, val, len, c; 00848 struct sockaddr sa={AF_INET, "127.0.0.1"}; 00849 struct hostent he; 00850 #endif 00851 double sigma_ref, cmos_ahead; 00852 char ch, buf[64], *s; 00853 int n, ret; 00854 struct timeval tv_sys; 00855 struct timezone tz; 00856 struct tm bdt; 00857 time_t when, tref; 00858 double ftime_ref, ftime_sys, ftime_cmos; 00859 00860 if (watch) 00861 { 00862 while(1) { 00863 printf("Please press <enter> when you know the time of day: "); 00864 ch = getchar(); 00865 gettimeofday(&tv_sys, &tz); 00866 when = tv_sys.tv_sec; 00867 bdt = *localtime(&when); /* set default values for most fields */ 00868 strftime(buf, sizeof(buf), "%Z", &bdt); 00869 printf(" system time then was %.24s %s\n", asctime(&bdt), buf); 00870 ftime_sys = tv_sys.tv_sec + tv_sys.tv_usec*.000001; 00871 printf("What time was that according to your reference (%s)?\n" 00872 "(hh:mm:ss, or `r' to retry, or `q' to quit): ", buf); 00873 if (fgets(buf, sizeof(buf), stdin) == NULL) exit(1); 00874 s = buf; 00875 while(isspace(*s)) s++; 00876 if (*s == 'q') exit(0); 00877 if (*s == 'r') continue; 00878 00879 strptime(buf, "%T", &bdt); /* set time fields from user input */ 00880 printf(" reference time is %s", asctime(&bdt)); 00881 tref = ftime_ref = mktime(&bdt); /* construct a time_t 00882 corresponding to the user 00883 input */ 00884 printf(" mktime returns time of %s", ctime(&tref)); 00885 00886 printf("reference time - system time = %12.3f - %12.3f " 00887 "= %4.3f sec\n", 00888 ftime_ref, ftime_sys, ftime_ref - ftime_sys); 00889 00890 printf("How big could the error be in this, in seconds?\n" 00891 "(or `r' to retry, or `q' to quit) [.5] : "); 00892 if (fgets(buf, sizeof(buf), stdin) == NULL) exit(1); 00893 s = buf; 00894 while(isspace(*s)) s++; 00895 if (*s == 'q') exit(0); 00896 if (*s == 'r') continue; 00897 00898 n = sscanf(buf, "%lf", &sigma_ref); 00899 if (n < 1) 00900 sigma_ref = .5; 00901 else if (sigma_ref < .02) 00902 { 00903 printf("You get credit for .02 sec.\n"); 00904 sigma_ref = .02; 00905 } 00906 break; 00907 } 00908 } 00909 else if (timeserver) 00910 { 00911 FILE *ifile; 00912 char command[128]; 00913 char buf[BUFLEN]; 00914 char *str[5]; 00915 int i, n=0; 00916 double d, mean=0, val, var=0, num=0; 00917 00918 #ifdef NTPDATE_STUB 00919 ifile = fopen("../ntpdate-sample", "r"); 00920 #else 00921 sprintf(command, "ntpdate -d %.32s ", timeserver); 00922 ifile = popen(command, "r"); 00923 #endif 00924 if (ifile == NULL) failntpdate("call to ntpdate failed"); 00925 00926 /* read and save the significant lines, which should look like this: 00927 filter offset: -0.02800 -0.01354 -0.01026 -0.01385 00928 offset -0.013543 00929 1 Sep 11:51:23 ntpdate[598]: adjust time server 1.2.3.4 offset -0.013543 sec 00930 */ 00931 while(fgets(buf, BUFLEN, ifile)) 00932 if (strstr(buf, "offset") && n < 4) 00933 str[n++] = strdup(buf); 00934 fclose(ifile); 00935 if (n != 3) failntpdate("cannot understand ntpdate output"); 00936 gettimeofday(&tv_sys, &tz); 00937 ftime_sys = tv_sys.tv_sec; 00938 00939 00940 /* ntpdate selects the offset from one of its samples (the one 00941 with the shortest round-trip delay?) */ 00942 ftime_ref = ftime_sys + atof(strstr(str[2], "offset") + 6); 00943 00944 { 00945 time_t now = (time_t)ftime_ref; 00946 bdt = *gmtime(&now); 00947 printf(" reference time is %s", ctime(&now)); 00948 printf("reference time - system time = %12.3f - %12.3f " 00949 "= %4.3f sec\n", 00950 ftime_ref, ftime_sys, ftime_ref - ftime_sys); 00951 } 00952 00953 /* The first saved line shows the offsets for each of ntpdate's 00954 samples. Find their variance, which we will use to indicate 00955 the accuracy of the offset we're using. This is probably 00956 conservative, since the offset we're using is probably not 00957 close to the mean. */ 00958 s = strstr(str[0], ":"); 00959 if (s++ == NULL) failntpdate("cannot understand ntpdate output"); 00960 for (i = 0; i < 4; i++) 00961 { 00962 val = strtod(s, &s); 00963 d = val - mean; 00964 num += 1.; 00965 var = (num-1)/num*(var + d*d/num); 00966 mean = ((num-1.)*mean + val)/num; 00967 } 00968 sigma_ref = sqrt(var); 00969 00970 #ifdef OWN_IMPLEMENTATION 00971 /* this is not even close to working yet */ 00972 proto = *getprotobyname("UDP"); 00973 sockfd = socket(AF_INET, SOCK_DGRAM, proto.p_proto); 00974 he = *gethostbyname("localhost"); 00975 len = he.h_length; 00976 memcpy(sa.sa_data, he.h_addr_list[0], len); 00977 00978 #ifdef SEND 00979 val = connect(sockfd, &sa, len); 00980 if (val == -1) {perror("connect"); exit(1);} 00981 /* 00982 int connect(int sockfd, struct sockaddr *serv_addr, int addrlen ); 00983 int send(int s, const void *msg, int len , unsigned int flags); 00984 int sendto(int s, const void *msg, int len unsigned int 00985 flags, const struct sockaddr *to, int tolen); 00986 */ 00987 #endif /* SEND */ 00988 val = sendto(sockfd, (const void *)" ", 1, 0, &sa, len); 00989 if (val == -1) {perror("sendto"); exit(1);} 00990 sigma_ref = .010; 00991 #endif /* OWN_IMPLEMENTATION */ 00992 00993 } 00994 else /* no absolute time reference */ 00995 { 00996 time_t now; 00997 gettimeofday(&tv_sys, &tz); 00998 now = (time_t)tv_sys.tv_sec; 00999 bdt = *gmtime(&now); 01000 ftime_sys = tv_sys.tv_sec + tv_sys.tv_usec*.000001; 01001 ftime_ref = 0; 01002 sigma_ref = 0; 01003 } 01004 01005 cmos_ahead = compare_cmos_sys(); 01006 ftime_cmos = ftime_sys + cmos_ahead; 01007 01008 /* 01009 -reference-time- --------system-time---------- --cmos-time---- 01010 1997-06-14 20:22 888888888.888 -3 888888888.888 10000 6666666 n 888888888.888 y 01011 */ 01012 01013 { 01014 struct hack h; 01015 h.ref = ftime_ref; 01016 h.sigma_ref = sigma_ref; 01017 h.log = (time_t)ftime_ref; 01018 h.sys = ftime_sys; 01019 txc.modes = 0; 01020 ret = adjtimex(&txc); 01021 h.tick = txc.tick; 01022 h.freq = txc.freq; 01023 h.sys_ok = valid_system_rate(ftime_sys, ftime_ref, sigma_ref); 01024 h.cmos = ftime_cmos; 01025 h.cmos_ok = valid_cmos_rate(ftime_cmos, ftime_ref, sigma_ref); 01026 puthackent(&h); 01027 } 01028 }
|
|
||||||||||||
|
Definition at line 273 of file adjtimex.c. References adjusting, compare(), comparing, count, HELP, interval, log_path, log_times(), logging, longopt, probe_time(), reset_time_status(), resetting, review(), reviewing, timeserver, txc, universal, usage(), and watch. 00274 { 00275 int ret, saveerr, changes; 00276 extern char *optarg; 00277 int c; 00278 00279 txc.modes = 0; 00280 00281 while((c = getopt_long_only(argc, argv, 00282 "a::c::l::e:f:h:i:m:o:prPPsPS:RT:t:uvw", 00283 longopt, NULL)) != -1) 00284 { 00285 switch(c) 00286 { 00287 case 'a': 00288 adjusting = 1; 00289 if (optarg) 00290 count = atoi(optarg); 00291 break; 00292 case 'c': 00293 comparing = 1; 00294 if (optarg) 00295 count = atoi(optarg); 00296 break; 00297 case 'l': 00298 logging = 1; 00299 if (optarg) 00300 log_path = strdup(optarg); 00301 if (!log_path) 00302 { 00303 fprintf (stderr, "insufficient memory\n"); 00304 exit(1); 00305 } 00306 break; 00307 case 'h': 00308 timeserver = strdup(optarg); 00309 if (!timeserver) 00310 { 00311 fprintf (stderr, "insufficient memory\n"); 00312 exit(1); 00313 } 00314 logging = 1; 00315 break; 00316 case 'r': 00317 reviewing = 1; 00318 if (optarg) 00319 log_path = strdup(optarg); 00320 if (!log_path) 00321 { 00322 fprintf (stderr, "insufficient memory\n"); 00323 exit(1); 00324 } 00325 break; 00326 case 'i': 00327 interval = atoi (optarg); 00328 if (interval <= 1 || interval > 1000) 00329 { 00330 fprintf (stderr, "repeat interval out of range\n"); 00331 exit (1); 00332 } 00333 break; 00334 case 'p': 00335 F_print = 1; 00336 break; 00337 case 'o': 00338 txc.offset = atol(optarg); 00339 txc.modes |= ADJ_OFFSET; 00340 break; 00341 case 's': 00342 txc.offset = atol(optarg); 00343 txc.modes |= ADJ_OFFSET_SINGLESHOT; 00344 break; 00345 case 'S': 00346 txc.status = atol(optarg); 00347 txc.modes |= ADJ_STATUS; 00348 break; 00349 case 'R': resetting = 1; break; 00350 case 'f': 00351 txc.freq = atol(optarg); 00352 txc.modes |= ADJ_FREQUENCY; 00353 break; 00354 case 'm': 00355 txc.maxerror = atol(optarg); 00356 txc.modes |= ADJ_MAXERROR; 00357 break; 00358 case 'e': 00359 txc.esterror = atol(optarg); 00360 txc.modes |= ADJ_ESTERROR; 00361 break; 00362 case 'T': 00363 txc.constant = atol(optarg); 00364 txc.modes |= ADJ_TIMECONST; 00365 break; 00366 case 't': 00367 txc.tick = atol(optarg); 00368 txc.modes |= ADJ_TICK; 00369 break; 00370 case 'u': 00371 universal = 1; 00372 break; 00373 case 'v': 00374 { 00375 printf("adjtimex %s\n", VERSION); 00376 exit(0); 00377 } 00378 case 'w': 00379 watch = 1; 00380 logging = 1; 00381 break; 00382 case HELP: 00383 usage(); 00384 break; 00385 case '?': 00386 default: 00387 fprintf(stderr, "For valid options, try 'adjtimex --help'\n"); 00388 exit(1); 00389 } 00390 } 00391 00392 changes = txc.modes; 00393 00394 if (count <= 0 ) { 00395 fprintf(stderr, "loop count out of range\n"); 00396 exit(1); 00397 } 00398 00399 if (reviewing) 00400 { 00401 review(); 00402 exit(0); 00403 } 00404 00405 if (adjusting || comparing) 00406 { 00407 if (changes || F_print) 00408 { 00409 fprintf(stderr, 00410 "-adjust or -compare cannot be used with any other options that" 00411 " set values\n"); 00412 exit(1); 00413 } 00414 compare(); 00415 } 00416 00417 if (logging) 00418 { 00419 /* 00420 if (geteuid() != 0) 00421 { 00422 fprintf(stderr, "sorry, only root can record clock comparisons\n"); 00423 exit(1); 00424 } 00425 */ 00426 log_times(); 00427 exit(0); 00428 } 00429 00430 if ((txc.modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT && 00431 txc.modes != ADJ_OFFSET_SINGLESHOT) 00432 { 00433 fprintf(stderr, "-singleshot cannot be used with " 00434 "any other option except -print\n"); 00435 usage(); 00436 } 00437 00438 errno = 0; 00439 ret = adjtimex(&txc); 00440 saveerr = errno; 00441 if (F_print) { 00442 printf(" mode: %d\n" 00443 " offset: %ld\n" 00444 " frequency: %ld\n" 00445 " maxerror: %ld\n" 00446 " esterror: %ld\n" 00447 " status: %d\n" 00448 "time_constant: %ld\n" 00449 " precision: %ld\n" 00450 " tolerance: %ld\n" 00451 " tick: %ld\n" 00452 " raw time: %ds %dus = %d.%06d\n", 00453 txc.modes, 00454 txc.offset, 00455 txc.freq, 00456 txc.maxerror, 00457 txc.esterror, 00458 txc.status, 00459 txc.constant, 00460 txc.precision, 00461 txc.tolerance, 00462 txc.tick, 00463 (int)txc.time.tv_sec, 00464 (int)txc.time.tv_usec, 00465 (int)txc.time.tv_sec, 00466 (int)txc.time.tv_usec); 00467 if (saveerr == 0 && ret != 0) 00468 printf(" return value = %d\n" |