~kris/9p

9hist

4be4bfc2e7dc7aa2441a01d738df84a58b122a99 — David du Colombier 28 years ago ffc3046
Plan 9 from Bell Labs 1998-09-16
M carrera/dat.h => carrera/dat.h +1 -0
@@ 47,6 47,7 @@ struct Conf
	ulong	upages;		/* user page pool */
	ulong	nimage;		/* number of page cache image headers */
	ulong	nswap;		/* number of swap pages */
	int	nswppo;		/* max # of pageouts per segment pass */
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */

M carrera/main.c => carrera/main.c +1 -0
@@ 482,6 482,7 @@ confinit(void)
	/* set up other configuration parameters */
	conf.nproc = 100;
	conf.nswap = conf.npage*3;
	conf.nswppo = 4096;
	conf.nimage = 200;

	conf.monitor = 1;

M carrera/mem.h => carrera/mem.h +1 -0
@@ 197,6 197,7 @@
#define	KPTELOG		7
#define	KPTESIZE	(1<<KPTELOG)
#define	SEGMAPSIZE	512
#define SSEGMAPSIZE	16

#define	NTLBPID	256	/* number of pids */
#define	NTLB	48	/* number of entries */

M pc/dat.h => pc/dat.h +1 -0
@@ 75,6 75,7 @@ struct Conf
	ulong	upages;		/* user page pool */
	ulong	nimage;		/* number of page cache image headers */
	ulong	nswap;		/* number of swap pages */
	int	nswppo;		/* max # of pageouts per segment pass */
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */

M pc/l.s => pc/l.s +1 -2
@@ 397,8 397,7 @@ TEXT fpinit(SB), $0				/* enable and init */

TEXT fpsave(SB), $0				/* save state and disable */
	MOVL	p+0(FP), AX
	WAIT
	FSAVE	0(AX)
	FSAVE	0(AX)				/* no WAIT */
	FPOFF
	RET


M pc/main.c => pc/main.c +51 -22
@@ 424,6 424,7 @@ confinit(void)
	if(conf.nproc > 2000)
		conf.nproc = 2000;
	conf.nswap = conf.nproc*80;
	conf.nswppo = 4096;
	conf.nimage = 200;
}



@@ 439,44 440,52 @@ static char* mathmsg[] =
	"error",
};

static void
mathnote(void)
{
	int i;
	ulong status;
	char *msg, note[ERRLEN];

	status = up->fpsave.status;

	/*
	 * Some attention should probably be paid here to the
	 * exception masks and error summary.
	 */
	msg = "unknown";
	for(i = 0; i < 8; i++){
		if(!((1<<i) & status))
			continue;
		msg = mathmsg[i];
		break;
	}
	sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.pc);
	postnote(up, 1, note, NDebug);
}

/*
 *  math coprocessor error
 */
static void
matherror(Ureg *ur, void*)
{
	ulong status;
	int i;
	char *msg;
	char note[ERRLEN];

	/*
	 *  a write cycle to port 0xF0 clears the interrupt latch attached
	 *  to the error# line from the 387
	 */
	outb(0xF0, 0xFF);
	if(!(m->cpuiddx & 0x01))
		outb(0xF0, 0xFF);

	/*
	 *  save floating point state to check out error
	 */
	fpenv(&up->fpsave);
	status = up->fpsave.status;
	mathnote();

	msg = 0;
	for(i = 0; i < 8; i++)
		if((1<<i) & status){
			msg = mathmsg[i];
			sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.pc);
			postnote(up, 1, note, NDebug);
			break;
		}
	if(msg == 0){
		sprint(note, "sys: fp: unknown fppc=0x%lux", up->fpsave.pc);
		postnote(up, 1, note, NDebug);
	}
	if(ur->pc & KZERO)
		panic("fp: status %lux fppc=0x%lux pc=0x%lux", status,
			up->fpsave.pc, ur->pc);
		panic("fp: status %lux fppc=0x%lux pc=0x%lux",
			up->fpsave.status, up->fpsave.pc, ur->pc);
}

