~kris/9p

9hist

07a64a72bcb5487cf53e6c6775412c92c2f6285b — David du Colombier 27 years ago 4e2e06d
Plan 9 from Bell Labs 1999-02-19
9 files changed, 195 insertions(+), 130 deletions(-)

M pc/clock.c
M pc/ether589.c
M pc/etherelnk3.c
M port/devaudio.c
M port/devcons.c
M port/devpipe.c
M port/portfns.h
M port/qio.c
A port/tod.c
M pc/clock.c => pc/clock.c +0 -1
@@ 42,7 42,6 @@ clockintr(Ureg* ureg, void*)
	m->ticks++;
	if(m->proc)
		m->proc->pc = ureg->pc;
	fixtod();

	accounttime();
	if(kproftimer != nil)

M pc/ether589.c => pc/ether589.c +1 -0
@@ 152,4 152,5 @@ ether589link(void)
{
	addethercard("3C589", reset);
	addethercard("3C562", reset);
	addethercard("589E", reset);
}

M pc/etherelnk3.c => pc/etherelnk3.c +13 -2
@@ 1399,11 1399,22 @@ tcm59Xpci(void)
	}
}

static char* tcmpcmcia[] = {
	"3C589",			/* 3COM 589[ABCD] */
	"3C562",			/* 3COM 562 */
	"589E",				/* 3COM Megahertz 589E */
	nil,
};

static int
tcm5XXpcmcia(Ether* ether)
{
	if(!cistrcmp(ether->type, "3C589") || !cistrcmp(ether->type, "3C562"))
		return ether->port;
	int i;

	for(i = 0; tcmpcmcia[i] != nil; i++){
		if(!cistrcmp(ether->type, tcmpcmcia[i]))
			return ether->port;
	}

	return 0;
}

M port/devaudio.c => port/devaudio.c +1 -1
@@ 885,7 885,7 @@ audioclose(Chan *c)
				b = audio.filling;
				if(b) {
					audio.filling = 0;
					memset(b->virt, 0, Bufsize-audio.curcount);
					memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);
					swab(b->virt);
					putbuf(&audio.full, b);
				}

M port/devcons.c => port/devcons.c +12 -118
@@ 27,6 27,7 @@ static struct
} kbd;

char	sysname[NAMELEN];
vlong	fasthz;

static ulong	randomread(void*, ulong);
static void	randominit(void);


@@ 393,115 394,6 @@ static Dirtab consdir[]={
	"user",		{Quser},	NAMELEN,	0666,
};

ulong	boottime;		/* seconds since epoch at boot */

struct
{
	Lock;
	vlong	hz;		/* frequency of fast clock */
	vlong	last;		/* last reading of fast clock */
	vlong	off;		/* offset from epoch to last */
	vlong	lastns;		/* last return value from gettod */
	vlong	bias;		/* current bias */
	vlong	delta;		/* amount to add to bias each slow clock tick */
	int	n;		/* number of times to add in delta */
	int	i;		/* number of times we've added in delta */
} tod;

void
settod(vlong now, vlong delta, int n)
{
	ilock(&tod);
	tod.last = fastticks(nil);
	tod.off = now;
	tod.delta = delta;
	tod.n = n;
	tod.i = 0;
	iunlock(&tod);
}

// largest vlong devided by 10, 100, ...
static vlong vlmax[9] = {
	9223372036LL,
	92233720368LL,
	922337203685LL,
	9223372036854LL,
	92233720368547LL,
	922337203685477LL,
	9223372036854775LL,
	92233720368547758LL,
	922337203685477580LL,
};
static vlong vlmult[9] = {
	1000000000LL,
	100000000LL,
	10000000LL,
	1000000LL,
	100000LL,
	10000LL,
	1000LL,
	100LL,
	10LL,
};

vlong
gettod(void)
{
	vlong x;
	int i;

	ilock(&tod);
	if(tod.hz == 0)
		x = fastticks((uvlong*)&tod.hz);
	else
		x = fastticks(nil);
	x -= tod.last;

	/* convert to nanoseconds */
	for(i = 0; i < 9; i++)
		if(x < vlmax[i]){
			x *= vlmult[i];
			break;
		}
	x /= tod.hz;
	if(i > 0)
		x *= vlmult[9-i];

	/* convert to epoch */
	x += tod.off;

	/* add in bias */
	x += tod.bias;

	if(x < tod.lastns)
		x = tod.lastns;
	tod.lastns = x;
	iunlock(&tod);

	return x;
}

