~kris/9p

9hist

bffc34b1d0eade0f7dfd2058c24981284a85193f — David du Colombier 34 years ago 2450bfa
Plan 9 from Bell Labs 1992-03-03
12 files changed, 224 insertions(+), 432 deletions(-)

M port/devmux.c
M port/devwren.c
M port/fault.c
M port/ipdat.h
M port/page.c
M port/portdat.h
M port/proc.c
M port/stil.c
D port/stnoether.c
A port/streboot.c
M port/swap.c
M port/tcpif.c
M port/devmux.c => port/devmux.c +47 -47
@@ 292,6 292,53 @@ muxcreate(Chan *c, char *name, int omode, ulong perm)
}

void
muxclose(Chan *c)
{
	Block *f1, *f2;
	Con *cm, *e;
	Mux *m;
	int nc;

	if(c->qid.path&CHDIR)
		return;

	m = &muxes[NMUX(c)];
	if(!(c->flag&COPEN) || m->srv)
		return;

	nc = NCON(c);
	f1 = 0;
	f2 = 0;
	switch(nc) {
	case Qhead:
		m->headopen = 0;
		cm = m->connects;
		for(e = &cm[Nmux]; cm < e; cm++)
			if(cm->ref)
				wakeup(&cm->conq.r);
		lock(m);
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
		break;
	case Qclone:
		break;
	default:
		lock(m);
		cm = &m->connects[nc-Qoffset];
		if(--cm->ref == 0)
			f1 = muxclq(&cm->conq);
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
	}
	if(f1)
		freeb(f1);
	if(f2)
		freeb(f2);
}

void
muxremove(Chan *c)
{
	Mux *m;


@@ 355,53 402,6 @@ muxwstat(Chan *c, char *db)
	}
}

void
muxclose(Chan *c)
{
	Block *f1, *f2;
	Con *cm, *e;
	Mux *m;
	int nc;

	if(c->qid.path&CHDIR)
		return;

	m = &muxes[NMUX(c)];
	if(!(c->flag&COPEN) || m->srv)
		return;

	nc = NCON(c);
	f1 = 0;
	f2 = 0;
	switch(nc) {
	case Qhead:
		m->headopen = 0;
		cm = m->connects;
		for(e = &cm[Nmux]; cm < e; cm++)
			if(cm->ref)
				wakeup(&cm->conq.r);
		lock(m);
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
		break;
	case Qclone:
		break;
	default:
		lock(m);
		cm = &m->connects[nc-Qoffset];
		if(--cm->ref == 0)
			f1 = muxclq(&cm->conq);
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
	}
	if(f1)
		freeb(f1);
	if(f2)
		freeb(f2);
}

long
muxread(Chan *c, void *va, long n, ulong offset)
{

M port/devwren.c => port/devwren.c +1 -0
@@ 326,5 326,6 @@ wrenpart(int dev)
	dp->npart = pp - dp->p;
	poperror();
	scsifree(b);
	poperror();
	qunlock(dp);
}

