timesync.c 25 KB

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