/*


@@ 491,6 500,17 @@ mathemu(Ureg*, void*)
		up->fpstate = FPactive;
		break;
	case FPinactive:
		/*
		 * Before restoring the state, check for any pending
		 * exceptions, there's no way to restore the state without
		 * generating an unmasked exception.
		 * More attention should probably be paid here to the
		 * exception masks and error summary.
		 */
		if((up->fpsave.status & ~up->fpsave.control) & 0x07F){
			mathnote();
			break;
		}
		fprestore(&up->fpsave);
		up->fpstate = FPactive;
		break;


@@ 538,8 558,17 @@ procsave(Proc *p)
	if(p->fpstate == FPactive){
		if(p->state == Moribund)
			fpoff();
		else
		else{
			/*
			 * Fpsave() stores without handling pending
			 * unmasked exeptions. Postnote() can't be called
			 * here as sleep() already has up->rlock, so
			 * the handling of pending exceptions is delayed
			 * until the process runs again and generates an
			 * emulation fault to activate the FPU.
			 */
			fpsave(&up->fpsave);
		}
		p->fpstate = FPinactive;
	}


M pc/mem.h => pc/mem.h +3 -2
@@ 50,7 50,7 @@
#define	KZERO		0x80000000		/* base of kernel address space */
#define	KTZERO		0x80100000		/* first address in kernel text */
#define	USTKTOP		(KZERO-BY2PG)		/* byte just beyond user stack */
#define	USTKSIZE	(4*1024*1024)		/* size of user stack */
#define	USTKSIZE	(16*1024*1024)		/* size of user stack */
#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
#define TSTKSIZ 	100



@@ 101,7 101,8 @@
 */
#define PTEMAPMEM	(1024*1024)	
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define SEGMAPSIZE	512
#define SEGMAPSIZE	1984
#define SSEGMAPSIZE	16
#define PPN(x)		((x)&~(BY2PG-1))

/*

M pc/scsi.c => pc/scsi.c +1 -1
@@ 45,7 45,7 @@ scsireset(void)
		if(isaconfig("scsi", ctlrno, ctlr) == 0)
			continue;
		for(i = 0; scsidev[i]; i++){
			if(strcmp(ctlr->type, scsidev[i]->type))
			if(cistrcmp(ctlr->type, scsidev[i]->type))
				continue;
			if((ctlr->io = scsidev[i]->reset(ctlrno, ctlr)) == 0)
				break;

M port/alloc.c => port/alloc.c +2 -1
@@ 484,9 484,10 @@ poolsummary(void)
	int i;

	for(i = 0; i < table.n; i++)
		print("Arena: %s cursize=%lud; maxsize=%lud\n",
		print("Arena: %s cursize=%lud; arenasize=%lud; maxsize=%lud\n",
			table.pool[i].name,
			table.pool[i].cursize,
			table.pool[i].arenasize,
			table.pool[i].maxsize);
}


M port/devmnt.c => port/devmnt.c +10 -1
@@ 11,6 11,7 @@ struct Mntrpc
	Mntrpc*	list;		/* Free/pending list */
	Fcall	request;	/* Outgoing file system protocol message */
	Fcall	reply;		/* Incoming reply */
	uvlong	stime;		/* start time */
	Mnt*	m;		/* Mount device during rpc */
	Rendez	r;		/* Place to hang out */
	char*	rpc;		/* I/O Data buffer */


@@ 55,6 56,7 @@ void	mntrecover(Mnt*, Mntrpc*);
Chan*	mntchan(void);

int defmaxmsg = MAXFDATA;
extern void (*mntstats)(int, Chan*, uvlong);

enum
{


@@ 676,6 678,8 @@ mountio(Mnt *m, Mntrpc *r)
			if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
				error(Emountrpc);
		}
		r->stime = fastticks(nil);
		r->bytes = n;
		poperror();
	}