M port/fault.c => port/fault.c +2 -0
@@ 170,6 170,7 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
		new = lookpage(s->image, daddr);
	}
	else {
print("reclaim\n");
		daddr = swapaddr(loadrec);
		new = lookpage(&swapimage, daddr);
		if(new)


@@ 221,6 222,7 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
			putpage(new);
	}
	else {					/* This is paged out */
print("SWAPIN\n");
		c = swapimage.c;
		qlock(&c->rdl);


M port/ipdat.h => port/ipdat.h +3 -0
@@ 98,6 98,8 @@ struct Ilcb				/* Control block */
{
	int	state;			/* Connection state */

	Rendez	syncer;			/* where syncer waits for a connect */

	QLock	ackq;			/* Unacknowledged queue */
	Block	*unacked;
	Block	*unackedtail;


@@ 247,6 249,7 @@ struct Tcpctl
{
	QLock;
	struct Tctl;
	Rendez syner;
};

struct	Tcp

M port/page.c => port/page.c +24 -14
@@ 103,7 103,7 @@ void
pageinit(void)
{
	ulong np, addr, lim;
	ulong i, vmem, pmem;
	ulong i, vmem, pmem, hw, hr;
	Page *p;

	/*


@@ 150,7 150,15 @@ pageinit(void)
	palloc.user = palloc.freecount = p - palloc.head;
	pmem = palloc.user*BY2PG/1024;
	vmem = pmem + ((conf.nswap)*BY2PG)/1024;
	print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem);

	/* Pageing numbers */
	swapalloc.highwater = (palloc.freecount*5)/100;
	swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
	hw = (swapalloc.highwater*BY2PG)/1024;
	hr = (swapalloc.headroom*BY2PG)/1024;
	
	print("%lud free pages, %dK bytes, swap %dK bytes, highwater %dK, headroom %dK\n", 
				palloc.user, pmem, vmem, hw, hr);
}

Page*


@@ 166,7 174,7 @@ newpage(int clear, Segment **s, ulong va)
	lock(&palloc);

	/* The kp test is a poor guard against the pager deadlocking */
	while((palloc.freecount < HIGHWATER && u->p->kp == 0) || palloc.freecount == 0) {
	while((palloc.freecount < swapalloc.highwater && u->p->kp == 0)||palloc.freecount == 0) {
		palloc.wanted++;
		unlock(&palloc);
		if(s && *s) {


@@ 223,53 231,54 @@ int
ispages(void *p)
{
	USED(p);
	return palloc.freecount >= HIGHWATER;
	return palloc.freecount >= swapalloc.highwater;
}

void
putpage(Page *p)
{
	int count;
	int wake;

	if(onswap(p)) {
		putswap(p);
		return;
	}

	wake = 0;
	lockpage(p);
	if(--p->ref == 0) {
		lock(&palloc);
		if(p->image) {
		if(p->image && p->image != &swapimage) {
			if(palloc.tail) {
				p->prev = palloc.tail;
				palloc.tail->next = p;
				palloc.tail = p;
			}
			else {
				palloc.head = palloc.tail = p;
				palloc.head = p;
				p->prev = 0;
			}
			palloc.tail = p;
			p->next = 0;
		}
		else {
			if(palloc.head) {
				p->next = palloc.head;
				palloc.head->prev = p;
				palloc.head = p;
			}
			else {
				palloc.head = palloc.tail = p;
				palloc.tail = p;
				p->next = 0;
			}
			palloc.head = p;
			p->prev = 0;
		}

		wake = 1;
		palloc.freecount++;		/* Release people waiting for memory */
		unlock(&palloc);
	}
	unlockpage(p);

	if(palloc.wanted)
	if(wake && palloc.wanted)
		wakeup(&palloc.r);
}



@@ 297,8 306,9 @@ duppage(Page *p)				/* Always call with p locked */

	lock(&palloc);

	if(palloc.freecount < HIGHWATER || /* No freelist cache when memory is very low */
	   p->image == &swapimage) {	   /* No dup for swap pages */
	/* No freelist cache when memory is very low, No dup for swap pages */
	if(palloc.freecount < swapalloc.highwater || 
	   p->image == &swapimage) {
		unlock(&palloc);
		uncachepage(p);	
		return;

M port/portdat.h => port/portdat.h +3 -3
@@ 311,6 311,8 @@ struct Swapalloc
	char	*alloc;			/* Round robin allocator */
	char	*top;			/* Top of swap map */
	Rendez	r;			/* Pager kproc idle sleep */
	ulong	highwater;		/* Threshold beyond which we must page */
	ulong	headroom;		/* Space pager attempts to clear below highwater */
}swapalloc;

struct Image


@@ 343,10 345,8 @@ struct Pte
#define SG_SHARED	004
#define SG_PHYSICAL	005
/* Segment flags */
#define SG_RONLY	040		/* Segment is read only */
#define SG_RONLY	040			/* Segment is read only */

#define HIGHWATER	((conf.npage*5)/100)
#define MAXHEADROOM	HIGHWATER*2	/* Silly but OK for debug */
#define PG_ONSWAP	1
#define pagedout(s)	(((ulong)s)==0 || (((ulong)s)&PG_ONSWAP))
#define swapaddr(s)	(((ulong)s)&~PG_ONSWAP)

M port/proc.c => port/proc.c +4 -1
@@ 522,7 522,10 @@ pexit(char *exitstr, int freemem)
	 * if not a kernel process and have a parent,
	 * do some housekeeping.
	 */
	if(c->kp == 0 && (p = c->parent)) {
	if(c->kp == 0) {
		if((p = c->parent) == 0)
			panic("boot process died");
			
		wq = newwaitq();
		wq->w.pid = c->pid;
		utime = c->time[TUser] + c->time[TCUser];

M port/stil.c => port/stil.c +26 -25
@@ 257,8 257,8 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
	dst = nhgetl(ih->src);

	if(ilcksum && ptcl_csum(bp, IL_EHSIZE, illen) != 0) {
		st = (ih->iltype < 0 || ih->iltype > Ilclose) ? "?" : iltype[ih->iltype];
/*		print("il: cksum error, pkt(%s id %lud ack %lud %d.%d.%d.%d/%d->%d)\n",
/*		st = (ih->iltype < 0 || ih->iltype > Ilclose) ? "?" : iltype[ih->iltype];
		print("il: cksum error, pkt(%s id %lud ack %lud %d.%d.%d.%d/%d->%d)\n",
			st, nhgetl(ih->ilid), nhgetl(ih->ilack), fmtaddr(dst), sp, dp); /**/
		goto drop;
	}


@@ 343,24 343,21 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
		default:
			break;
		case Ilsync:
			if(ack != ic->start) {
				ic->state = Ilclosed;
			if(ack != ic->start)
				ilhangup(s, "connection rejected");
			}
			else {
				ic->recvd = id;
				ic->rstart = id;
				ilsendctl(s, 0, Ilack, ic->next, ic->recvd);
				ic->state = Ilestablished;
				wakeup(&ic->syncer);
				ilpullup(s);
				Starttimer(ic);
			}
			break;
		case Ilclose:
			if(ack == ic->start) {
				ic->state = Ilclosed;
			if(ack == ic->start)
				ilhangup(s, "remote close");
			}
			break;
		}
		freeb(bp);


@@ 386,10 383,8 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
			}
			break;
		case Ilclose:
			if(id == ic->next) {
				ic->state = Ilclosed;
			if(id == ic->next)
				ilhangup(s, "remote close");
			}
			break;
		}
		freeb(bp);


@@ 397,10 392,8 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
	case Ilestablished:
		switch(h->iltype) {
		case Ilsync:
			if(id != ic->start) {
				ic->state = Ilclosed;
			if(id != ic->start)
				ilhangup(s, "remote close");
			}
			else {
				ilsendctl(s, 0, Ilack, ic->next, ic->rstart);
				Starttimer(ic);


@@ 458,10 451,8 @@ _ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
		case Ilclose:
			ic->recvd = id;
			ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
			if(ack == ic->next) {
				ic->state = Ilclosed;
			if(ack == ic->next)
				ilhangup(s, 0);
			}
			Starttimer(ic);
			break;
		default:


@@ 522,8 513,14 @@ ilhangup(Ipconv *s, char *msg)
{
	Block *nb;
	int l;
	Ilcb *ic;
	int callout;

	DBG("hangup! %s %d/%d\n", msg ? msg : "??", s->psrc, s->pdst);

	ic = &s->ilctl;
	callout = ic->state == Ilsyncer;
	ic->state = Ilclosed;
	if(s->readq) {
		if(msg) {
			l = strlen(msg);


@@ 537,6 534,8 @@ ilhangup(Ipconv *s, char *msg)
		nb->flags |= S_DELIM;
		PUTNEXT(s->readq, nb);
	}
	if(callout)
		wakeup(&ic->syncer);
	s->psrc = 0;
	s->pdst = 0;
	s->dst = 0;


@@ 697,10 696,8 @@ ilackproc(void *a)
					ilsendctl(s, 0, Ilclose, ic->next, ic->recvd);
					ilbackoff(ic);
				}
				if(ic->timeout >= ic->slowtime) {
					ic->state = Ilclosed;
				if(ic->timeout >= ic->slowtime)
					ilhangup(s, 0);
				}
				break;
			case Ilsyncee:
			case Ilsyncer:


@@ 708,10 705,8 @@ ilackproc(void *a)
					ilsendctl(s, 0, Ilsync, ic->start, ic->recvd);
					ilbackoff(ic);
				}
				if(ic->timeout >= ic->slowtime) {
					ic->state = Ilclosed;
				if(ic->timeout >= ic->slowtime)
					ilhangup(s, etime);
				}
				break;
			case Ilestablished:
				ic->acktime -= Iltickms;


@@ 721,7 716,6 @@ ilackproc(void *a)
				if(ic->querytime <= 0){
					ic->deathtime -= Querytime;
					if(ic->deathtime < 0){
						ic->state = Ilclosed;
						ilhangup(s, etime);
						break;
					}


@@ 737,7 731,6 @@ ilackproc(void *a)
					ilbackoff(ic);
				}
				if(ic->timeout >= ic->slowtime) {
					ic->state = Ilclosed;
					ilhangup(s, etime);
					break;
				}


@@ 756,6 749,11 @@ ilbackoff(Ilcb *ic)
		ic->fasttime = (ic->fasttime)*3/2;
}

static int
notsyncer(void *ic)
{
	return ((Ilcb*)ic)->state != Ilsyncer;
}
void
ilstart(Ipconv *ipc, int type, int window)
{


@@ 783,6 781,9 @@ ilstart(Ipconv *ipc, int type, int window)
	case IL_ACTIVE:
		ic->state = Ilsyncer;
		ilsendctl(ipc, 0, Ilsync, ic->start, ic->recvd);
		sleep(&ic->syncer, notsyncer, ic);
		if(ic->state == Ilclosed)
			error(Etimedout);
		break;
	}
}

D port/stnoether.c => port/stnoether.c +0 -289
@@ 1,289 0,0 @@
/*
 *  ethernet specific multiplexor for nonet
 *
 *  this line discipline gets pushed onto an ethernet channel
 *  to demultiplex/multiplex nonet conversations.
 */
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"
#include	"../port/nonet.h"

#define DPRINT if(pnonet)print
extern int pnonet;

static void	etherparse(uchar*, char*);
static void	noetherclose(Queue*);
static void	noetheriput(Queue*, Block*);
static void	noetheropen(Queue*, Stream*);
static void	noetheroput(Queue*, Block*);

/*
 *  ethernet header of a packet
 */
#define EHDRSIZE 	(ETHERHDRSIZE + NO_HDRSIZE)
#define EMAXBODY	(ETHERMAXTU - EHDRSIZE)	/* maximum ethernet packet body */
#define ETHER_TYPE	0x900	/* most significant byte last */

/*
 *  the ethernet multiplexor stream module definition
 */
Qinfo noetherinfo =
{
	noetheriput,
	noetheroput,
	noetheropen,
	noetherclose,
	"noether"
};

/*
 *  perform the ether specific part of nonetconnect.  just stick
 *  the address into the prototype header.
 */
void
noetherconnect(Noconv *cp, char *ea)
{
	Etherpkt *eh;

	eh = (Etherpkt*)cp->media->rptr;
	etherparse(eh->d, ea);
	eh->type[0] = ETHER_TYPE>>8;
	eh->type[1] = ETHER_TYPE & 0xff;
}

/*
 *  set up an ether interface
 */
static void
noetheropen(Queue *q, Stream *s)
{
	streamenter(s);
	nonetnewifc(q, s, ETHERMAXTU, ETHERMINTU, ETHERHDRSIZE, noetherconnect);
}

/*
 *  tear down an ether interface
 */
static void
noetherclose(Queue *q)
{
	Noifc *ifc;

	ifc = (Noifc*)q->ptr;
	nonetfreeifc(ifc);
}

/*
 *  configure the system
 */
static void
noetheroput(Queue *q, Block *bp)
{
	Noifc *ifc;

	ifc = (Noifc*)q->ptr;
	if(bp->type != M_DATA){
		if(streamparse("config", bp)){
			if(*bp->rptr == 0)
				strcpy(ifc->name, "nonet");
			else
				strncpy(ifc->name, (char *)bp->rptr, sizeof(ifc->name));
		} else
			PUTNEXT(q, bp);
		return;
	}

	PUTNEXT(q, bp);
}

/*
 *  respond to a misaddressed message with a close
 */
void
noetherbad(Noifc *ifc, Block *bp, int circuit)
{
	Etherpkt *eh, *neh;
	Nohdr *nh, *nnh;
	Block *nbp;
	int r;
	Noconv *cp, *ep;

	/*
	 *  crack the packet header
	 */
	eh = (Etherpkt*)bp->rptr;
	nh = (Nohdr*)eh->data;
/*	print("bad %.2ux%.2ux%.2ux%.2ux%.2ux%.2ux c %d m %d f %d\n",
		eh->s[0], eh->s[1], eh->s[2], eh->s[3], eh->s[4],
		eh->s[5], circuit, nh->mid, nh->flag); /**/
	if(nh->flag & NO_RESET)
		goto out;

	/*
	 *  only one reset per message
	 */
	r = (nh->remain[1]<<8) | nh->remain[0];
	if(r<0)
		goto out;

	/*
	 *  craft an error reply
	 */
/*	print("sending reset\n"); /**/
	nbp = allocb(60);
	nbp->flags |= S_DELIM;
	nbp->wptr = nbp->rptr + 60;
	memset(bp->rptr, 0, 60);
	neh = (Etherpkt *)nbp->rptr;
	nnh = (Nohdr*)neh->data;
	memmove(neh, eh, EHDRSIZE);
	nnh->circuit[0] ^= 1;
	nnh->remain[0] = nnh->remain[1] = 0;
	nnh->flag = NO_HANGUP | NO_RESET;
	nnh->ack = nh->mid;
	nnh->mid = nh->ack;
	memmove(neh->s, eh->d, sizeof(neh->s));
	memmove(neh->d, eh->s, sizeof(neh->d));
	nonetcksum(nbp, ETHERHDRSIZE);
	PUTNEXT(ifc->wq, nbp);
out:
	freeb(bp);
}

/*
 *  Input a packet and use the ether address to select the correct
 *  nonet device to pass it to.
 *
 *  Simplifying assumption:  one put == one packet && the complete header
 *	is in the first block.  If this isn't true, demultiplexing will not work.
 */
static void
noetheriput(Queue *q, Block *bp)
{
	Noifc *ifc;
	int circuit;
	Noconv *cp, *ep;
	Etherpkt *eh, *peh;
	Nohdr *nh;
	ulong s;
	Block *nbp;
	int next;
	Nocall *clp;

	if(bp->type != M_DATA){
		PUTNEXT(q, bp);
		return;
	}

	ifc = (Noifc*)q->ptr;
	eh = (Etherpkt*)bp->rptr;
	nh = (Nohdr*)eh->data;
	circuit = (nh->circuit[2]<<16) | (nh->circuit[1]<<8) | nh->circuit[0];
	s = (nh->sum[1]<<8) | nh->sum[0];
	if(s && s!=nonetcksum(bp, ETHERHDRSIZE)){
		print("checksum error %ux %ux\n", s, (nh->sum[1]<<8) | nh->sum[0]); /**/
		freeb(bp);
		return;
	}

	/*
	 *  look for an existing circuit.
	 */
	ep = &ifc->conv[conf.nnoconv];
	for(cp = &ifc->conv[0]; cp < ep; cp++){
		nbp = cp->media;
		if(nbp == 0)
			continue;
		peh = (Etherpkt*)nbp->rptr;
		if(circuit==cp->rcvcircuit && memcmp(peh->d, eh->s, sizeof(eh->s))==0){
			if(!canqlock(cp)){
				freeb(bp);
				return;
			}
			peh = (Etherpkt*)nbp->rptr;
			if(circuit==cp->rcvcircuit
			&& memcmp(peh->d, eh->s, sizeof(eh->s))==0){
				bp->rptr += ifc->hsize;
				nonetrcvmsg(cp, bp);
				qunlock(cp);
				return;
			}
			qunlock(cp);
		}
	}

	/*
	 *  if not a new call, then its misaddressed
	 */
	if((nh->flag & NO_NEWCALL) == 0 || nh->mid != 1){
		noetherbad(ifc, bp, circuit);
		return;
	}

	/*
	 *  Queue call in a circular queue and wakeup a listener.
	 */
	lock(&ifc->lock);
	next = (ifc->wptr + 1) % Nnocalls;
	if(next == ifc->rptr){
		/* no room in the queue */
		unlock(&ifc->lock);
		freeb(bp);
		return;
	}
	clp = &ifc->call[ifc->wptr];
	sprint(clp->raddr, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux",
		eh->s[0], eh->s[1], eh->s[2], eh->s[3], eh->s[4], eh->s[5]);
	clp->circuit = circuit^1;
	bp->rptr += ifc->hsize;
	clp->msg = bp;
	ifc->wptr = next;
	unlock(&ifc->lock);
	wakeup(&ifc->listenr);
	DPRINT("call from %s wptr %d\n", clp->raddr, ifc->wptr);
}

/*
 *  parse an ethernet address (assumed to be 12 ascii hex digits)
 */
static void
etherparse(uchar *to, char *from)
{
	ulong ip;
	uchar nip[4];
	int tdig;
	int fdig;
	int i;

#ifdef MAGNUM
	/* Dot means ip address */
	if(strchr(from, '.')) {
		ip = ipparse(from);
		if(ip == 0)
			error(Enetaddr);

		hnputl(nip, ip);			
		if(arp_lookup(nip, to))
			return;
	}
#endif

	if(strlen(from) != 12)
		error(Enetaddr);

	for(i = 0; i < 6; i++){
		fdig = (*from++)&0x7f;
		tdig = fdig >= 'a' ? ((fdig - 'a') + 10)
				: (fdig >= 'A' ? ((fdig - 'A') + 10) : (fdig - '0'));
		fdig = (*from++)&0x7f;
		tdig <<= 4;
		tdig |= fdig >= 'a' ? ((fdig - 'a') + 10)
				: (fdig >= 'A' ? ((fdig - 'A') + 10) : (fdig - '0'));
		*to++ = tdig;
	}
}

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

/*
 *  reboot stream module definition
 */
static void rebootopen(Queue*, Stream*);
static void rebootiput(Queue*, Block*);
static void rebootoput(Queue*, Block*);
static void rebootreset(void);
Qinfo rebootinfo =
{
	rebootiput,
	rebootoput,
	rebootopen,
	0,
	"reboot",
	0
};

static void
rebootopen(Queue *q, Stream *s)
{
	USED(q);
	if(strcmp(u->p->user, eve) != 0)
		error(Eperm);
}

void
rebootoput(Queue *q, Block *bp)
{
	PUTNEXT(q, bp);
}

static void
rebootiput(Queue *q, Block *bp)
{
	if(bp->type == M_HANGUP){
		print("lost connection to fs, rebooting");
		exit();
	}
	PUTNEXT(q, bp);
}

M port/swap.c => port/swap.c +55 -53
@@ 15,9 15,11 @@ int	canflush(Proc *p, Segment*);

enum
{
	Maxpages = 100,		/* Max number of pageouts per segment pass */
	Maxpages = 500,		/* Max number of pageouts per segment pass */
};

#define DBG	if(1)print

Image 	swapimage;
static 	int swopen;
Page	*iolist[Maxpages];


@@ 103,43 105,49 @@ pager(void *junk)
	Segment *s;
	int i;

	if(waserror()) 
		panic("pager: os error\n");

	USED(junk);
	p = proctab(0);
	ep = &p[conf.nproc];
	for(;;) {
		if(waserror()) 
			panic("pager: os error\n");

		u->p->psstate = "Idle";
		sleep(&swapalloc.r, needpages, 0);
		u->p->psstate = "Pageout";
loop:
	u->p->psstate = "Idle";
	sleep(&swapalloc.r, needpages, 0);
	u->p->psstate = "Pageout";

		for(p = proctab(0); p < ep; p++) {
			if(p->state == Dead || p->kp)
				continue;
	for(;;) {
		p++;
		if(p > ep)
			p = proctab(0);

			if(swapimage.c) {
				for(i = 0; i < NSEG; i++)
					if(s = p->seg[i]) {
						pageout(p, s);
						executeio();
					}
			}
			else 
			if(palloc.freecount < HIGHWATER) {
				/* Rob made me do it ! */
				if(conf.cntrlp == 0)
					freebroken();

				/* Emulate the old system if no swap channel */
				print("no physical memory\n");
				tsleep(&swapalloc.r, return0, 0, 1000);
				wakeup(&palloc.r);
		if(p->state == Dead || p->kp)
			continue;

		if(swapimage.c) {
			for(i = 0; i < NSEG; i++) {
				if(!needpages(junk))
					goto loop;
				if(s = p->seg[i]) {
					pageout(p, s);
					executeio();
				}
			}
		}

		poperror();
		else 
		if(palloc.freecount < swapalloc.highwater) {
			/* Rob made me do it ! */
			if(conf.cntrlp == 0)
				freebroken();

			/* Emulate the old system if no swap channel */
			print("no physical memory\n");
			tsleep(&swapalloc.r, return0, 0, 1000);
			wakeup(&palloc.r);
		}
	}
	goto loop;
}

void			


@@ 147,13 155,20 @@ pageout(Proc *p, Segment *s)
{
	Pte **sm, **endsm, *l;
	Page **pg, *entry;
	int type;
	int type, nr;
extern char *sname[];


	if(!canqlock(&s->lk))	/* We cannot afford to wait, we will surely deadlock */
		return;

	if(!canflush(p, s) || s->steal) {
	if(s->steal) {
		qunlock(&s->lk);
		putseg(s);
		return;
	}

	if(!canflush(p, s)) {
		qunlock(&s->lk);
		putseg(s);
		return;


@@ 166,6 181,7 @@ extern char *sname[];
	}

	scavenge = 0;
	nr = 0;

	/* Pass through the pte tables looking for memory pages to swap out */
	type = s->type&SG_TYPE;


@@ 175,13 191,13 @@ extern char *sname[];
		if(l == 0)
			continue;
		for(pg = l->first; pg < l->last; pg++) {
			nr++;
			entry = *pg;
			if(pagedout(entry))
				continue;
			if(entry->modref & PG_REF) {
				print("MODREF\n");

			if(entry->modref & PG_REF)
				entry->modref &= ~PG_REF;
			}
			else 
				pagepte(type, s, pg);



@@ 190,8 206,9 @@ extern char *sname[];
		}
	}
out:
	
	print("%s: %d: type %s %d pages\n", p->text, p->pid, sname[type], scavenge);
	DBG("%s: %d: %5s s %d nr %d fr %d\n", 
	p->text, p->pid, sname[type], scavenge, nr, palloc.freecount);

	poperror();
	qunlock(&s->lk);
	putseg(s);


@@ 235,14 252,9 @@ int
pagepte(int type, Segment *s, Page **pg)
{
	ulong daddr;
	char *kaddr;
	int n;
	Chan *c;
	Page *outp;
	KMap *k;

	outp = *pg;
print("outp: %lux\n", *pg);
	switch(type) {
	case SG_TEXT:					/* Revert to demand load */
		putpage(outp);


@@ 290,17 302,7 @@ executeio(void)

	for(i = 0; i < ioptr; i++) {
		out = iolist[i];
#ifdef asdf
		if(out->ref > 2) {
			lockpage(out);
			if(out->ref > 2) {	
				out->ref -= 2;
				unlockpage(out);
				continue;
			}
			unlockpage(out);
		}
#endif

		k = kmap(out);
		kaddr = (char*)VA(k);
		qlock(&c->wrl);


@@ 330,7 332,7 @@ int
needpages(void *p)
{
	USED(p);
	return palloc.freecount < HIGHWATER+MAXHEADROOM;
	return palloc.freecount < swapalloc.headroom;
}

void

M port/tcpif.c => port/tcpif.c +12 -0
@@ 15,6 15,7 @@ state_upcall(Ipconv *s, char oldstate, char newstate)
{
	Block *bp;
	int len;
	Tcpctl *tcb = &s->tcpctl;

	DPRINT("state_upcall: %s -> %s err %s\n", 
	      tcpstate[oldstate], tcpstate[newstate], s->err);


@@ 48,8 49,16 @@ state_upcall(Ipconv *s, char oldstate, char newstate)
		qunlock(s);
		break;
	}

	if(oldstate == Syn_sent)
		wakeup(&tcb->syner);
}

static int
notsyner(void *ic)
{
	return ((Tcpctl*)ic)->state != Syn_sent;
}
void
tcpstart(Ipconv *s, int mode, ushort window, char tos)
{


@@ 76,6 85,9 @@ tcpstart(Ipconv *s, int mode, ushort window, char tos)
		setstate(s, Syn_sent);
		tcp_output(s);
		qunlock(tcb);
		sleep(&tcb->syner, notsyner, tcb);
		if(tcb->state != Established && tcb->state != Syn_received)
			error(Etimedout);
		break;
	}
}