From 695a5b658a3e53ec57700c5b0d06b987f6601d2b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 5 Jun 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-06-05 --- pc/apic.c | 10 ++++ pc/dat.h | 2 +- pc/etherelnk3.c | 31 ++++++----- pc/l.s | 1 + pc/main.c | 10 ++++ pc/mmu.c | 141 ++++++++++++++++++++++-------------------------- pc/mp.c | 43 +++++---------- pc/trap.c | 5 ++ port/page.c | 136 ++++++++++++++++++++++------------------------ port/portdat.h | 3 +- port/portfns.h | 1 + port/proc.c | 4 +- port/qio.c | 58 ++++++++++++++------ port/taslock.c | 29 +++++++++- 14 files changed, 258 insertions(+), 216 deletions(-) diff --git a/pc/apic.c b/pc/apic.c index 864034f4e3c7e9d50563cc92fa664fe6ee54b2a6..32ca62bbfdb2ded924dd8a7352cf3e5a05f0c131 100644 --- a/pc/apic.c +++ b/pc/apic.c @@ -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); diff --git a/pc/dat.h b/pc/dat.h index 1e7f63fc98ae6cd43bfe67070f1b552f5a77588a..fbe1649d735a7181a8de50d2093f2a33331ebcea 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -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 diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index c9b8e5dd5a6890add9a6c2c4201c9b9c77689d3d..7a69e452d9f285cbbe6698c4786101476d9a0267 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -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); diff --git a/pc/l.s b/pc/l.s index e32df2dbde9f70c3abdffc11c18166741637c7a6..10085d14f356a66dfa0f5ae53dbdecbeb847eb52 100644 --- a/pc/l.s +++ b/pc/l.s @@ -142,6 +142,7 @@ _clearbss: */ TEXT idle(SB), $0 _idle: + STI HLT JMP _idle diff --git a/pc/main.c b/pc/main.c index 274f547f48ad499eea6131c230f7ec1f3eb22c9e..78472832e4001ef0c0f818ade6120c3c9cf5e8d4 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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 diff --git a/pc/mmu.c b/pc/mmu.c index cb2ad68f6375083d927fc88071180985a892815c..523c74d7b7065effb44845cad2967caf8d928192 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -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)]; diff --git a/pc/mp.c b/pc/mp.c index 85f3ad3ccf66d93b2dad7408b948a811431c1d30..d7f89cd52df44ec2498c14d218a30397af596f13 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -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<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; + } } /* diff --git a/port/page.c b/port/page.c index fff67c304ef12a80e38a6f79dc759fc63479074e..1373e4a54ea0ad83d5693e269e11f95d95413ae8 100644 --- a/port/page.c +++ b/port/page.c @@ -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); diff --git a/port/portdat.h b/port/portdat.h index e330947baffe4a4d79f77804ee91a8b57e411b2d..82bb8e299c99b0e8b1c2b587f201dc3265c573a8 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -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 */ diff --git a/port/portfns.h b/port/portfns.h index 1b1217d7a361e76e9c9adbe7fe67de1c47d2f743..1f72be919f451921b2141a5236df949a7e048cb6 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -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*); diff --git a/port/proc.c b/port/proc.c index a0d4e49f814aa027971f17f0a34def4540854f14..2ec0be280740885897969364aef7bb6c5d3b6b9b 100644 --- a/port/proc.c +++ b/port/proc.c @@ -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); diff --git a/port/qio.c b/port/qio.c index 96774f2d1c89bfe1199aa409e432936d1ad55176..ccb33f1402706da7c5bfbb401443932a06a98981 100644 --- a/port/qio.c +++ b/port/qio.c @@ -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; diff --git a/port/taslock.c b/port/taslock.c index c50e3fe1e97fb85fe347a56bee6fb29ac577dcf4..a161e07f03e6027b8afb3f829e052a7d5a635ff1 100644 --- a/port/taslock.c +++ b/port/taslock.c @@ -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(); }