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

📄 kern_clock.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 */	clkinfo.hz = hz;	clkinfo.tick = tick;	clkinfo.tickadj = tickadj;	clkinfo.profhz = profhz;	clkinfo.stathz = stathz ? stathz : hz;	return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req));}SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD,	0, 0, sysctl_kern_clockrate, "S,clockinfo","");#endif /* !OSKIT */static __inline unsignedtco_delta(struct timecounter *tc){	return ((tc->tc_get_timecount(tc) - tc->tc_offset_count) & 	    tc->tc_counter_mask);}/* * We have four functions for looking at the clock, two for microseconds * and two for nanoseconds.  For each there is fast but less precise * version "get{nano|micro}time" which will return a time which is up * to 1/HZ previous to the call, whereas the raw version "{nano|micro}time" * will return a timestamp which is as precise as possible. */voidgetmicrotime(struct timeval *tvp){	struct timecounter *tc;	if (!tco_method) {		tc = timecounter;		*tvp = tc->tc_microtime;	} else {		microtime(tvp);	}}voidgetnanotime(struct timespec *tsp){	struct timecounter *tc;	if (!tco_method) {		tc = timecounter;		*tsp = tc->tc_nanotime;	} else {		nanotime(tsp);	}}voidmicrotime(struct timeval *tv){	struct timecounter *tc;	tc = (struct timecounter *)timecounter;	tv->tv_sec = tc->tc_offset_sec;	tv->tv_usec = tc->tc_offset_micro;	tv->tv_usec += ((u_int64_t)tco_delta(tc) * tc->tc_scale_micro) >> 32;	tv->tv_usec += boottime.tv_usec;	tv->tv_sec += boottime.tv_sec;	while (tv->tv_usec >= 1000000) {		tv->tv_usec -= 1000000;		tv->tv_sec++;	}}voidnanotime(struct timespec *ts){	unsigned count;	u_int64_t delta;	struct timecounter *tc;	tc = (struct timecounter *)timecounter;	ts->tv_sec = tc->tc_offset_sec;	count = tco_delta(tc);	delta = tc->tc_offset_nano;	delta += ((u_int64_t)count * tc->tc_scale_nano_f);	delta >>= 32;	delta += ((u_int64_t)count * tc->tc_scale_nano_i);	delta += boottime.tv_usec * 1000;	ts->tv_sec += boottime.tv_sec;	while (delta >= 1000000000) {		delta -= 1000000000;		ts->tv_sec++;	}	ts->tv_nsec = delta;}voidtimecounter_timespec(unsigned count, struct timespec *ts){	u_int64_t delta;	struct timecounter *tc;	tc = (struct timecounter *)timecounter;	ts->tv_sec = tc->tc_offset_sec;	count -= tc->tc_offset_count;	count &= tc->tc_counter_mask;	delta = tc->tc_offset_nano;	delta += ((u_int64_t)count * tc->tc_scale_nano_f);	delta >>= 32;	delta += ((u_int64_t)count * tc->tc_scale_nano_i);	delta += boottime.tv_usec * 1000;	ts->tv_sec += boottime.tv_sec;	while (delta >= 1000000000) {		delta -= 1000000000;		ts->tv_sec++;	}	ts->tv_nsec = delta;}voidgetmicrouptime(struct timeval *tvp){	struct timecounter *tc;	if (!tco_method) {		tc = timecounter;		tvp->tv_sec = tc->tc_offset_sec;		tvp->tv_usec = tc->tc_offset_micro;	} else {		microuptime(tvp);	}}voidgetnanouptime(struct timespec *tsp){	struct timecounter *tc;	if (!tco_method) {		tc = timecounter;		tsp->tv_sec = tc->tc_offset_sec;		tsp->tv_nsec = tc->tc_offset_nano >> 32;	} else {		nanouptime(tsp);	}}voidmicrouptime(struct timeval *tv){	struct timecounter *tc;	tc = (struct timecounter *)timecounter;	tv->tv_sec = tc->tc_offset_sec;	tv->tv_usec = tc->tc_offset_micro;	tv->tv_usec += ((u_int64_t)tco_delta(tc) * tc->tc_scale_micro) >> 32;	if (tv->tv_usec >= 1000000) {		tv->tv_usec -= 1000000;		tv->tv_sec++;	}}voidnanouptime(struct timespec *ts){	unsigned count;	u_int64_t delta;	struct timecounter *tc;	tc = (struct timecounter *)timecounter;	ts->tv_sec = tc->tc_offset_sec;	count = tco_delta(tc);	delta = tc->tc_offset_nano;	delta += ((u_int64_t)count * tc->tc_scale_nano_f);	delta >>= 32;	delta += ((u_int64_t)count * tc->tc_scale_nano_i);	if (delta >= 1000000000) {		delta -= 1000000000;		ts->tv_sec++;	}	ts->tv_nsec = delta;}static voidtco_setscales(struct timecounter *tc){	u_int64_t scale;	scale = 1000000000LL << 32;	if (tc->tc_adjustment > 0)		scale += (tc->tc_adjustment * 1000LL) << 10;	else		scale -= (-tc->tc_adjustment * 1000LL) << 10;	scale /= tc->tc_frequency;	tc->tc_scale_micro = scale / 1000;	tc->tc_scale_nano_f = scale & 0xffffffff;	tc->tc_scale_nano_i = scale >> 32;}voidinit_timecounter(struct timecounter *tc){	struct timespec ts1;	struct timecounter *t1, *t2, *t3;	int i;	tc->tc_adjustment = 0;	tco_setscales(tc);	tc->tc_offset_count = tc->tc_get_timecount(tc);	tc->tc_tweak = tc;	MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK);	*t1 = *tc;	t2 = t1;	for (i = 1; i < NTIMECOUNTER; i++) {		MALLOC(t3, struct timecounter *, sizeof *t3,		    M_TIMECOUNTER, M_WAITOK);		*t3 = *tc;		t3->tc_other = t2;		t2 = t3;	}	t1->tc_other = t3;	tc = t1;#ifndef OSKIT	printf("Timecounter \"%s\"  frequency %lu Hz\n", 	    tc->tc_name, (u_long)tc->tc_frequency);#endif	/* XXX: For now always start using the counter. */	tc->tc_offset_count = tc->tc_get_timecount(tc);	nanouptime(&ts1);	tc->tc_offset_nano = (u_int64_t)ts1.tv_nsec << 32;	tc->tc_offset_micro = ts1.tv_nsec / 1000;	tc->tc_offset_sec = ts1.tv_sec;	timecounter = tc;}voidset_timecounter(struct timespec *ts){	struct timespec ts2;	nanouptime(&ts2);	boottime.tv_sec = ts->tv_sec - ts2.tv_sec;	boottime.tv_usec = (ts->tv_nsec - ts2.tv_nsec) / 1000;	if (boottime.tv_usec < 0) {		boottime.tv_usec += 1000000;		boottime.tv_sec--;	}	/* fiddle all the little crinkly bits around the fiords... */	tco_forward(1);}#if 0 /* Currently unused */voidswitch_timecounter(struct timecounter *newtc){	int s;	struct timecounter *tc;	struct timespec ts;	s = splclock();	tc = timecounter;	if (newtc == tc || newtc == tc->tc_other) {		splx(s);		return;	}	nanouptime(&ts);	newtc->tc_offset_sec = ts.tv_sec;	newtc->tc_offset_nano = (u_int64_t)ts.tv_nsec << 32;	newtc->tc_offset_micro = ts.tv_nsec / 1000;	newtc->tc_offset_count = newtc->tc_get_timecount(newtc);	timecounter = newtc;	splx(s);}#endifstatic struct timecounter *sync_other_counter(void){	struct timecounter *tc, *tcn, *tco;	unsigned delta;	tco = timecounter;	tc = tco->tc_other;	tcn = tc->tc_other;	*tc = *tco;	tc->tc_other = tcn;	delta = tco_delta(tc);	tc->tc_offset_count += delta;	tc->tc_offset_count &= tc->tc_counter_mask;	tc->tc_offset_nano += (u_int64_t)delta * tc->tc_scale_nano_f;	tc->tc_offset_nano += (u_int64_t)delta * tc->tc_scale_nano_i << 32;	return (tc);}static voidtco_forward(int force){	struct timecounter *tc, *tco;	tco = timecounter;	tc = sync_other_counter();	/*	 * We may be inducing a tiny error here, the tc_poll_pps() may	 * process a latched count which happens after the tco_delta()	 * in sync_other_counter(), which would extend the previous	 * counters parameters into the domain of this new one.	 * Since the timewindow is very small for this, the error is	 * going to be only a few weenieseconds (as Dave Mills would	 * say), so lets just not talk more about it, OK ?	 */	if (tco->tc_poll_pps) 		tco->tc_poll_pps(tco);#ifndef OSKIT	if (timedelta != 0) {		tc->tc_offset_nano += (u_int64_t)(tickdelta * 1000) << 32;		timedelta -= tickdelta;		force++;	}#endif	while (tc->tc_offset_nano >= 1000000000ULL << 32) {		tc->tc_offset_nano -= 1000000000ULL << 32;		tc->tc_offset_sec++;		tc->tc_frequency = tc->tc_tweak->tc_frequency;		tc->tc_adjustment = tc->tc_tweak->tc_adjustment;#ifndef OSKIT		ntp_update_second(tc);	/* XXX only needed if xntpd runs */#endif		tco_setscales(tc);		force++;	}	if (tco_method && !force)		return;	tc->tc_offset_micro = (tc->tc_offset_nano / 1000) >> 32;	/* Figure out the wall-clock time */	tc->tc_nanotime.tv_sec = tc->tc_offset_sec + boottime.tv_sec;	tc->tc_nanotime.tv_nsec = 	    (tc->tc_offset_nano >> 32) + boottime.tv_usec * 1000;	tc->tc_microtime.tv_usec = tc->tc_offset_micro + boottime.tv_usec;	if (tc->tc_nanotime.tv_nsec >= 1000000000) {		tc->tc_nanotime.tv_nsec -= 1000000000;		tc->tc_microtime.tv_usec -= 1000000;		tc->tc_nanotime.tv_sec++;	}	time_second = tc->tc_microtime.tv_sec = tc->tc_nanotime.tv_sec;	timecounter = tc;}static intsysctl_kern_timecounter_frequency SYSCTL_HANDLER_ARGS{	return (sysctl_handle_opaque(oidp, 	    &timecounter->tc_tweak->tc_frequency,	    sizeof(timecounter->tc_tweak->tc_frequency), req));}static intsysctl_kern_timecounter_adjustment SYSCTL_HANDLER_ARGS{	return (sysctl_handle_opaque(oidp, 	    &timecounter->tc_tweak->tc_adjustment,	    sizeof(timecounter->tc_tweak->tc_adjustment), req));}SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0,    "This variable determines the method used for updating timecounters. "    "If the default algorithm (0) fails with \"calcru negative...\" messages "    "try the alternate algorithm (1) which handles bad hardware better.");SYSCTL_PROC(_kern_timecounter, OID_AUTO, frequency, CTLTYPE_INT | CTLFLAG_RW,    0, sizeof(u_int), sysctl_kern_timecounter_frequency, "I", "");SYSCTL_PROC(_kern_timecounter, OID_AUTO, adjustment, CTLTYPE_INT | CTLFLAG_RW,    0, sizeof(int), sysctl_kern_timecounter_adjustment, "I", "");intpps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps){        pps_params_t *app;        pps_info_t *api;        switch (cmd) {        case PPS_IOC_CREATE:                return (0);        case PPS_IOC_DESTROY:                return (0);        case PPS_IOC_SETPARAMS:                app = (pps_params_t *)data;                if (app->mode & ~pps->ppscap)                        return (EINVAL);                pps->ppsparam = *app;                         return (0);        case PPS_IOC_GETPARAMS:                app = (pps_params_t *)data;                *app = pps->ppsparam;                return (0);        case PPS_IOC_GETCAP:                *(int*)data = pps->ppscap;                return (0);        case PPS_IOC_FETCH:                api = (pps_info_t *)data;                pps->ppsinfo.current_mode = pps->ppsparam.mode;                         *api = pps->ppsinfo;                return (0);        case PPS_IOC_WAIT:                return (EOPNOTSUPP);        default:                return (ENOTTY);        }}voidpps_init(struct pps_state *pps){	pps->ppscap |= PPS_TSFMT_TSPEC;	if (pps->ppscap & PPS_CAPTUREASSERT)		pps->ppscap |= PPS_OFFSETASSERT;	if (pps->ppscap & PPS_CAPTURECLEAR)		pps->ppscap |= PPS_OFFSETCLEAR;#ifdef PPS_SYNC	if (pps->ppscap & PPS_CAPTUREASSERT)		pps->ppscap |= PPS_HARDPPSONASSERT;	if (pps->ppscap & PPS_CAPTURECLEAR)		pps->ppscap |= PPS_HARDPPSONCLEAR;#endif}voidpps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event){	struct timespec ts, *tsp, *osp;	u_int64_t delta;	unsigned tcount, *pcount;	int foff, fhard;	pps_seq_t	*pseq;	/* Things would be easier with arrays... */	if (event == PPS_CAPTUREASSERT) {		tsp = &pps->ppsinfo.assert_timestamp;		osp = &pps->ppsparam.assert_offset;		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;		fhard = pps->ppsparam.mode & PPS_HARDPPSONASSERT;		pcount = &pps->ppscount[0];		pseq = &pps->ppsinfo.assert_sequence;	} else {		tsp = &pps->ppsinfo.clear_timestamp;		osp = &pps->ppsparam.clear_offset;		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;		fhard = pps->ppsparam.mode & PPS_HARDPPSONCLEAR;		pcount = &pps->ppscount[1];		pseq = &pps->ppsinfo.clear_sequence;	}	/* The timecounter changed: bail */	if (!pps->ppstc || 	    pps->ppstc->tc_name != tc->tc_name || 	    tc->tc_name != timecounter->tc_name) {		pps->ppstc = tc;		*pcount = count;		return;	}	/* Nothing really happened */	if (*pcount == count)		return;	*pcount = count;	/* Convert the count to timespec */	ts.tv_sec = tc->tc_offset_sec;	tcount = count - tc->tc_offset_count;	tcount &= tc->tc_counter_mask;	delta = tc->tc_offset_nano;	delta += ((u_int64_t)tcount * tc->tc_scale_nano_f);	delta >>= 32;	delta += ((u_int64_t)tcount * tc->tc_scale_nano_i);	delta += boottime.tv_usec * 1000;	ts.tv_sec += boottime.tv_sec;	while (delta >= 1000000000) {		delta -= 1000000000;		ts.tv_sec++;	}	ts.tv_nsec = delta;	(*pseq)++;	*tsp = ts;		if (foff) {		timespecadd(tsp, osp);		if (tsp->tv_nsec < 0) {			tsp->tv_nsec += 1000000000;			tsp->tv_sec -= 1;		}	}#ifdef PPS_SYNC	if (fhard) {		/* magic, at its best... */		tcount = count - pps->ppscount[2];		pps->ppscount[2] = count;		tcount &= tc->tc_counter_mask;		delta = ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_f);		delta >>= 32;		delta += ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_i);		hardpps(tsp, delta);	}#endif}

⌨️ 快捷键说明

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