~kris/9p

9hist

25d4fd9342a48e45eedeb0858f7996661bafca8d — David du Colombier 35 years ago fb85284
Plan 9 from Bell Labs 1991-07-23
M gnot/lock.c => gnot/lock.c +18 -28
@@ 7,55 7,45 @@

#define PCOFF -1

/*
 *  N.B.  Ken's compiler generates a TAS instruction for the sequence:
 *
 *  	if(l->key >= 0){
 *		l->key |= 0x80;
 *		...
 *
 *	DO NOT TAKE THE ADDRESS OF l->key or the TAS will disappear.
 */
void
lock(Lock *l)
{
	Lock *ll = l;	/* do NOT take the address of ll */
	int i;

	/*
	 * Try the fast grab first
	 */
    	if(ll->key >= 0){
		ll->key |= 0x80;
		ll->pc = ((ulong*)&l)[PCOFF];
    	if(tas(&l->key) == 0){
		if(u && u->p)
			u->p->hasspin = 1;
		l->pc = ((ulong*)&l)[PCOFF];
		return;
	}
	for(i=0; i<10000000; i++)
    		if(ll->key >= 0){
			ll->key |= 0x80;
			ll->pc = ((ulong*)&l)[PCOFF];
	for(i = 0; i < 1000; i++){
		sched();
    		if (tas(&l->key) == 0){
			if(u && u->p)
				u->p->hasspin = 1;
			l->pc = ((ulong*)&l)[PCOFF];
			return;
		}
	ll->key = 0;
	print("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&l)[PCOFF], l->pc);
	}
	i = l->key;
	l->key = 0;

	panic("lock loop 0x%lux key 0x%lux pc 0x%lux held by pc 0x%lux\n", l, i,
		((ulong*)&l)[PCOFF], l->pc);
}

int
canlock(Lock *l)
{
	Lock *ll = l;	/* do NOT take the address of ll */
	if(ll->key >= 0){
		ll->key |= 0x80;
		ll->pc = ((ulong*)&l)[PCOFF];
		if(u && u->p)
			u->p->hasspin = 1;
		return 1;
	}
	return 0;
	if(tas(&l->key))
		return 0;
	l->pc = ((ulong*)&l)[PCOFF];
	if(u && u->p)
		u->p->hasspin = 1;
	return 1;
}

void

M pc/fault386.c => pc/fault386.c +0 -3
@@ 16,7 16,6 @@ fault386(Ureg *ur)
	int user;
	int n;
	int insyscall;
	static int times;

	insyscall = u->p->insyscall;
	u->p->insyscall = 1;


@@ 29,8 28,6 @@ dumpregs(ur);
	read = !(ur->ecode & 2);
	user = (ur->ecode & 4);
	n = fault(addr, read);
if(++times==3)
	panic("3rd time in fault");
	if(n < 0){
		if(user){
			pprint("user %s error addr=0x%lux\n", read?"read":"write", addr);

M pc/fns.h => pc/fns.h +1 -0
@@ 64,4 64,5 @@ void	systrap(void);
void	touser(void);
void	trapinit(void);
int	tas(Lock*);
void	vgainit(void);
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))

M pc/main.c => pc/main.c +36 -0
@@ 19,6 19,7 @@ main(void)
	screeninit();
	printinit();
	mmuinit();
	vgainit();
	trapinit();
	kbdinit();
	clockinit();


@@ 273,3 274,38 @@ mouseputc(IOQ *q, int c)
{
	return c;
}

/*
 *  headland hip set for the safari.
 *  
 *  serious magic!!!
 */

enum
{
	Head=		0x92,		/* control port */
	 Reset=		(1<<0),		/* reset the 386 */
	 A20ena=	(1<<1),		/* enable address line 20 */
};

/*
 *  enable address bit 20
 */
void
a20enable(void)
{
	outb(Head, A20ena);
}

/*
 *  reset the chip
 */
void
exit(void)
{
	int i;

	u = 0;
	print("exiting\n");
	outb(Head, Reset);
}

M pc/mmu.c => pc/mmu.c +6 -5
@@ 178,8 178,8 @@ mapstack(Proc *p)
	/*
	 *  point top level page table to bottom level ones
	 */
	memmove(toppt, p->mmu, MAXMMU*sizeof(ulong));
	memmove(&toppt[TOPOFF(USTKBTM)], &p->mmu[MAXMMU], MAXSMMU*sizeof(ulong));
	memmove(toppt, p->mmue, MAXMMU*sizeof(ulong));
	memmove(&toppt[TOPOFF(USTKBTM)], &p->mmue[MAXMMU], MAXSMMU*sizeof(ulong));

	/* map in u area */
	upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE;


@@ 216,7 216,7 @@ putmmu(ulong va, ulong pa, Page *pg)
	int topoff;
	ulong *pt;
	Proc *p;
	int i;
	int i = 0;

print("putmmu %lux %lux\n", va, pa); /**/
	if(u==0)


@@ 238,18 238,19 @@ print("putmmu %lux %lux\n", va, pa); /**/
	 *  if bottom level page table missing, allocate one
	 */
	pg = p->mmu[i];
print("toppt[%d] was %lux\n", topoff, toppt[topoff]);
	if(pg == 0){
		pg = p->mmu[i] = newpage(1, 0, 0);
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE;
		toppt[topoff] = p->mmue[i];
print("toppt[%d] = %lux\n", topoff, toppt[topoff]);
print("toppt[%d] now %lux\n", topoff, toppt[topoff]);
	}

	/*
	 *  fill in the bottom level page table
	 */
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);
	pt = (ulong*)(p->mmu[i]->pa|KZERO);
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);
	pt[BTMOFF(va)] = pa | PTEUSER;
print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);


