~kris/9p

9hist

418d77ea904bffc84fe335bdc30f5bee72a13174 — David du Colombier 35 years ago 3cfbb85
Plan 9 from Bell Labs 1991-04-28
M gnot/dat.h => gnot/dat.h +68 -510
@@ 1,50 1,31 @@
typedef struct Alarm	Alarm;
typedef struct Block	Block;
typedef struct Blist	Blist;
typedef struct Chan	Chan;
typedef struct Conf	Conf;
typedef struct Dev	Dev;
typedef struct Dirtab	Dirtab;
typedef struct Env	Env;
typedef struct Envp	Envp;
typedef struct Envval	Envval;
typedef struct FFrame	FFrame;
typedef struct FPsave	FPsave;
typedef struct KMap	KMap;
typedef struct Label	Label;
typedef struct List	List;
typedef struct Lock	Lock;
typedef struct MMU	MMU;
typedef struct MMUCache	MMUCache;
typedef struct Mach	Mach;
typedef struct Mount	Mount;
typedef struct Mtab	Mtab;
typedef struct Note	Note;
typedef struct Orig	Orig;
typedef struct PTE	PTE;
typedef struct Page	Page;
typedef struct Portpage	Portpage;
typedef struct Pgrp	Pgrp;
typedef struct Proc	Proc;
typedef struct Qinfo	Qinfo;
typedef struct QLock	QLock;
typedef struct Queue	Queue;
typedef struct Ref	Ref;
typedef struct Rendez	Rendez;
typedef struct Scsi	Scsi;
typedef struct Scsidata	Scsidata;
typedef struct Seg	Seg;
typedef struct Service	Service;
typedef struct Stream	Stream;
typedef struct Ureg	Ureg;
typedef struct User	User;

typedef int Devgen(Chan*, Dirtab*, int, int, Dir*);
#define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)

struct List
{
	void	*next;
};
extern	Mach	mach0;
extern  void	(*kprofp)(ulong);

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	A_MAGIC

/*
 *  machine dependent definitions used by ../port/dat.h
 */

struct Lock
{


@@ 52,18 33,20 @@ struct Lock
	ulong	pc;
};

struct Ref
enum
{
	Lock;
	int	ref;
	FPinit,
	FPactive,
	FPdirty,
};

struct QLock
struct	FPsave
{
	Proc	*head;			/* next process waiting for object */
	Proc	*tail;			/* last process waiting for object */
	Lock	use;			/* to use object */
	Lock	queue;			/* to access list */
	uchar	type;
	uchar	size;
	short	reserved;
	char	junk[212];	/* 68881: sizes 24, 180; 68882: 56, 212 */
	char	reg[3*4+8*12];
};

struct Label


@@ 73,53 56,17 @@ struct Label
	ushort	sr;
};

struct Alarm
{
	List;
	Lock;
	int	busy;
	long	dt;		/* may underflow in clock(); must be signed */
	void	(*f)(void*);
	void	*arg;
};

#define	CHDIR	0x80000000L
#define	CHAPPEND 0x40000000L
#define	CHEXCL	0x20000000L
struct Chan
struct MMU
{
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Ref;
	union{
		Chan	*next;		/* allocation */
		ulong	offset;		/* in file */
	};
	ushort	type;
	ushort	dev;
	ushort	mode;			/* read/write */
	ushort	flag;
	Qid	qid;
	Mount	*mnt;			/* mount point that derived Chan */
	ulong	mountid;
	int	fid;			/* for devmnt */
	union {
		Stream	*stream;	/* for stream channels */
		void	*aux;
		Qid	pgrpid;		/* for #p/notepg */
		int	mntindex;	/* for devmnt */
	};
	Chan	*mchan;			/* channel to mounted server */
	Qid	mqid;			/* qid of root of mount point */
	ulong	va;
	ulong	pa;
};

struct	FPsave
#define NMMU 16
struct MMUCache
{
	uchar	type;
	uchar	size;
	short	reserved;
	char	junk[212];	/* 68881: sizes 24, 180; 68882: 56, 212 */
	char	reg[3*4+8*12];
	ulong	next;
	MMU	mmu[NMMU];
};

struct Conf


@@ 162,46 109,11 @@ struct Conf
	int	portispaged;	/* ??? */
};

struct Dev
{
	void	 (*reset)(void);
	void	 (*init)(void);
	Chan	*(*attach)(char*);
	Chan	*(*clone)(Chan*, Chan*);
	int	 (*walk)(Chan*, char*);
	void	 (*stat)(Chan*, char*);
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong);
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};

struct Dirtab
{
	char	name[NAMELEN];
	Qid	qid;
	long	length;
	long	perm;
};

struct Env
{
	Lock;
	Envval	*val;
	char	name[NAMELEN];
	Env	*next;			/* in chain of Envs for a pgrp */
	int	pgref;			/* # pgrps pointing here */
};

struct Envp
{
	Env	*env;
	int	chref;			/* # chans from pgrp pointing here */
};
#include "../port/portdat.h"

/*
 *  machine dependent definitions not used by ../port/dat.h
 */
struct KMap
{
	KMap	*next;


@@ 214,7 126,6 @@ struct Mach
{
	int	machno;			/* physical id of processor */
	ulong	splpc;			/* pc of last caller to splhi */
	int	mmask;			/* 1<<m->machno */
	ulong	ticks;			/* of the clock since boot time */
	Proc	*proc;			/* current process on this processor */
	Proc	*lproc;			/* last process on this processor */


@@ 233,145 144,47 @@ struct Mach
	int	stack[1];
};

struct Mount
{
	Ref;				/* also used as a lock when playing lists */
	short	term;			/* terminates list */
	ulong	mountid;
	Mount	*next;
	Chan	*c;			/* channel replacing underlying channel */
};

struct Mtab
{
	Chan	*c;			/* channel mounted upon */
	Mount	*mnt;			/* what's mounted upon it */
};

enum{
	NUser,				/* note provided externally */
	NExit,				/* process should exit */
	NDebug,				/* process should hang */
};

struct Note
{
	char	msg[ERRLEN];
	int	flag;			/* whether system posted it */
};

struct Orig
{
	Lock;
	Orig	*next;			/* for allocation */
	ushort	nproc;			/* processes using it */
	ushort	npage;			/* sum of refs of pages in it */
	ushort	flag;
	ulong	va;			/* va of 0th pte */
	ulong	npte;			/* #pte's in list */
	PTE	*pte;
	Chan	*chan;			/* channel deriving segment (if open) */
	ushort	type;			/* of channel (which could be non-open) */
	Qid	qid;
	Chan	*mchan;
	Qid	mqid;
	ulong	minca;			/* base of region in chan */
	ulong	maxca;			/* end of region in chan */
};

struct Page
{
	Orig	*o;			/* origin of segment owning page */
	ulong	va;			/* virtual address */
	ulong	pa;			/* physical address */
	ushort	ref;
	Page	*next;
	Page	*prev;
};

struct Pgrp
{
	Ref;				/* also used as a lock when mounting */
	Pgrp	*next;
	int	index;			/* index in pgrp table */
	ulong	pgrpid;
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};
/*
 *  gnot bus ports
 */
#define PORTSIZE	64
#define PORTSHIFT	6
#define PORTSELECT	PORT[32]

struct PTE
struct Portpage
{
	Proc	*proc;			/* process owning this PTE (0 in Orig) */
	PTE	*nextmod;		/* next at this va */
	PTE	*nextva;		/* next in this proc at higher va */
	Page	*page;
	union {
		Lock;
		QLock;
	};
	int	 select;
};

struct Rendez
{
	Lock;
	Proc	*p;
};
extern Portpage portpage;
extern int	portispaged;
extern int	(*portservice[])(void);

struct Seg
/*
 *  for SCSI bus
 */
struct Scsidata
{
	Proc	*proc;			/* process owning this segment */
	Orig	*o;			/* root list of pte's */
	ulong	minva;			/* va of 0th pte (not necessarily Seg->o->va) */
	ulong	maxva;			/* va of last pte */
	PTE	*mod;			/* list of modified pte's */
	ulong	pad[3]; /**/
	uchar *	base;
	uchar *	lim;
	uchar *	ptr;
};

struct Proc
struct Scsi
{
	Label	sched;
	Mach	*mach;			/* machine running this proc */
	char	text[NAMELEN];
	Proc	*rnext;			/* next process in run queue */
	Proc	*qnext;			/* next process on queue for a QLock */
	QLock	*qlock;			/* address of qlock being queued for DEBUG */
	int	state;
	int	spin;			/* spinning instead of unscheduled */
	Page	*upage;			/* BUG: should be unlinked from page list */
	Seg	seg[NSEG];
	ulong	bssend;			/* initial top of bss seg */
	QLock;
	ulong	pid;
	int	nchild;
	QLock	wait;			/* exiting children to be waited for */
	Waitmsg	waitmsg;		/* this is large but must be addressable */
	Proc	*child;
	Proc	*parent;
	Pgrp	*pgrp;
	ulong	parentpid;
	ulong	time[6];		/* User, Sys, Real; child U, S, R */
	short	exiting;
	short	insyscall;
	int	fpstate;
	Lock	debug;			/* to access debugging elements of User */
	Rendez	*r;			/* rendezvous point slept on */
	Rendez	sleep;			/* place for tsleep and syssleep */
	int	wokeup;			/* whether sleep was interrupted */
	ulong	pc;			/* DEBUG only */
	int	kp;			/* true if a kernel process */
	int	pidonmach[1];		/* !!Compatability with mips!! */
};

struct MMU
{
	ulong	va;
	ulong	pa;
};

#define NMMU 16
struct MMUCache
{
	ulong	next;
	MMU	mmu[NMMU];
	ushort	target, lun;
	ushort	rflag;
	ushort	status;
	Scsidata cmd;
	Scsidata data;
	uchar *	save;
	uchar	cmdblk[16];
};

#define	NERR	15


@@ 397,267 210,12 @@ struct User
	short	nnote;
	short	notified;		/* sysnoted is due */
	int	(*notify)(void*, char*);
	MMUCache mc;
	void	*ureg;
	/*
	 *  machine dependent User stuff
	 */
	MMUCache mc;
};

/*
 *  operations available to a queue
 */
struct Qinfo
{
	void (*iput)(Queue*, Block*);	/* input routine */
	void (*oput)(Queue*, Block*);	/* output routine */
	void (*open)(Queue*, Stream*);
	void (*close)(Queue*);
	char *name;
	void (*reset)(void);		/* initialization */
	Qinfo *next;
};

/*
 *  We reference lance buffers via descriptors kept in host memory
 */
struct Block
{
	Block	*next;
	uchar	*rptr;		/* first unconsumed byte */
	uchar	*wptr;		/* first empty byte */
	uchar	*lim;		/* 1 past the end of the buffer */
	uchar	*base;		/* start of the buffer */
	uchar	flags;
	uchar	type;
};

/* flag bits */
#define S_DELIM 0x80
#define S_CLASS 0x07

/* type values */
#define M_DATA 0
#define M_CTL 1
#define M_HANGUP 2

/*
 *  a list of blocks
 */
struct Blist {
	Lock;
	Block	*first;		/* first data block */
	Block	*last;		/* last data block */
	long	len;		/* length of list in bytes */
	int	nb;		/* number of blocks in list */
};

/*
 *  a queue of blocks
 */
struct Queue {
	Blist;
	int	flag;
	Qinfo	*info;		/* line discipline definition */
	Queue	*other;		/* opposite direction, same line discipline */
	Queue	*next;		/* next queue in the stream */
	void	(*put)(Queue*, Block*);
	QLock	rlock;		/* mutex for processes sleeping at r */
	Rendez	r;		/* standard place to wait for flow control */
	Rendez	*rp;		/* where flow control wakeups go to */
	void	*ptr;		/* private info for the queue */
};
#define QHUNGUP	0x1	/* flag bit meaning the stream has been hung up */
#define QINUSE	0x2
#define QHIWAT	0x4	/* queue has gone past the high water mark */	
#define QDEBUG	0x8