@@ 766,9 770,14 @@ mountmux(Mnt *m, Mntrpc *r)
				r->rpc = dp;
				q->reply = r->reply;
				q->done = 1;
				if(mntstats != nil)
					(*mntstats)(q->request.type, m->c, q->stime);
				wakeup(&q->r);
			}else
			}else {
				if(mntstats != nil)
					(*mntstats)(r->request.type, m->c, q->stime);
				q->done = 1;
			}
			return;
		}
		l = &q->list;

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

void (*mntstats)(int, Chan*, uvlong);

enum
{
	Qmntstat = 1<<12,

	Nhash=	31,
	Nms=	256,
	Nrpc=	(Tmax-Tnop)/2,
};

typedef struct Mntstats Mntstats;
struct Mntstats
{
	Mntstats *next;
	int	inuse;
	Chan	c;
	uvlong	hi[Nrpc];		/* high water time spent/msg type */
	uvlong	tot[Nrpc];		/* cumulative time spent/msg type */
	uvlong	bytes[Nrpc];		/* cumulative bytes xfered */
	ulong	n[Nrpc];		/* number of messages/msg type */
	ulong	last100[Nrpc];		/* avg time for last 100 */
};

static struct
{
	Lock;
	Mntstats	*hash[Nhash];
	Mntstats	all[Nms];
	int		n;
} msalloc;

static void
_mntstats(int type, Chan *c, uvlong start)
{
	uint h;
	Mntstats **l, *m;
	uvlong elapsed;
	ulong x;

	elapsed = fastticks(nil) - start;
	type -= Tnop;
	type >>= 1;

	h = (c->dev<<4)+(c->type<<2)+c->qid.path;
	h %= Nhash;
	for(l = &msalloc.hash[h]; *l; l = &(*l)->next)
		if(eqchan(&(*l)->c, c, 0))
			break;
	m = *l;

	if(m == nil){
		lock(&msalloc);
		for(m = msalloc.all; m < &msalloc.all[Nms]; m++)
			if(m->inuse && eqchan(&m->c, c, 0))
				break;
		if(m == &msalloc.all[Nms])
			for(m = msalloc.all; m < &msalloc.all[Nms]; m++){
				if(m->inuse == 0){
					m->inuse = 1;
					m->c = *c;
					*l = m;
					msalloc.n++;
					break;
				}
			}
		unlock(&msalloc);
		if(m >= &msalloc.all[Nms])
			return;
	}

	if(m->hi[type] < elapsed)
		m->hi[type] = elapsed;
	m->tot[type] += elapsed;
	m->n[type]++;
	x = elapsed;
	m->last100[type] = (m->last100[type]*127 + x)>>7;
}

static int
mntstatsgen(Chan *c, Dirtab*, int, int i, Dir *dp)
{
	Qid q;
	char name[NAMELEN];
	Mntstats *m;

	m = &msalloc.all[i];
	if(i > Nms || m->inuse == 0)
		return -1;

	q = (Qid){Qmntstat+i, 0};
	snprint(name, NAMELEN, "%C%lud.%lux", devtab[m->c.type]->dc, m->c.dev, m->c.qid.path);
	devdir(c, q, name, 0, eve, 0666, dp);

	return 1;
}

static void
mntstatsinit(void)
{
	mntstats = _mntstats;
}

static Chan*
mntstatsattach(char *spec)
{
	return devattach('z', spec);
}

static int
mntstatswalk(Chan *c, char *name)
{
	return devwalk(c, name, 0, msalloc.n, mntstatsgen);
}

static void
mntstatsstat(Chan *c, char *dp)
{
	devstat(c, dp, 0, msalloc.n, mntstatsgen);
}

static Chan*
mntstatsopen(Chan *c, int omode)
{
	return devopen(c, omode, 0, msalloc.n, mntstatsgen);
}

static void
mntstatsclose(Chan*)
{
}

enum
{
	Nline=	80,
};

char *rpcname[Nrpc] =
{
	"nop",
	"osession",
	"error",
	"flush",
	"oattach",
	"clone",
	"walk",
	"open",
	"create",
	"read",
	"write",
	"clunk",
	"remove",
	"stat",
	"wstat",
	"clwalk",
	"auth",
	"session",
	"attach",
};