M pc/trap.c => pc/trap.c +0 -8
@@ 223,8 223,6 @@ syscall(Ureg *ur)
	ulong	sp;
	long	ret;
	int	i;
	static int times;
ulong	*z;

	u->p->insyscall = 1;
	u->p->pc = ur->pc;


@@ 240,11 238,6 @@ ulong	*z;
	sp = ur->usp;
	u->nerrlab = 0;
	ret = -1;
z = (ulong *)sp;
print("syscall %lux %lux %lux %lux\n", *z, *(z+1), *(z+2), *(z+3));
dumpregs(ur);
if(++times==3)
	panic("3rd time in syscall");
	if(!waserror()){
		if(ax >= sizeof systab/BY2WD){
			pprint("bad sys call number %d pc %lux\n", ax, ur->pc);


@@ 256,7 249,6 @@ if(++times==3)
		ret = (*systab[ax])((ulong*)(sp+BY2WD));
		poperror();
	}
print("return from syscall\n");
	if(u->nerrlab){
		print("bad errstack [%d]: %d extra\n", ax, u->nerrlab);
		for(i = 0; i < NERR; i++)

A pc/vga.c => pc/vga.c +29 -0
@@ 0,0 1,29 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

enum
{
	GRX=		0x3CE,		/* index to graphics registers */
	GR=		0x3CF,		/* graphics registers 0-8 */
};

/*
 *  look at VGA registers
 */
void
vgainit(void)
{
	int i;
	uchar x;

	for(i = 0; i < 9; i++){
		outb(GRX, i);
		x = inb(GR);
		print("GR%d == %ux\n", i, x);
	}
	panic("for the hell of it");
}

M port/chan.c => port/chan.c +2 -10
@@ 34,17 34,9 @@ decref(Ref *r)
	lock(r);
	x = --r->ref;
	unlock(r);
	if(x < 0) {
		if(u) {
			print("%d: %s %lux %lux\n", u->p->pid, u->p->text, *(ulong*)((Ureg*)UREGADDR)->pc, r);
			for(i = 0; i < NSEG; i++) {
				s = u->p->seg[i];
				if(s)
					print("%d: %lux %lux %lux", i, s, s->base, s->top);
			}
		}
	if(x < 0) 
		panic("decref");
	}

	return x;
}


M port/devcons.c => port/devcons.c +2 -1
@@ 11,7 11,7 @@
struct {
	IOQ;			/* lock to klogputs */
	QLock;			/* qlock to getc */
}	klogq;
}klogq;

