timesync.c 24 KB

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