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:
cinap_lenrek 2015-06-15 16:05:00 +02:00
parent 9ab48ee370
commit 8a3b388ffe
4 changed files with 23 additions and 19 deletions

View file

@ -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);
} }

View file

@ -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 */
}; };

View file

@ -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);

View file

@ -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;
} }