IOQ	lineq;			/* lock to getc; interrupt putc's */
IOQ	printq;


@@ 141,6 141,7 @@ panic(char *fmt, ...)
	char buf[PRINTSIZE];
	int n;

	print("panic: %lux m=%lux\n", &fmt, m);
	strcpy(buf, "panic: ");
	n = doprint(buf+7, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
	buf[n] = '\n';

M port/devdk.c => port/devdk.c +1 -1
@@ 1464,7 1464,7 @@ dkcsckproc(void *a)
			break;
		
		case T_SRV:	/* ignore it, it's useless */
			print("dksrvmesg(%d)\n", line);
/*			print("dksrvmesg(%d)\n", line);		/**/
			break;
		
		case T_RESTART:	/* datakit reboot */

M port/devip.c => port/devip.c +0 -31
@@ 708,37 708,6 @@ tcpstclose(Queue *q)
	}
}

/*
 * Network byte order functions
 */

void
hnputs(uchar *ptr, ushort val)
{
	ptr[0] = val>>8;
	ptr[1] = val;
}

void
hnputl(uchar *ptr, ulong val)
{
	ptr[0] = val>>24;
	ptr[1] = val>>16;
	ptr[2] = val>>8;
	ptr[3] = val;
}

ulong
nhgetl(uchar *ptr)
{
	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
}

ushort
nhgets(uchar *ptr)
{
	return ((ptr[0]<<8) | ptr[1]);
}

/* 
 * ptcl_csum - protcol cecksum routine

M port/sysproc.c => port/sysproc.c +26 -10
@@ 96,6 96,15 @@ sysfork(ulong *arg)
	return pid;
}

static ulong
l2be(long l)
{
	uchar *cp;

	cp = (uchar*)&l;
	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
}

long
sysexec(ulong *arg)
{


@@ 114,6 123,7 @@ sysexec(ulong *arg)
	char line[sizeof(Exec)];
	Fgrp *f;
	Image *img;
	ulong magic, text, entry, data, bss;

	p = u->p;
	validaddr(arg[0], 1, 0);


@@ 132,10 142,13 @@ sysexec(ulong *arg)
	if(n < 2)
    Err:
		error(Ebadexec);
	if(n==sizeof(Exec) && exec.magic==AOUT_MAGIC){
		if((exec.text&KZERO)
		|| (ulong)exec.entry < UTZERO+sizeof(Exec)
		|| (ulong)exec.entry >= UTZERO+sizeof(Exec)+exec.text)
	magic = l2be(exec.magic);
	text = l2be(exec.text);
	entry = l2be(exec.entry);
	if(n==sizeof(Exec) && magic==AOUT_MAGIC){
		if((text&KZERO)
		|| entry < UTZERO+sizeof(Exec)
		|| entry >= UTZERO+sizeof(Exec)+text)
			goto Err;
		goto Binary;
	}


@@ 165,9 178,11 @@ sysexec(ulong *arg)

    Binary:
	poperror();
	t = (UTZERO+sizeof(Exec)+exec.text+(BY2PG-1)) & ~(BY2PG-1);
	d = (t + exec.data + (BY2PG-1)) & ~(BY2PG-1);
	bssend = t + exec.data + exec.bss;
	data = l2be(exec.data);
	bss = l2be(exec.bss);
	t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
	d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
	bssend = t + data + bss;
	b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
	if((t|d|b) & KZERO)
		error(Ebadexec);


@@ 254,7 269,7 @@ sysexec(ulong *arg)
	p->seg[TSEG] = ts;
	ts->flushme = 1;
	ts->fstart = 0;
	ts->flen = sizeof(Exec)+exec.text;
	ts->flen = sizeof(Exec)+text;

	/* Data. Shared. */
	s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);


@@ 264,7 279,7 @@ sysexec(ulong *arg)
	incref(img);
	s->image = img;
	s->fstart = ts->fstart+ts->flen;
	s->flen = exec.data;
	s->flen = data;

	/* BSS. Zero fill on demand */
	p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);


