diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index 5ab0c9f2e..b5c59d80f 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -140,14 +140,20 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) lkp = *pg; lock(lkp); - + if(lkp->ref <= 0) + panic("fault: lkp->ref %d <= 0", lkp->ref); if(lkp->image == &swapimage) ref = lkp->ref + swapcount(lkp->daddr); else ref = lkp->ref; - if(ref > 1) { - unlock(lkp); + if(ref == 1 && lkp->image){ + /* save a copy of the original for the image cache */ + duppage(lkp); + ref = lkp->ref; + } + unlock(lkp); + if(ref > 1){ new = newpage(0, &s, addr); if(s == 0) return -1; @@ -155,13 +161,6 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) copypage(lkp, *pg); putpage(lkp); } - else { - /* save a copy of the original for the image cache */ - if(lkp->image) - duppage(lkp); - - unlock(lkp); - } mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID; (*pg)->modref = PG_MOD|PG_REF; break; diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index fc5906b9e..abce72a6b 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -275,6 +275,17 @@ duppage(Page *p) /* Always call with p locked */ retries = 0; retry: + /* don't dup shared page */ + if(p->ref != 1){ + print("duppage: p->ref %d != 1\n", p->ref); + return 0; + } + + /* don't dup pages with no image */ + if(p->image == nil || p->image->notext){ + print("duppage: noimage\n"); + return 0; + } if(retries++ > dupretries){ print("duppage %d, up %p\n", retries, up); @@ -284,11 +295,6 @@ retry: uncachepage(p); return 1; } - - - /* don't dup pages with no image */ - if(p->ref == 0 || p->image == nil || p->image->notext) - return 0; /* * normal lock ordering is to call @@ -337,6 +343,8 @@ retry: * once they finally lock(np). */ lock(np); + if(np->ref != 0) /* should never happen */ + panic("duppage: np->ref %d != 0\n", np->ref); unlock(&palloc); /* Cache the new version */