static long
mntstatsread(Chan *c, void *buf, long n, vlong off)
{
	char *a, *start;
	ulong o;
	char xbuf[Nline+1];
	Mntstats *m;
	uvlong avg;

	start = a = buf;

	if(n <= 0)
		return n;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, 0, msalloc.n, mntstatsgen);

	m = &msalloc.all[c->qid.path - Qmntstat];
	o = off;
	if((o % Nline) != 0)
		error(Ebadarg);
	n = n/Nline;
	o = o/Nline;
	while(n > 0 && o < Nrpc){
		if(m->n[o] > 0)
			avg = m->tot[o]/m->n[o];
		else
			avg = 0;
		sprint(xbuf, "%-8.8s %16.0llud %16.0llud %9.0lud %16.0llud %9.0lud\n",
				rpcname[o],  m->hi[o],
				m->tot[o], m->n[o], avg, m->last100[o]);
		memmove(a, xbuf, Nline);
		a += Nline;
		o++;
		n--;
	}
	return a - start;
}

static long
mntstatswrite(Chan*, void*, long, vlong)
{
	lock(&msalloc);
	memset(msalloc.all, 0, sizeof(msalloc.all));
	msalloc.n = 0;
	unlock(&msalloc);
	return 0;
}

Dev mntstatsdevtab = {
	'z',
	"mntstats",

	devreset,
	mntstatsinit,
	mntstatsattach,
	devclone,
	mntstatswalk,
	mntstatsstat,
	mntstatsopen,
	devcreate,
	mntstatsclose,
	mntstatsread,
	devbread,
	mntstatswrite,
	devbwrite,
	devremove,
	devwstat,
};

M port/portdat.h => port/portdat.h +3 -2
@@ 374,7 374,6 @@ struct Segment
	Ref;
	QLock	lk;
	ushort	steal;		/* Page stealer lock */
	Segment	*next;		/* free list pointers */
	ushort	type;		/* segment type */
	ulong	base;		/* virtual base */
	ulong	top;		/* virtual top */


@@ 385,7 384,9 @@ struct Segment
	Image	*image;		/* text in file attached to this segment */
	Physseg *pseg;
	ulong*	profile;	/* Tick profile area */
	Pte	*map[SEGMAPSIZE];
	Pte	**map;
	int	mapsize;
	Pte	*ssegmap[SSEGMAPSIZE];
};

enum

M port/segment.c => port/segment.c +55 -19
@@ 48,6 48,7 @@ Segment *
newseg(int type, ulong base, ulong size)
{
	Segment *s;
	int mapsize;

	if(size > (SEGMAPSIZE*PTEPERTAB))
		error(Enovmem);


@@ 58,6 59,17 @@ newseg(int type, ulong base, ulong size)
	s->base = base;
	s->top = base+(size*BY2PG);
	s->size = size;

	mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
	if(mapsize > nelem(s->ssegmap)){
		s->map = smalloc(mapsize*sizeof(Pte*));
		s->mapsize = mapsize;
	}
	else{
		s->map = s->ssegmap;
		s->mapsize = nelem(s->ssegmap);
	}

	return s;
}



@@ 91,12 103,14 @@ putseg(Segment *s)
	if(i)
		putimage(i);

	emap = &s->map[SEGMAPSIZE];
	emap = &s->map[s->mapsize];
	for(pp = s->map; pp < emap; pp++)
		if(*pp)
			freepte(s, *pp);

	qunlock(&s->lk);
	if(s->map != s->ssegmap)
		free(s->map);
	if(s->profile != 0)
		free(s->profile);
	free(s);