void
fixtod(void)
{
	ilock(&tod);
	if(tod.n > tod.i)
		tod.bias += tod.delta;
	iunlock(&tod);
}

long
seconds(void)
{
	vlong x;
	int i;

	x = gettod();
	x /= 1000000000LL;
	i = x;
	return i;
}

int
readvlnum(ulong off, char *buf, ulong n, uvlong val, int size)
{


@@ 549,6 441,7 @@ readstr(ulong off, char *buf, ulong n, char *str)
static void
consinit(void)
{
	todinit();
	randominit();
}



@@ 718,8 611,8 @@ consread(Chan *c, void *buf, long n, vlong off)
		return n;

	case Qfastclock:
		if(tod.hz == 0L)
			ticks = fastticks((uvlong*)&tod.hz);
		if(fasthz == 0L)
			ticks = fastticks((uvlong*)&fasthz);
		else
			ticks = fastticks(nil);



@@ 729,7 622,7 @@ consread(Chan *c, void *buf, long n, vlong off)
		if(k+n > 4*NUMSIZE)
			n = 4*NUMSIZE - k;
		readvlnum(0, tmp, 2*NUMSIZE, ticks, 2*NUMSIZE);
		readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, tod.hz, 2*NUMSIZE);
		readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, fasthz, 2*NUMSIZE);
		memmove(buf, tmp+k, n);
		return n;



@@ 758,17 651,17 @@ consread(Chan *c, void *buf, long n, vlong off)
		return 0;

	case Qnsec:
		x = gettod();
		x = todget();
		return readvlnum((ulong)offset, buf, n, x, 2*NUMSIZE);

	case Qmsec:
		x = gettod();
		x = todget();
		x /= 1000000LL;
		i = x;
		return readnum((ulong)offset, buf, n, i, NUMSIZE);

	case Qtime:
		x = gettod();
		x = todget();
		x /= 1000000000LL;
		i = x;
		return readnum((ulong)offset, buf, n, i, NUMSIZE);


@@ 902,7 795,7 @@ conswrite(Chan *c, void *va, long n, vlong off)
		cbuf[n] = 0;
		nsec = strtol(cbuf, 0, 0);
		nsec *= 1000000000LL;
		settod(nsec, 0, 0);
		todset(nsec, 0, 0);
		break;

	case Qfastclock:


@@ 915,7 808,8 @@ conswrite(Chan *c, void *va, long n, vlong off)
		f = strtovl(cbuf, 0, 0);
		if(f <= 0L)
			error(Ebadarg);
		tod.hz = f;
		fasthz = f;
		todsetfreq(f);
		break;

	case Qnsec:


@@ 928,7 822,7 @@ conswrite(Chan *c, void *va, long n, vlong off)
		nsec = strtovl(cbuf, &a, 0);
		delta = strtovl(a, &a, 0);
		n = strtol(a, &a, 0);
		settod(nsec, delta, n);
		todset(nsec, delta, n);
		break;

	case Qkey:

M port/devpipe.c => port/devpipe.c +2 -2
@@ 294,7 294,7 @@ pipewrite(Chan *c, void *va, long n, vlong)
		/* avoid notes when pipe is a mounted queue */
		if((c->flag & CMSG) == 0)
			postnote(up, 1, "sys: write on closed pipe", NUser);
		error(Ehungup);
		nexterror();
	}

	p = c->aux;


@@ 326,7 326,7 @@ pipebwrite(Chan *c, Block *bp, ulong)
		/* avoid notes when pipe is a mounted queue */
		if((c->flag & CMSG) == 0)
			postnote(up, 1, "sys: write on closed pipe", NUser);
		error(Ehungup);
		nexterror();
	}

	p = c->aux;

M port/portfns.h => port/portfns.h +5 -1
@@ 96,7 96,6 @@ int		fault(ulong, int);
void		fdclose(int, int);
Chan*		fdtochan(int, int, int, int);
int		fixfault(Segment*, ulong, int, int);
void		fixtod(void);
void		flushmmu(void);
void		forkchild(Proc*, Ureg*);
void		forkret(void);


@@ 296,6 295,11 @@ void		srvrecover(Chan*, Chan*);
int		swapcount(ulong);
int		swapfull(void);
void		swapinit(void);
vlong		todget(void);
void		todfix(void);
void		todsetfreq(vlong);
void		todinit(void);
void		todset(vlong, vlong, int);
Block*		trimblock(Block*, int, int);
void		tsleep(Rendez*, int (*)(void*), void*, int);
void		unbreak(Proc*);