/*
 *  a stream head
 */
struct Stream {
	QLock;			/* structure lock */
	short	inuse;		/* number of processes in stream */
	short	opens;		/* number of processes with stream open */
	ushort	hread;		/* number of reads after hangup */
	ushort	type;		/* correlation with Chan */
	ushort	dev;		/* ... */
	ushort	id;		/* ... */
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)
#define GLOBAL(a)	(((ulong)(a)) & 0x80000000)
#define STREAMTYPE(x)	((x)&0x1f)
#define STREAMID(x)	(((x)&~CHDIR)>>5)
#define STREAMQID(i,t)	(((i)<<5)|(t))
#define PUTNEXT(q,b)	(*(q)->next->put)((q)->next, b)
#define BLEN(b)		((b)->wptr - (b)->rptr)
#define QFULL(q)	((q)->flag & QHIWAT)
#define FLOWCTL(q)	{ if(QFULL(q->next)) flowctl(q); }

/*
 *  stream file qid's & high water mark
 */
enum {
	Shighqid = STREAMQID(1,0) - 1,
	Sdataqid = Shighqid,
	Sctlqid = Sdataqid-1,
	Slowqid = Sctlqid,
	Streamhi= (9*1024),	/* byte count high water mark */
	Streambhi= 32,		/* block count high water mark */
};

#define NSTUB 32
struct Service
{
	Ref;
	Service *next;
	QLock	alock;
	int	die;
	Chan	*inc;
	Chan	*outc;
	char	name[NAMELEN];
};

#define	PRINTSIZE	256

extern Mach	*m;
extern User	*u;

/*
 * Process states
 */
enum
{
	Dead = 0,
	Moribund,
	Zombie,
	Ready,
	Scheding,
	Running,
	Queueing,
	MMUing,
	Exiting,
	Inwait,
	Wakeme,
	Broken,
};
extern	char	*statename[];

/*
 * Chan flags
 */
#define	COPEN	1	/* for i/o */
#define	CMOUNT	2	/* is result of a mount/bind */
#define	CCREATE	4	/* permits creation if CMOUNT */
#define	CCEXEC	8	/* close on exec */
#define	CFREE	16	/* not in use */

/*
 * Proc.time
 */
enum
{
	TUser,
	TSys,
	TReal,
	TCUser,
	TCSys,
	TCReal,
};

/*
 * floating point registers
 */
enum
{
	FPinit,
	FPactive,
	FPdirty,
};

/*
 * Memory management
 */
#define	SSEG	0
#define	TSEG	1
#define	DSEG	2
#define	BSEG	3
#define	ESEG	4	/* used by exec to build new stack */

#define	OWRPERM	0x01	/* write permission */
#define	OPURE	0x02	/* original data mustn't be written */
#define	OCACHED	0x04	/* cached; don't discard on exit */

/*
 * Access types in namec
 */
enum
{
	Aaccess,	/* as in access, stat */
	Atodir,		/* as in chdir */
	Aopen,		/* for i/o */
	Amount,		/* to be mounted upon */
	Acreate,	/* file is to be created */
};

#define	NUMSIZE	12		/* size of formatted number */

#define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)

extern	Conf	conf;
extern	ulong	initcode[];
extern	Dev	devtab[];
extern	char	devchar[];
extern	FPsave	initfp;
extern	Mach	mach0;
extern	char	user[NAMELEN];
extern	char	*errstrtab[];

extern  void	(*kprofp)(ulong);

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	A_MAGIC

/*
 *  for SCSI bus
 */
struct Scsidata
{
	uchar *	base;
	uchar *	lim;
	uchar *	ptr;
};

struct Scsi
{
	QLock;
	ulong	pid;
	ushort	target, lun;
	ushort	rflag;
	ushort	status;
	Scsidata cmd;
	Scsidata data;
	uchar *	save;
	uchar	cmdblk[16];
};

struct Portpage
{
	union {
		Lock;
		QLock;
	};
	int	 select;
};

#define PORTSIZE	64
#define PORTSHIFT	6
#define PORTSELECT	PORT[32]

extern Portpage portpage;
extern int	portispaged;
extern int	(*portservice[])(void);

M gnot/fns.h => gnot/fns.h +22 -194
@@ 1,40 1,13 @@
Alarm	*alarm(int, void (*)(Alarm*), void*);
void	alarminit(void);
Block	*allocb(ulong);
int	anyready(void);
#include "../port/portfns.h"

#define	P_oper(sel, inst)	(P_qlock(sel), inst, P_qunlock(sel))
#define	P_qlock(sel)	(sel >= 0 ? (qlock(&portpage), PORTSELECT = portpage.select = sel) : -1)
#define	P_qunlock(sel)	(sel >= 0 ? (qunlock(&portpage),0) : -1)
#define	P_read(sel, addr, val, type)	P_oper(sel, val = *(type *)(PORT+addr))
#define	P_write(sel, addr, val, type)	P_oper(sel, *(type *)(PORT+addr) = val)

void	addportintr(int (*)(void));
void	append(List**, List*);
void	cancel(Alarm*);
int	canlock(Lock*);
int	canqlock(QLock*);
void	chaninit(void);
void	chandevreset(void);
void	chandevinit(void);
void	checkalarms(void);
void	clearmmucache(void);
void	clock(Ureg*);
Chan	*clone(Chan*, Chan*);
void	close(Chan*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
long	clrfpintr(void);
int	compactpte(Orig*, ulong);
void	confinit(void);
Env	*copyenv(Env*, int);
int	decref(Ref*);
void	delay(int);
void	delete(List**, List*, List*);
void	delete0(List**, List*);
Chan	*devattach(int, char*);
Chan	*devclone(Chan*, Chan*);
Chan	*devclwalk(Chan*, char*);
void	devdir(Chan*, Qid, char*, long, long, Dir*);
long	devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen	devgen;
int	devno(int, int);
Chan	*devopen(Chan*, int, Dirtab*, int, Devgen*);
void	devstat(Chan*, char*, Dirtab*, int, Devgen*);
int	devwalk(Chan*, char*, Dirtab*, int, Devgen*);
void	duartbaud(int);
void	duartbreak(int);
void	duartdtr(int);


@@ 42,202 15,57 @@ int	duartinputport(void);
void	duartstartrs232o(void);
void	duartstarttimer(void);
void	duartstoptimer(void);
void	dumpregs(Ureg*);
void	dumpqueues(void);
void	dumpstack(void);
int	eqchan(Chan*, Chan*, long);
int	eqqid(Qid, Qid);
void	envpgclose(Env *);
void	error(int);
void	errors(char*);
void	execpc(ulong);
void	exit(void);
int	fault(ulong, int);
#define	evenaddr(x)	/* 68020 doesn't care */
void	fault68020(Ureg*, FFrame*);
void	fdclose(int);
Chan	*fdtochan(int, int);
void	filsys(Chan*, char*, long);
void	filsysinit(void);
void	firmware(void);
void	flowctl(Queue*);
#define	flushapage(x)
void	flushcpucache(void);
void	flushmmu(void);
void	forkmod(Seg*, Seg*, Proc*);
#define	flushpage(x) if(x)
#define	flushvirt()
int	fpcr(int);
void	fpsave(FPsave*);
void	fpregrestore(char*);
void	fpregsave(char*);
void	fprestore(FPsave*);
void	fpregrestore(char*);
void	freeb(Block*);
int	freebroken(void);
void	freechan(Chan*);
void	freenextmod(PTE*);
void	freepage(Orig*, int);
void	freepte(Orig*);
void	freesegs(int);
void	freealarm(Alarm*);
Block	*getb(Blist*);
int	getfields(char*, char**, int, char);
Block	*getq(Queue*);
void	fpsave(FPsave*);
int	getrs232o(void);
void	gotolabel(Label*);
void	growpte(Orig*, ulong);
void	*ialloc(ulong, int);
void	incontoggle(void);
int	incref(Ref*);
void	insert(List**, List*, List*);
void	invalidateu(void);
void	isdir(Chan*);
void	kbdchar(int);
void	kbdrepeat(int);
void	kbdclock(void);
void	kbdrepeat(int);
KMap*	kmap(Page*);
void	kmapinit(void);
KMap	*kmap(Page*);
int	kprint(char*, ...);
void	kproc(char*, void(*)(void*), void*);
void	kunmap(KMap*);
void	lock(Lock*);
void	lockinit(void);
Orig	*lookorig(ulong, ulong, int, Chan*);
void	machinit(void);
void	mapstack(Proc*);
void	mmuinit(void);
int	mount(Chan*, Chan*, int);
void	mousebuttons(int);
void	mouseclock(void);
Chan	*namec(char*, int, int, ulong);
void	nexterror(void);
Alarm	*newalarm(void);
Chan	*newchan(void);
PTE	*newmod(Orig *o);
Mount	*newmount(void);
Orig	*neworig(ulong, ulong, int, Chan*);
Page	*newpage(int, Orig*, ulong);
Pgrp	*newpgrp(void);
Proc	*newproc(void);
void	newqinfo(Qinfo*);
char	*nextelem(char*, char*);
void	notify(Ureg*);
void	nullput(Queue*, Block*);
int	openmode(ulong);
Block	*padb(Block*, int);
void	pageinit(void);
void	panic(char*, ...);
void	pexit(char*, int);
void	pgrpcpy(Pgrp*, Pgrp*);
void	pgrpinit(void);
void	pgrpnote(Pgrp*, char*, long, int);
Pgrp	*pgrptab(int);
int	portprobe(char*, int, int, int, long);
int	postnote(Proc*, int, char*, int);
int	pprint(char*, ...);
void	printinit(void);
void	printslave(void);
void	procinit0(void);
void	procrestore(Proc*, uchar*);
void	procsave(uchar*, int);
void	procsetup(Proc*);
Proc	*proctab(int);
Queue	*pushq(Stream*, Qinfo*);
void	putbq(Blist*, Block*);
void	putkmmu(ulong, ulong);
void	putmmu(ulong, ulong);
int	putq(Queue*, Block*);
void	putstr(char*);
void	putstrn(char*, long);
ulong	pwait(Waitmsg*);
int	readnum(ulong, char*, ulong, ulong, int);
void	ready(Proc*);
int	return0(void*);
void	rs232ichar(int);
Proc	*runproc(void);
void	qlock(QLock*);
void	qunlock(QLock*);
void	restartprint(Alarm*);
void	restfpregs(FPsave*);
void	savefpregs(FPsave*);
void	sched(void);
void	schedinit(void);
void	rs232ichar(int);
void	screeninit(void);
void	screenputc(int);
int	scsicap(int, uchar *);
Scsi	*scsicmd(int, int, long);
Scsi*	scsicmd(int, int, long);
void	scsictrlintr(void);
void	scsidmaintr(void);
int	scsiexec(Scsi *, int);
void	scsiinit(void);
void	scsirun(void);
int	scsiready(int);
uchar	*scsirecv(uchar *);
uchar*	scsirecv(uchar *);
void	scsireset(void);
void	scsirun(void);
int	scsisense(int, uchar *);
uchar	*scsixmit(uchar *);
long	seconds(void);
Seg	*seg(Proc*, ulong);
int	segaddr(Seg*, ulong, ulong);
void	serviceinit(void);
void	service(char*, Chan*, Chan*, void (*)(Chan*, char*, long));
int	setlabel(Label*);
char	*skipslash(char*);
void	sleep(Rendez*, int(*)(void*), void*);
uchar*	scsixmit(uchar *);
int	spl1(void);
int	splduart(void);
int	splhi(void);
int	spllo(void);
void	splx(int);
void	spldone(void);
Devgen	streamgen;
int	streamclose(Chan*);
int	streamclose1(Stream*);
int	streamenter(Stream*);
int	streamexit(Stream*, int);
void	streaminit(void);
void	streaminit0(void);
long	streamread(Chan*, void*, long);
long	streamwrite(Chan*, void*, long, int);
Stream	*streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
void	streamstat(Chan*, char*, char*);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
int	splduart(void);
int	tas(char*);
void	touser(void);
void	tsleep(Rendez*, int (*)(void*), void*, int);
void	twakeme(Alarm*);
long	unionread(Chan*, void*, long);
void	unlock(Lock*);
void	usepage(Page*, int);
void	unusepage(Page*, int);
void	userinit(void);
void	validaddr(ulong, ulong, int);
void	*vmemchr(void*, int, int);
void	wakeme(Alarm*);
void	wakeup(Rendez*);

#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define	poperror()	u->nerrlab--

#define	evenaddr(x)	/* 68020 doesn't care */

#define USED(x)	if(x)
#define SET(x)	x = 0
#define	flushvirt()
#define	flushapage(x)

/*
 *  for SCSI
 */
#define P_qlock(sel)	(sel >= 0 ? (qlock(&portpage), \
				PORTSELECT = portpage.select = sel) : -1)

