timesync.c 24 KB

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