~kris/9p

9hist

695a5b658a3e53ec57700c5b0d06b987f6601d2b — David du Colombier 28 years ago 68733b6
Plan 9 from Bell Labs 1998-06-05
14 files changed, 258 insertions(+), 216 deletions(-)

M pc/apic.c
M pc/dat.h
M pc/etherelnk3.c
M pc/l.s
M pc/main.c
M pc/mmu.c
M pc/mp.c
M pc/trap.c
M port/page.c
M port/portdat.h
M port/portfns.h
M port/proc.c
M port/qio.c
M port/taslock.c
M pc/apic.c => pc/apic.c +10 -0
@@ 154,6 154,7 @@ lapicinit(Apic* apic)
	lapicw(LapicSVR, LapicENABLE|VectorSPURIOUS);

	clkin = lapictimerinit();

	/*
	 * Some Pentium revisions have a bug whereby spurious
	 * interrupts are generated in the through-local mode.


@@ 165,8 166,17 @@ lapicinit(Apic* apic)
		wrmsr(0x0E, 1<<14);		/* TR12 */
		break;
	}

	/*
	 * Set the local interrupts. It's likely these should just be
	 * masked off for SMP mode as some Pentium Pros have problems if
	 * LINT[01] are set to ExtINT.
	 * Acknowledge any outstanding interrupts.
	lapicw(LapicLINT0, apic->lintr[0]);
	lapicw(LapicLINT1, apic->lintr[1]);
	 */
	lapiceoi(0);

	lvt = (lapicr(LapicVER)>>16) & 0xFF;
	if(lvt >= 4)
		lapicw(LapicPCINT, ApicIMASK);

M pc/dat.h => pc/dat.h +1 -1
@@ 13,9 13,9 @@ typedef struct Pcidev	Pcidev;
typedef struct PCMmap	PCMmap;
typedef struct Page	Page;
typedef struct PMMU	PMMU;
typedef struct Proc	Proc;
typedef struct Segdesc	Segdesc;
typedef struct Ureg	Ureg;
typedef struct Proc	Proc;

/*
 *  parameters for sysproc.c

M pc/etherelnk3.c => pc/etherelnk3.c +15 -16
@@ 1435,14 1435,14 @@ setfullduplex(int port)
}

static int
miir(Ether* ether, int phyad, int regad)
miir(int port, int phyad, int regad)
{
	int data, i, port, w, x;

	port = ether->port+PhysicalMgmt;
	int data, i, w, x;

	w = (STATUS(port)>>13) & 0x07;
	COMMAND(ether->port, SelectRegisterWindow, Wdiagnostic);
	COMMAND(port, SelectRegisterWindow, Wdiagnostic);

	port += PhysicalMgmt;

	/*
	 * Taken from the Cyclone manual appendix describing


@@ 1505,26 1505,26 @@ miir(Ether* ether, int phyad, int regad)
	microdelay(1);
	outs(port, mgmtClk);

	COMMAND(ether->port, SelectRegisterWindow, w);
	port -= PhysicalMgmt;
	COMMAND(port, SelectRegisterWindow, w);

	if(data & 0x10000)
		return -1;
print("%d/%d: data=%uX\n", phyad, regad, data);

	return data & 0xFFFF;
}

static void
scanphy(Ether* ether)
scanphy(int port)
{
	int i, x;

	for(i = 0; i < 32; i++){
		if((x = miir(ether, i, 2)) == -1)
		if((x = miir(port, i, 2)) == -1 || x == 0)
			continue;
		x <<= 6;
		x |= miir(ether, i, 3)>>10;
		XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(ether, i, 1));
		x |= miir(port, i, 3)>>10;
		XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
		USED(x);
	}
}


@@ 1748,17 1748,17 @@ if(did == 0x9055)
else
	if(xcvr & autoSelect)
		xcvr = autoselect(port, xcvr, rxstatus9);
	XCVRDEBUG("autoselect returns: xcvr %uX\n", xcvr);
	XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
	switch(xcvr){

	case xcvrMii:
		/*
		 * Quick hack.
		scanphy(ether);
		scanphy(port);
		 */
		phyaddr = 24;
		an = miir(ether, phyaddr, 0x04);
		an &= miir(ether, phyaddr, 0x05) & 0x03E0;
		an = miir(port, phyaddr, 0x04);
		an &= miir(port, phyaddr, 0x05) & 0x03E0;
		XCVRDEBUG("mii an: %uX\n", an);
		for(i = 0; i < ether->nopt; i++){
			if(cistrcmp(ether->opt[i], "fullduplex") == 0)


@@ 1869,7 1869,6 @@ else
		 */
		ctlr->upenabled = 1;
		x = eepromdata(port, 0x0F);
		//print("software info 2: %uX\n", x);
		if(!(x & 0x01))
			outl(port+PktStatus, upRxEarlyEnable);


M pc/l.s => pc/l.s +1 -0
@@ 142,6 142,7 @@ _clearbss:
 */
TEXT idle(SB), $0
_idle:
	STI
	HLT
	JMP	_idle


M pc/main.c => pc/main.c +10 -0
@@ 542,6 542,16 @@ procsave(Proc *p)
			fpsave(&up->fpsave);
		p->fpstate = FPinactive;
	}

	/*
	 * Switch to the prototype page tables for this processor.
	 * While this processor is in the scheduler, the process could run
	 * on another processor and exit, returning the page tables to
	 * the free list where they could be reallocated and overwritten.
	 * When this processor eventually has to get an entry from the
	 * trashed page tables it will crash.
	 */
	mmuflushtlb(PADDR(m->pdb));
}