@@ 108,7 122,7 @@ relocateseg(Segment *s, ulong offset)
	Page **pg, *x;
	Pte *pte, **p, **endpte;

	endpte = &s->map[SEGMAPSIZE];
	endpte = &s->map[s->mapsize];
	for(p = s->map; p < endpte; p++) {
		if(*p == 0)
			continue;


@@ 123,7 137,7 @@ relocateseg(Segment *s, ulong offset)
Segment*
dupseg(Segment **seg, int segno, int share)
{
	int i;
	int i, size;
	Pte *pte;
	Segment *n, *s;



@@ 174,7 188,8 @@ dupseg(Segment **seg, int segno, int share)
		n->flen = s->flen;
		break;
	}
	for(i = 0; i < SEGMAPSIZE; i++)
	size = s->mapsize;
	for(i = 0; i < size; i++)
		if(pte = s->map[i])
			n->map[i] = ptecpy(pte);



@@ 374,7 389,8 @@ ibrk(ulong addr, int seg)
{
	Segment *s, *ns;
	ulong newtop, newsize;
	int i;
	int i, mapsize;
	Pte **map;

	s = up->seg[seg];
	if(s == 0)


@@ 413,10 429,19 @@ ibrk(ulong addr, int seg)
		}
	}

	if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) {
	if(newsize > (SEGMAPSIZE*PTEPERTAB)) {
		qunlock(&s->lk);
		error(Enovmem);
	}
	mapsize = ROUND(newsize, PTEPERTAB)/PTEPERTAB;
	if(mapsize > s->mapsize){
		map = smalloc(mapsize*sizeof(Pte*));
		memmove(map, s->map, s->mapsize);
		if(s->map != s->ssegmap)
			free(s->map);
		s->map = map;
		s->mapsize = mapsize;
	}

	s->top = newtop;
	s->size = newsize;


@@ 430,7 455,7 @@ ibrk(ulong addr, int seg)
void
mfreeseg(Segment *s, ulong start, int pages)
{
	int i, j;
	int i, j, size;
	ulong soff;
	Page *pg;
	Page *list;


@@ 438,8 463,9 @@ mfreeseg(Segment *s, ulong start, int pages)
	soff = start-s->base;
	j = (soff&(PTEMAPMEM-1))/BY2PG;

	size = s->mapsize;
	list = nil;
	for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) {
	for(i = soff/PTEMAPMEM; i < size; i++) {
		if(pages <= 0)
			break;
		if(s->map[i] == 0) {


@@ 477,7 503,7 @@ out:
	}
}

int
Segment*
isoverlap(Proc *p, ulong va, int len)
{
	int i;


@@ 491,9 517,9 @@ isoverlap(Proc *p, ulong va, int len)
			continue;
		if((newtop > ns->base && newtop <= ns->top) ||
		   (va >= ns->base && va < ns->top))
			return 1;
			return ns;
	}
	return 0;
	return nil;
}

int


@@ 526,8 552,8 @@ addphysseg(Physseg* new)
ulong
segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
{
	int i, sno;
	Segment *s;
	int sno;
	Segment *s, *os;
	Physseg *ps;

	if(va != 0 && (va&KZERO) == KZERO)	/* BUG: Only ok for now */


@@ 537,7 563,7 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
	vmemchr(name, 0, ~0);

	for(sno = 0; sno < NSEG; sno++)
		if(p->seg[sno] == 0 && sno != ESEG)
		if(p->seg[sno] == nil && sno != ESEG)
			break;

	if(sno == NSEG)


@@ 545,18 571,28 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)

	len = PGROUND(len);

	/* Find a hole in the address space */
	/*
	 * Find a hole in the address space.
	 * Starting at the lowest possible stack address - len,
	 * check for an overlapping segment, and repeat at the
	 * base of that segment - len until either a hole is found
	 * or the address space is exhausted.
	 */
	if(va == 0) {
		va = p->seg[SSEG]->base - len;
		for(i = 0; i < 20; i++) {
			if(isoverlap(p, va, len) == 0)
		for(;;) {
			os = isoverlap(p, va, len);
			if(os == nil)
				break;
			va = os->base;
			if(len > va)
				error(Enovmem);
			va -= len;
		}
	}

	va = va&~(BY2PG-1);
	if(isoverlap(p, va, len))
	if(isoverlap(p, va, len) != nil)
		error(Esoverlap);

	for(ps = physseg; ps->name; ps++)


@@ 568,7 604,7 @@ found:
	if(len > ps->size)
		error(Enovmem);

	attr &= ~SG_TYPE;		/* Turn off what we are not allowed */
	attr &= ~SG_TYPE;		/* Turn off what is not allowed */
	attr |= ps->attr;		/* Copy in defaults */

	s = newseg(attr, va, len/BY2PG);

M port/swap.c => port/swap.c +5 -9
@@ 12,11 12,6 @@ static void	pageout(Proc*, Segment*);
static void	pagepte(int, Page**);
static void	pager(void*);

enum
{
	Maxpages = SEGMAXSIZE/BY2PG,	/* Max # of pageouts per segment pass */
};

	Image 	swapimage;
static 	int	swopen;
static	Page	**iolist;


@@ 30,7 25,7 @@ swapinit(void)
	swapalloc.alloc = swapalloc.swmap;
	swapalloc.last = swapalloc.swmap;
	swapalloc.free = conf.nswap;
	iolist = xalloc(Maxpages*sizeof(Page*));
	iolist = xalloc(conf.nswppo*sizeof(Page*));
	if(swapalloc.swmap == 0 || iolist == 0)
		panic("swapinit: not enough memory");



@@ 163,7 158,7 @@ loop:
static void
pageout(Proc *p, Segment *s)
{
	int type, i;
	int type, i, size;
	Pte *l;
	Page **pg, *entry;



@@ 189,7 184,8 @@ pageout(Proc *p, Segment *s)

	/* Pass through the pte tables looking for memory pages to swap out */
	type = s->type&SG_TYPE;
	for(i = 0; i < SEGMAPSIZE; i++) {
	size = s->mapsize;
	for(i = 0; i < size; i++) {
		l = s->map[i];
		if(l == 0)
			continue;


@@ 205,7 201,7 @@ pageout(Proc *p, Segment *s)

			pagepte(type, pg);

			if(ioptr >= Maxpages)
			if(ioptr >= conf.nswppo)
				goto out;
		}
	}

M port/systab.h => port/systab.h +7 -6
@@ 19,8 19,7 @@ Syscall syssegbrk;
Syscall sysmount;
Syscall sysopen;
Syscall sysread;
Syscall sysseek;
Syscall sysvseek;
Syscall sysoseek;
Syscall syssleep;
Syscall sysstat;
Syscall sysrfork;


@@ 43,6 42,8 @@ Syscall sysunmount;
Syscall syswait;
Syscall syswrite9p;
Syscall sysread9p;
Syscall sysseek;
Syscall	sysdeath;

Syscall *systab[]={
	[SYSR1]		sysr1,


@@ 61,8 62,7 @@ Syscall *systab[]={
	[MOUNT]		sysmount,
	[OPEN]		sysopen,
	[READ]		sysread,
	[SEEK]		sysseek,
	[VSEEK]		sysvseek,
	[OSEEK]		sysoseek,
	[SLEEP]		syssleep,
	[STAT]		sysstat,
	[RFORK]		sysrfork,


@@ 85,6 85,7 @@ Syscall *systab[]={
	[WAIT]		syswait,
	[WRITE9P]	syswrite9p,
	[READ9P]	sysread9p,
	[SEEK]		sysseek,
};

char *sysctab[]={


@@ 104,8 105,7 @@ char *sysctab[]={
	[MOUNT]		"Mount",
	[OPEN]		"Open",
	[READ]		"Read",
	[SEEK]		"Seek",
	[VSEEK]		"Vseek",
	[OSEEK]		"Oseek",
	[SLEEP]		"Sleep",
	[STAT]		"Stat",
	[RFORK]		"Rfork",


@@ 128,6 128,7 @@ char *sysctab[]={
	[WAIT]		"Wait",
	[WRITE9P]	"Write9p",
	[READ9P]	"Read9p",
	[SEEK]		"Seek",
};

int nsyscall = (sizeof systab/sizeof systab[0]);