#define P_qunlock(sel)	(sel >= 0 ? (qunlock(&portpage),0) : -1)

#define P_oper(sel, inst)	(P_qlock(sel), inst, P_qunlock(sel))

#define P_read(sel, addr, val, type)	P_oper(sel, val = *(type *)(PORT+addr))

#define P_write(sel, addr, val, type)	P_oper(sel, *(type *)(PORT+addr) = val)


#define flushpage(x) if(x)

M gnot/lock.c => gnot/lock.c +0 -52
@@ 57,55 57,3 @@ unlock(Lock *l)
	l->pc = 0;
	l->key = 0;
}

void
qlock(QLock *q)
{
	Proc *p;

	if(canlock(&q->use))
		return;
	lock(&q->queue);
	if(canlock(&q->use)){
		unlock(&q->queue);
		return;
	}
	p = q->tail;
	if(p == 0)
		q->head = u->p;
	else
		p->qnext = u->p;
	q->tail = u->p;
	u->p->qnext = 0;
	u->p->state = Queueing;
	u->p->qlock = q;	/* DEBUG */
	unlock(&q->queue);
	sched();
}

int
canqlock(QLock *q)
{
	return canlock(&q->use);
}

void
qunlock(QLock *q)
{
	Proc *p;

	lock(&q->queue);
	if(u)
		u->p->qlock = 0;
	if(q->head){
		p = q->head;
		q->head = p->qnext;
		if(q->head == 0)
			q->tail = 0;
		unlock(&q->queue);
		ready(p);
	}else{
		unlock(&q->use);
		unlock(&q->queue);
	}
}

M gnot/main.c => gnot/main.c +0 -1
@@ 74,7 74,6 @@ machinit(void)
	n = m->machno;
	memset(m, 0, sizeof(Mach));
	m->machno = n;
	m->mmask = 1<<m->machno;
	m->fpstate = FPinit;
	fprestore(&initfp);
}

R gnot/crc_16.h => port/crc_16.h +0 -0
A port/portdat.h => port/portdat.h +457 -0
@@ 0,0 1,457 @@
typedef struct Alarm	Alarm;
typedef struct Block	Block;
typedef struct Blist	Blist;
typedef struct Chan	Chan;
typedef struct Dev	Dev;
typedef struct Dirtab	Dirtab;
typedef struct Env	Env;
typedef struct Envp	Envp;
typedef struct Envval	Envval;
typedef struct Etherpkt	Etherpkt;
typedef struct List	List;
typedef struct Mount	Mount;
typedef struct Mtab	Mtab;
typedef struct Note	Note;
typedef struct Orig	Orig;
typedef struct PTE	PTE;
typedef struct Page	Page;
typedef struct Pgrp	Pgrp;
typedef struct Proc	Proc;
typedef struct Qinfo	Qinfo;
typedef struct QLock	QLock;
typedef struct Queue	Queue;
typedef struct Ref	Ref;
typedef struct Rendez	Rendez;
typedef struct Seg	Seg;
typedef struct Stream	Stream;

typedef int Devgen(Chan*, Dirtab*, int, int, Dir*);

struct List
{
	void	*next;
};

struct Ref
{
	Lock;
	int	ref;
};

struct Rendez
{
	Lock;
	Proc	*p;
};

struct QLock
{
	Proc	*head;			/* next process waiting for object */
	Proc	*tail;			/* last process waiting for object */
	Lock	use;			/* to use object */
	Lock	queue;			/* to access list */
};

struct Alarm
{
	List;
	Lock;
	int	busy;
	long	dt;		/* may underflow in clock(); must be signed */
	void	(*f)(void*);
	void	*arg;
};

/* Block.flags */
#define S_DELIM 0x80
#define S_CLASS 0x07

/* Block.type */
#define M_DATA 0
#define M_CTL 1
#define M_HANGUP 2

struct Block
{
	Block	*next;
	uchar	*rptr;		/* first unconsumed byte */
	uchar	*wptr;		/* first empty byte */
	uchar	*lim;		/* 1 past the end of the buffer */
	uchar	*base;		/* start of the buffer */
	uchar	flags;
	uchar	type;
};

struct Blist {
	Lock;
	Block	*first;		/* first data block */
	Block	*last;		/* last data block */
	long	len;		/* length of list in bytes */
	int	nb;		/* number of blocks in list */
};

/*
 * Access types in namec
 */
enum
{
	Aaccess,	/* as in access, stat */
	Atodir,		/* as in chdir */
	Aopen,		/* for i/o */
	Amount,		/* to be mounted upon */
	Acreate,	/* file is to be created */
};

/*
 *  Chan.flags
 */
#define	COPEN	1	/* for i/o */
#define	CMOUNT	2	/* is result of a mount/bind */
#define	CCREATE	4	/* permits creation if CMOUNT */
#define	CCEXEC	8	/* close on exec */
#define	CFREE	16	/* not in use */

struct Chan
{
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Ref;
	union{
		Chan	*next;		/* allocation */
		ulong	offset;		/* in file */
	};
	ushort	type;
	ushort	dev;
	ushort	mode;			/* read/write */
	ushort	flag;
	Qid	qid;
	Mount	*mnt;			/* mount point that derived Chan */
	ulong	mountid;
	int	fid;			/* for devmnt */
	union {
		Stream	*stream;	/* for stream channels */
		void	*aux;
		Qid	pgrpid;		/* for #p/notepg */
		int	mntindex;	/* for devmnt */
	};
	Chan	*mchan;			/* channel to mounted server */
	Qid	mqid;			/* qid of root of mount point */
};

struct Dev
{
	void	 (*reset)(void);
	void	 (*init)(void);
	Chan	*(*attach)(char*);
	Chan	*(*clone)(Chan*, Chan*);
	int	 (*walk)(Chan*, char*);
	void	 (*stat)(Chan*, char*);
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong);
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};

struct Dirtab
{
	char	name[NAMELEN];
	Qid	qid;
	long	length;
	long	perm;
};

struct Env
{
	Lock;
	Envval	*val;
	char	name[NAMELEN];
	Env	*next;			/* in chain of Envs for a pgrp */
	int	pgref;			/* # pgrps pointing here */
};

struct Envp
{
	Env	*env;
	int	chref;			/* # chans from pgrp pointing here */
};

/*
 *  Ethernet packet buffers.
 */
struct Etherpkt {
	uchar d[6];
	uchar s[6];
	uchar type[2];
	uchar data[1500];
	uchar crc[4];
};
#define	ETHERMINTU	60	/* minimum transmit size */
#define	ETHERMAXTU	1514	/* maximum transmit size */
#define ETHERHDRSIZE	14	/* size of an ethernet header */

struct Mount
{
	Ref;				/* also used as a lock when playing lists */
	short	term;			/* terminates list */
	ulong	mountid;
	Mount	*next;
	Chan	*c;			/* channel replacing underlying channel */
};

struct Mtab
{
	Chan	*c;			/* channel mounted upon */
	Mount	*mnt;			/* what's mounted upon it */
};

enum{
	NUser,				/* note provided externally */
	NExit,				/* process should exit */
	NDebug,				/* process should hang */
};

struct Note
{
	char	msg[ERRLEN];
	int	flag;			/* whether system posted it */
};

#define	OWRPERM	0x01	/* write permission */
#define	OPURE	0x02	/* original data mustn't be written */
#define	OCACHED	0x04	/* cached; don't discard on exit */

struct Orig
{
	Lock;
	Orig	*next;			/* for allocation */
	ushort	nproc;			/* processes using it */
	ushort	npage;			/* sum of refs of pages in it */
	ushort	flag;
	ulong	va;			/* va of 0th pte */
	ulong	npte;			/* #pte's in list */
	PTE	*pte;
	Chan	*chan;			/* channel deriving segment (if open) */
	ushort	type;			/* of channel (which could be non-open) */
	Qid	qid;
	Chan	*mchan;
	Qid	mqid;
	ulong	minca;			/* base of region in chan */
	ulong	maxca;			/* end of region in chan */
};

struct Page
{
	Orig	*o;			/* origin of segment owning page */
	ulong	va;			/* virtual address */
	ulong	pa;			/* physical address */
	ushort	ref;
	Page	*next;
	Page	*prev;
};

struct Pgrp
{
	Ref;				/* also used as a lock when mounting */
	Pgrp	*next;
	int	index;			/* index in pgrp table */
	ulong	pgrpid;
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};

/*
 *  process memory segments
 */
#define	SSEG	0
#define	TSEG	1
#define	DSEG	2
#define	BSEG	3
#define	ESEG	4	/* used by exec to build new stack */

struct Seg
{
	Proc	*proc;			/* process owning this segment */
	Orig	*o;			/* root list of pte's */
	ulong	minva;			/* va of 0th pte (not necessarily Seg->o->va) */
	ulong	maxva;			/* va of last pte */
	PTE	*mod;			/* list of modified pte's */
	ulong	pad[3]; /**/
};

/*
 * Process states
 */
enum
{
	Dead = 0,
	Moribund,
	Zombie,
	Ready,
	Scheding,
	Running,
	Queueing,
	MMUing,
	Exiting,
	Inwait,
	Wakeme,
	Broken,
};

/*
 * Proc.time
 */
enum
{
	TUser,
	TSys,
	TReal,
	TCUser,
	TCSys,
	TCReal,
};

struct Proc
{
	Label	sched;
	Mach	*mach;			/* machine running this proc */
	char	text[NAMELEN];
	Proc	*rnext;			/* next process in run queue */
	Proc	*qnext;			/* next process on queue for a QLock */
	QLock	*qlock;			/* address of qlock being queued for DEBUG */
	int	state;
	Page	*upage;			/* BUG: should be unlinked from page list */
	Seg	seg[NSEG];
	ulong	bssend;			/* initial top of bss seg */
	ulong	pid;
	int	nchild;
	QLock	wait;			/* exiting children to be waited for */
	Waitmsg	waitmsg;		/* this is large but must be addressable */
	Proc	*child;
	Proc	*parent;
	Pgrp	*pgrp;
	ulong	parentpid;
	ulong	time[6];		/* User, Sys, Real; child U, S, R */
	short	exiting;
	short	insyscall;
	int	fpstate;
	Lock	debug;			/* to access debugging elements of User */
	Rendez	*r;			/* rendezvous point slept on */
	Rendez	sleep;			/* place for tsleep and syssleep */
	int	wokeup;			/* whether sleep was interrupted */
	ulong	pc;			/* DEBUG only */
	int	kp;			/* true if a kernel process */
	union {
		int	pidonmach[MAXMACH];	/* !!Compatability with mips!! */
		MMU	*mmu;
		int	nmmuseg;		/* number of segments active in mmu */
	};
};

