kernel: implement separate wait queues for page allocation
give kernel processes and local disk file servers (procs having noswap flag set) a clear advantage for page allocation under starved condition by giving them ther own wait queue so they get readied as soon as pages become available.
This commit is contained in:
parent
9ab48ee370
commit
8a3b388ffe
4 changed files with 23 additions and 19 deletions
|
@ -78,9 +78,12 @@ freepages(Page *head, Page *tail, int n)
|
||||||
tail->next = palloc.head;
|
tail->next = palloc.head;
|
||||||
palloc.head = head;
|
palloc.head = head;
|
||||||
palloc.freecount += n;
|
palloc.freecount += n;
|
||||||
if(palloc.r.p != nil)
|
|
||||||
wakeup(&palloc.r);
|
|
||||||
unlock(&palloc);
|
unlock(&palloc);
|
||||||
|
|
||||||
|
if(palloc.pwait[0].p != nil && wakeup(&palloc.pwait[0]) != nil)
|
||||||
|
return;
|
||||||
|
if(palloc.pwait[1].p != nil)
|
||||||
|
wakeup(&palloc.pwait[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -135,10 +138,10 @@ pagereclaim(Image *i, int min)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
ispages(void*)
|
ispages(void*)
|
||||||
{
|
{
|
||||||
return palloc.freecount >= swapalloc.highwater;
|
return palloc.freecount > swapalloc.highwater || up->noswap && palloc.freecount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Page*
|
Page*
|
||||||
|
@ -149,26 +152,22 @@ newpage(int clear, Segment **s, uintptr va)
|
||||||
int color;
|
int color;
|
||||||
|
|
||||||
lock(&palloc);
|
lock(&palloc);
|
||||||
for(;;) {
|
while(!ispages(nil)){
|
||||||
if(palloc.freecount > swapalloc.highwater)
|
|
||||||
break;
|
|
||||||
if(up->kp && palloc.freecount > 0)
|
|
||||||
break;
|
|
||||||
unlock(&palloc);
|
unlock(&palloc);
|
||||||
if(s != nil)
|
if(s != nil)
|
||||||
qunlock(*s);
|
qunlock(*s);
|
||||||
|
|
||||||
if(!waserror()){
|
if(!waserror()){
|
||||||
eqlock(&palloc.pwait); /* Hold memory requesters here */
|
Rendezq *q;
|
||||||
|
|
||||||
|
q = &palloc.pwait[!up->noswap];
|
||||||
|
eqlock(q);
|
||||||
if(!waserror()){
|
if(!waserror()){
|
||||||
kickpager();
|
kickpager();
|
||||||
tsleep(&palloc.r, ispages, 0, 1000);
|
sleep(q, ispages, nil);
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
|
qunlock(q);
|
||||||
qunlock(&palloc.pwait);
|
|
||||||
|
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +181,6 @@ newpage(int clear, Segment **s, uintptr va)
|
||||||
*s = nil;
|
*s = nil;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock(&palloc);
|
lock(&palloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ typedef struct QLock QLock;
|
||||||
typedef struct Queue Queue;
|
typedef struct Queue Queue;
|
||||||
typedef struct Ref Ref;
|
typedef struct Ref Ref;
|
||||||
typedef struct Rendez Rendez;
|
typedef struct Rendez Rendez;
|
||||||
|
typedef struct Rendezq Rendezq;
|
||||||
typedef struct Rgrp Rgrp;
|
typedef struct Rgrp Rgrp;
|
||||||
typedef struct RWlock RWlock;
|
typedef struct RWlock RWlock;
|
||||||
typedef struct Sargs Sargs;
|
typedef struct Sargs Sargs;
|
||||||
|
@ -77,6 +78,12 @@ struct QLock
|
||||||
int locked; /* flag */
|
int locked; /* flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Rendezq
|
||||||
|
{
|
||||||
|
QLock;
|
||||||
|
Rendez;
|
||||||
|
};
|
||||||
|
|
||||||
struct RWlock
|
struct RWlock
|
||||||
{
|
{
|
||||||
Lock use;
|
Lock use;
|
||||||
|
@ -506,8 +513,7 @@ struct Palloc
|
||||||
ulong freecount; /* how many pages on free list now */
|
ulong freecount; /* how many pages on free list now */
|
||||||
Page *pages; /* array of all pages */
|
Page *pages; /* array of all pages */
|
||||||
ulong user; /* how many user pages */
|
ulong user; /* how many user pages */
|
||||||
Rendez r; /* Sleep for free mem */
|
Rendezq pwait[2]; /* Queues of procs waiting for memory */
|
||||||
QLock pwait; /* Queue of procs waiting for memory */
|
|
||||||
Pallocmem mem[16]; /* physical user page banks */
|
Pallocmem mem[16]; /* physical user page banks */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,6 @@ void isdir(Chan*);
|
||||||
int iseve(void);
|
int iseve(void);
|
||||||
int islo(void);
|
int islo(void);
|
||||||
Segment* isoverlap(Proc*, uintptr, uintptr);
|
Segment* isoverlap(Proc*, uintptr, uintptr);
|
||||||
int ispages(void*);
|
|
||||||
int isphysseg(char*);
|
int isphysseg(char*);
|
||||||
void ixsummary(void);
|
void ixsummary(void);
|
||||||
void kickpager(void);
|
void kickpager(void);
|
||||||
|
|
|
@ -159,7 +159,8 @@ pager(void*)
|
||||||
up->psstate = "Reclaim";
|
up->psstate = "Reclaim";
|
||||||
if(reclaim()){
|
if(reclaim()){
|
||||||
up->psstate = "Idle";
|
up->psstate = "Idle";
|
||||||
wakeup(&palloc.r);
|
wakeup(&palloc.pwait[0]);
|
||||||
|
wakeup(&palloc.pwait[1]);
|
||||||
sleep(&swapalloc.r, needpages, nil);
|
sleep(&swapalloc.r, needpages, nil);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue