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

📄 tod.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"/* * Compute nanosecond epoch time from the fastest ticking clock * on the system.  Converting the time to nanoseconds requires * the following formula * *	t = (((1000000000<<31)/f)*ticks)>>31 * *  where * *	'f'		is the clock frequency *	'ticks'		are clock ticks * *  to avoid too much calculation in todget(), we calculate * *	mult = (1000000000<<32)/f * *  each time f is set.  f is normally set by a user level *  program writing to /dev/fastclock.  mul64fract will then *  take that fractional multiplier and a 64 bit integer and *  return the resulting integer product. * *  We assume that the cpu's of a multiprocessor are synchronized. *  This assumption needs to be questioned with each new architecture. *//* frequency of the tod clock */#define TODFREQ		1000000000ULL#define MicroFREQ	1000000ULLstruct {	int	init;		// true if initialized	ulong	cnt;	Lock;	uvlong	multiplier;	// ns = off + (multiplier*ticks)>>31	uvlong	divider;	// ticks = (divider*(ns-off))>>31	uvlong	umultiplier;	// µs = (µmultiplier*ticks)>>31	uvlong	udivider;	// ticks = (µdivider*µs)>>31	vlong	hz;		// frequency of fast clock	vlong	last;		// last reading of fast clock	vlong	off;		// offset from epoch to last	vlong	lasttime;	// last return value from todget	vlong	delta;		// add 'delta' each slow clock tick from sstart to send	ulong	sstart;		// ...	ulong	send;		// ...} tod;static void todfix(void);voidtodinit(void){	if(tod.init)		return;	ilock(&tod);	tod.last = fastticks((uvlong*)&tod.hz);	iunlock(&tod);	todsetfreq(tod.hz);	tod.init = 1;	addclock0link(todfix, 100);}/* *  calculate multiplier */voidtodsetfreq(vlong f){	ilock(&tod);	tod.hz = f;	/* calculate multiplier for time conversion */	tod.multiplier = mk64fract(TODFREQ, f);	tod.divider = mk64fract(f, TODFREQ);	tod.umultiplier = mk64fract(MicroFREQ, f);	tod.udivider = mk64fract(f, MicroFREQ);	iunlock(&tod);}/* *  Set the time of day struct */voidtodset(vlong t, vlong delta, int n){	if(!tod.init)		todinit();	ilock(&tod);	if(t >= 0){		tod.off = t;		tod.last = fastticks(nil);		tod.lasttime = 0;		tod.delta = 0;		tod.sstart = tod.send;	} else {		if(n <= 0)			n = 1;		n *= HZ;		if(delta < 0 && n > -delta)			n = -delta;		if(delta > 0 && n > delta)			n = delta;		delta = delta/n;		tod.sstart = MACHP(0)->ticks;		tod.send = tod.sstart + n;		tod.delta = delta;	}	iunlock(&tod);}/* *  get time of day */vlongtodget(vlong *ticksp){	uvlong x;	vlong ticks, diff;	ulong t;	if(!tod.init)		todinit();	// we don't want time to pass twixt the measuring of fastticks	// and grabbing tod.last.  Also none of the vlongs are atomic so	// we have to look at them inside the lock.	ilock(&tod);	tod.cnt++;	ticks = fastticks(nil);	// add in correction	if(tod.sstart != tod.send){		t = MACHP(0)->ticks;		if(t >= tod.send)			t = tod.send;		tod.off = tod.off + tod.delta*(t - tod.sstart);		tod.sstart = t;	}	// convert to epoch	diff = ticks - tod.last;	if(diff < 0)		diff = 0;	mul64fract(&x, diff, tod.multiplier);	x += tod.off;	// time can't go backwards	if(x < tod.lasttime)		x = tod.lasttime;	else		tod.lasttime = x;	iunlock(&tod);	if(ticksp != nil)		*ticksp = ticks;	return x;}/* *  convert time of day to ticks */uvlongtod2fastticks(vlong ns){	uvlong x;	ilock(&tod);	mul64fract(&x, ns-tod.off, tod.divider);	x += tod.last;	iunlock(&tod);	return x;}/* *  called regularly to avoid calculation overflows */static voidtodfix(void){	vlong ticks, diff;	uvlong x;	ticks = fastticks(nil);	diff = ticks - tod.last;	if(diff > tod.hz){		ilock(&tod);			// convert to epoch		mul64fract(&x, diff, tod.multiplier);if(x > 30000000000ULL) print("todfix %llud\n", x);		x += tod.off;			// protect against overflows		tod.last = ticks;		tod.off = x;			iunlock(&tod);	}}longseconds(void){	vlong x;	int i;	x = todget(nil);	x = x/TODFREQ;	i = x;	return i;}uvlongfastticks2us(uvlong ticks){	uvlong res;	if(!tod.init)		todinit();	mul64fract(&res, ticks, tod.umultiplier);	return res;}uvlongus2fastticks(uvlong us){	uvlong res;	if(!tod.init)		todinit();	mul64fract(&res, us, tod.udivider);	return res;}/* *  convert milliseconds to fast ticks */uvlongms2fastticks(ulong ms){	if(!tod.init)		todinit();	return (tod.hz*ms)/1000ULL;}/* *  convert nanoseconds to fast ticks */uvlongns2fastticks(uvlong ns){	uvlong res;	if(!tod.init)		todinit();	mul64fract(&res, ns, tod.divider);	return res;}/* *  convert fast ticks to ns */uvlongfastticks2ns(uvlong ticks){	uvlong res;	if(!tod.init)		todinit();	mul64fract(&res, ticks, tod.multiplier);	return res;}/* * Make a 64 bit fixed point number that has a decimal point * to the left of the low order 32 bits.  This is used with * mul64fract for converting twixt nanoseconds and fastticks. * *	multiplier = (to<<32)/from */uvlongmk64fract(uvlong to, uvlong from){/*	int shift;	if(to == 0ULL)		return 0ULL;	shift = 0;	while(shift < 32 && to < (1ULL<<(32+24))){		to <<= 8;		shift += 8;	}	while(shift < 32 && to < (1ULL<<(32+31))){		to <<= 1;		shift += 1;	}	return (to/from)<<(32-shift);*/	return (to<<32)/from;}

⌨️ 快捷键说明

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