struct PTE
{
	Proc	*proc;			/* process owning this PTE (0 in Orig) */
	PTE	*nextmod;		/* next at this va */
	PTE	*nextva;		/* next in this proc at higher va */
	Page	*page;
};

/*
 *  operations available to a queue
 */
struct Qinfo
{
	void (*iput)(Queue*, Block*);	/* input routine */
	void (*oput)(Queue*, Block*);	/* output routine */
	void (*open)(Queue*, Stream*);
	void (*close)(Queue*);
	char *name;
	void (*reset)(void);		/* initialization */
	Qinfo *next;
};

/*
 *  Queue.flag
 */
#define QHUNGUP	0x1	/* flag bit meaning the stream has been hung up */
#define QINUSE	0x2
#define QHIWAT	0x4	/* queue has gone past the high water mark */	
#define QDEBUG	0x8

struct Queue {
	Blist;
	int	flag;
	Qinfo	*info;		/* line discipline definition */
	Queue	*other;		/* opposite direction, same line discipline */
	Queue	*next;		/* next queue in the stream */
	void	(*put)(Queue*, Block*);
	QLock	rlock;		/* mutex for processes sleeping at r */
	Rendez	r;		/* standard place to wait for flow control */
	Rendez	*rp;		/* where flow control wakeups go to */
	void	*ptr;		/* private info for the queue */
};

struct Stream {
	QLock;			/* structure lock */
	short	inuse;		/* number of processes in stream */
	short	opens;		/* number of processes with stream open */
	ushort	hread;		/* number of reads after hangup */
	ushort	type;		/* correlation with Chan */
	ushort	dev;		/* ... */
	ushort	id;		/* ... */
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};

/*
 *  useful stream macros
 */
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)
#define GLOBAL(a)	(((ulong)(a)) & 0x80000000)
#define STREAMTYPE(x)	((x)&0x1f)
#define STREAMID(x)	(((x)&~CHDIR)>>5)
#define STREAMQID(i,t)	(((i)<<5)|(t))
#define PUTNEXT(q,b)	(*(q)->next->put)((q)->next, b)
#define BLEN(b)		((b)->wptr - (b)->rptr)
#define QFULL(q)	((q)->flag & QHIWAT)
#define FLOWCTL(q)	{ if(QFULL(q->next)) flowctl(q); }

/*
 *  stream file qid's & high water mark
 */
enum {
	Shighqid = STREAMQID(1,0) - 1,
	Sdataqid = Shighqid,
	Sctlqid = Sdataqid-1,
	Slowqid = Sctlqid,
	Streamhi= (9*1024),	/* byte count high water mark */
	Streambhi= 32,		/* block count high water mark */
};

#define	PRINTSIZE	256
#define	NUMSIZE	12		/* size of formatted number */

extern	FPsave	initfp;
extern	Conf	conf;
extern	ulong	initcode[];
extern	Dev	devtab[];
extern	char	devchar[];
extern	char	user[NAMELEN];
extern	char	*errstrtab[];
extern	char	*statename[];

#define	CHDIR	0x80000000L
#define	CHAPPEND 0x40000000L
#define	CHEXCL	0x20000000L




A port/portfns.h => port/portfns.h +157 -0
@@ 0,0 1,157 @@
#define	SET(x)	x = 0
#define	USED(x)	if(x)

void	alarminit(void);
Alarm*	alarm(int, void (*)(Alarm*), void*);
Block*	allocb(ulong);
int	anyready(void);
void	append(List**, List*);
void	cancel(Alarm*);
int	canlock(Lock*);
int	canqlock(QLock*);
void	chandevinit(void);
void	chandevreset(void);
void	chaninit(void);
void	checkalarms(void);
void	clock(Ureg*);
Chan*	clone(Chan*, Chan*);
void	close(Chan*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
long	clrfpintr(void);
int	compactpte(Orig*, ulong);
void	confinit(void);
Env*	copyenv(Env*, int);
int	decref(Ref*);
void	delay(int);
void	delete0(List**, List*);
void	delete(List**, List*, List*);
Chan*	devattach(int, char*);
Chan*	devclone(Chan*, Chan*);
void	devdir(Chan*, Qid, char*, long, long, Dir*);
long	devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen	devgen;
int	devno(int, int);
Chan*	devopen(Chan*, int, Dirtab*, int, Devgen*);
void	devstat(Chan*, char*, Dirtab*, int, Devgen*);
int	devwalk(Chan*, char*, Dirtab*, int, Devgen*);
void	dumpqueues(void);
void	dumpregs(Ureg*);
void	dumpstack(void);
void	envpgclose(Env *);
int	eqchan(Chan*, Chan*, long);
int	eqqid(Qid, Qid);
void	error(int);
void	errors(char*);
void	execpc(ulong);
void	exit(void);
int	fault(ulong, int);
void	fdclose(int);
Chan*	fdtochan(int, int);
void	firmware(void);
void	flowctl(Queue*);
void	flushmmu(void);
void	forkmod(Seg*, Seg*, Proc*);
void	freealarm(Alarm*);
void	freeb(Block*);
int	freebroken(void);
void	freechan(Chan*);
void	freepage(Orig*, int);
void	freepte(Orig*);
void	freesegs(int);
Block*	getb(Blist*);
int	getfields(char*, char**, int, char);
Block*	getq(Queue*);
void	gotolabel(Label*);
void	growpte(Orig*, ulong);
void*	ialloc(ulong, int);
int	incref(Ref*);
void	insert(List**, List*, List*);
void	invalidateu(void);
void	isdir(Chan*);
void	kproc(char*, void(*)(void*), void*);
void	lock(Lock*);
void	lockinit(void);
Orig*	lookorig(ulong, ulong, int, Chan*);
void	machinit(void);
void	mapstack(Proc*);
int	mount(Chan*, Chan*, int);
Chan*	namec(char*, int, int, ulong);
Alarm*	newalarm(void);
Chan*	newchan(void);
PTE*	newmod(Orig*);
Mount*	newmount(void);
Orig*	neworig(ulong, ulong, int, Chan*);
Page*	newpage(int, Orig*, ulong);
Pgrp*	newpgrp(void);
Proc*	newproc(void);
void	newqinfo(Qinfo*);
char*	nextelem(char*, char*);
void	nexterror(void);
void	notify(Ureg*);
void	nullput(Queue*, Block*);
int	openmode(ulong);
Block*	padb(Block*, int);
void	pageinit(void);
void	panic(char*, ...);
void	pexit(char*, int);
void	pgrpcpy(Pgrp*, Pgrp*);
void	pgrpinit(void);
void	pgrpnote(Pgrp*, char*, long, int);
Pgrp*	pgrptab(int);
#define	poperror()	u->nerrlab--
int	postnote(Proc*, int, char*, int);
int	pprint(char*, ...);
void	printslave(void);
void	procinit0(void);
Proc*	proctab(int);
Queue*	pushq(Stream*, Qinfo*);
int	putb(Blist*, Block*);
void	putbq(Blist*, Block*);
void	putmmu(ulong, ulong);
int	putq(Queue*, Block*);
ulong	pwait(Waitmsg*);
void	qlock(QLock*);
void	qunlock(QLock*);
int	readnum(ulong, char*, ulong, ulong, int);
void	ready(Proc*);
int	return0(void*);
Proc*	runproc(void);
void	savefpregs(FPsave*);
void	schedinit(void);
void	sched(void);
long	seconds(void);
Seg*	seg(Proc*, ulong);
int	segaddr(Seg*, ulong, ulong);
int	setlabel(Label*);
char*	skipslash(char*);
void	sleep(Rendez*, int(*)(void*), void*);
int	splhi(void);
int	spllo(void);
void	splx(int);
int	streamclose1(Stream*);
int	streamclose(Chan*);
int	streamenter(Stream*);
int	streamexit(Stream*, int);
Devgen	streamgen;
void	streaminit0(void);
void	streaminit(void);
Stream*	streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
long	streamread(Chan*, void*, long);
void	streamstat(Chan*, char*, char*);
long	streamwrite(Chan*, void*, long, int);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
void	tsleep(Rendez*, int (*)(void*), void*, int);
void	twakeme(Alarm*);
long	unionread(Chan*, void*, long);
void	unlock(Lock*);
void	unusepage(Page*, int);
void	usepage(Page*, int);
void	userinit(void);
void	validaddr(ulong, ulong, int);
void*	vmemchr(void*, int, int);
void	wakeme(Alarm*);
void	wakeup(Rendez*);

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


void
qlock(QLock *q)
{
	Proc *p;

	if(canlock(&q->use))
		return;
	lock(&q->queue);
	if(canlock(&q->use)){
		unlock(&q->queue);
		return;
	}
	p = q->tail;
	if(p == 0)
		q->head = u->p;
	else
		p->qnext = u->p;
	q->tail = u->p;
	u->p->qnext = 0;
	u->p->state = Queueing;
/*	u->p->qlock = q;	/* DEBUG */
	unlock(&q->queue);
	sched();
}

int
canqlock(QLock *q)
{
	return canlock(&q->use);
}

void
qunlock(QLock *q)
{
	Proc *p;

	lock(&q->queue);
/*	u->p->qlock = 0; /* DEBUG */
	if(q->head){
		p = q->head;
		q->head = p->qnext;
		if(q->head == 0)
			q->tail = 0;
		unlock(&q->queue);
		ready(p);
	}else{
		unlock(&q->use);
		unlock(&q->queue);
	}
}

M port/stasync.c => port/stasync.c +1 -1
@@ 74,7 74,7 @@ int asyncdebug = 3;
int asyncerror;

static ushort crc_table[256] = {
#include "crc_16.h"
#include "../port/crc_16.h"
};

#define	BOT	0050		/* begin trailer */

M power/dat.h => power/dat.h +86 -523
@@ 1,48 1,25 @@
typedef struct Alarm	Alarm;
typedef struct Bit3msg	Bit3msg;
typedef struct Blist	Blist;
typedef struct Block	Block;
typedef struct Chan	Chan;
typedef struct Conf	Conf;
typedef struct Dev	Dev;
typedef struct Dirtab	Dirtab;
typedef struct Env	Env;
typedef struct Envp	Envp;
typedef struct Envval	Envval;
typedef struct Etherpkt	Etherpkt;
typedef struct FPsave	FPsave;
typedef struct Hotmsg	Hotmsg;
typedef struct Lance	Lance;
typedef struct Lancemem	Lancemem;
typedef struct Label	Label;
typedef struct List	List;
typedef struct Lock	Lock;
typedef struct Mach	Mach;
typedef struct MMU	MMU;
typedef struct Softtlb	Softtlb;
typedef struct Mount	Mount;
typedef struct Mtab	Mtab;
typedef struct Note	Note;
typedef struct Orig	Orig;
typedef struct PTE	PTE;
typedef struct Page	Page;
typedef struct Pgrp	Pgrp;
typedef struct Proc	Proc;
typedef struct QLock	QLock;
typedef struct Qinfo	Qinfo;
typedef struct Queue	Queue;
typedef struct Ref	Ref;
typedef struct Rendez	Rendez;
typedef struct Seg	Seg;
typedef struct Stream	Stream;
typedef struct Ureg	Ureg;
typedef struct User	User;

typedef int Devgen(Chan*, Dirtab*, int, int, Dir*);
/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	V_MAGIC

struct List
{
	void	*next;
};
/*
 *  machine dependent definitions used by ../port/dat.h
 */

struct Lock
{


@@ 50,94 27,12 @@ struct Lock
	ulong	pc;
};

struct Ref
{
	Lock;
	int	ref;
};

struct QLock
{
	Proc	*head;			/* next process waiting for object */
	Proc	*tail;			/* last process waiting for object */
	Lock	use;			/* to use object */
	Lock	queue;			/* to access list */
};

struct Rendez
{
	Lock;
	Proc	*p;
};

struct Label
{
	ulong	pc;
	ulong	sp;
};

struct Alarm
{
	List;
	Lock;
	int	busy;
	long	dt;		/* may underflow in clock(); must be signed */
	void	(*f)(void*);
	void	*arg;
};

struct Bit3msg
{
	ulong	cmd;
	ulong	addr;
	ulong	count;
	ulong	rcount;
};

struct Hotmsg
{
	ulong	cmd;
	ulong	param[5];
	Rendez	r;
	uchar	intr;			/* flag: interrupt has occurred */
	uchar	abort;			/* flag: don't interrupt */
	ushort	wlen;			/* length of last message written */
};

#define	CHDIR	0x80000000L
struct Chan
{
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Ref;
	union{
		Chan	*next;		/* allocation */
		ulong	offset;		/* in file */
	};
	ushort	type;
	ushort	dev;
	ushort	mode;			/* read/write */
	ushort	flag;
	Qid	qid;
	Mount	*mnt;			/* mount point that derived Chan */
	ulong	mountid;
	int	fid;			/* for devmnt */
	union{
		Stream	*stream;	/* for stream channels */
		void	*aux;
		Qid	pgrpid;		/* for #p/notepg */
		int	mntindex;	/* for devmnt */
	};
	Chan	*mchan;			/* channel to mounted server */
	Qid	mqid;			/* qid of root of mount point */
};

struct	FPsave
{
	long	fpreg[32];
	long	fpstatus;
};

struct Conf
{
	ulong	nmach;		/* processors */


@@ 178,50 73,43 @@ struct Conf

};

struct Dev
/*
 * floating point registers
 */
enum
{
	void	 (*reset)(void);
	void	 (*init)(void);
	Chan	*(*attach)(char*);
	Chan	*(*clone)(Chan*, Chan*);
	int	 (*walk)(Chan*, char*);
	void	 (*stat)(Chan*, char*);
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong);
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
	FPinit,
	FPactive,
	FPinactive,
};