void

M pc/mmu.c => pc/mmu.c +65 -76
@@ 24,7 24,7 @@ Segdesc gdt[6] =
#define PTX(va)		((((ulong)(va))>>12) & 0x03FF)

static void
taskswitch(ulong pagetbl, ulong stack)
taskswitch(ulong pdb, ulong stack)
{
	Tss *tss;



@@ 35,8 35,8 @@ taskswitch(ulong pagetbl, ulong stack)
	tss->esp1 = stack;
	tss->ss2 = KDSEL;
	tss->esp2 = stack;
	tss->cr3 = pagetbl;
	putcr3(pagetbl);
	tss->cr3 = pdb;
	putcr3(pdb);
}

void


@@ 81,126 81,115 @@ flushmmu(void)
}

static void
mmuptefree(Proc* p)
mmuptefree(Proc* proc)
{
	ulong *pdb;
	Page **lpg, *pg;

	if(p->mmupdb && p->mmuused){
		pdb = (ulong*)p->mmupdb->va;
		lpg = &p->mmuused;
		for(pg = *lpg; pg; pg = pg->next){
			pdb[pg->daddr] = 0;
			lpg = &pg->next;
	Page **last, *page;

	if(proc->mmupdb && proc->mmuused){
		pdb = (ulong*)proc->mmupdb->va;
		last = &proc->mmuused;
		for(page = *last; page; page = page->next){
			pdb[page->daddr] = 0;
			last = &page->next;
		}
		*lpg = p->mmufree;
		p->mmufree = p->mmuused;
		p->mmuused = 0;
		*last = proc->mmufree;
		proc->mmufree = proc->mmuused;
		proc->mmuused = 0;
	}
}

void
mmuswitch(Proc* p)
mmuswitch(Proc* proc)
{
	ulong *top;
	ulong *pdb;

	if(p->newtlb){
		mmuptefree(p);
		p->newtlb = 0;
	if(proc->newtlb){
		mmuptefree(proc);
		proc->newtlb = 0;
	}

	if(p->mmupdb){
		top = (ulong*)p->mmupdb->va;
		top[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
		taskswitch(p->mmupdb->pa, (ulong)(p->kstack+KSTACK));
	if(proc->mmupdb){
		pdb = (ulong*)proc->mmupdb->va;
		pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
		taskswitch(proc->mmupdb->pa, (ulong)(proc->kstack+KSTACK));
	}
	else
		taskswitch(PADDR(m->pdb), (ulong)(p->kstack+KSTACK));
		taskswitch(PADDR(m->pdb), (ulong)(proc->kstack+KSTACK));
}

void
mmurelease(Proc* p)
mmurelease(Proc* proc)
{
	Page *pg, *next;
	Page *page, *next;

	/*
	 * Release any pages allocated for a page directory base or page-tables
	 * for this process:
	 *   switch to the prototype pdb for this processor (m->pdb);
	 *   call mmuptefree() to place all pages used for page-tables (p->mmuused)
	 *   onto the process' free list (p->mmufree). This has the side-effect of
	 *   cleaning any user entries in the pdb (p->mmupdb);
	 *   call mmuptefree() to place all pages used for page-tables (proc->mmuused)
	 *   onto the process' free list (proc->mmufree). This has the side-effect of
	 *   cleaning any user entries in the pdb (proc->mmupdb);
	 *   if there's a pdb put it in the cache of pre-initialised pdb's
	 *   for this processor (m->pdbpool) or on the process' free list;
	 *   finally, place any pages freed back into the free pool (palloc).
	 * This routine is only called from sched() with palloc locked.
	 */
	taskswitch(PADDR(m->pdb), (ulong)m + BY2PG);
	mmuptefree(p);
	mmuptefree(proc);

	if(p->mmupdb){
	if(proc->mmupdb){
		if(m->pdbcnt > 10){
			p->mmupdb->next = p->mmufree;
			p->mmufree = p->mmupdb;
			proc->mmupdb->next = proc->mmufree;
			proc->mmufree = proc->mmupdb;
		}
		else{
			p->mmupdb->next = m->pdbpool;
			m->pdbpool = p->mmupdb;
			proc->mmupdb->next = m->pdbpool;
			m->pdbpool = proc->mmupdb;
			m->pdbcnt++;
		}
		p->mmupdb = 0;
		proc->mmupdb = 0;
	}

	for(pg = p->mmufree; pg; pg = next){
		next = pg->next;
		if(--pg->ref)
			panic("mmurelease: pg->ref %d\n", pg->ref);
		pg->ref = 0;
		if(palloc.head){
			pg->next = palloc.head;
			palloc.head->prev = pg;
		}
		else{
			palloc.tail = pg;
			pg->next = 0;
		}
		palloc.head = pg;
		pg->prev = 0;

		palloc.freecount++;
	for(page = proc->mmufree; page; page = next){
		next = page->next;
		if(--page->ref)
			panic("mmurelease: page->ref %d\n", page->ref);
		pagechainhead(page);
	}
	if(p->mmufree && palloc.r.p)
	if(proc->mmufree && palloc.r.p)
		wakeup(&palloc.r);
	p->mmufree = 0;
	proc->mmufree = 0;
}

static Page*
mmupdballoc(void)
{
	int s;
	Page *pg;
	Page *page;

	s = splhi();
	if(m->pdbpool == 0){
		spllo();
		pg = newpage(0, 0, 0);
		pg->va = VA(kmap(pg));
		memmove((void*)pg->va, m->pdb, BY2PG);
		page = newpage(0, 0, 0);
		page->va = VA(kmap(page));
		memmove((void*)page->va, m->pdb, BY2PG);
	}
	else{
		pg = m->pdbpool;
		m->pdbpool = pg->next;
		page = m->pdbpool;
		m->pdbpool = page->next;
		m->pdbcnt--;
	}
	splx(s);
	return pg;
	return page;
}

void
putmmu(ulong va, ulong pa, Page* pg)
putmmu(ulong va, ulong pa, Page*)
{
	int pdbx;
	ulong *pdb, *pt;
	Page *page;
	ulong *pdb, *pte;
	int s;

	if(up->mmupdb == 0)


@@ 210,22 199,22 @@ putmmu(ulong va, ulong pa, Page* pg)

	if(PPN(pdb[pdbx]) == 0){
		if(up->mmufree == 0){
			pg = newpage(1, 0, 0);
			pg->va = VA(kmap(pg));
			page = newpage(1, 0, 0);
			page->va = VA(kmap(page));
		}
		else {
			pg = up->mmufree;
			up->mmufree = pg->next;
			memset((void*)pg->va, 0, BY2PG);
			page = up->mmufree;
			up->mmufree = page->next;
			memset((void*)page->va, 0, BY2PG);
		}
		pdb[pdbx] = PPN(pg->pa)|PTEUSER|PTEWRITE|PTEVALID;
		pg->daddr = pdbx;
		pg->next = up->mmuused;
		up->mmuused = pg;
		pdb[pdbx] = PPN(page->pa)|PTEUSER|PTEWRITE|PTEVALID;
		page->daddr = pdbx;
		page->next = up->mmuused;
		up->mmuused = page;
	}

	pt = KADDR(PPN(pdb[pdbx]));
	pt[PTX(va)] = pa|PTEUSER;
	pte = KADDR(PPN(pdb[pdbx]));
	pte[PTX(va)] = pa|PTEUSER;

	s = splhi();
	pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];

M pc/mp.c => pc/mp.c +12 -31
@@ 271,7 271,15 @@ mklintr(PCMPintr* p)
	if((bus = mpgetbus(p->busno)) == 0)
		return 0;
	intin = p->intin;
	v = mpintrinit(bus, p, VectorLAPIC+intin);

	/*
	 * Pentium Pros have problems if LINT[01] are set to ExtINT
	 * so just bag it. Should be OK for SMP mode.
	 */
	if(p->intr == PcmpExtINT || p->intr == PcmpNMI)
		v = ApicIMASK;
	else
		v = mpintrinit(bus, p, VectorLAPIC+intin);

	if(p->apicno == 0xFF){
		for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){


@@ 446,21 454,6 @@ mpstartap(Apic* apic)
	nvramwrite(0x0F, 0x00);
}

static void
senddbgnmi(void)
{
	/*
	 * NMI all excluding self.
	 */
	lapicicrw(0, 0x000C0000|ApicNMI);
}

static void
mpdbg(Ureg* ureg, void*)
{
	iprint("MPDBG: cpu%d: PC 0x%uX\n", m->machno, ureg->pc);
}

void
mpinit(void)
{


@@ 568,9 561,6 @@ mpinit(void)
	 */
	if(conf.nmach > 1)
		conf.copymode = 1;

	consdebug = senddbgnmi;
	intrenable(VectorNMI, mpdbg, 0, BUSUNKNOWN);
}

static int


@@ 695,34 685,25 @@ mpintrenable(int v, int tbdf, Irqctl* irqctl)
	return -1;
}

static Lock mpshutdownlock;

void
mpshutdown(void)
{
	int apicno, machno;

	/*
	 * To be done...
	 */
	if(m->machno){
	if(!canlock(&mpshutdownlock)){
		/*
		 * If this processor received the CTRL-ALT-DEL from
		 * the keyboard, acknowledge it. Send an INIT to self.
		 */
		if(lapicisr(VectorKBD))
			lapiceoi(VectorKBD);
		lapicicrw(0, 0x00040000|ApicINIT);	
		idle();
	}

	print("apshutdown: active = 0x%2.2uX\n", active.machs);
	if(active.machs){
		for(machno = 1; machno < conf.nmach; machno++){
			if(!(active.machs & (1<<machno)))
				continue;
			apicno = machno2apicno[machno];
			lapicicrw(1<<apicno, ApicNMI);
		}
	}
	delay(1000);
	splhi();


M pc/trap.c => pc/trap.c +5 -0
@@ 171,6 171,7 @@ trap(Ureg* ureg)
			sched();
			splhi();
			up->preempted = 0;
			return;
		}
	}
	else if(v <= 16 && user){


@@ 418,6 419,10 @@ syscall(Ureg* ureg)
		splhi();
		notify(ureg);
	}
	if (up->nlocks != 0) {
		print("nlock = %d\n", up->nlocks);
		up->nlocks = 0;
	}
}

/*

M port/page.c => port/page.c +65 -71
@@ 7,7 7,6 @@

#define	pghash(daddr)	palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]

static	Lock pglock;
struct	Palloc palloc;

void


@@ 63,6 62,59 @@ pageinit(void)
	print("%dK swap\n", vm);
}

static void
pageunchain(Page *p)
{
	if(canlock(&palloc))
		panic("pageunchain");
	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	p->prev = p->next = nil;
	palloc.freecount--;
}

void
pagechaintail(Page *p)
{
	if(canlock(&palloc))
		panic("pagechaintail");
	if(palloc.tail) {
		p->prev = palloc.tail;
		palloc.tail->next = p;
	}
	else {
		palloc.head = p;
		p->prev = 0;
	}
	palloc.tail = p;
	p->next = 0;
	palloc.freecount++;
}

void
pagechainhead(Page *p)
{
	if(canlock(&palloc))
		panic("pagechainhead");
	if(palloc.head) {
		p->next = palloc.head;
		palloc.head->prev = p;
	}
	else {
		palloc.tail = p;
		p->next = 0;
	}
	palloc.head = p;
	p->prev = 0;
	palloc.freecount++;
}

Page*
newpage(int clear, Segment **s, ulong va)
{


@@ 71,7 123,6 @@ newpage(int clear, Segment **s, ulong va)
	uchar ct;
	int i, hw, dontalloc, color;


	lock(&palloc);
	color = getpgcolor(va);
	hw = swapalloc.highwater;


@@ 124,15 175,7 @@ newpage(int clear, Segment **s, ulong va)
		ct = PG_NEWCOL;
	}

	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	palloc.freecount--;
	pageunchain(p);

	lock(p);
	if(p->ref != 0)


@@ 178,31 221,10 @@ putpage(Page *p)
		return;
	}

	if(p->image && p->image != &swapimage) {
		if(palloc.tail) {
			p->prev = palloc.tail;
			palloc.tail->next = p;
		}
		else {
			palloc.head = p;
			p->prev = 0;
		}
		palloc.tail = p;
		p->next = 0;
	}
	else {
		if(palloc.head) {
			p->next = palloc.head;
			palloc.head->prev = p;
		}
		else {
			palloc.tail = p;
			p->next = 0;
		}
		palloc.head = p;
		p->prev = 0;
	}
	palloc.freecount++;
	if(p->image && p->image != &swapimage)
		pagechaintail(p);
	else 
		pagechainhead(p);

	if(palloc.r.p != 0)
		wakeup(&palloc.r);


@@ 222,9 244,7 @@ auxpage()
		unlock(&palloc);
		return 0;
	}
	p->next->prev = 0;
	palloc.head = p->next;
	palloc.freecount--;
	pageunchain(p);

	lock(p);
	if(p->ref != 0)


@@ 246,8 266,9 @@ duppage(Page *p)				/* Always call with p locked */

	retries = 0;
retry:

	if(retries++ > 10000)
		panic("duppage");
		panic("duppage %d", retries);

	/* No dup for swap/cache pages */
	if(p->ref == 0 || p->image == nil || p->image->notext)


@@ 286,26 307,8 @@ retry:
		return;
	}

	if(np->prev)
		np->prev->next = np->next;
	else
		palloc.head = np->next;
	if(np->next)
		np->next->prev = np->prev;
	else
		palloc.tail = np->prev;

	/* Link back onto tail to give us lru in the free list */
	if(palloc.tail) {
		np->prev = palloc.tail;
		palloc.tail->next = np;
		np->next = 0;
		palloc.tail = np;
	}
	else {
		palloc.head = palloc.tail = np;
		np->prev = np->next = 0;
	}
	pageunchain(np);
	pagechaintail(np);

	lock(np);
	unlock(&palloc);


@@ 411,17 414,8 @@ lookpage(Image *i, ulong daddr)
				unlock(&palloc);
				return 0;
			}
			if(++f->ref == 1) {
				if(f->prev)
					f->prev->next = f->next;
				else
					palloc.head = f->next;
				if(f->next)
					f->next->prev = f->prev;
				else
					palloc.tail = f->prev;
				palloc.freecount--;
			}
			if(++f->ref == 1)
				pageunchain(f);
			unlock(&palloc);
			unlock(f);


M port/portdat.h => port/portdat.h +2 -1
@@ 536,7 536,6 @@ struct Proc
	QLock	*qlock;		/* addrof qlock being queued for DEBUG */
	int	state;
	char	*psstate;	/* What /proc/#/status reports */
	Page	*upage;		/* page from palloc */
	Segment	*seg[NSEG];
	ulong	pid;
	ulong	noteid;		/* Equivalent of note group */


@@ 602,6 601,8 @@ struct Proc
	Note	lastnote;
	int	(*notify)(void*, char*);

	int	nlocks;		/* Number of locks held */

	Mach	*wired;
	Mach	*mp;		/* machine this process last ran on */
	ulong	priority;	/* priority level */

M port/portfns.h => port/portfns.h +1 -0
@@ 170,6 170,7 @@ int		nrand(int);
int		okaddr(ulong, ulong, int);
int		openmode(ulong);
Block*		padblock(Block*, int);
void		pagechainhead(Page*);
void		pageinit(void);
void		panic(char*, ...);
int		parseether(uchar*, char*);

M port/proc.c => port/proc.c +3 -1
@@ 66,6 66,7 @@ schedinit(void)		/* never returns */
			/*
			 * Holding locks from pexit:
			 * 	procalloc
			 *	palloc
			 */
			mmurelease(up);



@@ 330,6 331,7 @@ newproc(void)
		panic("pidalloc");
	if(p->kstack == 0)
		p->kstack = smalloc(KSTACK);
	p->nlocks = 0;

	return p;
}


@@ 812,7 814,7 @@ pexit(char *exitstr, int freemem)
	}
	qunlock(&up->debug);

	/* Sched must not loop for this lock */
	/* Sched must not loop for these locks */
	lock(&procalloc);
	lock(&palloc);


M port/qio.c => port/qio.c +41 -17
@@ 19,7 19,7 @@ static ulong consumecnt;
static ulong producecnt;
static ulong qcopycnt;

static int debuging;
static int debugging;

#define QDEBUG	if(0)



@@ 62,15 62,24 @@ enum
	Qflow		= (1<<3),

	Hdrspc		= 64,		/* leave room for high-level headers */

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

void
checkb(Block *b, char *msg)
{
	void *dead = (void*)0xDEADBABE;
	void *dead = (void*)Bdead;

	if(b == dead)
		panic("checkb b %s %lux", msg, b);
	if(b->base == dead || b->lim == dead || b->next == dead
	  || b->rp == dead || b->wp == dead){
		print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
			b->base, b->lim, b->next);
		print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
		panic("checkb dead: %s\n", msg);
	}

	if(b->base > b->lim)
		panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);