@@ 288,7 303,7 @@ sysexec(ulong *arg)
	 */
	flushmmu();
	clearmmucache();
	execpc(exec.entry);
	execpc(entry);
	sp = (ulong*)(USTKTOP - ssize);
	*--sp = nargs;
	((Ureg*)UREGADDR)->usp = (ulong)sp;


@@ 488,6 503,7 @@ syssegdetach(ulong *arg)
	int i;
	Segment *s;

	s = 0;
	for(i = 0; i < NSEG; i++)
		if(s = u->p->seg[i]) {
			qlock(&s->lk);

M port/tcpoutput.c => port/tcpoutput.c +32 -0
@@ 282,3 282,35 @@ tcprcvwin(Ipconv *s)
	else
		tcb->rcv.wnd = Streamhi;
}

/*
 * Network byte order functions
 */

void
hnputs(uchar *ptr, ushort val)
{
	ptr[0] = val>>8;
	ptr[1] = val;
}

void
hnputl(uchar *ptr, ulong val)
{
	ptr[0] = val>>24;
	ptr[1] = val>>16;
	ptr[2] = val>>8;
	ptr[3] = val;
}

ulong
nhgetl(uchar *ptr)
{
	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
}

ushort
nhgets(uchar *ptr)
{
	return ((ptr[0]<<8) | ptr[1]);
}

M power/devhotrod.c => power/devhotrod.c +1 -0
@@ 13,6 13,7 @@
/*
 * If defined, ENABMEMTEST causes memory test to be run at device open
 */
#define	ENABMEMTEST
#ifdef	ENABMEMTEST
void	mem(Hot*, ulong*, ulong);
#define	NTESTBUF	256

A ss/bbmalloc.c => ss/bbmalloc.c +73 -0
@@ 0,0 1,73 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

/*
 * Allocate memory for use in kernel bitblts.
 * The allocated memory must have a flushed instruction
 * cache, and the data cache must be flushed by bbdflush().
 * To avoid the need for frequent cache flushes, the memory
 * is allocated out of an arena, and the i-cache is only
 * flushed when it has to be reused.  By returning an
 * address in non-cached space, the need for flushing the
 * d-cache is avoided.
 *
 * Currently, the only kernel users of bitblt are devbit,
 * print, and the cursor stuff in devbit.  The cursor
 * can get drawn at clock interrupt time, so it might need
 * to bbmalloc while another bitblt is going on.
 *
 * This code will have to be interlocked if we ever get
 * a multiprocessor with a bitmapped display.
 */

/* a 0->3 bitblt can take 900 words */
enum {
	nbbarena=8192	/* number of words in an arena */
};

static ulong	bbarena[nbbarena];
static ulong	*bbcur = bbarena;
static ulong	*bblast = 0;

void *
bbmalloc(int nbytes)
{
	int nw;
	int s;
	ulong *ans;

	nw = nbytes/sizeof(long);
	s = splhi();
	if(bbcur + nw > &bbarena[nbbarena])
		ans = bbarena;
	else
		ans = bbcur;
	bbcur = ans + nw;
	splx(s);
/*
	if(ans == bbarena)
		icflush(ans, sizeof(bbarena));
*/
	bblast = ans;
	ans = (void *)ans;
	return ans;
}

void
bbfree(void *p, int n)
{
	ulong *up;

	if(p == bblast)
		bbcur = (ulong *)(((char *)bblast) + n);
}

void *
bbdflush(void *p, int n)
{
	return p;
}

M ss/clock.c => ss/clock.c +1 -1
@@ 60,7 60,7 @@ clock(Ureg *ur)
		if(anyready())
			sched();
		if((ur->psr&PSRPSUPER) == 0){
			*(ulong*)(USTKTOP-BY2WD) += TK2MS(1);
/*			*(ulong*)(USTKTOP-BY2WD) += TK2MS(1); /**/
			if(u->nnote)
				notify(ur);
		}