diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-03-02 20:55:26 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-03-02 20:55:26 +0100 |
commit | 9405f4c95f229a173c6f430c12d96ac2c19e8626 (patch) | |
tree | b51ff1e4ca888774d7ad51661e201339ee8fef79 /sys | |
parent | 142858b176c3b3a256389e1c700b78ba89e85e69 (diff) |
kernel: getting rid of duppage() (thanks charles)
simplifying paging code by getting rid of duppage(). instead,
fixfault() now always makes a copy of the shared/cached page
and leaves the cache alone. newpage() uncaches pages as
neccesary.
thanks charles forsyth for the suggestion.
from http://9fans.net/archive/2014/03/26:
> It isn't needed at all. When a cached page is written, it's trying hard to
> replace the page in the cache by a new copy,
> to return the previously cached page. Instead, I copy the cached page and
> return the copy, which is what it already
> does in another instance. ...
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/9/port/fault.c | 27 | ||||
-rw-r--r-- | sys/src/9/port/page.c | 77 | ||||
-rw-r--r-- | sys/src/9/port/portfns.h | 1 | ||||
-rw-r--r-- | sys/src/9/port/swap.c | 2 |
4 files changed, 9 insertions, 98 deletions
diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index 9b2d05392..1919c2890 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -80,7 +80,6 @@ int fixfault(Segment *s, uintptr addr, int read, int doputmmu) { int type; - int ref; Pte **p, *etp; uintptr soff, mmuphys=0; Page **pg, *lkp, *new; @@ -121,7 +120,6 @@ fixfault(Segment *s, uintptr addr, int read, int doputmmu) new = newpage(1, &s, addr); if(s == 0) return -1; - *pg = new; } goto common; @@ -143,24 +141,15 @@ fixfault(Segment *s, uintptr addr, int read, int doputmmu) lkp = *pg; lock(lkp); - ref = lkp->ref; - if(ref == 0) + if(lkp->ref == 0) panic("fault %#p ref == 0", lkp); - if(lkp->image == &swapimage) - ref += swapcount(lkp->daddr); - if(ref == 1 && lkp->image) { - /* - * save a copy of the original for the image cache - * and uncache the page. page might temporarily be - * unlocked while trying to acquire palloc lock so - * recheck ref in case it got grabbed. - */ - duppage(lkp); - - ref = lkp->ref; - } - unlock(lkp); - if(ref > 1){ + if(lkp->ref == 1 && lkp->image == nil) { + unlock(lkp); + } else if(lkp->image == &swapimage && (lkp->ref + swapcount(lkp->daddr)) == 1) { + uncachepage(lkp); + unlock(lkp); + } else { + unlock(lkp); new = newpage(0, &s, addr); if(s == 0) return -1; diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index 60cbee12e..c1efb906a 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -265,83 +265,6 @@ auxpage(void) } void -duppage(Page *p) /* Always call with p locked */ -{ - Page *np; - int color; - - /* - * normal lock ordering is to call - * lock(&palloc) before lock(p). - * To avoid deadlock, we have to drop - * our locks and try again. as the page - * is from the image cache, this might - * let someone else come in and grab it - * so we check page ref below. - */ - if(!canlock(&palloc)){ - unlock(p); - lock(&palloc); - lock(p); - } - - /* don't dup pages that are shared or have no image */ - if(p->ref != 1 || p->image == nil || p->image->notext){ - unlock(&palloc); - return; - } - - /* No freelist cache when memory is very low */ - if(palloc.freecount < swapalloc.highwater) { - unlock(&palloc); - uncachepage(p); - return; - } - - color = getpgcolor(p->va); - for(np = palloc.head; np; np = np->next) - if(np->color == color) - break; - - /* No page of the correct color */ - if(np == 0) { - unlock(&palloc); - uncachepage(p); - return; - } - - pageunchain(np); - pagechaintail(np); -/* -* XXX - here's a bug? - np is on the freelist but it's not really free. -* when we unlock palloc someone else can come in, decide to -* use np, and then try to lock it. they succeed after we've -* run copypage and cachepage and unlock(np). then what? -* they call pageunchain before locking(np), so it's removed -* from the freelist, but still in the cache because of -* cachepage below. if someone else looks in the cache -* before they remove it, the page will have a nonzero ref -* once they finally lock(np). This does not happen because -* newpage, auxpage, duppage and lookpage all lock(&palloc) -* so while they hold it nobody is going to grab anything -* from the cache. -*/ - lock(np); - if(np->ref != 0) /* should never happen */ - panic("duppage: np->ref %d != 0", np->ref); - unlock(&palloc); - - /* Cache the new version */ - uncachepage(np); - np->va = p->va; - np->daddr = p->daddr; - copypage(p, np); - cachepage(np, p->image); - unlock(np); - uncachepage(p); -} - -void copypage(Page *f, Page *t) { KMap *ks, *kd; diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 96071501c..5200be1e9 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -82,7 +82,6 @@ void dumpaproc(Proc*); void dumpregs(Ureg*); void dumpstack(void); Fgrp* dupfgrp(Fgrp*); -void duppage(Page*); void dupswap(Page*); void edfinit(Proc*); char* edfadmit(Proc*); diff --git a/sys/src/9/port/swap.c b/sys/src/9/port/swap.c index 69d822fc6..b8e0631ff 100644 --- a/sys/src/9/port/swap.c +++ b/sys/src/9/port/swap.c @@ -49,7 +49,7 @@ swapinit(void) swapimage.notext = 1; } -ulong +uintptr newswap(void) { uchar *look; |