xref: /plan9/sys/src/cmd/aux/timesync.c (revision 282e677fa45fb578cdb8bc2c412ac084c367776e)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <ip.h>
5 #include <mp.h>
6 
7 /* nanosecond times */
8 #define SEC 1000000000LL
9 #define MIN (60LL*SEC)
10 #define HOUR (60LL*MIN)
11 #define DAY (24LL*HOUR)
12 
13 enum {
14 	Fs,
15 	Rtc,
16 	Ntp,
17 	Utc,
18 
19 	HZAvgSecs=	3*60,	/* target averaging period for the frequency in seconds */
20 	MinSampleSecs=	60,	/* minimum sampling time in seconds */
21 };
22 
23 
24 char *dir = "/tmp";	// directory sample files live in
25 char *logfile = "timesync";
26 char *timeserver;
27 char *Rootid;
28 int utcfil;
29 int debug;
30 int impotent;
31 int logging;
32 int type;
33 int gmtdelta;	// rtc+gmtdelta = gmt
34 uvlong avgerr;
35 
36 // ntp server info
37 int stratum = 14;
38 vlong mydisp, rootdisp;
39 vlong mydelay, rootdelay;
40 vlong avgdelay;
41 vlong lastutc;
42 uchar rootid[4];
43 char *sysid;
44 int myprec;
45 
46 // list of time samples
47 typedef struct Sample Sample;
48 struct Sample
49 {
50 	Sample	*next;
51 	uvlong	ticks;
52 	vlong	ltime;
53 	vlong	stime;
54 };
55 
56 // ntp packet
57 typedef struct NTPpkt NTPpkt;
58 struct NTPpkt
59 {
60 	uchar	mode;
61 	uchar	stratum;
62 	uchar	poll;
63 	uchar	precision;
64 	uchar	rootdelay[4];
65 	uchar	rootdisp[4];
66 	uchar	rootid[4];
67 	uchar	refts[8];
68 	uchar	origts[8];		// departed client
69 	uchar	recvts[8];		// arrived at server
70 	uchar	xmitts[8];		// departed server
71 	uchar	keyid[4];
72 	uchar	digest[16];
73 };
74 
75 // ntp server
76 typedef struct NTPserver NTPserver;
77 struct NTPserver
78 {
79 	NTPserver *next;
80 	char	*name;
81 	uchar	stratum;
82 	uchar	precision;
83 	vlong	rootdelay;
84 	vlong	rootdisp;
85 	vlong	rtt;
86 	vlong	dt;
87 };
88 
89 NTPserver *ntpservers;
90 
91 enum
92 {
93 	NTPSIZE= 	48,		// basic ntp packet
94 	NTPDIGESTSIZE=	20,		// key and digest
95 };
96 
97 // error bound of last sample
98 ulong	ε;
99 
100 static void	addntpserver(char *name);
101 static int	adjustperiod(vlong diff, vlong accuracy, int secs);
102 static void	background(void);
103 static int	caperror(vlong dhz, int tsecs, vlong taccuracy);
104 static long	fstime(void);
105 static int	gettime(vlong *nsec, uvlong *ticks, uvlong *hz); // returns time, ticks, hz
106 static int	getclockprecision(vlong);
107 static void	hnputts(void *p, vlong nsec);
108 static void	hnputts(void *p, vlong nsec);
109 static void	inittime(void);
110 static vlong	nhgetts(void *p);
111 static vlong	nhgetts(void *p);
112 static void	ntpserver(char*);
113 static vlong	ntpsample(void);
114 static int	ntptimediff(NTPserver *ns);
115 static int	openfreqfile(void);
116 static vlong	readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz);
117 static long	rtctime(void);
118 static vlong	sample(long (*get)(void));
119 static void	setpriority(void);
120 static void	setrootid(char *d);
121 static void	settime(vlong now, uvlong hz, vlong delta, int n); // set time, hz, delta, period
122 static vlong	utcsample(void);
123 static uvlong	vabs(vlong);
124 static uvlong	whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period);
125 static void	writefreqfile(int fd, vlong hz, int secs, vlong diff);
126 
127 // ((1970-1900)*365 + 17/*leap days*/)*24*60*60
128 #define EPOCHDIFF 2208988800UL
129 
130 void
131 main(int argc, char **argv)
132 {
133 	int i;
134 	int secs;	// sampling period
135 	int tsecs;	// temporary sampling period
136 	int t, fd;
137 	Sample *s, *x, *first, **l;
138 	vlong diff, accuracy, taccuracy;
139 	uvlong hz, minhz, maxhz, period, nhz;
140 	char *servenet[4];
141 	int nservenet;
142 	char *a;
143 	Tm tl, tg;
144 
145 	type = Fs;		// by default, sync with the file system
146 	debug = 0;
147 	accuracy = 1000000LL;	// default accuracy is 1 millisecond
148 	nservenet = 0;
149 	tsecs = secs = MinSampleSecs;
150 	timeserver = "";
151 
152 	ARGBEGIN{
153 	case 'a':
154 		a = ARGF();
155 		if(a == nil)
156 			sysfatal("bad accuracy specified");
157 		accuracy = strtoll(a, 0, 0);	// accuracy specified in ns
158 		if(accuracy <= 1LL)
159 			sysfatal("bad accuracy specified");
160 		break;
161 	case 'f':
162 		type = Fs;
163 		stratum = 2;
164 		break;
165 	case 'r':
166 		type = Rtc;
167 		stratum = 0;
168 		break;
169 	case 'U':
170 		type = Utc;
171 		stratum = 1;
172 		timeserver = ARGF();
173 		if (timeserver == nil)
174 			sysfatal("bad time source");
175 		break;
176 	case 'n':
177 		type = Ntp;
178 		break;
179 	case 'D':
180 		debug = 1;
181 		break;
182 	case 'd':
183 		dir = ARGF();
184 		break;
185 	case 'L':
186 		//
187 		// Assume time source in local time rather than GMT.
188 		// Calculate difference so that rtctime can return GMT.
189 		// This is useful with the rtc on PC's that run Windows
190 		// since Windows keeps the local time in the rtc.
191 		//
192 		t = time(0);
193 		tl = *localtime(t);
194 		tg = *gmtime(t);
195 
196 		// if the years are different, we're at most a day off, so just rewrite
197 		if(tl.year < tg.year){
198 			tg.year--;
199 			tg.yday = tl.yday + 1;
200 		}else if(tl.year > tg.year){
201 			tl.year--;
202 			tl.yday = tg.yday+1;
203 		}
204 		assert(tl.year == tg.year);
205 
206 		tg.sec -= tl.sec;
207 		tg.min -= tl.min;
208 		tg.hour -= tl.hour;
209 		tg.yday -= tl.yday;
210 		gmtdelta = tg.sec+60*(tg.min+60*(tg.hour+tg.yday*24));
211 
212 		assert(abs(gmtdelta) <= 24*60*60);
213 		break;
214 	case 'i':
215 		impotent = 1;
216 		break;
217 	case 'I':
218 		Rootid = ARGF();
219 		break;
220 	case 's':
221 		if(nservenet >= nelem(servenet))
222 			sysfatal("too many networks to serve on");
223 		a = ARGF();
224 		if(a == nil)
225 			sysfatal("must specify network to serve on");
226 		servenet[nservenet++] = a;
227 		break;
228 	case 'l':
229 		logging = 1;
230 		break;
231 	case 'S':
232 		a = ARGF();
233 		if(a == nil)
234 			sysfatal("bad stratum specified");
235 		stratum = strtoll(a, 0, 0);
236 		break;
237 	}ARGEND;
238 
239 	fmtinstall('E', eipfmt);
240 	fmtinstall('I', eipfmt);
241 	fmtinstall('V', eipfmt);
242 	sysid = getenv("sysname");
243 
244 	//  detach from the current namespace
245 	if(debug)
246 		rfork(RFNAMEG);
247 
248 	switch(type){
249 	case Fs:
250 		if(argc > 0)
251 			timeserver = argv[0];
252 		else
253 			timeserver = "/srv/boot";
254 		break;
255 	case Ntp:
256 		if(argc > 0){
257 			for(i = 0; i <argc; i++)
258 				addntpserver(argv[i]);
259 		} else {
260 			addntpserver("$ntp");
261 		}
262 		break;
263 	}
264 
265 	setpriority();
266 
267 	// figure out our time interface and initial frequency
268 	inittime();
269 	gettime(0, 0, &hz);
270 	minhz = hz/10;
271 	maxhz = hz*10;
272 	myprec = getclockprecision(hz);
273 
274 	// convert the accuracy from nanoseconds to ticks
275 	taccuracy = hz*accuracy/SEC;
276 
277 	//
278 	//  bind in clocks
279 	//
280 	switch(type){
281 	case Fs:
282 		fd = open(timeserver, ORDWR);
283 		if(fd < 0)
284 			sysfatal("opening %s: %r\n", timeserver);
285 		if(amount(fd, "/n/boot", MREPL, "") < 0)
286 			sysfatal("mounting %s: %r\n", timeserver);
287 		close(fd);
288 		break;
289 	case Rtc:
290 		bind("#r", "/dev", MAFTER);
291 		if(access("/dev/rtc", AREAD) < 0)
292 			sysfatal("accessing /dev/rtc: %r\n");
293 		break;
294 	case Utc:
295 		fd = open(timeserver, OREAD);
296 		if(fd < 0)
297 			sysfatal("opening %s: %r\n", timeserver);
298 		utcfil = fd;
299 		break;
300 	}
301 
302 	//
303 	//  start a local ntp server(s)
304 	//
305 	for(i = 0; i < nservenet; i++){
306 		switch(rfork(RFPROC|RFFDG|RFMEM|RFNOWAIT)){
307 		case -1:
308 			sysfatal("forking: %r");
309 			break;
310 		case 0:
311 			ntpserver(servenet[i]);
312 			_exits(0);
313 			break;
314 		default:
315 			break;
316 		}
317 	}
318 
319 	// get the last known frequency from the file
320 	fd = openfreqfile();
321 	hz = readfreqfile(fd, hz, minhz, maxhz);
322 
323 	// this is the main loop.  it gets a sample, adjusts the
324 	// clock and computes a sleep period until the next loop.
325 	// we balance frequency drift against the length of the
326 	// period to avoid blowing the accuracy limit.
327 	first = nil;
328 	l = &first;
329 	avgerr = accuracy>>1;
330 	for(;; background(),sleep(tsecs*(1000))){
331 		s = mallocz(sizeof(*s), 1);
332 		diff = 0;
333 
334 		// get times for this sample
335 		ε = ~0;
336 		switch(type){
337 		case Fs:
338 			s->stime = sample(fstime);
339 			break;
340 		case Rtc:
341 			s->stime = sample(rtctime);
342 			break;
343 		case Utc:
344 			s->stime = utcsample();
345 			if(s->stime == 0LL){
346 				if(logging)
347 					syslog(0, logfile, "no sample");
348 				free(s);
349 				if (secs > 60 * 15)
350 					tsecs = 60*15;
351 				continue;
352 			}
353 			break;
354 		case Ntp:
355 			diff = ntpsample();
356 			if(diff == 0LL){
357 				if(logging)
358 					syslog(0, logfile, "no sample");
359 				free(s);
360 				if(secs > 60*15)
361 					tsecs = 60*15;
362 				continue;
363 			}
364 			break;
365 		}
366 
367 		// use fastest method to read local clock and ticks
368 		gettime(&s->ltime, &s->ticks, 0);
369 		if(type == Ntp)
370 			s->stime = s->ltime + diff;
371 
372 		// if the sample was bad, ignore it
373 		if(s->stime < 0){
374 			free(s);
375 			continue;
376 		}
377 
378 		// reset local time
379 		diff = s->stime - s->ltime;
380 		if(diff > 10*SEC || diff < -10*SEC){
381 			// we're way off, just set the time
382 			secs = MinSampleSecs;
383 			settime(s->stime, 0, 0, 0);
384 		} else {
385 			// keep a running average of the error.
386 			avgerr = (avgerr>>1) + (vabs(diff)>>1);
387 
388 			// the time to next sample depends on how good or
389 			// bad we're doing.
390 			tsecs = secs = adjustperiod(diff, accuracy, secs);
391 
392 			// work off the fixed difference.  This is done
393 			// by adding a ramp to the clock.  Each 100th of a
394 			// second (or so) the kernel will add diff/(4*secs*100)
395 			// to the clock.  we only do 1/4 of the difference per
396 			// period to dampen any measurement noise.
397 			//
398 			// any difference greater than ε we work off during the
399 			// sampling period.
400 			if(abs(diff) > ε){
401 				if(diff > 0)
402 					settime(-1, 0, diff-((3*ε)/4), secs);
403 				else
404 					settime(-1, 0, diff+((3*ε)/4), secs);
405 			} else
406 				settime(-1, 0, diff, 4*secs);
407 
408 		}
409 		if(debug)
410 			fprint(2, "δ %lld avgδ %lld f %lld\n", diff, avgerr, hz);
411 
412 		// dump old samples (keep at least one)
413 		while(first != nil){
414 			if(first->next == nil)
415 				break;
416 			if(s->stime - first->next->stime < DAY)
417 				break;
418 			x = first;
419 			first = first->next;
420 			free(x);
421 		}
422 
423 		// The sampling error is limited by the total error.  If
424 		// we make sure the sampling period is at least 16 million
425 		// times the average error, we should calculate a frequency
426 		// with on average a 1e-7 error.
427 		//
428 		// So that big hz changes don't blow our accuracy requirement,
429 		// we shorten the period to make sure that δhz*secs will be
430 		// greater than the accuracy limit.
431 		period = avgerr<<24;
432 		for(x = first; x != nil; x = x->next){
433 			if(s->stime - x->stime < period)
434 				break;
435 			if(x->next == nil || s->stime - x->next->stime < period)
436 				break;
437 		}
438 		if(x != nil){
439 			nhz = whatisthefrequencykenneth(
440 				hz, minhz, maxhz,
441 				s->stime - x->stime,
442 				s->ticks - x->ticks,
443 				period);
444 			tsecs = caperror(vabs(nhz-hz), tsecs, taccuracy);
445 			hz = nhz;
446 			writefreqfile(fd, hz, (s->stime - x->stime)/SEC, diff);
447 		}
448 
449 		// add current sample to list.
450 		*l = s;
451 		l = &s->next;
452 
453 		if(logging)
454 			syslog(0, logfile, "δ %lld avgδ %lld hz %lld",
455 				diff, avgerr, hz);
456 	}
457 }
458 
459 //
460 // adjust the sampling period with some histeresis
461 //
462 static int
463 adjustperiod(vlong diff, vlong accuracy, int secs)
464 {
465 	uvlong absdiff;
466 
467 	absdiff = vabs(diff);
468 
469 	if(absdiff < (accuracy>>1))
470 		secs += 60;
471 	else if(absdiff > accuracy)
472 		secs >>= 1;
473 	else
474 		secs -= 60;
475 	if(secs < MinSampleSecs)
476 		secs = MinSampleSecs;
477 	return secs;
478 }
479 
480 //
481 // adjust the frequency
482 //
483 static uvlong
484 whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period)
485 {
486 	static mpint *mpdt;
487 	static mpint *mpticks;
488 	static mpint *mphz;
489 	static mpint *mpbillion;
490 	uvlong ohz = hz;
491 
492 	// sanity check
493 	if(dt <= 0 || ticks <= 0)
494 		return hz;
495 
496 	if(mphz == nil){
497 		mphz = mpnew(0);
498 		mpbillion = uvtomp(SEC, nil);
499 	}
500 
501 	// hz = (ticks*SEC)/dt
502 	mpdt = vtomp(dt, mpdt);
503 	mpticks = vtomp(ticks, mpticks);
504 	mpmul(mpticks, mpbillion, mpticks);
505 	mpdiv(mpticks, mpdt, mphz, nil);
506 	hz = mptoui(mphz);
507 
508 	// sanity
509 	if(hz < minhz || hz > maxhz)
510 		return ohz;
511 
512 	// damp the change if we're shorter than the target period
513 	if(period > dt)
514 		hz = (12ULL*ohz + 4ULL*hz)/16ULL;
515 
516 	settime(-1, hz, 0, 0);
517 	return hz;
518 }
519 
520 // We may be changing the frequency to match a bad measurement
521 // or to match a condition no longer in effet.  To make sure
522 // that this doesn't blow our error budget over the next measurement
523 // period, shorten the period to make sure that δhz*secs will be
524 // less than the accuracy limit.  Here taccuracy is accuracy converted
525 // from nanoseconds to ticks.
526 static int
527 caperror(vlong dhz, int tsecs, vlong taccuracy)
528 {
529 	if(dhz*tsecs <= taccuracy)
530 		return tsecs;
531 
532 	if(debug)
533 		fprint(2, "δhz %lld tsecs %d tacc %lld\n", dhz, tsecs, taccuracy);
534 
535 	tsecs = taccuracy/dhz;
536 	if(tsecs < MinSampleSecs)
537 		tsecs = MinSampleSecs;
538 	return tsecs;
539 }
540 
541 //
542 //  kernel interface
543 //
544 enum
545 {
546 	Ibintime,
547 	Insec,
548 	Itiming,
549 };
550 int ifc;
551 int bintimefd = -1;
552 int timingfd = -1;
553 int nsecfd = -1;
554 int fastclockfd = -1;
555 
556 static void
557 inittime(void)
558 {
559 	int mode;
560 
561 	if(impotent)
562 		mode = OREAD;
563 	else
564 		mode = ORDWR;
565 
566 	// bind in clocks
567 	if(access("/dev/time", 0) < 0)
568 		bind("#c", "/dev", MAFTER);
569 	if(access("/dev/rtc", 0) < 0)
570 		bind("#r", "/dev", MAFTER);
571 
572 	// figure out what interface we have
573 	ifc = Ibintime;
574 	bintimefd = open("/dev/bintime", mode);
575 	if(bintimefd >= 0)
576 		return;
577 	ifc = Insec;
578 	nsecfd = open("/dev/nsec", mode);
579 	if(nsecfd < 0)
580 		sysfatal("opening /dev/nsec");
581 	fastclockfd = open("/dev/fastclock", mode);
582 	if(fastclockfd < 0)
583 		sysfatal("opening /dev/fastclock");
584 	timingfd = open("/dev/timing", OREAD);
585 	if(timingfd < 0)
586 		return;
587 	ifc = Itiming;
588 }
589 
590 //
591 //  convert binary numbers from/to kernel
592 //
593 static uvlong uvorder = 0x0001020304050607ULL;
594 
595 static uchar*
596 be2vlong(vlong *to, uchar *f)
597 {
598 	uchar *t, *o;
599 	int i;
600 
601 	t = (uchar*)to;
602 	o = (uchar*)&uvorder;
603 	for(i = 0; i < sizeof(vlong); i++)
604 		t[o[i]] = f[i];
605 	return f+sizeof(vlong);
606 }
607 
608 static uchar*
609 vlong2be(uchar *t, vlong from)
610 {
611 	uchar *f, *o;
612 	int i;
613 
614 	f = (uchar*)&from;
615 	o = (uchar*)&uvorder;
616 	for(i = 0; i < sizeof(vlong); i++)
617 		t[i] = f[o[i]];
618 	return t+sizeof(vlong);
619 }
620 
621 static long order = 0x00010203;
622 
623 static uchar*
624 be2long(long *to, uchar *f)
625 {
626 	uchar *t, *o;
627 	int i;
628 
629 	t = (uchar*)to;
630 	o = (uchar*)&order;
631 	for(i = 0; i < sizeof(long); i++)
632 		t[o[i]] = f[i];
633 	return f+sizeof(long);
634 }
635 
636 static uchar*
637 long2be(uchar *t, long from)
638 {
639 	uchar *f, *o;
640 	int i;
641 
642 	f = (uchar*)&from;
643 	o = (uchar*)&order;
644 	for(i = 0; i < sizeof(long); i++)
645 		t[i] = f[o[i]];
646 	return t+sizeof(long);
647 }
648 
649 //
650 // read ticks and local time in nanoseconds
651 //
652 static int
653 gettime(vlong *nsec, uvlong *ticks, uvlong *hz)
654 {
655 	int i, n;
656 	uchar ub[3*8], *p;
657 	char b[2*24+1];
658 
659 	switch(ifc){
660 	case Ibintime:
661 		n = sizeof(vlong);
662 		if(hz != nil)
663 			n = 3*sizeof(vlong);
664 		if(ticks != nil)
665 			n = 2*sizeof(vlong);
666 		i = read(bintimefd, ub, n);
667 		if(i != n)
668 			break;
669 		p = ub;
670 		if(nsec != nil)
671 			be2vlong(nsec, ub);
672 		p += sizeof(vlong);
673 		if(ticks != nil)
674 			be2vlong((vlong*)ticks, p);
675 		p += sizeof(vlong);
676 		if(hz != nil)
677 			be2vlong((vlong*)hz, p);
678 		return 0;
679 	case Itiming:
680 		n = sizeof(vlong);
681 		if(ticks != nil)
682 			n = 2*sizeof(vlong);
683 		i = read(timingfd, ub, n);
684 		if(i != n)
685 			break;
686 		p = ub;
687 		if(nsec != nil)
688 			be2vlong(nsec, ub);
689 		p += sizeof(vlong);
690 		if(ticks != nil)
691 			be2vlong((vlong*)ticks, p);
692 		if(hz != nil){
693 			seek(fastclockfd, 0, 0);
694 			n = read(fastclockfd, b, sizeof(b)-1);
695 			if(n <= 0)
696 				break;
697 			b[n] = 0;
698 			*hz = strtoll(b+24, 0, 0);
699 		}
700 		return 0;
701 	case Insec:
702 		if(nsec != nil){
703 			seek(nsecfd, 0, 0);
704 			n = read(nsecfd, b, sizeof(b)-1);
705 			if(n <= 0)
706 				break;
707 			b[n] = 0;
708 			*nsec = strtoll(b, 0, 0);
709 		}
710 		if(ticks != nil){
711 			seek(fastclockfd, 0, 0);
712 			n = read(fastclockfd, b, sizeof(b)-1);
713 			if(n <= 0)
714 				break;
715 			b[n] = 0;
716 			*ticks = strtoll(b, 0, 0);
717 		}
718 		if(hz != nil){
719 			seek(fastclockfd, 0, 0);
720 			n = read(fastclockfd, b, sizeof(b)-1);
721 			if(n <= 24)
722 				break;
723 			b[n] = 0;
724 			*hz = strtoll(b+24, 0, 0);
725 		}
726 		return 0;
727 	}
728 	return -1;
729 }
730 
731 static void
732 settime(vlong now, uvlong hz, vlong delta, int n)
733 {
734 	uchar b[1+sizeof(vlong)+sizeof(long)], *p;
735 
736 	if(debug)
737 		fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n", now, hz, delta, n);
738 	if(impotent)
739 		return;
740 	switch(ifc){
741 	case Ibintime:
742 		if(now >= 0){
743 			p = b;
744 			*p++ = 'n';
745 			p = vlong2be(p, now);
746 			if(write(bintimefd, b, p-b) < 0)
747 				sysfatal("writing /dev/bintime: %r");
748 		}
749 		if(delta != 0){
750 			p = b;
751 			*p++ = 'd';
752 			p = vlong2be(p, delta);
753 			p = long2be(p, n);
754 			if(write(bintimefd, b, p-b) < 0)
755 				sysfatal("writing /dev/bintime: %r");
756 		}
757 		if(hz != 0){
758 			p = b;
759 			*p++ = 'f';
760 			p = vlong2be(p, hz);
761 			if(write(bintimefd, b, p-b) < 0)
762 				sysfatal("writing /dev/bintime: %r");
763 		}
764 		break;
765 	case Itiming:
766 	case Insec:
767 		seek(nsecfd, 0, 0);
768 		if(now >= 0 || delta != 0){
769 			if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0)
770 				sysfatal("writing /dev/nsec: %r");
771 		}
772 		if(hz > 0){
773 			seek(fastclockfd, 0, 0);
774 			if(fprint(fastclockfd, "%lld", hz) < 0)
775 				sysfatal("writing /dev/fastclock: %r");
776 		}
777 	}
778 }
779 
780 //
781 //  set priority high and wire process to a processor
782 //
783 static void
784 setpriority(void)
785 {
786 	int fd;
787 	char buf[32];
788 
789 	sprint(buf, "/proc/%d/ctl", getpid());
790 	fd = open(buf, ORDWR);
791 	if(fd < 0){
792 		fprint(2, "can't set priority\n");
793 		return;
794 	}
795 	if(fprint(fd, "pri 100") < 0)
796 		fprint(2, "can't set priority\n");
797 	if(fprint(fd, "wired 2") < 0)
798 		fprint(2, "can't wire process\n");
799 	close(fd);
800 }
801 
802 // convert to ntp timestamps
803 static void
804 hnputts(void *p, vlong nsec)
805 {
806 	uchar *a;
807 	ulong tsh;
808 	ulong tsl;
809 
810 	a = p;
811 
812 	// zero is a special case
813 	if(nsec == 0)
814 		return;
815 
816 	tsh = (nsec/SEC);
817 	nsec -= tsh*SEC;
818 	tsl = (nsec<<32)/SEC;
819 	hnputl(a, tsh+EPOCHDIFF);
820 	hnputl(a+4, tsl);
821 }
822 
823 // convert from ntp timestamps
824 static vlong
825 nhgetts(void *p)
826 {
827 	uchar *a;
828 	ulong tsh, tsl;
829 	vlong nsec;
830 
831 	a = p;
832 	tsh = nhgetl(a);
833 	tsl = nhgetl(a+4);
834 	nsec = tsl*SEC;
835 	nsec >>= 32;
836 	nsec += (tsh - EPOCHDIFF)*SEC;
837 	return nsec;
838 }
839 
840 // convert to ntp 32 bit fixed point
841 static void
842 hnputfp(void *p, vlong nsec)
843 {
844 	uchar *a;
845 	ulong fp;
846 
847 	a = p;
848 
849 	fp = nsec/(SEC/((vlong)(1<<16)));
850 	hnputl(a, fp);
851 }
852 
853 // convert from ntp fixed point to nanosecs
854 static vlong
855 nhgetfp(void *p)
856 {
857 	uchar *a;
858 	ulong fp;
859 	vlong nsec;
860 
861 	a = p;
862 	fp = nhgetl(a);
863 	nsec = ((vlong)fp)*(SEC/((vlong)(1<<16)));
864 	return nsec;
865 }
866 
867 // get network address of the server
868 static void
869 setrootid(char *d)
870 {
871 	char buf[128];
872 	int fd, n;
873 	char *p;
874 
875 	snprint(buf, sizeof(buf), "%s/remote", d);
876 	fd = open(buf, OREAD);
877 	if(fd < 0)
878 		return;
879 	n = read(fd, buf, sizeof buf);
880 	close(fd);
881 	if(n <= 0)
882 		return;
883 	p = strchr(buf, '!');
884 	if(p != nil)
885 		*p = 0;
886 	v4parseip(rootid, buf);
887 }
888 
889 static void
890 ding(void*, char *s)
891 {
892 	if(strstr(s, "alarm") != nil)
893 		noted(NCONT);
894 	noted(NDFLT);
895 }
896 
897 static void
898 addntpserver(char *name)
899 {
900 	NTPserver *ns, **l;
901 
902 	ns = mallocz(sizeof(NTPserver), 1);
903 	if(ns == nil)
904 		sysfatal("addntpserver: %r");
905 	timeserver = strdup(name);
906 	ns->name = name;
907 	for(l = &ntpservers; *l != nil; l = &(*l)->next)
908 		;
909 	*l = ns;
910 }
911 
912 //
913 //  sntp client, we keep calling if the delay seems
914 //  unusually high, i.e., 30% longer than avg.
915 //
916 static int
917 ntptimediff(NTPserver *ns)
918 {
919 	int fd, tries, n;
920 	NTPpkt ntpin, ntpout;
921 	vlong dt, recvts, origts, xmitts, destts, x;
922 	char dir[64];
923 
924 	fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0);
925 	if(fd < 0){
926 		syslog(0, logfile, "can't reach %s: %r", ns->name);
927 		return -1;
928 	}
929 	setrootid(dir);
930 	notify(ding);
931 
932 	memset(&ntpout, 0, sizeof(ntpout));
933 	ntpout.mode = 3 | (3 << 3);
934 
935 	for(tries = 0; tries < 3; tries++){
936 		alarm(2*1000);
937 
938 		gettime(&x, 0, 0);
939 		hnputts(ntpout.xmitts, x);
940 		if(write(fd, &ntpout, NTPSIZE) < 0){
941 			alarm(0);
942 			continue;
943 		}
944 
945 		n = read(fd, &ntpin, sizeof(ntpin));
946 		alarm(0);
947 		gettime(&destts, 0, 0);
948 		if(n >= NTPSIZE){
949 			close(fd);
950 
951 			// we got one, use it
952 			recvts = nhgetts(ntpin.recvts);
953 			origts = nhgetts(ntpin.origts);
954 			xmitts = nhgetts(ntpin.xmitts);
955 			dt = ((recvts - origts) + (xmitts - destts))/2;
956 
957 			// save results
958 			ns->rtt = ((destts - origts) - (xmitts - recvts))/2;
959 			ns->dt = dt;
960 			ns->stratum = ntpin.stratum;
961 			ns->precision = ntpin.precision;
962 			ns->rootdelay = nhgetfp(ntpin.rootdelay);
963 			ns->rootdisp = nhgetfp(ntpin.rootdisp);
964 
965 			if(debug)
966 				fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n",
967 					ns->name, ntpin.stratum, ns->rtt);
968 			return 0;
969 		}
970 
971 		// try again
972 		sleep(250);
973 	}
974 	close(fd);
975 	return -1;
976 }
977 
978 static vlong
979 ntpsample(void)
980 {
981 	NTPserver *tns, *ns;
982 	vlong metric, x;
983 
984 	metric = 1000LL*SEC;
985 	ns = nil;
986 	for(tns = ntpservers; tns != nil; tns = tns->next){
987 		if(ntptimediff(tns) < 0)
988 			continue;
989 		x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1);
990 		if(debug)
991 			fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n",
992 				tns->name, tns->rootdelay, tns->rootdisp, x);
993 		if(x < metric){
994 			metric = x;
995 			ns = tns;
996 		}
997 	}
998 
999 	if(ns == nil)
1000 		return 0LL;
1001 
1002 	// save data for our server
1003 	rootdisp = ns->rootdisp;
1004 	rootdelay = ns->rootdelay;
1005 	mydelay = ns->rtt;
1006 	mydisp = avgerr;
1007 	if(ns->stratum == 0)
1008 		stratum = 0;
1009 	else
1010 		stratum = ns->stratum + 1;
1011 
1012 	ε = abs(ns->rtt/2);
1013 	return ns->dt;
1014 }
1015 
1016 //
1017 // sample the utc file
1018 //
1019 static vlong
1020 utcsample(void)
1021 {
1022 	vlong	s;
1023 	int	n;
1024 	char	*v[2], buf[128];
1025 
1026 	s = 0;
1027 	seek(utcfil, 0, 0);
1028 	n = read(utcfil, buf, sizeof buf - 1);
1029 	if (n <= 0)
1030 		return(0LL);
1031 	buf[n] = 0;
1032 	n = tokenize(buf, v, nelem(v));
1033 	if (strcmp(v[0], "0") == 0)
1034 		return(0LL);
1035 	if (n == 2) {
1036 		gettime(&s, nil, nil);
1037 		s -= atoll(v[1]);
1038 	}
1039 	lastutc = atoll(v[0]) + s;
1040 	return(lastutc);
1041 }
1042 
1043 //
1044 //  sntp server
1045 //
1046 static int
1047 openlisten(char *net)
1048 {
1049 	int fd, cfd;
1050 	char data[128];
1051 	char devdir[40];
1052 
1053 	sprint(data, "%s/udp!*!ntp", net);
1054 	cfd = announce(data, devdir);
1055 	if(cfd < 0)
1056 		sysfatal("can't announce");
1057 	if(fprint(cfd, "headers") < 0)
1058 		sysfatal("can't set header mode");
1059 	fprint(cfd, "oldheaders");
1060 
1061 	sprint(data, "%s/data", devdir);
1062 
1063 	fd = open(data, ORDWR);
1064 	if(fd < 0)
1065 		sysfatal("open udp data");
1066 	return fd;
1067 }
1068 static void
1069 ntpserver(char *servenet)
1070 {
1071 	int fd, n;
1072 	NTPpkt *ntp;
1073 	char buf[512];
1074 	int vers, mode;
1075 	vlong recvts, x;
1076 
1077 	fd = openlisten(servenet);
1078 
1079 	if (Rootid == nil)
1080 		switch(type){
1081 		case Fs:
1082 			Rootid = "WWV";
1083 			break;
1084 		case Rtc:
1085 			Rootid = "LOCL";
1086 			break;
1087 		case Utc:
1088 			Rootid = "UTC";
1089 			break;
1090 		case Ntp:
1091 			/* set by the ntp client */
1092 			break;
1093 		}
1094 	if (Rootid != nil)
1095 		memmove(rootid, Rootid, strlen(Rootid) > 4 ? 4 : strlen(Rootid));
1096 
1097 	for(;;){
1098 		n = read(fd, buf, sizeof(buf));
1099 		gettime(&recvts, 0, 0);
1100 		if(n < 0)
1101 			return;
1102 		if(n < OUdphdrsize + NTPSIZE)
1103 			continue;
1104 
1105 		ntp = (NTPpkt*)(buf+OUdphdrsize);
1106 		mode = ntp->mode & 7;
1107 		vers = (ntp->mode>>3) & 7;
1108 		if(mode != 3)
1109 			continue;
1110 
1111 		ntp->mode = (vers<<3)|4;
1112 		ntp->stratum = stratum;
1113 		ntp->precision = myprec;
1114 		hnputfp(ntp->rootdelay, rootdelay + mydelay);
1115 		hnputfp(ntp->rootdisp, rootdisp + mydisp);
1116 		hnputts(ntp->refts, lastutc);
1117 		memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));
1118 		hnputts(ntp->recvts, recvts);
1119 		memmove(ntp->rootid, rootid, sizeof(ntp->rootid));
1120 		gettime(&x, 0, 0);
1121 		hnputts(ntp->xmitts, x);
1122 		write(fd, buf, NTPSIZE+OUdphdrsize);
1123 	}
1124 }
1125 
1126 //
1127 //  get the current time from the file system
1128 //
1129 static long
1130 fstime(void)
1131 {
1132 	Dir *d;
1133 	ulong t;
1134 
1135 	d = dirstat("/n/boot");
1136 	if(d != nil){
1137 		t = d->atime;
1138 		free(d);
1139 	} else
1140 		t = 0;
1141 	return t;
1142 }
1143 
1144 //
1145 //  get the current time from the real time clock
1146 //
1147 static long
1148 rtctime(void)
1149 {
1150 	char b[20];
1151 	static int f = -1;
1152 	int i, retries;
1153 
1154 	memset(b, 0, sizeof(b));
1155 	for(retries = 0; retries < 100; retries++){
1156 		if(f < 0)
1157 			f = open("/dev/rtc", OREAD|OCEXEC);
1158 		if(f < 0)
1159 			break;
1160 		if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){
1161 			close(f);
1162 			f = -1;
1163 		} else {
1164 			if(i != 0)
1165 				break;
1166 		}
1167 	}
1168 	return strtoul(b, 0, 10)+gmtdelta;
1169 }
1170 
1171 
1172 //
1173 //  Sample a clock.  We wait for the clock to always
1174 //  be at the leading edge of a clock period.
1175 //
1176 static vlong
1177 sample(long (*get)(void))
1178 {
1179 	long this, last;
1180 	vlong start, end;
1181 
1182 	/*
1183 	 *  wait for the second to change
1184 	 */
1185 	last = (*get)();
1186 	for(;;){
1187 		gettime(&start, 0, 0);
1188 		this = (*get)();
1189 		gettime(&end, 0, 0);
1190 		if(this != last)
1191 			break;
1192 		last = this;
1193 	}
1194 	return SEC*this - (end-start)/2;
1195 }
1196 
1197 //
1198 // the name of the frequency file has the method and possibly the
1199 // server name encoded in it.
1200 //
1201 static int
1202 openfreqfile(void)
1203 {
1204 	char *p;
1205 	int fd;
1206 
1207 	if(sysid == nil)
1208 		return -1;
1209 
1210 	switch(type){
1211 	case Ntp:
1212 		p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);
1213 		break;
1214 	default:
1215 		p = smprint("%s/ts.%s.%d", dir, sysid, type);
1216 		break;
1217 	}
1218 	fd = open(p, ORDWR);
1219 	if(fd < 0)
1220 		fd = create(p, ORDWR, 0666);
1221 	free(p);
1222 	if(fd < 0)
1223 		return -1;
1224 	return fd;
1225 }
1226 
1227 //
1228 //  the file contains the last known frequency and the
1229 //  number of seconds it was sampled over
1230 //
1231 static vlong
1232 readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz)
1233 {
1234 	int n;
1235 	char buf[128];
1236 	vlong hz;
1237 
1238 	n = read(fd, buf, sizeof(buf)-1);
1239 	if(n <= 0)
1240 		return ohz;
1241 	buf[n] = 0;
1242 	hz = strtoll(buf, nil, 0);
1243 
1244 	if(hz > maxhz || hz < minhz)
1245 		return ohz;
1246 
1247 	settime(-1, hz, 0, 0);
1248 	return hz;
1249 }
1250 
1251 //
1252 //  remember hz and averaging period
1253 //
1254 static void
1255 writefreqfile(int fd, vlong hz, int secs, vlong diff)
1256 {
1257 	long now;
1258 	static long last;
1259 
1260 	if(fd < 0)
1261 		return;
1262 	now = time(0);
1263 	if(now - last < 10*60)
1264 		return;
1265 	last = now;
1266 	if(seek(fd, 0, 0) < 0)
1267 		return;
1268 	fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);
1269 }
1270 
1271 static uvlong
1272 vabs(vlong x)
1273 {
1274 	if(x < 0LL)
1275 		return (uvlong)-x;
1276 	else
1277 		return (uvlong)x;
1278 }
1279 
1280 static void
1281 background(void)
1282 {
1283 	static int inbackground;
1284 
1285 	if(inbackground)
1286 		return;
1287 
1288 	if(!debug) {
1289 		switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){
1290 		case -1:
1291 			sysfatal("forking: %r");
1292 			break;
1293 		case 0:
1294 			break;
1295 		default:
1296 			exits(0);
1297 		}
1298 	}
1299 	inbackground = 1;
1300 }
1301 
1302 static int
1303 getclockprecision(vlong hz)
1304 {
1305 	int i;
1306 
1307 	i = 8;
1308 	while(hz > 0){
1309 		i--;
1310 		hz >>= 1;
1311 	}
1312 	return i;
1313 }
1314