struct Dirtab
struct	FPsave
{
	char	name[NAMELEN];
	Qid	qid;
	long	length;
	long	perm;
	long	fpreg[32];
	long	fpstatus;
};

struct Env
{
	Lock;
	Envval	*val;
	char	name[NAMELEN];
	Env	*next;			/* in chain of Envs for a pgrp */
	int	pgref;			/* # pgrps pointing here */
};
#include "../port/portdat.h"

struct Envp
/*
 *  machine dependent definitions not used by ../port/dat.h
 */
struct Bit3msg
{
	Env	*env;
	int	chref;			/* # chans from pgrp pointing here */
	ulong	cmd;
	ulong	addr;
	ulong	count;
	ulong	rcount;
};

struct Softtlb
struct Hotmsg
{
	ulong	virt;
	ulong	phys;
	ulong	cmd;
	ulong	param[5];
	Rendez	r;
	uchar	intr;			/* flag: interrupt has occurred */
	uchar	abort;			/* flag: don't interrupt */
	ushort	wlen;			/* length of last message written */
};

struct Mach


@@ 248,168 136,13 @@ struct Mach
	int	stack[1];
};

struct Mount
{
	Ref;				/* also used as a lock when playing lists */
	short	term;			/* terminates list */
	ulong	mountid;
	Mount	*next;
	Chan	*c;			/* channel replacing underlying channel */
};

struct Mtab
{
	Chan	*c;			/* channel mounted upon */
	Mount	*mnt;			/* what's mounted upon it */
};

enum{
	NUser,				/* note provided externally */
	NExit,				/* process should exit */
	NDebug,				/* process should hang */
};

struct Note
{
	char	msg[ERRLEN];
	int	flag;			/* whether system posted it */
};

struct Orig
{
	Lock;
	Orig	*next;			/* for allocation */
	ushort	nproc;			/* processes using it */
	ushort	npage;			/* sum of refs of pages in it */
	ushort	flag;
	ulong	va;			/* va of 0th pte */
	ulong	npte;			/* #pte's in list */
	PTE	*pte;
	Chan	*chan;			/* channel deriving segment (if open) */
	ushort	type;			/* of channel (which could be non-open) */
	Qid	qid;
	Chan	*mchan;
	Qid	mqid;
	ulong	minca;			/* base of region in chan */
	ulong	maxca;			/* end of region in chan */
};

struct Page
{
	Orig	*o;			/* origin of segment owning page */
	ulong	va;			/* virtual address */
	ulong	pa;			/* physical address */
	ushort	ref;
	Page	*next;
	Page	*prev;
};

struct Pgrp
{
	Ref;				/* also used as a lock when mounting */
	Pgrp	*next;
	int	index;			/* index in pgrp table */
	ulong	pgrpid;
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};

struct PTE
{
	Proc	*proc;			/* process owning this PTE (0 in Orig) */
	PTE	*nextmod;		/* next at this va */
	PTE	*nextva;		/* next in this proc at higher va */
	Page	*page;
};

struct Seg
{
	Proc	*proc;			/* process owning this segment */
	Orig	*o;			/* root list of pte's */
	ulong	minva;			/* va of 0th pte (not necessarily Seg->o->va) */
	ulong	maxva;			/* va of last pte */
	PTE	*mod;			/* list of modified pte's */
	ulong	pad[3]; /**/
};

struct Proc
{
	Label	sched;
	Mach	*mach;			/* machine running this proc */
	char	text[NAMELEN];
	Proc	*rnext;			/* next process in run queue */
	Proc	*qnext;			/* next process on queue for a QLock */
	int	state;
	short	pidonmach[MAXMACH];	/* TLB pid on each mmu */
	Page	*upage;			/* BUG: should be unlinked from page list */
	Seg	seg[NSEG];
	ulong	bssend;			/* initial top of bss seg */
	ulong	pid;
	int	nchild;
	QLock	wait;			/* exiting children to be waited for */
	Waitmsg	waitmsg;		/* this is large but must be addressable */
	Proc	*child;
	Proc	*parent;
	Pgrp	*pgrp;
	ulong	parentpid;
	ulong	time[6];		/* User, Sys, Real; child U, S, R */
	short	exiting;
	short	insyscall;
	int	fpstate;
	Lock	debug;			/* to access debugging elements of User */
	Rendez	*r;			/* rendezvous point slept on */
	Rendez	sleep;			/* place for tsleep and syssleep */
	int	wokeup;			/* whether sleep was interrupted */
	ulong	pc;			/* DEBUG only */
	int	kp;			/* true if kernel process */

};

#define	NERR	20
#define	NFD	100
#define	NNOTE	5
struct User
/*
 *  machine dependent definitions not used by ../port/dat.h
 */
struct Softtlb
{
	Proc	*p;
	Label	errlab[NERR];
	int	nerrlab;
	char	error[ERRLEN];
	FPsave	fpsave;			/* address of this is known by vdb */
	char	elem[NAMELEN];		/* last name element from namec */
	Chan	*slash;
	Chan	*dot;
	Chan	*fd[NFD];
	int	maxfd;			/* highest fd in use */
	/*
	 * I/O point for bit3 and hotrod interfaces.
	 * This is the easiest way to allocate
	 * them, but not the prettiest or most general.
	 */
	union{				/* for i/o from kernel */
		Bit3msg	kbit3;
		Hotmsg	khot;
	};
	union{				/* for i/o from user */
		Bit3msg	ubit3;
		Hotmsg	uhot;
	};
	union{				/* special location for Tflush */
		Bit3msg	fbit3;
		Hotmsg	fhot;
	};
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.
	 */
	Note	note[NNOTE];
	short	nnote;
	short	notified;		/* sysnoted is due */
	int	(*notify)(void*, char*);
	void	*ureg;
	ulong	virt;
	ulong	phys;
};

/*


@@ 422,128 155,6 @@ typedef void		KMap;
#define PPN(x)		x

/*
 *  operations available to a queue
 */
struct Qinfo
{
	void (*iput)(Queue*, Block*);	/* input routine */
	void (*oput)(Queue*, Block*);	/* output routine */
	void (*open)(Queue*, Stream*);
	void (*close)(Queue*);
	char *name;
	void (*reset)(void);
	Qinfo *next;
};

/*
 *  We reference lance buffers via descriptors kept in host memory
 */
struct Block
{
	Block	*next;
	uchar	*rptr;		/* first unconsumed byte */
	uchar	*wptr;		/* first empty byte */
	uchar	*lim;		/* 1 past the end of the buffer */
	uchar	*base;		/* start of the buffer */
	uchar	flags;
	uchar	type;
	ulong	va;		/* virtual address if mapped for a dev */
};

/* flag bits */
#define S_DELIM 0x80
#define S_CLASS 0x07

/* type values */
#define M_DATA 0
#define M_CTL 1
#define M_HANGUP 2

/*
 *  a list of blocks
 */
struct Blist {
	Lock;
	Block	*first;		/* first data block */
	Block	*last;		/* last data block */
	long	len;		/* length of list in bytes */
	int	nb;		/* number of blocks in list */
};

/*
 *  a queue of blocks
 */
struct Queue {
	Blist;
	int	flag;
	Qinfo	*info;		/* line discipline definition */
	Queue	*other;		/* opposite direction, same line discipline */
	Queue	*next;		/* next queue in the stream */
	void	(*put)(Queue*, Block*);
	QLock	rlock;		/* mutex for r */
	Rendez	r;		/* standard place to wait for flow control */
	Rendez	*rp;		/* where flow control wakeups go to */
	void	*ptr;		/* private info for the queue */
};
#define QHUNGUP	0x1	/* flag bit meaning the stream has been hung up */
#define QINUSE	0x2
#define QHIWAT	0x4	/* queue has gone past the high water mark */	
#define QDEBUG	0x8

/*
 *  a stream head
 */
struct Stream {
	QLock;			/* structure lock */
	short	inuse;		/* number of processes in stream */
	short	opens;		/* number of processes with stream open */
	ushort	hread;		/* number of reads after hangup */
	ushort	type;		/* correlation with Chan */
	ushort	dev;		/* ... */
	ushort	id;		/* ... */
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)
#define GLOBAL(a)	(((ulong)(a)) & 0x80000000)
#define STREAMTYPE(x)	((x)&0x1f)
#define STREAMID(x)	(((x)&~CHDIR)>>5)
#define STREAMQID(i,t)	(((i)<<5)|(t))
#define PUTNEXT(q,b)	(*(q)->next->put)((q)->next, b)
#define BLEN(b)		((b)->wptr - (b)->rptr)
#define QFULL(q)	((q)->flag & QHIWAT)
#define FLOWCTL(q)	{ if(QFULL(q->next)) flowctl(q); }

/*
 *  stream file qid's & high water mark
 */
enum {
	Shighqid = STREAMQID(1,0) - 1,
	Sdataqid = Shighqid,
	Sctlqid = Sdataqid-1,
	Slowqid = Sctlqid,
	Streamhi= (17*1024),	/* byte count high water mark */
	Streambhi= 32,		/* block count high water mark */
};

/*
 *  Ethernet packet buffers.
 */
struct Etherpkt {
	uchar d[6];
	uchar s[6];
	uchar type[2];
	uchar data[1500];
	uchar crc[4];
};
#define	ETHERMINTU	60	/* minimum transmit size */
#define	ETHERMAXTU	1514	/* maximum transmit size */
#define ETHERHDRSIZE	14	/* size of an ethernet header */

/*
 *  LANCE CSR3 (bus control bits)
 */
#define BSWP	0x4


@@ 574,7 185,6 @@ struct Lance
	Etherpkt *ltp;		/* transmit buffers (lance address) */
};

#define	PRINTSIZE	256
struct
{
	Lock;


@@ 582,100 192,53 @@ struct
	short	exiting;
}active;

extern register	Mach	*m;
extern register	User	*u;

/*
 * Process states
 */
enum
{
	Dead = 0,
	Moribund,
	Zombie,
	Ready,
	Scheding,
	Running,
	Queueing,
	MMUing,
	Exiting,
	Inwait,
	Wakeme,
	Broken,
};
extern	char	*statename[];

extern	char	user[NAMELEN];
extern	char	*errstrtab[];

/*
 * Chan flags
 */
#define	COPEN	1	/* for i/o */
#define	CMOUNT	2	/* is result of a mount/bind */
#define	CCREATE	4	/* permits creation if CMOUNT */
#define	CCEXEC	8	/* close on exec */
#define	CFREE	16	/* not in use */

/*
 * Proc.time
 */
enum
{
	TUser,
	TSys,
	TReal,
	TCUser,
	TCSys,
	TCReal,
};

/*
 * floating point registers
 */
enum
{
	FPinit,
	FPactive,
	FPinactive,
};

/*
 * Memory management
 */
#define	SSEG	0
#define	TSEG	1
#define	DSEG	2
#define	BSEG	3
#define	ESEG	4	/* used by exec to build new stack */

#define	OWRPERM	0x01	/* write permission */
#define	OPURE	0x02	/* original data mustn't be written */
#define	OCACHED	0x04	/* cached; don't discard on exit */
#define	MACHP(n)	((Mach *)(MACHADDR+n*BY2PG))

/*
 * Access types in namec
 */
enum
#define	NERR	15
#define	NNOTE	5
#define	NFD	100
struct User
{
	Aaccess,	/* as in access, stat */
	Atodir,		/* as in chdir */
	Aopen,		/* for i/o */
	Amount,		/* to be mounted upon */
	Acreate,	/* file is to be created */
	Proc	*p;
	int	nerrlab;
	Label	errlab[NERR];
	char	error[ERRLEN];
	FPsave	fpsave;			/* address of this is known by vdb */
	char	elem[NAMELEN];		/* last name element from namec */
	Chan	*slash;
	Chan	*dot;
	Chan	*fd[NFD];
	int	maxfd;			/* highest fd in use */
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.
	 */
	Note	note[NNOTE];
	short	nnote;
	short	notified;		/* sysnoted is due */
	int	(*notify)(void*, char*);
	void	*ureg;
	/*
	 *  machine dependent User stuff
	 */
	/*
	 * I/O point for bit3 and hotrod interfaces.
	 * This is the easiest way to allocate
	 * them, but not the prettiest or most general.
	 */
	union{				/* for i/o from kernel */
		Bit3msg	kbit3;
		Hotmsg	khot;
	};
	union{				/* for i/o from user */
		Bit3msg	ubit3;
		Hotmsg	uhot;
	};
	union{				/* special location for Tflush */
		Bit3msg	fbit3;
		Hotmsg	fhot;
	};
};

#define	NUMSIZE	12		/* size of formatted number */

#define	MACHP(n)	((Mach *)(MACHADDR+n*BY2PG))

extern	Conf	conf;
extern	ulong	initcode[];
extern	Dev	devtab[];
extern	char	devchar[];
extern	FPsave	initfp;

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	V_MAGIC
extern register Mach	*m;
extern register User	*u;

M power/fns.h => power/fns.h +20 -178
@@ 1,231 1,73 @@
Alarm	*alarm(int, void (*)(Alarm*), void*);
void	alarminit(void);
Block	*allocb(ulong);
int	anyready(void);
void	append(List**, List*);
#include "../port/portfns.h"

void	arginit(void);
int	blen(Block *);
int	bround(Block *, int);
void	cancel(Alarm*);
int	canlock(Lock*);
int	canqlock(QLock*);
void	chaninit(void);
void	chandevreset(void);
void	chandevinit(void);
void	checkalarms(void);
void	clock(Ureg*);
void	clockinit(void);
Chan	*clone(Chan*, Chan*);
void	close(Chan*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
void	clearmmucache(void);
long	clrfpintr(void);
int	compactpte(Orig*, ulong);
void	clockinit(void);
ulong	confeval(char*);
void	confprint(void);
void	confinit(void);
void	confread(void);
void	confprint(void);
void	confset(char*);
int	consactive(void);
int	conschar(void);
void	consoff(void);
int	consputc(int);
Env	*copyenv(Env*, int);
int	decref(Ref*);
void	delay(int);
void	delete(List**, List*, List*);
void	delete0(List**, List*);
Chan	*devattach(int, char*);
Chan	*devclone(Chan*, Chan*);
Chan	*devclwalk(Chan*, char*);
void	devdir(Chan*, Qid, char*, long, long, Dir*);
long	devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen	devgen;
int	devno(int, int);
Chan	*devopen(Chan*, int, Dirtab*, int, Devgen*);
void	devstat(Chan*, char*, Dirtab*, int, Devgen*);
int	devwalk(Chan*, char*, Dirtab*, int, Devgen*);
void	duartinit(void);
void	duartintr(void);
int	duartputc(int);
void	duartputs(char*);
void	duartreset(void);
void	duartxmit(int);
void	dumpregs(Ureg*);
void	dumpstack(void);
int	eqchan(Chan*, Chan*, long);
int	eqqid(Qid, Qid);
void	envpgclose(Env*);
void	error(int);
void	errors(char*);
void	evenaddr(ulong);
void	execpc(ulong);
void	exit(void);
int	fault(ulong, int);
void	faultmips(Ureg*, int, int);
ulong	fcr31(void);
void	fdclose(int);
Chan	*fdtochan(int, int);
void	firmware(void);
void	flowctl(Queue*);
void	flushmmu(void);
void	forkmod(Seg*, Seg*, Proc*);
void	freeb(Block*);
int	freebroken(void);
void	freechan(Chan*);
void	freepage(Orig*, int);
void	freepte(Orig*);
void	freesegs(int);
void	freealarm(Alarm*);
Block	*getb(Blist*);
int	getfields(char*, char**, int, char);
Block	*getq(Queue*);
#define	flushpage(x)
#define	flushvirt()
void	gettlb(int, ulong*);
ulong	gettlbvirt(int);
void	gotolabel(Label*);
void	gotopc(ulong);
void	growpte(Orig*, ulong);
void	*ialloc(ulong, int);
void	icflush(void *, int);
int	incref(Ref*);
void	insert(List**, List*, List*);
void	intr(Ureg*);
void	invalidateu(void);
void	ioboardinit(void);
void	isdir(Chan*);
void	kbdchar(int);
void	kproc(char*, void(*)(void*), void*);
void	launchinit(void);
void	intr(Ureg*);
void	lanceintr(void);
void	lanceparity(void);
void	lancesetup(Lance*);
void	launchinit(void);
void	launch(int);
void	lights(int);
void	lock(Lock*);
void	lockinit(void);
Orig	*lookorig(ulong, ulong, int, Chan*);
void	machinit(void);
void	mapstack(Proc*);
int	mount(Chan*, Chan*, int);
Chan	*namec(char*, int, int, ulong);
void	nexterror(void);
Alarm	*newalarm(void);
Chan	*newchan(void);
PTE	*newmod(Orig*);
Mount	*newmount(void);
Orig	*neworig(ulong, ulong, int, Chan*);
Page	*newpage(int, Orig*, ulong);
Pgrp	*newpgrp(void);
Proc	*newproc(void);
void	newqinfo(Qinfo*);
char	*nextelem(char*, char*);
void	newstart(void);
int	newtlbpid(Proc*);
void	notify(Ureg*);
void	novme(int);
void	nullput(Queue*, Block*);
void	online(void);
int	openmode(ulong);
Block	*padb(Block*, int);
void	pageinit(void);
void	panic(char*, ...);
void	pexit(char*, int);
void	pgrpcpy(Pgrp*, Pgrp*);
void	pgrpinit(void);
void	pgrpnote(Pgrp*, char*, long, int);
Pgrp	*pgrptab(int);
int	postnote(Proc*, int, char*, int);
int	pprint(char*, ...);
Block	*prepend(Block*, int);
void	prflush(void);
void	printinit(void);
void	printslave(void);
void	procinit0(void);
Proc	*proctab(int);
Block	*pullup(Block *, int);
Block*	prepend(Block*, int);
void	prflush(void);
#define procsetup(p)	((p)->fpstate = FPinit)
#define procsave(x,y)
#define procrestore(x,y)
Block*	pullup(Block *, int);
void	purgetlb(int);
Queue	*pushq(Stream*, Qinfo*);
void	putmmu(ulong, ulong);
void	putstlb(ulong, ulong);
void	putstrn(char*, long);
void	puttlb(ulong, ulong);
void	puttlbx(int, ulong, ulong);
int	putb(Blist*, Block*);
void	putbq(Blist*, Block*);
int	putq(Queue*, Block*);
void	putstrn(char*, long);
ulong	pwait(Waitmsg*);
int	readlog(ulong, char*, ulong);
int	readnum(ulong, char*, ulong, ulong, int);
void	ready(Proc*);
void	qlock(QLock*);
void	qunlock(QLock*);
void	restfpregs(FPsave*, ulong);
int	return0(void*);
Proc	*runproc(void);
void	savefpregs(FPsave*);
void	sched(void);
void	schedinit(void);
long	seconds(void);
Seg	*seg(Proc*, ulong);
int	segaddr(Seg*, ulong, ulong);
int	setlabel(Label*);
void	setvmevec(int, void (*)(int));
void	sinit(void);
char	*skipslash(char*);
void	sleep(Rendez*, int(*)(void*), void*);
uchar	*smap(int, uchar*);
int	splhi(void);
int	spllo(void);
void	splx(int);
uchar*	smap(int, uchar*);
void	sunmap(int, uchar*);
Devgen	streamgen;
int	streamclose(Chan*);
int	streamclose1(Stream*);
int	streamenter(Stream*);
int	streamexit(Stream*, int);
void	streaminit(void);
void	streaminit0(void);
long	streamread(Chan*, void*, long);
long	streamwrite(Chan*, void*, long, int);
Stream	*streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
void	streamstat(Chan*, char*, char*);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
void	sysloginit(void);
void	syslog(char*, int);
void	sysloginit(void);
void	tlbinit(void);
Block	*tolance(Block*, int);
void	touser(void *);
void	tsleep(Rendez*, int (*)(void*), void*, int);
void	twakeme(Alarm*);
void	unlock(Lock*);
void	unusepage(Page*, int);
void	usepage(Page*, int);
void	userinit(void);
void	validaddr(ulong, ulong, int);
Block*	tolance(Block*, int);
void	touser(void*);
void	vecinit(void);
void	vector80(void);
void	vector0(void);
void	*vmemchr(void*, int, int);
void	vector80(void);
void	vmereset(void);
void	wakeme(Alarm*);
void	wakeup(Rendez*);
void	wbflush(void);

#define	waserror()	setlabel(&u->errlab[u->nerrlab++])
#define	poperror()	u->nerrlab--

/*
 *  no external state to save on the SGI
 */
#define procsetup(p)	((p)->fpstate = FPinit)
#define procsave(x,y)
#define procrestore(x,y)

#define USED(x) if(x)
#define SET(x) x = 0
#define	flushvirt()
#define	flushpage(x)

M power/lock.c => power/lock.c +0 -49
@@ 109,52 109,3 @@ unlock(Lock *l)
	l->pc = 0;
	*l->sbsem = 0;
}

int
canqlock(QLock *q)
{
	return canlock(&q->use);
}

void
qlock(QLock *q)
{
	Proc *p;

	if(canlock(&q->use))
		return;
	lock(&q->queue);
	if(canlock(&q->use)){
		unlock(&q->queue);
		return;
	}
	p = q->tail;
	if(p == 0)
		q->head = u->p;
	else
		p->qnext = u->p;
	q->tail = u->p;
	u->p->qnext = 0;
	u->p->state = Queueing;
	unlock(&q->queue);
	sched();
}

void
qunlock(QLock *q)
{
	Proc *p;

	lock(&q->queue);
	if(q->head){
		p = q->head;
		q->head = p->qnext;
		if(q->head == 0)
			q->tail = 0;
		unlock(&q->queue);
		ready(p);
	}else{
		unlock(&q->use);
		unlock(&q->queue);
	}
}

M ss/dat.h => ss/dat.h +24 -502
@@ 1,55 1,30 @@
typedef struct Alarm	Alarm;
typedef struct Block	Block;
typedef struct Blist	Blist;
typedef struct Chan	Chan;
typedef struct Conf	Conf;
typedef struct Dev	Dev;
typedef struct Dirtab	Dirtab;
typedef struct Env	Env;
typedef struct Envp	Envp;
typedef struct Envval	Envval;
typedef struct Etherpkt	Etherpkt;
typedef struct FFrame	FFrame;
typedef struct FPsave	FPsave;
typedef struct KMap	KMap;
typedef struct Lance	Lance;
typedef struct Lancemem	Lancemem;
typedef struct Label	Label;
typedef struct List	List;
typedef struct Lock	Lock;
typedef struct MMU	MMU;
typedef struct MMUCache	MMUCache;
typedef struct Mach	Mach;
typedef struct Mount	Mount;
typedef struct Mtab	Mtab;
typedef struct Noconv	Noconv;
typedef struct Nohdr	Nohdr;
typedef struct Noifc	Noifc;
typedef struct Note	Note;
typedef struct Nomsg	Nomsg;
typedef struct Nocall	Nocall;
typedef struct Orig	Orig;
typedef struct PTE	PTE;
typedef struct Page	Page;
typedef struct Pgrp	Pgrp;
typedef struct Proc	Proc;
typedef struct Qinfo	Qinfo;
typedef struct QLock	QLock;
typedef struct Queue	Queue;
typedef struct Ref	Ref;
typedef struct Rendez	Rendez;
typedef struct Seg	Seg;
typedef struct Service	Service;
typedef struct Stream	Stream;
typedef struct Ureg	Ureg;
typedef struct User	User;

typedef int Devgen(Chan*, Dirtab*, int, int, Dir*);

struct List
{
	void	*next;
};
#define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)

extern	Mach	mach0;
extern  void	(*kprofp)(ulong);

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	K_MAGIC

/*
 *  machine dependent definitions used by ../port/dat.h
 */

struct Lock
{


@@ 57,64 32,20 @@ struct Lock
	ulong	pc;
};

struct Ref
{
	Lock;
	int	ref;
};

struct QLock
{
	Proc	*head;			/* next process waiting for object */
	Proc	*tail;			/* last process waiting for object */
	Lock	use;			/* to use object */
	Lock	queue;			/* to access list */
};

struct Label
{
	ulong	sp;
	ulong	pc;
};

struct Alarm
{
	List;
	Lock;
	int	busy;
	long	dt;		/* may underflow in clock(); must be signed */
	void	(*f)(void*);
	void	*arg;
};

#define	CHDIR	0x80000000L
#define	CHAPPEND 0x40000000L
#define	CHEXCL	0x20000000L
struct Chan
/*
 * floating point registers
 */
enum
{
	QLock	rdl;
	QLock	wrl;
	Ref;
	union{
		Chan	*next;		/* allocation */
		ulong	offset;		/* in file */
	};
	ushort	type;
	ushort	dev;
	ushort	mode;			/* read/write */
	ushort	flag;
	Qid	qid;
	Mount	*mnt;			/* mount point that derived Chan */
	ulong	mountid;
	int	fid;			/* for devmnt */
	union {
		Stream	*stream;	/* for stream channels */
		void	*aux;
		Qid	pgrpid;		/* for #p/notepg */
		int	mntindex;	/* for devmnt */
	};
	Chan	*mchan;			/* channel to mounted server */
	Qid	mqid;			/* qid of root of mount point */
	FPinit,
	FPactive,
	FPinactive,
};

struct	FPsave


@@ 164,46 95,11 @@ struct Conf
	int	copymode;	/* 0 is copy on write, 1 is copy on reference */
};

struct Dev
{
	void	 (*reset)(void);
	void	 (*init)(void);
	Chan	*(*attach)(char*);
	Chan	*(*clone)(Chan*, Chan*);
	int	 (*walk)(Chan*, char*);
	void	 (*stat)(Chan*, char*);
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong );
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};

struct Dirtab
{
	char	name[NAMELEN];
	Qid	qid;
	long	length;
	long	perm;
};

struct Env
{
	Lock;
	Envval	*val;
	char	name[NAMELEN];
	Env	*next;			/* in chain of Envs for a pgrp */
	int	pgref;			/* # pgrps pointing here */
};

struct Envp
{
	Env	*env;
	int	chref;			/* # chans from pgrp pointing here */
};
#include "../port/portdat.h"

/*
 *  machine dependent definitions not used by ../port/dat.h
 */
struct KMap
{
	KMap	*next;


@@ 239,147 135,6 @@ struct Mach
	int	stack[1];
};

struct Mount
{
	Ref;				/* also used as a lock when playing lists */
	short	term;			/* terminates list */
	ulong	mountid;
	Mount	*next;
	Chan	*c;			/* channel replacing underlying channel */
};

struct Mtab
{
	Chan	*c;			/* channel mounted upon */
	Mount	*mnt;			/* what's mounted upon it */
};

enum{
	NUser,				/* note provided externally */
	NExit,				/* process should exit */
	NDebug,				/* process should hang */
};

struct Note
{
	char	msg[ERRLEN];
	int	flag;			/* whether system posted it */
};

struct Orig
{
	Lock;
	Orig	*next;			/* for allocation */
	ushort	nproc;			/* processes using it */
	ushort	npage;			/* sum of refs of pages in it */
	ushort	flag;
	ulong	va;			/* va of 0th pte */
	ulong	npte;			/* #pte's in list */
	PTE	*pte;
	Chan	*chan;			/* channel deriving segment (if open) */
	ushort	type;			/* of channel (which could be non-open) */
	Qid	qid;
	Chan	*mchan;
	Qid	mqid;
	ulong	minca;			/* base of region in chan */
	ulong	maxca;			/* end of region in chan */
};

struct Page
{
	Orig	*o;			/* origin of segment owning page */
	ulong	va;			/* virtual address */
	ulong	pa;			/* physical address */
	ushort	ref;
	Page	*next;
	Page	*prev;
};

struct Pgrp
{
	Ref;				/* also used as a lock when mounting */
	Pgrp	*next;
	int	index;			/* index in pgrp table */
	ulong	pgrpid;
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};

struct PTE
{
	Proc	*proc;			/* process owning this PTE (0 in Orig) */
	PTE	*nextmod;		/* next at this va */
	PTE	*nextva;		/* next in this proc at higher va */
	Page	*page;
};

struct Rendez
{
	Lock;
	Proc	*p;
};

struct Seg
{
	Proc	*proc;			/* process owning this segment */
	Orig	*o;			/* root list of pte's */
	ulong	minva;			/* va of 0th pte (not necessarily Seg->o->va) */
	ulong	maxva;			/* va of last pte */
	PTE	*mod;			/* list of modified pte's */
	ulong	pad[3]; /**/
};

struct Proc
{
	Label	sched;
	Mach	*mach;			/* machine running this proc */
	char	text[NAMELEN];
	Proc	*rnext;			/* next process in run queue */
	Proc	*qnext;			/* next process on queue for a QLock */
	int	state;
	int	spin;			/* spinning instead of unscheduled */
	Page	*upage;			/* BUG: should be unlinked from page list */
	Seg	seg[NSEG];
	ulong	bssend;			/* initial top of bss seg */
	ulong	pid;
	int	nchild;
	QLock	wait;			/* exiting children to be waited for */
	Waitmsg	waitmsg;		/* this is large but must be addressable */
	Proc	*child;
	Proc	*parent;
	Pgrp	*pgrp;
	ulong	parentpid;
	ulong	time[6];		/* User, Sys, Real; child U, S, R */
	short	exiting;
	short	insyscall;
	int	fpstate;
	Lock	debug;			/* to access debugging elements of User */
	Rendez	*r;			/* rendezvous point slept on */
	Rendez	sleep;			/* place for tsleep and syssleep */
	int	wokeup;			/* whether sleep was interrupted */
	ulong	pc;			/* DEBUG only */
	int	kp;			/* true if a kernel process */
	int	pidonmach[MAXMACH];	/* TLB pid on each mmu */
	int	nmmuseg;		/* number of segments active in mmu */
};

struct MMU
{
	ulong	va;
	ulong	pa;
};

#define NMMU 16
struct MMUCache
{
	ulong	next;
	MMU	mmu[NMMU];
};

#define	NERR	15
#define	NNOTE	5
#define	NFD	100


@@ 403,144 158,10 @@ struct User
	short	nnote;
	short	notified;		/* sysnoted is due */
	int	(*notify)(void*, char*);
	MMUCache mc;
	void	*ureg;
};

/*
 *  operations available to a queue
 */
struct Qinfo
{
	void (*iput)(Queue*, Block*);	/* input routine */
	void (*oput)(Queue*, Block*);	/* output routine */
	void (*open)(Queue*, Stream*);
	void (*close)(Queue*);
	char *name;
	void (*reset)(void);		/* initialization */
	Qinfo *next;
};

/*
 *  We reference lance buffers via descriptors kept in host memory
 */
struct Block
{
	Block	*next;
	uchar	*rptr;		/* first unconsumed byte */
	uchar	*wptr;		/* first empty byte */
	uchar	*lim;		/* 1 past the end of the buffer */
	uchar	*base;		/* start of the buffer */
	uchar	flags;
	uchar	type;
};

/* flag bits */
#define S_DELIM 0x80
#define S_CLASS 0x07

/* type values */
#define M_DATA 0
#define M_CTL 1
#define M_HANGUP 2

/*
 *  a list of blocks
 */
struct Blist {
	Lock;
	Block	*first;		/* first data block */
	Block	*last;		/* last data block */
	long	len;		/* length of list in bytes */
	int	nb;		/* number of blocks in list */
};

/*
 *  a queue of blocks
 */
struct Queue {
	Blist;
	int	flag;
	Qinfo	*info;		/* line discipline definition */
	Queue	*other;		/* opposite direction, same line discipline */
	Queue	*next;		/* next queue in the stream */
	void	(*put)(Queue*, Block*);
	QLock	rlock;		/* mutex for processes sleeping at r */
	Rendez	r;		/* standard place to wait for flow control */
	Rendez	*rp;		/* where flow control wakeups go to */
	void	*ptr;		/* private info for the queue */
};
#define QHUNGUP	0x1	/* flag bit meaning the stream has been hung up */
#define QINUSE	0x2
#define QHIWAT	0x4	/* queue has gone past the high water mark */	
#define QDEBUG	0x8

/*
 *  a stream head
 */
struct Stream {
	QLock;			/* structure lock */
	short	inuse;		/* number of processes in stream */
	short	opens;		/* number of processes with stream open */
	ushort	hread;		/* number of reads after hangup */
	ushort	type;		/* correlation with Chan */
	ushort	dev;		/* ... */
	ushort	id;		/* ... */
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)
#define GLOBAL(a)	(((ulong)(a)) & 0x80000000)
#define STREAMTYPE(x)	((x)&0x1f)
#define STREAMID(x)	(((x)&~CHDIR)>>5)
#define STREAMQID(i,t)	(((i)<<5)|(t))
#define PUTNEXT(q,b)	(*(q)->next->put)((q)->next, b)
#define BLEN(b)		((b)->wptr - (b)->rptr)
#define QFULL(q)	((q)->flag & QHIWAT)
#define FLOWCTL(q)	{ if(QFULL(q->next)) flowctl(q); }

/*
 *  stream file qid's & high water mark
 */
