From a49d112bf1cebd590c182d9a1cd66e72a50cab1c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 13 May 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-05-13 --- port/page.c | 72 +++++++++++++++++++++++---------------------- port/proc.c | 84 ++++++++++++++++++++++++++--------------------------- 2 files changed, 80 insertions(+), 76 deletions(-) diff --git a/port/page.c b/port/page.c index 099467ee3646901d18ba7e5957873c0c7fc27b6c..fff67c304ef12a80e38a6f79dc759fc63479074e 100644 --- a/port/page.c +++ b/port/page.c @@ -73,7 +73,6 @@ newpage(int clear, Segment **s, ulong va) lock(&palloc); -retry: color = getpgcolor(va); hw = swapalloc.highwater; for(;;) { @@ -129,23 +128,15 @@ retry: 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--; - unlock(&palloc); lock(p); - if(p->ref != 0) { /* lookpage has priority on steal */ - unlock(p); - print("stolen\n"); - lock(&palloc); - palloc.freecount++; - goto retry; - } + if(p->ref != 0) + panic("newpage"); uncachepage(p); p->ref++; @@ -154,6 +145,7 @@ retry: for(i = 0; i < MAXMACH; i++) p->cachectl[i] = ct; unlock(p); + unlock(&palloc); if(clear) { k = kmap(p); @@ -178,13 +170,14 @@ putpage(Page *p) return; } + lock(&palloc); lock(p); if(--p->ref > 0) { unlock(p); + unlock(&palloc); return; } - lock(&palloc); if(p->image && p->image != &swapimage) { if(palloc.tail) { p->prev = palloc.tail; @@ -209,13 +202,13 @@ putpage(Page *p) palloc.head = p; p->prev = 0; } - palloc.freecount++; + if(palloc.r.p != 0) wakeup(&palloc.r); - unlock(&palloc); unlock(p); + unlock(&palloc); } Page* @@ -232,16 +225,15 @@ auxpage() p->next->prev = 0; palloc.head = p->next; palloc.freecount--; - unlock(&palloc); lock(p); - if(p->ref != 0) { /* Stolen by lookpage */ - unlock(p); - return 0; - } + if(p->ref != 0) + panic("auxpage"); p->ref++; uncachepage(p); unlock(p); + unlock(&palloc); + return p; } @@ -250,12 +242,31 @@ duppage(Page *p) /* Always call with p locked */ { Page *np; int color; + int retries; + + retries = 0; +retry: + if(retries++ > 10000) + panic("duppage"); /* No dup for swap/cache pages */ - if(p->image->notext) + if(p->ref == 0 || p->image == nil || p->image->notext) return; - lock(&palloc); + /* + * normal lock ordering is to call + * lock(&palloc) before lock(p). + * To avoid deadlock, we have to drop + * our locks and try again. + */ + if(!canlock(&palloc)){ + unlock(p); + if(up) + sched(); + lock(p); + goto retry; + } + /* No freelist cache when memory is very low */ if(palloc.freecount < swapalloc.highwater) { unlock(&palloc); @@ -279,7 +290,6 @@ duppage(Page *p) /* Always call with p locked */ np->prev->next = np->next; else palloc.head = np->next; - if(np->next) np->next->prev = np->prev; else @@ -297,15 +307,10 @@ duppage(Page *p) /* Always call with p locked */ np->prev = np->next = 0; } + lock(np); unlock(&palloc); - lock(np); /* Cache the new version */ - if(np->ref != 0) { /* Stolen by lookpage */ - uncachepage(p); - unlock(np); - return; - } - + /* Cache the new version */ uncachepage(np); np->va = p->va; np->daddr = p->daddr; @@ -399,33 +404,32 @@ lookpage(Image *i, ulong daddr) if(f->image == i && f->daddr == daddr) { unlock(&palloc.hashlock); + lock(&palloc); lock(f); if(f->image != i || f->daddr != daddr) { unlock(f); + unlock(&palloc); return 0; } - - lock(&palloc); 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--; } unlock(&palloc); - unlock(f); + return f; } } unlock(&palloc.hashlock); + return 0; } diff --git a/port/proc.c b/port/proc.c index 46ad2e7d1e5bed29b34af0a69efb6d6cb67f52a4..24b450eaa4bf4a0ed4e7915a2d2ed2f0ee21021d 100644 --- a/port/proc.c +++ b/port/proc.c @@ -378,68 +378,68 @@ procinit0(void) /* bad planning - clashes with devproc.c */ } void -sleep1(Rendez *r, int (*f)(void*), void *arg) +sleep(Rendez *r, int (*f)(void*), void *arg) { int s; - /* - * spl is to allow lock to be called - * at interrupt time. lock is mutual exclusion - */ s = splhi(); + lock(&up->rlock); if(r->p){ print("double sleep %d %d\n", r->p->pid, up->pid); dumpstack(); } - r->p = up; - - coherence(); /* force memory state to reflect processor state */ - - /* - * if condition happened, never mind - */ - if((*f)(arg)){ - r->p = 0; - unlock(&up->rlock); - splx(s); - return; - } /* - * now we are committed to - * change state and call scheduler + * Wakeup only knows there may be something to do by testing + * r->p in order to get something to lock on. + * Flush that information out to memory in case the sleep is + * committed. */ - up->state = Wakeme; - up->r = r; - unlock(&up->rlock); - splx(s); -} + r->p = up; + coherence(); -void -sleep(Rendez *r, int (*f)(void*), void *arg) -{ - int s; + if((*f)(arg) || up->notepending){ + /* + * if condition happened or a note is pending + * never mind + */ + r->p = nil; + unlock(&up->rlock); + } else { + /* + * now we are committed to + * change state and call scheduler + */ + up->state = Wakeme; + up->r = r; - sleep1(r, f, arg); - if(up->notepending == 0) - sched(); /* notepending may go true while asleep */ + /* statistics */ + m->cs++; + + procsave(up); + if(setlabel(&up->sched)) { + /* + * here when the process is awakened + */ + procrestore(up); + spllo(); + } else { + /* + * here to go to sleep (i.e. stop Running) + */ + unlock(&up->rlock); + gotolabel(&m->sched); + } + } if(up->notepending) { up->notepending = 0; - s = splhi(); - lock(&up->rlock); - if(r->p == up){ - /* undo the sleep1() */ - up->r = 0; - r->p = 0; - if(up->state == Wakeme) - up->state = Running; - } - unlock(&up->rlock); splx(s); error(Eintr); } + + splx(s); } int