code: plan9front

Download patch

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