M port/qio.c => port/qio.c +7 -5
@@ 65,6 65,8 @@ enum
	Hdrspc		= 64,		/* leave room for high-level headers */

	Bdead		= 0x51494F42,	/* "QIOB" */

	Maxatomic	= 32*1024,
};

void


@@ 1092,7 1094,7 @@ qbwrite(Queue *q, Block *b)
}

/*
 *  write to a queue.  only 128k at a time is atomic.
 *  write to a queue.  only Maxatomic bytes at a time is atomic.
 */
int
qwrite(Queue *q, void *vp, int len)


@@ 1107,8 1109,8 @@ qwrite(Queue *q, void *vp, int len)
	sofar = 0;
	do {
		n = len-sofar;
		if(n > 128*1024)
			n = 128*1024;
		if(n > Maxatomic)
			n = Maxatomic;

		b = allocb(n);
		if(waserror()){


@@ 1143,8 1145,8 @@ qiwrite(Queue *q, void *vp, int len)
	sofar = 0;
	do {
		n = len-sofar;
		if(n > 128*1024)
			n = 128*1024;
		if(n > Maxatomic)
			n = Maxatomic;

		b = allocb(n);
		memmove(b->wp, p+sofar, n);

A port/tod.c => port/tod.c +154 -0
@@ 0,0 1,154 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"


// frequency of the tod clock
#define TODFREQ	1000000000LL

enum
{
	Log2mult=	22,	// multiplier should have 22 bits
	Log2todfreq=	30,	// number of significant bits of TODFREQ
};

static vlong logtab[40];

struct {
	Lock;
	int	shift;		// time = (ticks*multiplier)>>shift
	vlong	multiplier;	// ...
	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 gettod
	vlong	delta;		// amount to add to bias each slow clock tick
	int	n;		// number of times to add in delta
	int	i;		// number of times we've added in delta
} tod;

int
log2(vlong x)
{
	int i;

	for(i = 0; i < nelem(logtab); i++){
		if(x < logtab[i])
			break;
	}
	return i+8;
}

void
todinit(void)
{
	vlong v;
	int i;

	v = 1LL<<8;
	for(i = 0; i < nelem(logtab); i++){
		logtab[i] = v;
		v <<= 1;
	}
	fastticks((uvlong*)&tod.hz);
	todsetfreq(tod.hz);
	addclock0link(todfix);
}

//
//  This routine makes sure that the multiplier has
//  at least Log2mult bits to guarantee that precision.
//
void
todsetfreq(vlong f)
{
	// this ensures that the multiplier has 22 bits
	ilock(&tod);
	tod.hz = f;
	tod.shift = Log2mult - Log2todfreq + log2(f);
	tod.multiplier = (TODFREQ<<tod.shift)/f;
	iunlock(&tod);
}

//
//  Set the time of day struct
//
void
todset(vlong t, vlong delta, int n)
{
	ilock(&tod);
	tod.i = tod.n = 0;
	if(t >= 0){
		tod.off = t;
		tod.last = fastticks(nil);
		tod.lasttime = 0;
	} else {
		tod.delta = delta;
		tod.n = n;
	}
	iunlock(&tod);
}

//
//  get time of day
//
vlong
todget(void)
{
	vlong ticks, x, diff;

	ilock(&tod);

	if(tod.hz == 0)
		ticks = fastticks((uvlong*)&tod.hz);
	else
		ticks = fastticks(nil);
	diff = ticks - tod.last;

	// convert to epoch
	x = (diff*tod.multiplier)>>tod.shift;
	x += tod.off;

	// protect against overflows
	if(diff > (1LL<<(63-Log2mult))){
		tod.last = ticks;
		tod.off = x;
	}

	/* time can't go backwards */
	if(x < tod.lasttime)
		x = tod.lasttime;
	tod.lasttime = x;

	iunlock(&tod);
	return x;
}

//
//  called every clock tick
//
void
todfix(void)
{
	if((MACHP(0)->ticks % HZ) != 0)
		return;
	ilock(&tod);
	if(tod.n > tod.i++)
		tod.off += tod.delta;
	iunlock(&tod);
}

long
seconds(void)
{
	vlong x;
	int i;

	x = todget();
	x /= TODFREQ;
	i = x;
	return i;
}