ref: 8a3b388ffee44db7d878296cb83660139e749962
parent: 9ab48ee37050e2676ae0ddbf253bb3ae5567eb45
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jun 15 12:05:00 EDT 2015
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.
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -78,9 +78,12 @@
tail->next = palloc.head;
palloc.head = head;
palloc.freecount += n;
- if(palloc.r.p != nil)
- wakeup(&palloc.r);
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
@@ -135,10 +138,10 @@
return n;
}
-int
+static int
ispages(void*)
{
- return palloc.freecount >= swapalloc.highwater;
+ return palloc.freecount > swapalloc.highwater || up->noswap && palloc.freecount > 0;
}
Page*
@@ -149,26 +152,22 @@
int color;
lock(&palloc);
- for(;;) {
- if(palloc.freecount > swapalloc.highwater)
- break;
- if(up->kp && palloc.freecount > 0)
- break;
+ while(!ispages(nil)){
unlock(&palloc);
if(s != nil)
qunlock(*s);
if(!waserror()){
- eqlock(&palloc.pwait); /* Hold memory requesters here */
+ Rendezq *q;
+ q = &palloc.pwait[!up->noswap];
+ eqlock(q);
if(!waserror()){
kickpager();
- tsleep(&palloc.r, ispages, 0, 1000);
+ sleep(q, ispages, nil);
poperror();
}
-
- qunlock(&palloc.pwait);
-
+ qunlock(q);
poperror();
}
@@ -182,7 +181,6 @@
*s = nil;
return nil;
}
-
lock(&palloc);
}
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -34,6 +34,7 @@
typedef struct Queue Queue;
typedef struct Ref Ref;
typedef struct Rendez Rendez;
+typedef struct Rendezq Rendezq;
typedef struct Rgrp Rgrp;
typedef struct RWlock RWlock;
typedef struct Sargs Sargs;
@@ -77,6 +78,12 @@
int locked; /* flag */
};
+struct Rendezq
+{
+ QLock;
+ Rendez;
+};
+
struct RWlock
{
Lock use;
@@ -506,8 +513,7 @@
ulong freecount; /* how many pages on free list now */
Page *pages; /* array of all pages */
ulong user; /* how many user pages */
- Rendez r; /* Sleep for free mem */
- QLock pwait; /* Queue of procs waiting for memory */
+ Rendezq pwait[2]; /* Queues of procs waiting for memory */
Pallocmem mem[16]; /* physical user page banks */
};
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -138,7 +138,6 @@
int iseve(void);
int islo(void);
Segment* isoverlap(Proc*, uintptr, uintptr);
-int ispages(void*);
int isphysseg(char*);
void ixsummary(void);
void kickpager(void);
--- a/sys/src/9/port/swap.c
+++ b/sys/src/9/port/swap.c
@@ -159,7 +159,8 @@
up->psstate = "Reclaim";
if(reclaim()){
up->psstate = "Idle";
- wakeup(&palloc.r);
+ wakeup(&palloc.pwait[0]);
+ wakeup(&palloc.pwait[1]);
sleep(&swapalloc.r, needpages, nil);
continue;
}