@@ 83,20 92,13 @@ checkb(Block *b, char *msg)
	if(b->wp > b->lim)
		panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);

	if(b->base == dead || b->lim == dead || b->next == dead
	  || b->rp == dead || b->wp == dead){
		print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
			b->base, b->lim, b->next);
		print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
		panic("checkb dead: %s\n", msg);
	}
}

void
ixsummary(void)
{
	debuging ^= 1;
	print("ialloc %d/%d %d\n", ialloc.bytes, conf.ialloc, debuging);
	debugging ^= 1;
	print("ialloc %d/%d %d\n", ialloc.bytes, conf.ialloc, debugging);
	print("pad %lud, concat %lud, pullup %lud, copy %lud\n",
		padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt);
	print("consume %lud, produce %lud, qcopy %lud\n",


@@ 177,6 179,8 @@ iallocb(int size)
void
freeb(Block *b)
{
	void *dead = (void*)Bdead;

	/*
	 * drivers which perform non cache coherent DMA manage their own buffer
	 * pool of uncached buffers and provide their own free routine.


@@ 192,11 196,11 @@ freeb(Block *b)
	}

	/* poison the block in case someone is still holding onto it */
	b->next = (void*)0xdeadbabe;
	b->rp = (void*)0xdeadbabe;
	b->wp = (void*)0xdeadbabe;
	b->lim = (void*)0xdeadbabe;
	b->base = (void*)0xdeadbabe;
	b->next = dead;
	b->rp = dead;
	b->wp = dead;
	b->lim = dead;
	b->base = dead;

	free(b);
}


@@ 225,12 229,15 @@ padblock(Block *bp, int size)
	int n;
	Block *nbp;

	QDEBUG checkb(bp, "padblock 1");
	if(size >= 0){
		if(bp->rp - bp->base >= size){
			bp->rp -= size;
			return bp;
		}

		if(bp->next)
			panic("padblock 0x%uX", getcallerpc(bp));
		n = BLEN(bp);
		padblockcnt++;
		nbp = allocb(size+n);


@@ 246,6 253,8 @@ padblock(Block *bp, int size)
		if(bp->lim - bp->wp >= size)
			return bp;

		if(bp->next)
			panic("padblock 0x%uX", getcallerpc(bp));
		n = BLEN(bp);
		padblockcnt++;
		nbp = allocb(size+n);


@@ 253,6 262,7 @@ padblock(Block *bp, int size)
		nbp->wp += n;
		freeb(bp);
	}
	QDEBUG checkb(nbp, "padblock 1");
	return nbp;
}



@@ 293,6 303,7 @@ concatblock(Block *bp)
	}
	concatblockcnt += BLEN(nb);
	freeblist(bp);
	QDEBUG checkb(nb, "concatblock 1");
	return nb;
}



