8 #define SEC 1000000000LL
10 #define HOUR (60LL*MIN)
11 #define DAY (24LL*HOUR)
20 HZAvgSecs= 3*60, /* target averaging period for frequency in seconds */
21 MinSampleSecs= 60, /* minimum sampling time in seconds */
25 char *dir = "/tmp"; /* directory sample files live in */
26 char *logfile = "timesync";
35 int gmtdelta; /* rtc+gmtdelta = gmt */
40 vlong mydisp, rootdisp;
41 vlong mydelay, rootdelay;
48 /* list of time samples */
49 typedef struct Sample Sample;
59 typedef struct NTPpkt NTPpkt;
70 uchar origts[8]; /* departed client */
71 uchar recvts[8]; /* arrived at server */
72 uchar xmitts[8]; /* departed server */
78 typedef struct NTPserver NTPserver;
91 NTPserver *ntpservers;
95 NTPSIZE= 48, /* basic ntp packet */
96 NTPDIGESTSIZE= 20, /* key and digest */
99 /* error bound of last sample */
102 static void addntpserver(char *name);
103 static int adjustperiod(vlong diff, vlong accuracy, int secs);
104 static void background(void);
105 static int caperror(vlong dhz, int tsecs, vlong taccuracy);
106 static long fstime(void);
107 static int gettime(vlong *nsec, uvlong *ticks, uvlong *hz); /* returns time, ticks, hz */
108 static int getclockprecision(vlong);
109 static vlong gpssample(void);
110 static void hnputts(void *p, vlong nsec);
111 static void hnputts(void *p, vlong nsec);
112 static void inittime(void);
113 static vlong nhgetts(void *p);
114 static vlong nhgetts(void *p);
115 static void ntpserver(char*);
116 static vlong ntpsample(void);
117 static int ntptimediff(NTPserver *ns);
118 static int openfreqfile(void);
119 static vlong readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz);
120 static long rtctime(void);
121 static void setrtctime(long);
122 static vlong sample(long (*get)(void));
123 static void setpriority(void);
124 static void setrootid(char *d);
125 static void settime(vlong now, uvlong hz, vlong delta, int n); /* set time, hz, delta, period */
126 static vlong utcsample(void);
127 static uvlong vabs(vlong);
128 static uvlong whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz,
129 vlong dt, vlong ticks, vlong period);
130 static void writefreqfile(int fd, vlong hz, int secs, vlong diff);
132 // ((1970-1900)*365 + 17 /*leap days*/)*24*60*60
133 #define EPOCHDIFF 2208988800UL
138 fprint(2, "usage: %s [-a accuracy][-d dir][-I rootid][-s net]"
139 "[-S stratum][-DfGilLnrU] timesource ...\n", argv0);
144 main(int argc, char **argv)
146 int i, t, fd, nservenet;
147 int secs; /* sampling period */
148 int tsecs; /* temporary sampling period */
150 uvlong hz, minhz, maxhz, period, nhz;
151 vlong diff, accuracy, taccuracy;
153 Sample *s, *x, *first, **l;
156 type = Fs; /* by default, sync with the file system */
159 accuracy = 1000000LL; /* default accuracy is 1 millisecond */
161 tsecs = secs = MinSampleSecs;
166 accuracy = strtoll(EARGF(usage()), 0, 0); /* specified in ns */
168 sysfatal("bad accuracy specified");
171 dir = EARGF(usage());
188 Rootid = EARGF(usage());
195 * Assume time source in local time rather than GMT.
196 * Calculate difference so that rtctime can return GMT.
197 * This is useful with the rtc on PC's that run Windows
198 * since Windows keeps the local time in the rtc.
205 * if the years are different, we're at most a day off,
208 if(tl.year < tg.year){
210 tg.yday = tl.yday + 1;
211 }else if(tl.year > tg.year){
215 assert(tl.year == tg.year);
221 gmtdelta = tg.sec+60*(tg.min+60*(tg.hour+tg.yday*24));
223 assert(abs(gmtdelta) <= 24*60*60);
238 if(nservenet >= nelem(servenet))
239 sysfatal("too many networks to serve on");
240 servenet[nservenet++] = EARGF(usage());
243 stratum = strtoll(EARGF(usage()), 0, 0);
249 fmtinstall('E', eipfmt);
250 fmtinstall('I', eipfmt);
251 fmtinstall('V', eipfmt);
252 sysid = getenv("sysname");
254 /* detach from the current namespace */
261 timeserver = argv[0];
263 sysfatal("bad time source");
267 timeserver = argv[0];
269 timeserver = "/mnt/gps/time";
273 timeserver = argv[0];
275 timeserver = "/srv/boot";
279 for(i = 0; i < argc; i++)
280 addntpserver(argv[i]);
282 addntpserver("$ntp");
288 /* figure out our time interface and initial frequency */
293 myprec = getclockprecision(hz);
295 /* convert the accuracy from nanoseconds to ticks */
296 taccuracy = hz*accuracy/SEC;
303 fd = open(timeserver, ORDWR);
305 sysfatal("opening %s: %r", timeserver);
306 if(amount(fd, "/n/boot", MREPL, "") < 0)
307 sysfatal("mounting %s: %r", timeserver);
311 bind("#r", "/dev", MAFTER);
312 if(access("/dev/rtc", AREAD) < 0)
313 sysfatal("accessing /dev/rtc: %r");
316 fd = open(timeserver, OREAD);
318 sysfatal("opening %s: %r", timeserver);
322 fd = open(timeserver, OREAD);
324 sysfatal("opening %s: %r", timeserver);
330 * start a local ntp server(s)
332 for(i = 0; i < nservenet; i++)
333 switch(rfork(RFPROC|RFFDG|RFMEM|RFNOWAIT)){
335 sysfatal("forking: %r");
337 ntpserver(servenet[i]);
341 /* get the last known frequency from the file */
343 hz = readfreqfile(fd, hz, minhz, maxhz);
346 * this is the main loop. it gets a sample, adjusts the
347 * clock and computes a sleep period until the next loop.
348 * we balance frequency drift against the length of the
349 * period to avoid blowing the accuracy limit.
353 avgerr = accuracy >> 1;
354 for(;; background(), sleep(tsecs*1000)){
355 s = mallocz(sizeof *s, 1);
358 /* get times for this sample */
362 s->stime = sample(fstime);
365 s->stime = sample(rtctime);
368 s->stime = utcsample();
371 syslog(0, logfile, "no sample");
382 syslog(0, logfile, "no sample");
393 syslog(0, logfile, "no sample");
401 /* use fastest method to read local clock and ticks */
402 gettime(&s->ltime, &s->ticks, 0);
403 if(type == Ntp || type == Gps)
404 s->stime = s->ltime + diff;
406 /* if the sample was bad, ignore it */
412 /* reset local time */
413 diff = s->stime - s->ltime;
414 if(diff > 10*SEC || diff < -10*SEC){
415 /* we're way off, just set the time */
416 secs = MinSampleSecs;
417 settime(s->stime, 0, 0, 0);
419 /* keep a running average of the error. */
420 avgerr = (avgerr>>1) + (vabs(diff)>>1);
423 * the time to next sample depends on how good or
426 tsecs = secs = adjustperiod(diff, accuracy, secs);
429 * work off the fixed difference. This is done
430 * by adding a ramp to the clock. Each 100th of a
431 * second (or so) the kernel will add diff/(4*secs*100)
432 * to the clock. we only do 1/4 of the difference per
433 * period to dampen any measurement noise.
435 * any difference greater than ε we work off during the
440 settime(-1, 0, diff-((3*ε)/4), secs);
442 settime(-1, 0, diff+((3*ε)/4), secs);
444 settime(-1, 0, diff, 4*secs);
449 setrtctime(s->stime / SEC);
452 fprint(2, "δ %lld avgδ %lld f %lld\n", diff, avgerr, hz);
454 /* dump old samples (keep at least one) */
456 if(first->next == nil)
458 if(s->stime - first->next->stime < DAY)
466 * The sampling error is limited by the total error. If
467 * we make sure the sampling period is at least 16 million
468 * times the average error, we should calculate a frequency
469 * with on average a 1e-7 error.
471 * So that big hz changes don't blow our accuracy requirement,
472 * we shorten the period to make sure that δhz*secs will be
473 * greater than the accuracy limit.
475 period = avgerr << 24;
476 for(x = first; x != nil; x = x->next)
477 if(s->stime - x->stime < period ||
478 x->next == nil || s->stime - x->next->stime < period)
481 nhz = whatisthefrequencykenneth(
486 tsecs = caperror(vabs(nhz-hz), tsecs, taccuracy);
488 writefreqfile(fd, hz, (s->stime - x->stime)/SEC, diff);
491 /* add current sample to list. */
496 syslog(0, logfile, "δ %lld avgδ %lld hz %lld",
502 * adjust the sampling period with some histeresis
505 adjustperiod(vlong diff, vlong accuracy, int secs)
509 absdiff = vabs(diff);
511 if(absdiff < (accuracy>>1))
513 else if(absdiff > accuracy)
517 if(secs < MinSampleSecs)
518 secs = MinSampleSecs;
523 * adjust the frequency
526 whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt,
527 vlong ticks, vlong period)
530 static mpint *mpdt, *mpticks, *mphz, *mpbillion;
533 if(dt <= 0 || ticks <= 0)
538 mpbillion = uvtomp(SEC, nil);
541 /* hz = (ticks*SEC)/dt */
542 mpdt = vtomp(dt, mpdt);
543 mpticks = vtomp(ticks, mpticks);
544 mpmul(mpticks, mpbillion, mpticks);
545 mpdiv(mpticks, mpdt, mphz, nil);
549 if(hz < minhz || hz > maxhz)
552 /* damp the change if we're shorter than the target period */
554 hz = (12ULL*ohz + 4ULL*hz)/16ULL;
556 settime(-1, hz, 0, 0);
561 * We may be changing the frequency to match a bad measurement
562 * or to match a condition no longer in effect. To make sure
563 * that this doesn't blow our error budget over the next measurement
564 * period, shorten the period to make sure that δhz*secs will be
565 * less than the accuracy limit. Here taccuracy is accuracy converted
566 * from nanoseconds to ticks.
569 caperror(vlong dhz, int tsecs, vlong taccuracy)
571 if(dhz*tsecs <= taccuracy)
575 fprint(2, "δhz %lld tsecs %d tacc %lld\n", dhz, tsecs, taccuracy);
577 tsecs = taccuracy/dhz;
578 if(tsecs < MinSampleSecs)
579 tsecs = MinSampleSecs;
596 int fastclockfd = -1;
609 if(access("/dev/time", 0) < 0)
610 bind("#c", "/dev", MAFTER);
611 if(access("/dev/rtc", 0) < 0)
612 bind("#r", "/dev", MAFTER);
614 /* figure out what interface we have */
616 bintimefd = open("/dev/bintime", mode);
620 nsecfd = open("/dev/nsec", mode);
622 sysfatal("opening /dev/nsec");
623 fastclockfd = open("/dev/fastclock", mode);
625 sysfatal("opening /dev/fastclock");
626 timingfd = open("/dev/timing", OREAD);
633 * convert binary numbers from/to kernel
635 static uvlong uvorder = 0x0001020304050607ULL;
638 be2vlong(vlong *to, uchar *f)
644 o = (uchar*)&uvorder;
645 for(i = 0; i < sizeof(vlong); i++)
647 return f+sizeof(vlong);
651 vlong2be(uchar *t, vlong from)
657 o = (uchar*)&uvorder;
658 for(i = 0; i < sizeof(vlong); i++)
660 return t+sizeof(vlong);
663 static long order = 0x00010203;
666 long2be(uchar *t, long from)
673 for(i = 0; i < sizeof(long); i++)
675 return t+sizeof(long);
679 * read ticks and local time in nanoseconds
682 gettime(vlong *nsec, uvlong *ticks, uvlong *hz)
695 i = read(bintimefd, ub, n);
703 be2vlong((vlong*)ticks, p);
706 be2vlong((vlong*)hz, p);
712 i = read(timingfd, ub, n);
720 be2vlong((vlong*)ticks, p);
722 seek(fastclockfd, 0, 0);
723 n = read(fastclockfd, b, sizeof(b)-1);
727 *hz = strtoll(b+24, 0, 0);
733 n = read(nsecfd, b, sizeof(b)-1);
737 *nsec = strtoll(b, 0, 0);
740 seek(fastclockfd, 0, 0);
741 n = read(fastclockfd, b, sizeof(b)-1);
745 *ticks = strtoll(b, 0, 0);
748 seek(fastclockfd, 0, 0);
749 n = read(fastclockfd, b, sizeof(b)-1);
753 *hz = strtoll(b+24, 0, 0);
761 settime(vlong now, uvlong hz, vlong delta, int n)
763 uchar b[1+sizeof(vlong)+sizeof(long)], *p;
766 fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n",
775 p = vlong2be(p, now);
776 if(write(bintimefd, b, p-b) < 0)
777 sysfatal("writing /dev/bintime: %r");
782 p = vlong2be(p, delta);
784 if(write(bintimefd, b, p-b) < 0)
785 sysfatal("writing /dev/bintime: %r");
791 if(write(bintimefd, b, p-b) < 0)
792 sysfatal("writing /dev/bintime: %r");
798 if(now >= 0 || delta != 0){
799 if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0)
800 sysfatal("writing /dev/nsec: %r");
803 seek(fastclockfd, 0, 0);
804 if(fprint(fastclockfd, "%lld", hz) < 0)
805 sysfatal("writing /dev/fastclock: %r");
811 * set priority high and wire process to a processor
819 sprint(buf, "/proc/%d/ctl", getpid());
820 fd = open(buf, ORDWR);
822 fprint(2, "can't set priority\n");
825 if(fprint(fd, "pri 100") < 0)
826 fprint(2, "can't set priority\n");
827 if(fprint(fd, "wired 2") < 0)
828 fprint(2, "can't wire process\n");
832 /* convert to ntp timestamps */
834 hnputts(void *p, vlong nsec)
841 /* zero is a special case */
847 tsl = (nsec<<32)/SEC;
848 hnputl(a, tsh+EPOCHDIFF);
852 /* convert from ntp timestamps */
865 nsec += (tsh - EPOCHDIFF)*SEC;
869 /* convert to ntp 32 bit fixed point */
871 hnputfp(void *p, vlong nsec)
878 fp = nsec/(SEC/((vlong)(1<<16)));
882 /* convert from ntp fixed point to nanosecs */
892 nsec = ((vlong)fp)*(SEC/((vlong)(1<<16)));
896 /* get network address of the server */
904 snprint(buf, sizeof buf, "%s/remote", d);
905 fd = open(buf, OREAD);
908 n = read(fd, buf, sizeof buf);
912 p = strchr(buf, '!');
915 v4parseip(rootid, buf);
921 if(strstr(s, "alarm") != nil)
927 addntpserver(char *name)
931 ns = mallocz(sizeof(NTPserver), 1);
933 sysfatal("addntpserver: %r");
934 timeserver = strdup(name);
936 for(l = &ntpservers; *l != nil; l = &(*l)->next)
942 * sntp client, we keep calling if the delay seems
943 * unusually high, i.e., 30% longer than avg.
946 ntptimediff(NTPserver *ns)
949 NTPpkt ntpin, ntpout;
950 vlong dt, recvts, origts, xmitts, destts, x;
955 alarm(30*1000); /* don't wait forever if ns->name is unreachable */
956 fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0);
959 syslog(0, logfile, "can't reach %s: %r", ns->name);
964 memset(&ntpout, 0, sizeof(ntpout));
965 ntpout.mode = 3 | (3 << 3);
967 for(tries = 0; tries < 3; tries++){
971 hnputts(ntpout.xmitts, x);
972 if(write(fd, &ntpout, NTPSIZE) < 0){
977 n = read(fd, &ntpin, sizeof ntpin);
979 gettime(&destts, 0, 0);
983 /* we got one, use it */
984 recvts = nhgetts(ntpin.recvts);
985 origts = nhgetts(ntpin.origts);
986 xmitts = nhgetts(ntpin.xmitts);
987 dt = ((recvts - origts) + (xmitts - destts))/2;
990 ns->rtt = ((destts - origts) - (xmitts - recvts))/2;
992 ns->stratum = ntpin.stratum;
993 ns->precision = ntpin.precision;
994 ns->rootdelay = nhgetfp(ntpin.rootdelay);
995 ns->rootdisp = nhgetfp(ntpin.rootdisp);
998 fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n",
999 ns->name, ntpin.stratum, ns->rtt);
1015 char *v[4], buf[128];
1017 d = -1000000000000000000LL;
1018 for(i = 0; i < 5; i++){
1021 n = read(gpsfil, buf, sizeof buf - 1);
1025 n = tokenize(buf, v, nelem(v));
1026 if(n != 4 || strcmp(v[3], "A") != 0)
1039 NTPserver *tns, *ns;
1042 metric = 1000LL*SEC;
1044 for(tns = ntpservers; tns != nil; tns = tns->next){
1045 if(ntptimediff(tns) < 0)
1047 x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1);
1049 fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n",
1050 tns->name, tns->rootdelay, tns->rootdisp, x);
1060 /* save data for our server */
1061 rootdisp = ns->rootdisp;
1062 rootdelay = ns->rootdelay;
1065 if(ns->stratum == 0)
1068 stratum = ns->stratum + 1;
1075 * sample the utc file
1082 char *v[2], buf[128];
1086 n = read(utcfil, buf, sizeof buf - 1);
1090 n = tokenize(buf, v, nelem(v));
1091 if (strcmp(v[0], "0") == 0)
1094 gettime(&s, nil, nil);
1097 lastutc = atoll(v[0]) + s;
1105 openlisten(char *net)
1108 char data[128], devdir[40];
1110 sprint(data, "%s/udp!*!ntp", net);
1111 cfd = announce(data, devdir);
1113 sysfatal("can't announce");
1114 if(fprint(cfd, "headers") < 0)
1115 sysfatal("can't set header mode");
1117 sprint(data, "%s/data", devdir);
1118 fd = open(data, ORDWR);
1120 sysfatal("open %s: %r", data);
1125 ntpserver(char *servenet)
1127 int fd, n, vers, mode;
1132 fd = openlisten(servenet);
1149 /* set by the ntp client */
1153 memmove(rootid, Rootid, strlen(Rootid) > 4? 4: strlen(Rootid));
1156 n = read(fd, buf, sizeof buf);
1157 gettime(&recvts, 0, 0);
1159 /* don't croak on input error, but don't spin either */
1163 if(n < Udphdrsize + NTPSIZE)
1166 ntp = (NTPpkt*)(buf + Udphdrsize);
1167 mode = ntp->mode & 7;
1168 vers = (ntp->mode>>3) & 7;
1172 ntp->mode = (vers<<3)|4;
1173 ntp->stratum = stratum;
1174 ntp->precision = myprec;
1175 hnputfp(ntp->rootdelay, rootdelay + mydelay);
1176 hnputfp(ntp->rootdisp, rootdisp + mydisp);
1177 hnputts(ntp->refts, lastutc);
1178 memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));
1179 hnputts(ntp->recvts, recvts);
1180 memmove(ntp->rootid, rootid, sizeof(ntp->rootid));
1182 hnputts(ntp->xmitts, x);
1183 write(fd, buf, NTPSIZE + Udphdrsize);
1188 * get the current time from the file system
1196 d = dirstat("/n/boot");
1206 * get the current time from the real time clock
1215 memset(b, 0, sizeof(b));
1216 for(retries = 0; retries < 100; retries++){
1218 f = open("/dev/rtc", OREAD|OCEXEC);
1221 if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof b)) < 0){
1228 return strtoul(b, 0, 10)+gmtdelta;
1237 f = open("/dev/rtc", OWRITE|OCEXEC);
1240 if(seek(f, 0, 0) < 0 || fprint(f, "%ld", t-gmtdelta) < 0){
1248 * Sample a clock. We wait for the clock to always
1249 * be at the leading edge of a clock period.
1252 sample(long (*get)(void))
1258 * wait for the second to change
1262 gettime(&start, 0, 0);
1265 gettime(&end, 0, 0);
1270 return SEC*this - (end-start)/2;
1274 * the name of the frequency file has the method and possibly the
1275 * server name encoded in it.
1288 p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);
1291 p = smprint("%s/ts.%s.%d", dir, sysid, type);
1294 fd = open(p, ORDWR);
1296 fd = create(p, ORDWR, 0666);
1304 * the file contains the last known frequency and the
1305 * number of seconds it was sampled over
1308 readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz)
1314 n = read(fd, buf, sizeof buf-1);
1318 hz = strtoll(buf, nil, 0);
1320 if(hz > maxhz || hz < minhz)
1323 settime(-1, hz, 0, 0);
1328 * remember hz and averaging period
1331 writefreqfile(int fd, vlong hz, int secs, vlong diff)
1339 if(now - last < 10*60)
1342 if(seek(fd, 0, 0) < 0)
1344 fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);
1359 static int inbackground;
1365 switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){
1367 sysfatal("forking: %r");
1378 getclockprecision(vlong hz)