kernel: improve page reclaimation strategy and locking
when reclaiming pages from an image, always reclaim all the hash chains equally. that way, we avoid being biased towards the chains at the start of the Image.pghash[] array. images can be in two states: active or inactive. inactive images are the ones which are not used by program while active ones aare. when reclaiming pages, we should try to reclaim pages from inactive images first and only if that set becomes exhausted attempt to release text pages and attempt to reclaim pages from active images. when we run out of Image structures, it makes only sense to reclaim pages from inactive images, as reclaiming pages from active ones will never free any Image structures. change putimage() to require a image already locked and make it unlock the image. this avoids many pointless unlock()/lock() sequences as all callers of putimage() already had the image locked.
This commit is contained in:
parent
c6f7989176
commit
61a062ee9f
4 changed files with 23 additions and 37 deletions
|
@ -137,12 +137,12 @@ reclaim(void)
|
|||
ulong np;
|
||||
|
||||
for(;;){
|
||||
if((np = pagereclaim(&fscache, 1000)) > 0) {
|
||||
if(0) print("reclaim: %lud fscache\n", np);
|
||||
} else if((np = pagereclaim(&swapimage, 1000)) > 0) {
|
||||
if((np = pagereclaim(&fscache) + imagereclaim(0)) > 0){
|
||||
if(0) print("reclaim: %lud fscache + inactive image\n", np);
|
||||
} else if((np = pagereclaim(&swapimage)) > 0) {
|
||||
if(0) print("reclaim: %lud swap\n", np);
|
||||
} else if((np = imagereclaim(1000)) > 0) {
|
||||
if(0) print("reclaim: %lud image\n", np);
|
||||
} else if((np = imagereclaim(1)) > 0) {
|
||||
if(0) print("reclaim: %lud active image\n", np);
|
||||
}
|
||||
if(!needpages(nil))
|
||||
return 1; /* have pages, done */
|
||||
|
|
|
@ -93,15 +93,12 @@ freepages(Page *head, Page *tail, ulong np)
|
|||
}
|
||||
|
||||
ulong
|
||||
pagereclaim(Image *i, ulong pages)
|
||||
pagereclaim(Image *i)
|
||||
{
|
||||
Page **h, **l, **x, *p;
|
||||
Page *fh, *ft;
|
||||
ulong np;
|
||||
|
||||
if(pages == 0)
|
||||
return 0;
|
||||
|
||||
lock(i);
|
||||
if(i->pgref == 0){
|
||||
unlock(i);
|
||||
|
@ -127,18 +124,18 @@ pagereclaim(Image *i, ulong pages)
|
|||
p->next = nil;
|
||||
p->image = nil;
|
||||
p->daddr = ~0;
|
||||
i->pgref--;
|
||||
decref(i);
|
||||
|
||||
if(fh == nil)
|
||||
fh = p;
|
||||
else
|
||||
ft->next = p;
|
||||
ft = p;
|
||||
if(++np >= pages)
|
||||
np++;
|
||||
|
||||
decref(i);
|
||||
if(--i->pgref == 0)
|
||||
break;
|
||||
}
|
||||
unlock(i);
|
||||
putimage(i);
|
||||
|
||||
if(np > 0){
|
||||
|
@ -297,7 +294,6 @@ uncachepage(Page *p)
|
|||
p->image = nil;
|
||||
p->daddr = ~0;
|
||||
i->pgref--;
|
||||
unlock(i);
|
||||
putimage(i);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ void ilock(Lock*);
|
|||
void interrupted(void);
|
||||
void iunlock(Lock*);
|
||||
ulong imagecached(void);
|
||||
ulong imagereclaim(ulong);
|
||||
ulong imagereclaim(int);
|
||||
long incref(Ref*);
|
||||
void init0(void);
|
||||
void initseg(void);
|
||||
|
@ -213,7 +213,7 @@ Block* padblock(Block*, int);
|
|||
void pagechaindone(void);
|
||||
void pagechainhead(Page*);
|
||||
void pageinit(void);
|
||||
ulong pagereclaim(Image*, ulong);
|
||||
ulong pagereclaim(Image*);
|
||||
void panic(char*, ...);
|
||||
Cmdbuf* parsecmd(char *a, int n);
|
||||
void pathclose(Path*);
|
||||
|
|
|
@ -102,7 +102,6 @@ putseg(Segment *s)
|
|||
}
|
||||
if(i->s == s)
|
||||
i->s = nil;
|
||||
unlock(i);
|
||||
putimage(i);
|
||||
} else if(decref(s) != 0)
|
||||
return;
|
||||
|
@ -260,7 +259,7 @@ attachimage(int type, Chan *c, uintptr base, ulong len)
|
|||
/* dump pages of inactive images to free image structures */
|
||||
while((i = imagealloc.free) == nil) {
|
||||
unlock(&imagealloc);
|
||||
if(imagereclaim(1000) == 0 && imagealloc.free == nil){
|
||||
if(imagereclaim(0) == 0 && imagealloc.free == nil){
|
||||
freebroken(); /* can use the memory */
|
||||
resrcwait("no image after reclaim");
|
||||
}
|
||||
|
@ -288,7 +287,6 @@ found:
|
|||
if(i->s == nil) {
|
||||
incref(i);
|
||||
if(waserror()) {
|
||||
unlock(i);
|
||||
putimage(i);
|
||||
nexterror();
|
||||
}
|
||||
|
@ -316,14 +314,11 @@ imagecached(void)
|
|||
}
|
||||
|
||||
ulong
|
||||
imagereclaim(ulong pages)
|
||||
imagereclaim(int active)
|
||||
{
|
||||
static Image *i, *ie;
|
||||
ulong np;
|
||||
int j;
|
||||
|
||||
if(pages == 0)
|
||||
return 0;
|
||||
ulong np;
|
||||
|
||||
eqlock(&imagealloc.ireclaim);
|
||||
if(i == nil){
|
||||
|
@ -334,23 +329,19 @@ imagereclaim(ulong pages)
|
|||
for(j = 0; j < conf.nimage; j++, i++){
|
||||
if(i >= ie)
|
||||
i = imagealloc.list;
|
||||
if(i->ref == 0)
|
||||
if(i->ref == 0 || (i->ref != i->pgref) == !active)
|
||||
continue;
|
||||
/*
|
||||
* if there are no free image structures, only
|
||||
* reclaim pages from inactive images.
|
||||
*/
|
||||
if(imagealloc.free != nil || i->ref == i->pgref){
|
||||
np += pagereclaim(i, pages - np);
|
||||
if(np >= pages)
|
||||
break;
|
||||
}
|
||||
np += pagereclaim(i);
|
||||
if(np >= 1000)
|
||||
goto Done;
|
||||
}
|
||||
Done:
|
||||
qunlock(&imagealloc.ireclaim);
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
/* putimage(): called with image locked and unlocks */
|
||||
void
|
||||
putimage(Image *i)
|
||||
{
|
||||
|
@ -358,14 +349,13 @@ putimage(Image *i)
|
|||
Chan *c;
|
||||
long r;
|
||||
|
||||
r = decref(i);
|
||||
if(i->notext){
|
||||
decref(i);
|
||||
unlock(i);
|
||||
return;
|
||||
}
|
||||
|
||||
c = nil;
|
||||
lock(i);
|
||||
r = decref(i);
|
||||
if(r == i->pgref){
|
||||
/*
|
||||
* all remaining references to this image are from the
|
||||
|
|
Loading…
Reference in a new issue