@@ 333,6 344,7 @@ pullupblock(Block *bp, int n)
			pullupblockcnt++;
			bp->wp += n;
			nbp->rp += n;
			QDEBUG checkb(bp, "pullupblock 1");
			return bp;
		}
		else {


@@ 343,8 355,10 @@ pullupblock(Block *bp, int n)
			nbp->next = 0;
			freeb(nbp);
			n -= i;
			if(n == 0)
			if(n == 0){
				QDEBUG checkb(bp, "pullupblock 2");
				return bp;
			}
		}
	}
	freeb(bp);


@@ 360,6 374,7 @@ trimblock(Block *bp, int offset, int len)
	ulong l;
	Block *nb, *startb;

	QDEBUG checkb(bp, "trimblock 1");
	if(blocklen(bp) < offset+len) {
		freeblist(bp);
		return nil;


@@ 400,6 415,7 @@ copyblock(Block *bp, int count)
	int l;
	Block *nbp;

	QDEBUG checkb(bp, "copyblock 0");
	nbp = allocb(count);
	for(; count > 0 && bp != 0; bp = bp->next){
		l = BLEN(bp);


@@ 414,6 430,7 @@ copyblock(Block *bp, int count)
		nbp->wp += count;
	}
	copyblockcnt++;
	QDEBUG checkb(nbp, "copyblock 1");

	return nbp;
}