enum {
	Shighqid = STREAMQID(1,0) - 1,
	Sdataqid = Shighqid,
	Sctlqid = Sdataqid-1,
	Slowqid = Sctlqid,
	Streamhi= (9*1024),	/* byte count high water mark */
	Streambhi= 32,		/* block count high water mark */
};

/*
 *  Ethernet packet buffers.
 */
struct Etherpkt {
	uchar d[6];
	uchar s[6];
	uchar type[2];
	uchar data[1500];
	uchar crc[4];
};
#define	ETHERMINTU	60	/* minimum transmit size */
#define	ETHERMAXTU	1514	/* maximum transmit size */
#define ETHERHDRSIZE	14	/* size of an ethernet header */

#define NSTUB 32
struct Service
{
	Ref;
	Service *next;
	QLock	alock;
	int	die;
	Chan	*inc;
	Chan	*outc;
	char	name[NAMELEN];
};

/*
 *  LANCE CSR3 (bus control bits)
 */
#define BSWP	0x4


@@ 571,106 192,7 @@ struct Lance
	Etherpkt *ltp;		/* transmit buffers (lance address) */
};

#define	PRINTSIZE	256

extern register Mach	*m;		/* R6 */
extern register User	*u;		/* R5 */

/*
 * Process states
 */
enum
{
	Dead = 0,
	Moribund,
	Zombie,
	Ready,
	Scheding,
	Running,
	Queueing,
	MMUing,
	Exiting,
	Inwait,
	Wakeme,
	Broken,
};
extern	char	*statename[];

/*
 * Chan flags
 */
#define	COPEN	1	/* for i/o */
#define	CMOUNT	2	/* is result of a mount/bind */
#define	CCREATE	4	/* permits creation if CMOUNT */
#define	CCEXEC	8	/* close on exec */
#define	CFREE	16	/* not in use */

/*
 * Proc.time
 */
enum
{
	TUser,
	TSys,
	TReal,
	TCUser,
	TCSys,
	TCReal,
};

/*
 * floating point registers
 */
enum
{
	FPinit,
	FPactive,
	FPinactive,
};

/*
 * Memory management
 */
#define	SSEG	0
#define	TSEG	1
#define	DSEG	2
#define	BSEG	3
#define	ESEG	4	/* used by exec to build new stack */

#define	OWRPERM	0x01	/* write permission */
#define	OPURE	0x02	/* original data mustn't be written */
#define	OCACHED	0x04	/* cached; don't discard on exit */

/*
 * Access types in namec
 */
enum
{
	Aaccess,	/* as in access, stat */
	Atodir,		/* as in chdir */
	Aopen,		/* for i/o */
	Amount,		/* to be mounted upon */
	Acreate,	/* file is to be created */
};

#define	NUMSIZE	12		/* size of formatted number */

#define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)

extern	Conf	conf;
extern	ulong	initcode[];
extern	Dev	devtab[];
extern	char	devchar[];
extern	FPsave	initfp;
extern	Mach	mach0;
extern	char	user[NAMELEN];
extern	char	*errstrtab[];
extern	uchar	*intrreg;

extern  void	(*kprofp)(ulong);

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	K_MAGIC
#define ENTRYOFFSET	0

M ss/fns.h => ss/fns.h +18 -191
@@ 1,167 1,58 @@
Alarm	*alarm(int, void (*)(Alarm*), void*);
void	alarminit(void);
Block	*allocb(ulong);
int	anyready(void);
void	append(List**, List*);
#include "../port/portfns.h"

void	cacheinit(void);
void	cancel(Alarm*);
int	canlock(Lock*);
int	canqlock(QLock*);
void	chaninit(void);
void	chandevreset(void);
void	chandevinit(void);
void	checkalarms(void);
void	clearfpintr(void);
#define	clearmmucache()
void	clock(Ureg*);
void	clockinit(void);
Chan	*clone(Chan*, Chan*);
void	close(Chan*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
long	clrfpintr(void);
int	compactpte(Orig*, ulong);
void	confinit(void);
Env	*copyenv(Env*, int);
Chan	*createdir(Chan*);
int	decref(Ref*);
void	delay(int);
void	delete(List**, List*, List*);
void	delete0(List**, List*);
Chan	*devattach(int, char*);
Chan	*devclone(Chan*, Chan*);
Chan	*devclwalk(Chan*, char*);
void	devdir(Chan*, Qid, char*, long, long, Dir*);
long	devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen	devgen;
int	devno(int, int);
Chan	*devopen(Chan*, int, Dirtab*, int, Devgen*);
void	devstat(Chan*, char*, Dirtab*, int, Devgen*);
int	devwalk(Chan*, char*, Dirtab*, int, Devgen*);
Chan	*domount(Chan*);
void	duartbaud(int);
void	duartbreak(int);
void	duartdtr(int);
void	duartinit(void);
void	duartintr(void);
int	duartinputport(void);
void	duartintr(void);
void	duartstartrs232o(void);
void	duartstarttimer(void);
void	duartstoptimer(void);
void	dumpregs(Ureg*);
void	dumpstack(void);
int	eqchan(Chan*, Chan*, long);
int	eqqid(Qid, Qid);
void	envpgclose(Env *);
void	error(int);
void	errors(char*);
void	evenaddr(ulong);
char	*excname(ulong);
void	execpc(ulong);
void	exit(void);
int	fault(ulong, int);
char*	excname(ulong);
void	faultasync(Ureg*);
void	faultsparc(Ureg*);
void	fdclose(int);
Chan	*fdtochan(int, int);
void	filsys(Chan*, char*, long);
void	filsysinit(void);
void	firmware(void);
void	flowctl(Queue*);
void	flushcpucache(void);
void	flushmmu(void);
void	forkmod(Seg*, Seg*, Proc*);
#define	flushpage(x)
#define	flushvirt()	flushmmu()
int	fpcr(int);
void	fpsave(FPsave*);
void	fpregrestore(char*);
void	fpregsave(char*);
void	fprestore(FPsave*);
void	fpregrestore(char*);
void	freeb(Block*);
int	freebroken(void);
void	freechan(Chan*);
void	freenextmod(PTE*);
void	freepage(Orig*, int);
void	freepte(Orig*);
void	freesegs(int);
void	freealarm(Alarm*);
Block	*getb(Blist*);
void	fpsave(FPsave*);
int	getb2(ulong);
int	getfields(char*, char**, int, char);
Block	*getq(Queue*);
int	getrs232o(void);
int	getw2(ulong);
void	gotolabel(Label*);
void	growpte(Orig*, ulong);
void	*ialloc(ulong, int);
int	incref(Ref*);
void	insert(List**, List*, List*);
void	intrinit(void);
void	invalidateu(void);
void	isdir(Chan*);
void	kbdchar(int);
void	kbdrepeat(int);
void	kbdclock(void);
void	kbdrepeat(int);
KMap*	kmap(Page*);
void	kmapinit(void);
KMap	*kmap(Page*);
KMap	*kmappa(ulong, ulong);
KMap*	kmappa(ulong, ulong);
int	kprint(char*, ...);
void	kproc(char*, void(*)(void*), void*);
void	kunmap(KMap*);
void	lanceintr(void);
void	lancesetup(Lance*);
void	lancetoggle(void);
void	lock(Lock*);
void	lockinit(void);
Orig	*lookorig(ulong, ulong, int, Chan*);
void	machinit(void);
void	mapstack(Proc*);
void	mmuinit(void);
int	mount(Chan*, Chan*, int);
void	mousebuttons(int);
void	mousechar(int);
void	mouseclock(void);
Chan	*namec(char*, int, int, ulong);
void	nexterror(void);
Alarm	*newalarm(void);
Chan	*newchan(void);
PTE	*newmod(Orig *o);
Mount	*newmount(void);
Orig	*neworig(ulong, ulong, int, Chan*);
Page	*newpage(int, Orig*, ulong);
Pgrp	*newpgrp(void);
Proc	*newproc(void);
void	newqinfo(Qinfo*);
char	*nextelem(char*, char*);
void	notify(Ureg*);
void	nullput(Queue*, Block*);
int	openmode(ulong);
Block	*padb(Block*, int);
void	pageinit(void);
void	panic(char*, ...);
void	pexit(char*, int);
void	pgrpcpy(Pgrp*, Pgrp*);
void	pgrpinit(void);
void	pgrpnote(Pgrp*, char*, long, int);
Pgrp	*pgrptab(int);
int	postnote(Proc*, int, char*, int);
int	pprint(char*, ...);
void	printinit(void);
void	printslave(void);
void	procinit0(void);
void	procrestore(Proc*, uchar*);
void	procsave(uchar*, int);
void	procsetup(Proc*);
Proc	*proctab(int);
Queue	*pushq(Stream*, Qinfo*);
int	putb(Blist*, Block*);
#define	procrestore(x,y)
#define	procsave(x,y)
#define	procsetup(x)	((p)->fpstate = FPinit)
void	putb2(ulong, int);
void	putbq(Blist*, Block*);
void	putcontext(int);
void	putcxreg(int);
void	putcxsegm(int, ulong, int);
void	putmmu(ulong, ulong);
void	putpmeg(ulong, ulong);
int	putq(Queue*, Block*);
void	putsegm(ulong, int);
void	putstr(char*);
void	putstrn(char*, long);


@@ 169,84 60,20 @@ void	puttbr(ulong);
void	putw2(ulong, ulong);
void	putw4(ulong, ulong);
void	putwC(ulong, ulong);
void	putwD(ulong, ulong);
void	putwD16(ulong, ulong);
void	putwE(ulong, ulong);
void	putwD(ulong, ulong);
void	putwE16(ulong, ulong);
ulong	pwait(Waitmsg*);
int	readnum(ulong, char*, ulong, ulong, int);
void	ready(Proc*);
void	putwE(ulong, ulong);
void	reset(void);
int	return0(void*);
void	rs232ichar(int);
Proc	*runproc(void);
void	qlock(QLock*);
void	qunlock(QLock*);
void	restartprint(Alarm*);
void	restfpregs(FPsave*);
void	savefpregs(FPsave*);
void	sched(void);
void	schedinit(void);
void	rs232ichar(int);
void	screeninit(void);
void	screenputc(int);
long	seconds(void);
Seg	*seg(Proc*, ulong);
int	segaddr(Seg*, ulong, ulong);
void	serviceinit(void);
void	service(char*, Chan*, Chan*, void (*)(Chan*, char*, long));
int	setlabel(Label*);
char	*skipslash(char*);
void	sleep(Rendez*, int(*)(void*), void*);
int	splhi(void);
int	spllo(void);
void	splx(int);
void	spldone(void);
ulong	swap1(ulong*);
Devgen	streamgen;
int	streamclose(Chan*);
int	streamclose1(Stream*);
int	streamenter(Stream*);
int	streamexit(Stream*, int);
void	streaminit(void);
void	streaminit0(void);
long	streamread(Chan*, void*, long);
long	streamwrite(Chan*, void*, long, int);
Stream	*streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
void	streamstat(Chan*, char*, char*);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
int	tas(char*);
void	touser(ulong);
void	trap(Ureg*);
void	trapinit(void);
void	tsleep(Rendez*, int (*)(void*), void*, int);
void	twakeme(Alarm*);
long	unionread(Chan*, void*, long);
void	unlock(Lock*);
void	usepage(Page*, int);
void	unusepage(Page*, int);
void	userinit(void);
void	validaddr(ulong, ulong, int);
void	*vmemchr(void*, int, int);
void	wakeme(Alarm*);
void	wakeup(Rendez*);
Chan	*walk(Chan*, char*, int);

#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define	poperror()	u->nerrlab--

/*
 *  no external state to save on the SPARC
 */
#define procsetup(x)	((p)->fpstate = FPinit)
#define procsave(x,y)
#define procrestore(x,y)


#define USED(x) if(x)
#define SET(x) x = 0
#define	wbflush()	/* mips compatibility */
#define	flushvirt()	flushmmu()
#define	flushpage(x)
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))