From edd4dbfa92556a4498704ac0942a8eaee431dc58 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 9 Jan 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-01-09 --- port/fault.c | 67 +++++++++++++++++++++++++++++++++++----------------- port/page.c | 24 ++++++++++--------- port/swap.c | 33 +++++++++++++++++--------- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/port/fault.c b/port/fault.c index 1efa3894dba4e0de796954087216a0c2312b58cf..b83fbbe2ac4eca390e4ccce8f47fa9531526a480 100644 --- a/port/fault.c +++ b/port/fault.c @@ -17,7 +17,7 @@ fault(ulong addr, int read) m->pfault++; for(;;) { - s = seg(up, addr, 1); + s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */ if(s == 0) { up->psstate = sps; return -1; @@ -88,18 +88,21 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) break; case SG_SHDATA: /* Shared data */ + shared: if(pagedout(*pg)) pio(s, addr, soff, pg); lkp = *pg; lock(lkp); - /* uncache the current page (since we may be changing it) - * and, if a text page, put a duplicate back onto - * the free list - */ - if(lkp->image) - duppage(lkp); + /* uncache the current swap image (since we may be changing it) */ + if(lkp->image){ + if(lkp->image == &swapimage) + uncachepage(lkp); + else + duppage(lkp); + } + unlock(lkp); goto done; @@ -118,15 +121,16 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) *pg = new; } - /* NO break */ + if(type == SG_SHARED) + goto shared; - case SG_DATA: /* Demand load/pagein/copy on write */ + goto notshared; + + case SG_DATA: + notshared: /* Demand load/pagein/copy on write */ if(pagedout(*pg)) pio(s, addr, soff, pg); - if(type == SG_SHARED) - goto done; - if(read && conf.copymode == 0) { mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID; (*pg)->modref |= PG_REF; @@ -135,7 +139,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) lkp = *pg; lock(lkp); - if(lkp->image == &swapimage && lkp->daddr) + if(lkp->image == &swapimage) ref = lkp->ref + swapcount(lkp->daddr); else ref = lkp->ref; @@ -153,8 +157,12 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) * and, if a text page, put a duplicate back onto * the free list */ - if(lkp->image) - duppage(lkp); + if(lkp->image){ + if(lkp->image == &swapimage) + uncachepage(lkp); + else + duppage(lkp); + } unlock(lkp); } @@ -201,18 +209,18 @@ pio(Segment *s, ulong addr, ulong soff, Page **p) Page *loadrec; loadrec = *p; - if(loadrec == 0) { - daddr = s->fstart+soff; /* Compute disc address */ + if(loadrec == 0) { /* from a text/data image */ + daddr = s->fstart+soff; new = lookpage(s->image, daddr); } - else { + else { /* from a swap image */ daddr = swapaddr(loadrec); new = lookpage(&swapimage, daddr); if(new != nil) putswap(loadrec); } - if(new) { /* Page found from cache */ + if(new != nil) { /* Page found from cache */ *p = new; return; } @@ -259,13 +267,27 @@ pio(Segment *s, ulong addr, ulong soff, Page **p) c = swapimage.c; qlock(&swapimage.rdlock); /* mutex */ + /* + * multiple processes could be swapping in the + * same page for the same segment + */ + if(!pagedout(*p)){ + putpage(new); + qunlock(&swapimage.rdlock); + goto done; + } + + /* + * multiple processes could be swapping in the + * same page for different segments + */ new2 = lookpage(&swapimage, daddr); if(new2 != nil){ putpage(new); - putswap(*p); *p = new2; + putswap(loadrec); qunlock(&swapimage.rdlock); - return; + goto done; } if(waserror()) { @@ -286,13 +308,14 @@ pio(Segment *s, ulong addr, ulong soff, Page **p) qlock(&s->lk); new->daddr = daddr; - putswap(*p); cachepage(new, &swapimage); *p = new; + putswap(loadrec); qunlock(&swapimage.rdlock); } +done: if(s->flushme) memset((*p)->cachectl, PG_TXTFLUSH, sizeof((*p)->cachectl)); } diff --git a/port/page.c b/port/page.c index f93a21dc6e4903edbfc1b3752dbe849b832ddafd..793533e5ead334a318840372486df802389de6ec 100644 --- a/port/page.c +++ b/port/page.c @@ -215,6 +215,10 @@ putpage(Page *p) lock(&palloc); lock(p); + + if(p->ref == 0) + panic("putpage"); + if(--p->ref > 0) { unlock(p); unlock(&palloc); @@ -271,15 +275,9 @@ retry: panic("duppage %d", retries); /* don't dup pages with no image */ - if(p->ref == 0 || p->image == nil) + if(p->ref == 0 || p->image == nil || p->image->notext) return; - /* No dup for swap/cache pages but we still have to uncache */ - if(p->image->notext){ - uncachepage(p); - return; - } - /* * normal lock ordering is to call * lock(&palloc) before lock(p). @@ -395,10 +393,14 @@ cachedel(Image *i, ulong daddr) l = &pghash(daddr); for(f = *l; f; f = f->hash) { if(f->image == i && f->daddr == daddr) { - *l = f->hash; - putimage(f->image); - f->image = 0; - f->daddr = 0; + lock(f); + if(f->image == i && f->daddr == daddr){ + *l = f->hash; + putimage(f->image); + f->image = 0; + f->daddr = 0; + } + unlock(f); break; } l = &f->hash; diff --git a/port/swap.c b/port/swap.c index dd911d5ed241b9f100f73eb06f8b5bc70b761e71..acf0c2611c86696c182f63337a50afb7474a64bb 100644 --- a/port/swap.c +++ b/port/swap.c @@ -60,12 +60,12 @@ putswap(Page *p) lock(&swapalloc); idx = &swapalloc.swmap[((ulong)p)/BY2PG]; if(--(*idx) == 0) { - if(swapalloc.swmap[((ulong)p)/BY2PG]==255) - panic("putswap"); swapalloc.free++; if(idx < swapalloc.last) swapalloc.last = idx; } + if(*idx >= 254) + panic("putswap %lux == %ud", p, *idx); unlock(&swapalloc); } @@ -73,9 +73,8 @@ void dupswap(Page *p) { lock(&swapalloc); - if(swapalloc.swmap[((ulong)p)/BY2PG]==255) + if(++swapalloc.swmap[((ulong)p)/BY2PG] == 0) panic("dupswap"); - swapalloc.swmap[((ulong)p)/BY2PG]++; unlock(&swapalloc); } @@ -279,10 +278,10 @@ pagepte(int type, Page **pg) case SG_SHARED: case SG_SHDATA: case SG_MAP: - /* if it's already on disk, we're done */ + /* if it's already on disk, no need to do io again */ #ifdef asdf lock(outp); - if(outp->daddr != 0 && outp->image == &swapimage){ + if(outp->image == &swapimage){ dupswap((Page*)outp->daddr); *pg = (Page*)(outp->daddr|PG_ONSWAP); unlock(outp); @@ -292,22 +291,34 @@ pagepte(int type, Page **pg) unlock(outp); #endif asdf + /* + * get a new swap address and clear any pages + * referring to it from the cache + */ daddr = newswap(); cachedel(&swapimage, daddr); + lock(outp); - outp->ref++; + + /* forget anything that it used to cache */ uncachepage(outp); - /* Enter swap page into cache before segment is unlocked so that - * a fault will cause a cache recovery rather than a pagein on a - * partially written block. + /* + * incr the reference count to make sure it sticks around while + * being written + */ + outp->ref++; + + /* + * enter it into the cache so that a fault happening + * during the write will grab the page from the cache */ outp->daddr = daddr; cachepage(outp, &swapimage); *pg = (Page*)(daddr|PG_ONSWAP); unlock(outp); - /* Add me to IO transaction list */ + /* Add page to IO transaction list */ iolist[ioptr++] = outp; break; }