@@ 432,6 449,7 @@ adjustblock(Block* bp, int len)
	if(bp->rp+len > bp->lim){
		nbp = copyblock(bp, len);
		freeblist(bp);
		QDEBUG checkb(nbp, "adjustblock 1");

		return nbp;
	}


@@ 440,6 458,7 @@ adjustblock(Block* bp, int len)
	if(len > n)
		memset(bp->wp, 0, len-n);
	bp->wp = bp->rp+len;
	QDEBUG checkb(bp, "adjustblock 2");

	return bp;
}


@@ 468,6 487,7 @@ pullblock(Block **bph, int count)
		bytes += n;
		count -= n;
		bp->rp += n;
		QDEBUG checkb(bp, "pullblock ");
		if(BLEN(bp) == 0) {
			*bph = bp->next;
			bp->next = nil;


@@ 498,6 518,7 @@ qget(Queue *q)
	q->bfirst = b->next;
	b->next = 0;
	q->len -= BLEN(b);
	QDEBUG checkb(b, "qget");

	/* if writer flow controlled, restart */
	if((q->state & Qflow) && q->len < q->limit/2){


@@ 528,6 549,7 @@ qdiscard(Queue *q, int len)
		b = q->bfirst;
		if(b == nil)
			break;
		QDEBUG checkb(b, "qdiscard");
		n = BLEN(b);
		if(n <= len - sofar){
			q->bfirst = b->next;


@@ 732,6 754,7 @@ qcopy(Queue *q, int len, ulong offset)
			n -= offset - sofar;
			break;
		}
		QDEBUG checkb(b, "qcopy");
		b = b->next;
	}



@@ 952,6 975,7 @@ qbwrite(Queue *q, Block *b)
	q->blast = b;
	b->next = 0;
	q->len += n;
	QDEBUG checkb(b, "qbwrite");

	if(q->state & Qstarve){
		q->state &= ~Qstarve;

M port/taslock.c => port/taslock.c +27 -2
@@ 29,6 29,7 @@ lock(Lock *l)
		l->p = up;
		l->isilock = 0;
		if(up){
			up->nlocks++;
			l->pri = up->priority;
			up->priority = PriLock;
		}


@@ 56,6 57,7 @@ lock(Lock *l)
			l->p = up;
			l->isilock = 0;
			if(up){
				up->nlocks++;
				l->pri = up->priority;
				up->priority = PriLock;
			}


@@ 74,6 76,8 @@ ilock(Lock *l)

	x = splhi();
	if(tas(&l->key) == 0){
		if (up)
			up->nlocks++;
		l->sr = x;
		l->pc = pc;
		l->p = up;


@@ 90,6 94,8 @@ ilock(Lock *l)
			;
		x = splhi();
		if(tas(&l->key) == 0){
			if (up)
			 up->nlocks++;
			l->sr = x;
			l->pc = pc;
			l->p = up;


@@ 109,6 115,7 @@ canlock(Lock *l)
	l->p = up;
	l->isilock = 0;
	if(up){
		up->nlocks++;
		l->pri = up->priority;
		up->priority = PriLock;
	}


@@ 119,6 126,9 @@ void
unlock(Lock *l)
{
	int p;
	ulong pc;

	pc = getcallerpc(l);

	p = l->pri;
	if(l->key == 0)


@@ 127,8 137,18 @@ unlock(Lock *l)
		print("iunlock of lock: pc %lux, held by %lux\n", getcallerpc(l), l->pc);
	l->pc = 0;
	l->key = 0;
	if(up && p < up->priority)
		up->priority = p;
	if(up) {
		if (up != l->p) {
			print("different unlocker 0x%lux pc 0x%lux held by pc 0x%lux proc %d\n",
				l->key, pc, l->pc, l->p ? l->p->pid : 0);
			dumpaproc(up);
		}
		if (--up->nlocks < 0)
			print("number of locks < 0: pc %lux, held by %lux\n",
				getcallerpc(l), l->pc);
		if (p < up->priority)
			up->priority = p;
	}
	coherence();
}



@@ 145,6 165,11 @@ iunlock(Lock *l)
	sr = l->sr;
	l->pc = 0;
	l->key = 0;
	if(up) {
		if (--up->nlocks < 0)
			print("number of locks < 0: pc %lux, held by %lux\n",
				getcallerpc(l), l->pc);
	}
	splx(sr);
	coherence();
}