diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-24 22:42:22 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-24 22:42:22 +0100 |
commit | 521a34d33b85e75013656b3dbb333035ed1d8a41 (patch) | |
tree | f12dc4bd2ec00443ac2ddf25a2f01cf89e92a342 /sys/src/9 | |
parent | 60c3c3b3dbf4e1ae03c1a376babec80900c14ecb (diff) |
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.
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/port/page.c | 2 | ||||
-rw-r--r-- | sys/src/9/port/portfns.h | 1 | ||||
-rw-r--r-- | sys/src/9/port/segment.c | 9 |
3 files changed, 9 insertions, 3 deletions
diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index d76fc4038..60cbee12e 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -64,7 +64,7 @@ pageinit(void) print("%ldM swap\n", vkb/1024); } -static void +void pageunchain(Page *p) { if(canlock(&palloc)) diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 41b4b105d..96071501c 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -202,6 +202,7 @@ int okaddr(uintptr, ulong, int); int openmode(ulong); Block* packblock(Block*); Block* padblock(Block*, int); +void pageunchain(Page*); void pagechainhead(Page*); void pageinit(void); ulong pagenumber(Page*); diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c index cd48d52b4..c73698b9e 100644 --- a/sys/src/9/port/segment.c +++ b/sys/src/9/port/segment.c @@ -313,7 +313,7 @@ static void imagereclaim(void) { int n; - Page *p; + Page *p, *x; uvlong ticks; irstats.calls++; @@ -329,11 +329,16 @@ imagereclaim(void) * 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); } |