Module Name:    src
Committed By:   pooka
Date:           Tue Feb 22 20:17:38 UTC 2011

Modified Files:
        src/sys/rump/librump/rumpkern: vm.c
        src/sys/rump/librump/rumpvfs: vm_vfs.c

Log Message:
Shuffle the pagedaemon algorithm a bit to record the number of
pageouts active and give up only if the pagedaemon could not free
memory and there are no outstanding pageouts.

This should fix the "out of memory" pauses reported by Mihai Chelaru
and Taylor R Campbell.  Tested by copying files to and from an ffs
backed by /dev/wd0 (with and without -o log) using a 1MB rump kernel
memory limit.


To generate a diff of this commit:
cvs rdiff -u -r1.112 -r1.113 src/sys/rump/librump/rumpkern/vm.c
cvs rdiff -u -r1.24 -r1.25 src/sys/rump/librump/rumpvfs/vm_vfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/librump/rumpkern/vm.c
diff -u src/sys/rump/librump/rumpkern/vm.c:1.112 src/sys/rump/librump/rumpkern/vm.c:1.113
--- src/sys/rump/librump/rumpkern/vm.c:1.112	Tue Feb 22 18:43:20 2011
+++ src/sys/rump/librump/rumpkern/vm.c	Tue Feb 22 20:17:38 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm.c,v 1.112 2011/02/22 18:43:20 pooka Exp $	*/
+/*	$NetBSD: vm.c,v 1.113 2011/02/22 20:17:38 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.112 2011/02/22 18:43:20 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.113 2011/02/22 20:17:38 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -923,14 +923,27 @@
 uvm_pageout_start(int npages)
 {
 
-	/* we don't have the heuristics */
+	mutex_enter(&pdaemonmtx);
+	uvmexp.paging += npages;
+	mutex_exit(&pdaemonmtx);
 }
 
 void
 uvm_pageout_done(int npages)
 {
 
-	/* could wakeup waiters, but just let the pagedaemon do it */
+	if (!npages)
+		return;
+
+	mutex_enter(&pdaemonmtx);
+	KASSERT(uvmexp.paging >= npages);
+	uvmexp.paging -= npages;
+
+	if (pdaemon_waiters) {
+		pdaemon_waiters = 0;
+		cv_broadcast(&oomwait);
+	}
+	mutex_exit(&pdaemonmtx);
 }
 
 static bool
@@ -969,6 +982,8 @@
 
 /*
  * The Diabolical pageDaemon Director (DDD).
+ *
+ * This routine can always use better heuristics.
  */
 void
 uvm_pageout(void *arg)
@@ -976,35 +991,30 @@
 	struct vm_page *pg;
 	struct pool *pp, *pp_first;
 	uint64_t where;
-	int timo = 0;
 	int cleaned, skip, skipped;
-	bool succ = false;
+	int waspaging;
+	bool succ;
 	bool lockrunning;
 
 	mutex_enter(&pdaemonmtx);
 	for (;;) {
-		if (succ) {
+		if (!NEED_PAGEDAEMON()) {
 			kernel_map->flags &= ~VM_MAP_WANTVA;
 			kmem_map->flags &= ~VM_MAP_WANTVA;
-			timo = 0;
-			if (pdaemon_waiters) {
-				pdaemon_waiters = 0;
-				cv_broadcast(&oomwait);
-			}
 		}
-		succ = false;
 
-		if (pdaemon_waiters == 0) {
-			cv_timedwait(&pdaemoncv, &pdaemonmtx, timo);
-			uvmexp.pdwoke++;
+		if (pdaemon_waiters) {
+			pdaemon_waiters = 0;
+			cv_broadcast(&oomwait);
 		}
 
+		cv_wait(&pdaemoncv, &pdaemonmtx);
+		uvmexp.pdwoke++;
+		waspaging = uvmexp.paging;
+
 		/* tell the world that we are hungry */
 		kernel_map->flags |= VM_MAP_WANTVA;
 		kmem_map->flags |= VM_MAP_WANTVA;
-
-		if (pdaemon_waiters == 0 && !NEED_PAGEDAEMON())
-			continue;
 		mutex_exit(&pdaemonmtx);
 
 		/*
@@ -1014,7 +1024,6 @@
 		 */
 		pool_cache_reclaim(&pagecache);
 		if (!NEED_PAGEDAEMON()) {
-			succ = true;
 			mutex_enter(&pdaemonmtx);
 			continue;
 		}
@@ -1081,7 +1090,6 @@
 		 */
 		pool_cache_reclaim(&pagecache);
 		if (!NEED_PAGEDAEMON()) {
-			succ = true;
 			mutex_enter(&pdaemonmtx);
 			continue;
 		}
@@ -1118,13 +1126,14 @@
 		 * Unfortunately, the wife just borrowed it.
 		 */
 
-		if (!succ && cleaned == 0) {
+		mutex_enter(&pdaemonmtx);
+		if (!succ && cleaned == 0 && pdaemon_waiters &&
+		    uvmexp.paging == 0) {
 			rumpuser_dprintf("pagedaemoness: failed to reclaim "
 			    "memory ... sleeping (deadlock?)\n");
-			timo = hz;
+			cv_timedwait(&pdaemoncv, &pdaemonmtx, hz);
+			mutex_enter(&pdaemonmtx);
 		}
-
-		mutex_enter(&pdaemonmtx);
 	}
 
 	panic("you can swap out any time you like, but you can never leave");

Index: src/sys/rump/librump/rumpvfs/vm_vfs.c
diff -u src/sys/rump/librump/rumpvfs/vm_vfs.c:1.24 src/sys/rump/librump/rumpvfs/vm_vfs.c:1.25
--- src/sys/rump/librump/rumpvfs/vm_vfs.c:1.24	Sat Dec 18 11:45:09 2010
+++ src/sys/rump/librump/rumpvfs/vm_vfs.c	Tue Feb 22 20:17:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm_vfs.c,v 1.24 2010/12/18 11:45:09 pooka Exp $	*/
+/*	$NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.24 2010/12/18 11:45:09 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.25 2011/02/22 20:17:37 pooka Exp $");
 
 #include <sys/param.h>
 
@@ -67,7 +67,6 @@
 	}
 
 	uvm_pagermapout((vaddr_t)bp->b_data, npages);
-	uvm_pageout_done(pageout);
 
 	/* get uobj because we need it after pages might be recycled */
 	uobj = pgs[0]->uobject;
@@ -79,6 +78,8 @@
 	mutex_exit(&uvm_pageqlock);
 	mutex_exit(&uobj->vmobjlock);
 
+	uvm_pageout_done(pageout);
+
 	if (BUF_ISWRITE(bp) && (bp->b_cflags & BC_AGE) != 0) {
 		mutex_enter(bp->b_objlock);
 		vwakeup(bp);

Reply via email to