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 be2long(long *to, uchar *f)
673 for(i = 0; i < sizeof(long); i++)
675 return f+sizeof(long);
679 long2be(uchar *t, long from)
686 for(i = 0; i < sizeof(long); i++)
688 return t+sizeof(long);
692 * read ticks and local time in nanoseconds
695 gettime(vlong *nsec, uvlong *ticks, uvlong *hz)
708 i = read(bintimefd, ub, n);
716 be2vlong((vlong*)ticks, p);
719 be2vlong((vlong*)hz, p);
725 i = read(timingfd, ub, n);
733 be2vlong((vlong*)ticks, p);
735 seek(fastclockfd, 0, 0);
736 n = read(fastclockfd, b, sizeof(b)-1);
740 *hz = strtoll(b+24, 0, 0);
746 n = read(nsecfd, b, sizeof(b)-1);
750 *nsec = strtoll(b, 0, 0);
753 seek(fastclockfd, 0, 0);
754 n = read(fastclockfd, b, sizeof(b)-1);
758 *ticks = strtoll(b, 0, 0);
761 seek(fastclockfd, 0, 0);
762 n = read(fastclockfd, b, sizeof(b)-1);
766 *hz = strtoll(b+24, 0, 0);
774 settime(vlong now, uvlong hz, vlong delta, int n)
776 uchar b[1+sizeof(vlong)+sizeof(long)], *p;
779 fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n",
788 p = vlong2be(p, now);
789 if(write(bintimefd, b, p-b) < 0)
790 sysfatal("writing /dev/bintime: %r");
795 p = vlong2be(p, delta);
797 if(write(bintimefd, b, p-b) < 0)
798 sysfatal("writing /dev/bintime: %r");
804 if(write(bintimefd, b, p-b) < 0)
805 sysfatal("writing /dev/bintime: %r");
811 if(now >= 0 || delta != 0){
812 if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0)
813 sysfatal("writing /dev/nsec: %r");
816 seek(fastclockfd, 0, 0);
817 if(fprint(fastclockfd, "%lld", hz) < 0)
818 sysfatal("writing /dev/fastclock: %r");
824 * set priority high and wire process to a processor
832 sprint(buf, "/proc/%d/ctl", getpid());
833 fd = open(buf, ORDWR);
835 fprint(2, "can't set priority\n");
838 if(fprint(fd, "pri 100") < 0)
839 fprint(2, "can't set priority\n");
840 if(fprint(fd, "wired 2") < 0)
841 fprint(2, "can't wire process\n");
845 /* convert to ntp timestamps */
847 hnputts(void *p, vlong nsec)
854 /* zero is a special case */
860 tsl = (nsec<<32)/SEC;
861 hnputl(a, tsh+EPOCHDIFF);
865 /* convert from ntp timestamps */
878 nsec += (tsh - EPOCHDIFF)*SEC;
882 /* convert to ntp 32 bit fixed point */
884 hnputfp(void *p, vlong nsec)
891 fp = nsec/(SEC/((vlong)(1<<16)));
895 /* convert from ntp fixed point to nanosecs */
905 nsec = ((vlong)fp)*(SEC/((vlong)(1<<16)));
909 /* get network address of the server */
917 snprint(buf, sizeof buf, "%s/remote", d);
918 fd = open(buf, OREAD);
921 n = read(fd, buf, sizeof buf);
925 p = strchr(buf, '!');
928 v4parseip(rootid, buf);
934 if(strstr(s, "alarm") != nil)
940 addntpserver(char *name)
944 ns = mallocz(sizeof(NTPserver), 1);
946 sysfatal("addntpserver: %r");
947 timeserver = strdup(name);
949 for(l = &ntpservers; *l != nil; l = &(*l)->next)
955 * sntp client, we keep calling if the delay seems
956 * unusually high, i.e., 30% longer than avg.
959 ntptimediff(NTPserver *ns)
962 NTPpkt ntpin, ntpout;
963 vlong dt, recvts, origts, xmitts, destts, x;
968 alarm(30*1000); /* don't wait forever if ns->name is unreachable */
969 fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0);
972 syslog(0, logfile, "can't reach %s: %r", ns->name);
977 memset(&ntpout, 0, sizeof(ntpout));
978 ntpout.mode = 3 | (3 << 3);
980 for(tries = 0; tries < 3; tries++){
984 hnputts(ntpout.xmitts, x);
985 if(write(fd, &ntpout, NTPSIZE) < 0){
990 n = read(fd, &ntpin, sizeof ntpin);
992 gettime(&destts, 0, 0);
996 /* we got one, use it */
997 recvts = nhgetts(ntpin.recvts);
998 origts = nhgetts(ntpin.origts);
999 xmitts = nhgetts(ntpin.xmitts);
1000 dt = ((recvts - origts) + (xmitts - destts))/2;
1003 ns->rtt = ((destts - origts) - (xmitts - recvts))/2;
1005 ns->stratum = ntpin.stratum;
1006 ns->precision = ntpin.precision;
1007 ns->rootdelay = nhgetfp(ntpin.rootdelay);
1008 ns->rootdisp = nhgetfp(ntpin.rootdisp);
1011 fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n",
1012 ns->name, ntpin.stratum, ns->rtt);
1028 char *v[4], buf[128];
1030 d = -1000000000000000000LL;
1031 for(i = 0; i < 5; i++){
1034 n = read(gpsfil, buf, sizeof buf - 1);
1038 n = tokenize(buf, v, nelem(v));
1039 if(n != 4 || strcmp(v[3], "A") != 0)
1052 NTPserver *tns, *ns;
1055 metric = 1000LL*SEC;
1057 for(tns = ntpservers; tns != nil; tns = tns->next){
1058 if(ntptimediff(tns) < 0)
1060 x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1);
1062 fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n",
1063 tns->name, tns->rootdelay, tns->rootdisp, x);
1073 /* save data for our server */
1074 rootdisp = ns->rootdisp;
1075 rootdelay = ns->rootdelay;
1078 if(ns->stratum == 0)
1081 stratum = ns->stratum + 1;
1088 * sample the utc file
1095 char *v[2], buf[128];
1099 n = read(utcfil, buf, sizeof buf - 1);
1103 n = tokenize(buf, v, nelem(v));
1104 if (strcmp(v[0], "0") == 0)
1107 gettime(&s, nil, nil);
1110 lastutc = atoll(v[0]) + s;
1118 openlisten(char *net)
1121 char data[128], devdir[40];
1123 sprint(data, "%s/udp!*!ntp", net);
1124 cfd = announce(data, devdir);
1126 sysfatal("can't announce");
1127 if(fprint(cfd, "headers") < 0)
1128 sysfatal("can't set header mode");
1130 sprint(data, "%s/data", devdir);
1131 fd = open(data, ORDWR);
1133 sysfatal("open %s: %r", data);
1138 ntpserver(char *servenet)
1140 int fd, n, vers, mode;
1145 fd = openlisten(servenet);
1162 /* set by the ntp client */
1166 memmove(rootid, Rootid, strlen(Rootid) > 4? 4: strlen(Rootid));
1169 n = read(fd, buf, sizeof buf);
1170 gettime(&recvts, 0, 0);
1172 /* don't croak on input error, but don't spin either */
1176 if(n < Udphdrsize + NTPSIZE)
1179 ntp = (NTPpkt*)(buf + Udphdrsize);
1180 mode = ntp->mode & 7;
1181 vers = (ntp->mode>>3) & 7;
1185 ntp->mode = (vers<<3)|4;
1186 ntp->stratum = stratum;
1187 ntp->precision = myprec;
1188 hnputfp(ntp->rootdelay, rootdelay + mydelay);
1189 hnputfp(ntp->rootdisp, rootdisp + mydisp);
1190 hnputts(ntp->refts, lastutc);
1191 memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));
1192 hnputts(ntp->recvts, recvts);
1193 memmove(ntp->rootid, rootid, sizeof(ntp->rootid));
1195 hnputts(ntp->xmitts, x);
1196 write(fd, buf, NTPSIZE + Udphdrsize);
1201 * get the current time from the file system
1209 d = dirstat("/n/boot");
1219 * get the current time from the real time clock
1228 memset(b, 0, sizeof(b));
1229 for(retries = 0; retries < 100; retries++){
1231 f = open("/dev/rtc", OREAD|OCEXEC);
1234 if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof b)) < 0){
1241 return strtoul(b, 0, 10)+gmtdelta;
1250 f = open("/dev/rtc", OWRITE|OCEXEC);
1253 if(seek(f, 0, 0) < 0 || fprint(f, "%ld", t-gmtdelta) < 0){
1261 * Sample a clock. We wait for the clock to always
1262 * be at the leading edge of a clock period.
1265 sample(long (*get)(void))
1271 * wait for the second to change
1275 gettime(&start, 0, 0);
1278 gettime(&end, 0, 0);
1283 return SEC*this - (end-start)/2;
1287 * the name of the frequency file has the method and possibly the
1288 * server name encoded in it.
1301 p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);
1304 p = smprint("%s/ts.%s.%d", dir, sysid, type);
1307 fd = open(p, ORDWR);
1309 fd = create(p, ORDWR, 0666);
1317 * the file contains the last known frequency and the
1318 * number of seconds it was sampled over
1321 readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz)
1327 n = read(fd, buf, sizeof buf-1);
1331 hz = strtoll(buf, nil, 0);
1333 if(hz > maxhz || hz < minhz)
1336 settime(-1, hz, 0, 0);
1341 * remember hz and averaging period
1344 writefreqfile(int fd, vlong hz, int secs, vlong diff)
1352 if(now - last < 10*60)
1355 if(seek(fd, 0, 0) < 0)
1357 fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);
1372 static int inbackground;
1378 switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){
1380 sysfatal("forking: %r");
1391 getclockprecision(vlong hz)