git: 9front

Download patch

ref: c89fc5e28726593249e6d31d76bbb62ba4e48d41
parent: f94a33df20e1bd713a0d696532f8604cc37e656c
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Feb 24 17:42:22 EST 2014

kernel: keep cached pages continuous at the end of the page list on imagereclaim()

imagereclaim() sabotaged itself by breaking the invariant
that cached pages are kept at the end of the page list.

once we made a hole of uncached pages, we would stop
reclaiming cached pages before it as the loop breaks
once it hits a uncached page. (we iterate backwards from
the tail to the head of the pagelist until pages have been
reclaimed or we hit a uncached page).

the solution is to move pages to the head of the pagelist
after removing them from the image cache.

--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -64,7 +64,7 @@
 	print("%ldM swap\n", vkb/1024);
 }
 
-static void
+void
 pageunchain(Page *p)
 {
 	if(canlock(&palloc))
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -202,6 +202,7 @@
 int		openmode(ulong);
 Block*		packblock(Block*);
 Block*		padblock(Block*, int);
+void		pageunchain(Page*);
 void		pagechainhead(Page*);
 void		pageinit(void);
 ulong	pagenumber(Page*);
--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -313,7 +313,7 @@
 imagereclaim(void)
 {
 	int n;
-	Page *p;
+	Page *p, *x;
 	uvlong ticks;
 
 	irstats.calls++;
@@ -329,11 +329,16 @@
 	 * end of the list (see putpage) so start there and work
 	 * backward.
 	 */
-	for(p = palloc.tail; p && p->image && (n<1000 || !imagealloc.free); p = p->prev) {
+	for(p = palloc.tail; p && p->image && (n<1000 || !imagealloc.free); p = x) {
+		x = p->prev;
 		if(p->ref == 0 && canlock(p)) {
 			if(p->ref == 0 && p->image && !p->image->notext) {
 				n++;
 				uncachepage(p);
+
+				/* move to head to maintain the invariant above */
+				pageunchain(p);
+				pagechainhead(p);
 			}
 			unlock(p);
 		}
--