shithub: riscv

Download patch

ref: 9405f4c95f229a173c6f430c12d96ac2c19e8626
parent: 142858b176c3b3a256389e1c700b78ba89e85e69
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 2 15:55:26 EST 2014

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. ...

--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -80,7 +80,6 @@
 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 @@
 			new = newpage(1, &s, addr);
 			if(s == 0)
 				return -1;
-
 			*pg = new;
 		}
 		goto common;
@@ -143,24 +141,15 @@
 
 		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;
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -265,83 +265,6 @@
 }
 
 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;
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -82,7 +82,6 @@
 void		dumpregs(Ureg*);
 void		dumpstack(void);
 Fgrp*		dupfgrp(Fgrp*);
-void		duppage(Page*);
 void		dupswap(Page*);
 void		edfinit(Proc*);
 char*		edfadmit(Proc*);
--- a/sys/src/9/port/swap.c
+++ b/sys/src/9/port/swap.c
@@ -49,7 +49,7 @@
 	swapimage.notext = 1;
 }
 
-ulong
+uintptr
 newswap(void)
 {
 	uchar *look;