⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timesync.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	uchar ub[3*8], *p;	char b[2*24+1];	switch(ifc){	case Ibintime:		n = sizeof(vlong);		if(hz != nil)			n = 3*sizeof(vlong);		if(ticks != nil)			n = 2*sizeof(vlong);		i = read(bintimefd, ub, n);		if(i != n)			break;		p = ub;		if(nsec != nil)			be2vlong(nsec, ub);		p += sizeof(vlong);		if(ticks != nil)			be2vlong((vlong*)ticks, p);		p += sizeof(vlong);		if(hz != nil)			be2vlong((vlong*)hz, p);		return 0;	case Itiming:		n = sizeof(vlong);		if(ticks != nil)			n = 2*sizeof(vlong);		i = read(timingfd, ub, n);		if(i != n)			break;		p = ub;		if(nsec != nil)			be2vlong(nsec, ub);		p += sizeof(vlong);		if(ticks != nil)			be2vlong((vlong*)ticks, p);		if(hz != nil){			seek(fastclockfd, 0, 0);			n = read(fastclockfd, b, sizeof(b)-1);			if(n <= 0)				break;			b[n] = 0;			*hz = strtoll(b+24, 0, 0);		}		return 0;	case Insec:		if(nsec != nil){			seek(nsecfd, 0, 0);			n = read(nsecfd, b, sizeof(b)-1);			if(n <= 0)				break;			b[n] = 0;			*nsec = strtoll(b, 0, 0);		}		if(ticks != nil){			seek(fastclockfd, 0, 0);			n = read(fastclockfd, b, sizeof(b)-1);			if(n <= 0)				break;			b[n] = 0;			*ticks = strtoll(b, 0, 0);		}		if(hz != nil){			seek(fastclockfd, 0, 0);			n = read(fastclockfd, b, sizeof(b)-1);			if(n <= 24)				break;			b[n] = 0;			*hz = strtoll(b+24, 0, 0);		}		return 0;	}	return -1;}static voidsettime(vlong now, uvlong hz, vlong delta, int n){	uchar b[1+sizeof(vlong)+sizeof(long)], *p;	if(debug)		fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n", now, hz, delta, n);	if(impotent)		return;	switch(ifc){	case Ibintime:		if(now >= 0){			p = b;			*p++ = 'n';			p = vlong2be(p, now);			if(write(bintimefd, b, p-b) < 0)				sysfatal("writing /dev/bintime: %r");		}		if(delta != 0){			p = b;			*p++ = 'd';			p = vlong2be(p, delta);			p = long2be(p, n);			if(write(bintimefd, b, p-b) < 0)				sysfatal("writing /dev/bintime: %r");		}		if(hz != 0){			p = b;			*p++ = 'f';			p = vlong2be(p, hz);			if(write(bintimefd, b, p-b) < 0)				sysfatal("writing /dev/bintime: %r");		}		break;	case Itiming:	case Insec:		seek(nsecfd, 0, 0);		if(now >= 0 || delta != 0){			if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0)				sysfatal("writing /dev/nsec: %r");		}		if(hz > 0){			seek(fastclockfd, 0, 0);			if(fprint(fastclockfd, "%lld", hz) < 0)				sysfatal("writing /dev/fastclock: %r");		}	}}////  set priority high and wire process to a processor//static voidsetpriority(void){	int fd;	char buf[32];	sprint(buf, "/proc/%d/ctl", getpid());	fd = open(buf, ORDWR);	if(fd < 0){		fprint(2, "can't set priority\n");		return;	}	if(fprint(fd, "pri 100") < 0)		fprint(2, "can't set priority\n");	if(fprint(fd, "wired 2") < 0)		fprint(2, "can't wire process\n");	close(fd);}// convert to ntp timestampsstatic voidhnputts(void *p, vlong nsec){	uchar *a;	ulong tsh;	ulong tsl;	a = p;	// zero is a special case	if(nsec == 0)		return;	tsh = (nsec/SEC);	nsec -= tsh*SEC;	tsl = (nsec<<32)/SEC;	hnputl(a, tsh+EPOCHDIFF);	hnputl(a+4, tsl);}// convert from ntp timestampsstatic vlongnhgetts(void *p){	uchar *a;	ulong tsh, tsl;	vlong nsec;	a = p;	tsh = nhgetl(a);	tsl = nhgetl(a+4);	nsec = tsl*SEC;	nsec >>= 32;	nsec += (tsh - EPOCHDIFF)*SEC;	return nsec;}// convert to ntp 32 bit fixed pointstatic voidhnputfp(void *p, vlong nsec){	uchar *a;	ulong fp;	a = p;	fp = nsec/(SEC/((vlong)(1<<16)));	hnputl(a, fp);}// convert from ntp fixed point to nanosecsstatic vlongnhgetfp(void *p){	uchar *a;	ulong fp;	vlong nsec;	a = p;	fp = nhgetl(a);	nsec = ((vlong)fp)*(SEC/((vlong)(1<<16)));	return nsec;}// get network address of the serverstatic voidsetrootid(char *d){	char buf[128];	int fd, n;	char *p;	snprint(buf, sizeof(buf), "%s/remote", d);	fd = open(buf, OREAD);	if(fd < 0)		return;	n = read(fd, buf, sizeof buf);	close(fd);	if(n <= 0)		return;	p = strchr(buf, '!');	if(p != nil)		*p = 0;	v4parseip(rootid, buf);}static voidding(void*, char *s){	if(strstr(s, "alarm") != nil)		noted(NCONT);	noted(NDFLT);}static voidaddntpserver(char *name){	NTPserver *ns, **l;	ns = mallocz(sizeof(NTPserver), 1);	if(ns == nil)		sysfatal("addntpserver: %r");	timeserver = strdup(name);	ns->name = name;	for(l = &ntpservers; *l != nil; l = &(*l)->next)		;	*l = ns;}////  sntp client, we keep calling if the delay seems//  unusually high, i.e., 30% longer than avg.//static intntptimediff(NTPserver *ns){	int fd, tries, n;	NTPpkt ntpin, ntpout;	vlong dt, recvts, origts, xmitts, destts, x;	char dir[64];	fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0);	if(fd < 0){		syslog(0, logfile, "can't reach %s: %r", ns->name);		return -1;	}	setrootid(dir);	notify(ding);	memset(&ntpout, 0, sizeof(ntpout));	ntpout.mode = 3 | (3 << 3);	for(tries = 0; tries < 3; tries++){		alarm(2*1000);		gettime(&x, 0, 0);		hnputts(ntpout.xmitts, x);		if(write(fd, &ntpout, NTPSIZE) < 0){			alarm(0);			continue;		}		n = read(fd, &ntpin, sizeof(ntpin));		alarm(0);		gettime(&destts, 0, 0);		if(n >= NTPSIZE){			close(fd);			// we got one, use it			recvts = nhgetts(ntpin.recvts);			origts = nhgetts(ntpin.origts);			xmitts = nhgetts(ntpin.xmitts);			dt = ((recvts - origts) + (xmitts - destts))/2;			// save results			ns->rtt = ((destts - origts) - (xmitts - recvts))/2;			ns->dt = dt;			ns->stratum = ntpin.stratum;			ns->precision = ntpin.precision;			ns->rootdelay = nhgetfp(ntpin.rootdelay);			ns->rootdisp = nhgetfp(ntpin.rootdisp);			if(debug)				fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n", 					ns->name, ntpin.stratum, ns->rtt);			return 0;		}		// try again		sleep(250);	}	close(fd);	return -1;}static vlonggpssample(void){	vlong	l, g, d;	int	i, n;	char	*v[4], buf[128];	d = -1000000000000000000LL;	for(i = 0; i < 5; i++){		sleep(1100);		seek(gpsfil, 0, 0);		n = read(gpsfil, buf, sizeof buf - 1);		if (n <= 0)			return(0LL);		buf[n] = 0;		n = tokenize(buf, v, nelem(v));		if(n != 4)			return(0LL);		if(strcmp(v[3], "A") != 0)			return(0LL);		g = atoll(v[1]);		l = atoll(v[2]);		if(g-l > d)			d = g-l;	}	return(d);}static vlongntpsample(void){	NTPserver *tns, *ns;	vlong metric, x;	metric = 1000LL*SEC;	ns = nil;	for(tns = ntpservers; tns != nil; tns = tns->next){		if(ntptimediff(tns) < 0)			continue;		x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1);		if(debug)			fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n",				tns->name, tns->rootdelay, tns->rootdisp, x);		if(x < metric){			metric = x;			ns = tns;		}	}	if(ns == nil)		return 0LL;	// save data for our server	rootdisp = ns->rootdisp;	rootdelay = ns->rootdelay;	mydelay = ns->rtt;	mydisp = avgerr;	if(ns->stratum == 0)		stratum = 0;	else		stratum = ns->stratum + 1;	ε = abs(ns->rtt/2);	return ns->dt;}//// sample the utc file//static vlongutcsample(void){	vlong	s;	int	n;	char	*v[2], buf[128];	s = 0;	seek(utcfil, 0, 0);	n = read(utcfil, buf, sizeof buf - 1);	if (n <= 0)		return(0LL);	buf[n] = 0;	n = tokenize(buf, v, nelem(v));	if (strcmp(v[0], "0") == 0)		return(0LL);	if (n == 2) {		gettime(&s, nil, nil);		s -= atoll(v[1]);	}	lastutc = atoll(v[0]) + s;	return(lastutc);}////  sntp server//static intopenlisten(char *net){	int fd, cfd;	char data[128];	char devdir[40];	sprint(data, "%s/udp!*!ntp", net);	cfd = announce(data, devdir);	if(cfd < 0)		sysfatal("can't announce");	if(fprint(cfd, "headers") < 0)		sysfatal("can't set header mode");	fprint(cfd, "oldheaders");	sprint(data, "%s/data", devdir);	fd = open(data, ORDWR);	if(fd < 0)		sysfatal("open udp data");	return fd;}static voidntpserver(char *servenet){	int fd, n;	NTPpkt *ntp;	char buf[512];	int vers, mode;	vlong recvts, x;	fd = openlisten(servenet);	if (Rootid == nil)		switch(type){		case Fs:			Rootid = "WWV";			break;		case Rtc:			Rootid = "LOCL";			break;		case Utc:			Rootid = "UTC";			break;		case Ntp:			/* set by the ntp client */			break;		}	if (Rootid != nil)		memmove(rootid, Rootid, strlen(Rootid) > 4 ? 4 : strlen(Rootid));	for(;;){		n = read(fd, buf, sizeof(buf));		gettime(&recvts, 0, 0);		if(n < 0)			return;		if(n < OUdphdrsize + NTPSIZE)			continue;		ntp = (NTPpkt*)(buf+OUdphdrsize);		mode = ntp->mode & 7;		vers = (ntp->mode>>3) & 7;		if(mode != 3)			continue;		ntp->mode = (vers<<3)|4;		ntp->stratum = stratum;		ntp->precision = myprec;		hnputfp(ntp->rootdelay, rootdelay + mydelay);		hnputfp(ntp->rootdisp, rootdisp + mydisp);		hnputts(ntp->refts, lastutc);		memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));		hnputts(ntp->recvts, recvts);		memmove(ntp->rootid, rootid, sizeof(ntp->rootid));		gettime(&x, 0, 0);		hnputts(ntp->xmitts, x);		write(fd, buf, NTPSIZE+OUdphdrsize);	}}////  get the current time from the file system//static longfstime(void){	Dir *d;	ulong t;	d = dirstat("/n/boot");	if(d != nil){		t = d->atime;		free(d);	} else		t = 0;	return t;}////  get the current time from the real time clock//static longrtctime(void){	char b[20];	static int f = -1;	int i, retries;	memset(b, 0, sizeof(b));	for(retries = 0; retries < 100; retries++){		if(f < 0)			f = open("/dev/rtc", OREAD|OCEXEC);		if(f < 0)			break;		if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){			close(f);			f = -1;		} else {			if(i != 0)				break;		}	}	return strtoul(b, 0, 10)+gmtdelta;}////  Sample a clock.  We wait for the clock to always//  be at the leading edge of a clock period.//static vlongsample(long (*get)(void)){	long this, last;	vlong start, end;	/*	 *  wait for the second to change	 */	last = (*get)();	for(;;){		gettime(&start, 0, 0);		this = (*get)();		gettime(&end, 0, 0);		if(this != last)			break;		last = this;	}	return SEC*this - (end-start)/2;}//// the name of the frequency file has the method and possibly the// server name encoded in it.//static intopenfreqfile(void){	char *p;	int fd;	if(sysid == nil)		return -1;	switch(type){	case Ntp:		p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);		break;	default:		p = smprint("%s/ts.%s.%d", dir, sysid, type);		break;	}	fd = open(p, ORDWR);	if(fd < 0)		fd = create(p, ORDWR, 0666);	free(p);	if(fd < 0)		return -1;	return fd;}////  the file contains the last known frequency and the//  number of seconds it was sampled over//static vlongreadfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz){	int n;	char buf[128];	vlong hz;	n = read(fd, buf, sizeof(buf)-1);	if(n <= 0)		return ohz;	buf[n] = 0;	hz = strtoll(buf, nil, 0);	if(hz > maxhz || hz < minhz)		return ohz;	settime(-1, hz, 0, 0);	return hz;}////  remember hz and averaging period//static voidwritefreqfile(int fd, vlong hz, int secs, vlong diff){	long now;	static long last;	if(fd < 0)		return;	now = time(0);	if(now - last < 10*60)		return;	last = now;	if(seek(fd, 0, 0) < 0)		return;	fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);}static uvlongvabs(vlong x){	if(x < 0LL)		return (uvlong)-x;	else		return (uvlong)x;}static voidbackground(void){	static int inbackground;	if(inbackground)		return;	if(!debug) {		switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){		case -1:			sysfatal("forking: %r");			break;		case 0:			break;		default:			exits(0);		}	}	inbackground = 1;}static intgetclockprecision(vlong hz){	int i;	i = 8;	while(hz > 0){		i--;		hz >>= 1;	}	return i;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -