timesync.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  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 Ntp:
  1032. /* set by the ntp client */
  1033. break;
  1034. }
  1035. if (Rootid != nil)
  1036. memmove(rootid, Rootid, strlen(Rootid) > 4? 4: strlen(Rootid));
  1037. for(;;){
  1038. n = read(fd, buf, sizeof buf);
  1039. gettime(&recvts, 0, 0);
  1040. if(n < 0)
  1041. return;
  1042. if(n < Udphdrsize + NTPSIZE)
  1043. continue;
  1044. ntp = (NTPpkt*)(buf + Udphdrsize);
  1045. mode = ntp->mode & 7;
  1046. vers = (ntp->mode>>3) & 7;
  1047. if(mode != 3)
  1048. continue;
  1049. ntp->mode = (vers<<3)|4;
  1050. ntp->stratum = stratum;
  1051. ntp->precision = myprec;
  1052. hnputfp(ntp->rootdelay, rootdelay + mydelay);
  1053. hnputfp(ntp->rootdisp, rootdisp + mydisp);
  1054. hnputts(ntp->refts, lastutc);
  1055. memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));
  1056. hnputts(ntp->recvts, recvts);
  1057. memmove(ntp->rootid, rootid, sizeof(ntp->rootid));
  1058. gettime(&x, 0, 0);
  1059. hnputts(ntp->xmitts, x);
  1060. write(fd, buf, NTPSIZE + Udphdrsize);
  1061. }
  1062. }
  1063. /*
  1064. * get the current time from the file system
  1065. */
  1066. static long
  1067. fstime(void)
  1068. {
  1069. Dir *d;
  1070. ulong t;
  1071. d = dirstat("/n/boot");
  1072. if(d != nil){
  1073. t = d->atime;
  1074. free(d);
  1075. } else
  1076. t = 0;
  1077. return t;
  1078. }
  1079. /*
  1080. * get the current time from the real time clock
  1081. */
  1082. static long
  1083. rtctime(void)
  1084. {
  1085. char b[20];
  1086. static int f = -1;
  1087. int i, retries;
  1088. memset(b, 0, sizeof(b));
  1089. for(retries = 0; retries < 100; retries++){
  1090. if(f < 0)
  1091. f = open("/dev/rtc", OREAD|OCEXEC);
  1092. if(f < 0)
  1093. break;
  1094. if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof b)) < 0){
  1095. close(f);
  1096. f = -1;
  1097. } else
  1098. if(i != 0)
  1099. break;
  1100. }
  1101. return strtoul(b, 0, 10)+gmtdelta;
  1102. }
  1103. /*
  1104. * Sample a clock. We wait for the clock to always
  1105. * be at the leading edge of a clock period.
  1106. */
  1107. static vlong
  1108. sample(long (*get)(void))
  1109. {
  1110. long this, last;
  1111. vlong start, end;
  1112. /*
  1113. * wait for the second to change
  1114. */
  1115. last = (*get)();
  1116. for(;;){
  1117. gettime(&start, 0, 0);
  1118. this = (*get)();
  1119. gettime(&end, 0, 0);
  1120. if(this != last)
  1121. break;
  1122. last = this;
  1123. }
  1124. return SEC*this - (end-start)/2;
  1125. }
  1126. /*
  1127. * the name of the frequency file has the method and possibly the
  1128. * server name encoded in it.
  1129. */
  1130. static int
  1131. openfreqfile(void)
  1132. {
  1133. char *p;
  1134. int fd;
  1135. if(sysid == nil)
  1136. return -1;
  1137. switch(type){
  1138. case Ntp:
  1139. p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);
  1140. break;
  1141. default:
  1142. p = smprint("%s/ts.%s.%d", dir, sysid, type);
  1143. break;
  1144. }
  1145. fd = open(p, ORDWR);
  1146. if(fd < 0)
  1147. fd = create(p, ORDWR, 0666);
  1148. free(p);
  1149. if(fd < 0)
  1150. return -1;
  1151. return fd;
  1152. }
  1153. /*
  1154. * the file contains the last known frequency and the
  1155. * number of seconds it was sampled over
  1156. */
  1157. static vlong
  1158. readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz)
  1159. {
  1160. int n;
  1161. char buf[128];
  1162. vlong hz;
  1163. n = read(fd, buf, sizeof buf-1);
  1164. if(n <= 0)
  1165. return ohz;
  1166. buf[n] = 0;
  1167. hz = strtoll(buf, nil, 0);
  1168. if(hz > maxhz || hz < minhz)
  1169. return ohz;
  1170. settime(-1, hz, 0, 0);
  1171. return hz;
  1172. }
  1173. /*
  1174. * remember hz and averaging period
  1175. */
  1176. static void
  1177. writefreqfile(int fd, vlong hz, int secs, vlong diff)
  1178. {
  1179. long now;
  1180. static long last;
  1181. if(fd < 0)
  1182. return;
  1183. now = time(0);
  1184. if(now - last < 10*60)
  1185. return;
  1186. last = now;
  1187. if(seek(fd, 0, 0) < 0)
  1188. return;
  1189. fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);
  1190. }
  1191. static uvlong
  1192. vabs(vlong x)
  1193. {
  1194. if(x < 0)
  1195. return -x;
  1196. else
  1197. return x;
  1198. }
  1199. static void
  1200. background(void)
  1201. {
  1202. static int inbackground;
  1203. if(inbackground)
  1204. return;
  1205. if(!debug)
  1206. switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){
  1207. case -1:
  1208. sysfatal("forking: %r");
  1209. break;
  1210. case 0:
  1211. break;
  1212. default:
  1213. exits(0);
  1214. }
  1215. inbackground = 1;
  1216. }
  1217. static int
  1218. getclockprecision(vlong hz)
  1219. {
  1220. int i;
  1221. i = 8;
  1222. while(hz > 0){
  1223. i--;
  1224. hz >>= 1;
  1225. }
  1226. return i;
  1227. }