Module Name:    src
Committed By:   ad
Date:           Sat Dec 21 14:50:35 UTC 2019

Modified Files:
        src/sys/kern: subr_vmem.c
        src/sys/uvm: uvm_page.c uvm_pdaemon.c uvm_pglist.c

Log Message:
Detangle the pagedaemon from uvm_fpageqlock:

- Have a single lock (uvmpd_lock) to protect pagedaemon state that was
  previously covered by uvmpd_pool_drain_lock plus uvm_fpageqlock.
- Don't require any locks be held when calling uvm_kick_pdaemon().
- Use uvm_free().


To generate a diff of this commit:
cvs rdiff -u -r1.99 -r1.100 src/sys/kern/subr_vmem.c
cvs rdiff -u -r1.209 -r1.210 src/sys/uvm/uvm_page.c
cvs rdiff -u -r1.116 -r1.117 src/sys/uvm/uvm_pdaemon.c
cvs rdiff -u -r1.76 -r1.77 src/sys/uvm/uvm_pglist.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/kern/subr_vmem.c
diff -u src/sys/kern/subr_vmem.c:1.99 src/sys/kern/subr_vmem.c:1.100
--- src/sys/kern/subr_vmem.c:1.99	Wed Oct 16 18:29:49 2019
+++ src/sys/kern/subr_vmem.c	Sat Dec 21 14:50:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_vmem.c,v 1.99 2019/10/16 18:29:49 christos Exp $	*/
+/*	$NetBSD: subr_vmem.c,v 1.100 2019/12/21 14:50:34 ad Exp $	*/
 
 /*-
  * Copyright (c)2006,2007,2008,2009 YAMAMOTO Takashi,
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.99 2019/10/16 18:29:49 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.100 2019/12/21 14:50:34 ad Exp $");
 
 #if defined(_KERNEL) && defined(_KERNEL_OPT)
 #include "opt_ddb.h"
@@ -198,9 +198,7 @@ static void
 vmem_kick_pdaemon(void)
 {
 #if defined(_KERNEL)
-	mutex_spin_enter(&uvm_fpageqlock);
 	uvm_kick_pdaemon();
-	mutex_spin_exit(&uvm_fpageqlock);
 #endif
 }
 

Index: src/sys/uvm/uvm_page.c
diff -u src/sys/uvm/uvm_page.c:1.209 src/sys/uvm/uvm_page.c:1.210
--- src/sys/uvm/uvm_page.c:1.209	Sat Dec 21 14:41:44 2019
+++ src/sys/uvm/uvm_page.c	Sat Dec 21 14:50:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page.c,v 1.209 2019/12/21 14:41:44 ad Exp $	*/
+/*	$NetBSD: uvm_page.c,v 1.210 2019/12/21 14:50:34 ad Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.209 2019/12/21 14:41:44 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.210 2019/12/21 14:50:34 ad Exp $");
 
 #include "opt_ddb.h"
 #include "opt_uvm.h"
@@ -878,8 +878,6 @@ uvm_pagealloc_strat(struct uvm_object *o
 	KASSERT(anon == NULL || anon->an_lock == NULL ||
 	    mutex_owned(anon->an_lock));
 
-	mutex_spin_enter(&uvm_fpageqlock);
-
 	/*
 	 * This implements a global round-robin page coloring
 	 * algorithm.
@@ -909,6 +907,7 @@ uvm_pagealloc_strat(struct uvm_object *o
 	 * we make kernel reserve pages available if called by a
 	 * kernel thread or a realtime thread.
 	 */
+	mutex_spin_enter(&uvm_fpageqlock);
 	l = curlwp;
 	if (__predict_true(l != NULL) && lwp_eprio(l) >= PRI_KTHREAD) {
 		flags |= UVM_PGA_USERESERVE;

Index: src/sys/uvm/uvm_pdaemon.c
diff -u src/sys/uvm/uvm_pdaemon.c:1.116 src/sys/uvm/uvm_pdaemon.c:1.117
--- src/sys/uvm/uvm_pdaemon.c:1.116	Sat Dec 21 11:41:18 2019
+++ src/sys/uvm/uvm_pdaemon.c	Sat Dec 21 14:50:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_pdaemon.c,v 1.116 2019/12/21 11:41:18 ad Exp $	*/
+/*	$NetBSD: uvm_pdaemon.c,v 1.117 2019/12/21 14:50:34 ad Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pdaemon.c,v 1.116 2019/12/21 11:41:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pdaemon.c,v 1.117 2019/12/21 14:50:34 ad Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_readahead.h"
@@ -112,7 +112,7 @@ static void	uvmpd_pool_drain_wakeup(void
 static unsigned int uvm_pagedaemon_waiters;
 
 /* State for the pool drainer thread */
-static kmutex_t uvmpd_pool_drain_lock __cacheline_aligned;
+static kmutex_t uvmpd_lock __cacheline_aligned;
 static kcondvar_t uvmpd_pool_drain_cv;
 static bool uvmpd_pool_drain_run = false;
 
@@ -136,7 +136,7 @@ uvm_wait(const char *wmsg)
 	if (uvm.pagedaemon_lwp == NULL)
 		panic("out of memory before the pagedaemon thread exists");
 
-	mutex_spin_enter(&uvm_fpageqlock);
+	mutex_spin_enter(&uvmpd_lock);
 
 	/*
 	 * check for page daemon going to sleep (waiting for itself)
@@ -170,27 +170,26 @@ uvm_wait(const char *wmsg)
 
 	uvm_pagedaemon_waiters++;
 	wakeup(&uvm.pagedaemon);		/* wake the daemon! */
-	UVM_UNLOCK_AND_WAIT(&uvmexp.free, &uvm_fpageqlock, false, wmsg, timo);
+	UVM_UNLOCK_AND_WAIT(&uvmexp.free, &uvmpd_lock, false, wmsg, timo);
 }
 
 /*
  * uvm_kick_pdaemon: perform checks to determine if we need to
  * give the pagedaemon a nudge, and do so if necessary.
- *
- * => called with uvm_fpageqlock held.
  */
 
 void
 uvm_kick_pdaemon(void)
 {
+	int fpages = uvm_free();
 
-	KASSERT(mutex_owned(&uvm_fpageqlock));
-
-	if (uvmexp.free + uvmexp.paging < uvmexp.freemin ||
-	    (uvmexp.free + uvmexp.paging < uvmexp.freetarg &&
+	if (fpages + uvmexp.paging < uvmexp.freemin ||
+	    (fpages + uvmexp.paging < uvmexp.freetarg &&
 	     uvmpdpol_needsscan_p()) ||
 	     uvm_km_va_starved_p()) {
+	     	mutex_spin_enter(&uvmpd_lock);
 		wakeup(&uvm.pagedaemon);
+	     	mutex_spin_exit(&uvmpd_lock);
 	}
 }
 
@@ -241,12 +240,14 @@ uvm_pageout(void *arg)
 {
 	int npages = 0;
 	int extrapages = 0;
+	int fpages;
 	
 	UVMHIST_FUNC("uvm_pageout"); UVMHIST_CALLED(pdhist);
 
 	UVMHIST_LOG(pdhist,"<starting uvm pagedaemon>", 0, 0, 0, 0);
 
-	mutex_init(&uvmpd_pool_drain_lock, MUTEX_DEFAULT, IPL_VM);
+	mutex_init(&uvmpd_lock, MUTEX_DEFAULT, IPL_VM);
+	mutex_init(&uvmpd_lock, MUTEX_DEFAULT, IPL_VM);
 	cv_init(&uvmpd_pool_drain_cv, "pooldrain");
 
 	/* Create the pool drainer kernel thread. */
@@ -271,16 +272,16 @@ uvm_pageout(void *arg)
 
 		kmem_va_starved = uvm_km_va_starved_p();
 
-		mutex_spin_enter(&uvm_fpageqlock);
+		mutex_spin_enter(&uvmpd_lock);
 		if ((uvm_pagedaemon_waiters == 0 || uvmexp.paging > 0) &&
 		    !kmem_va_starved) {
 			UVMHIST_LOG(pdhist,"  <<SLEEPING>>",0,0,0,0);
 			UVM_UNLOCK_AND_WAIT(&uvm.pagedaemon,
-			    &uvm_fpageqlock, false, "pgdaemon", 0);
+			    &uvmpd_lock, false, "pgdaemon", 0);
 			uvmexp.pdwoke++;
 			UVMHIST_LOG(pdhist,"  <<WOKE UP>>",0,0,0,0);
 		} else {
-			mutex_spin_exit(&uvm_fpageqlock);
+			mutex_spin_exit(&uvmpd_lock);
 		}
 
 		/*
@@ -290,9 +291,7 @@ uvm_pageout(void *arg)
 		if (npages != uvmexp.npages || extrapages != uvm_extrapages) {
 			npages = uvmexp.npages;
 			extrapages = uvm_extrapages;
-			mutex_spin_enter(&uvm_fpageqlock);
 			uvmpd_tune();
-			mutex_spin_exit(&uvm_fpageqlock);
 		}
 
 		uvmpdpol_tune();
@@ -301,33 +300,30 @@ uvm_pageout(void *arg)
 		 * Estimate a hint.  Note that bufmem are returned to
 		 * system only when entire pool page is empty.
 		 */
-		mutex_spin_enter(&uvm_fpageqlock);
-
+		fpages = uvm_free();
 		UVMHIST_LOG(pdhist,"  free/ftarg=%jd/%jd",
-		    uvmexp.free, uvmexp.freetarg, 0,0);
+		    fpages, uvmexp.freetarg, 0,0);
 
-		needsfree = uvmexp.free + uvmexp.paging < uvmexp.freetarg;
+		needsfree = fpages + uvmexp.paging < uvmexp.freetarg;
 		needsscan = needsfree || uvmpdpol_needsscan_p();
 
 		/*
 		 * scan if needed
 		 */
 		if (needsscan) {
-			mutex_spin_exit(&uvm_fpageqlock);
 			uvmpd_scan();
-			mutex_spin_enter(&uvm_fpageqlock);
 		}
 
 		/*
 		 * if there's any free memory to be had,
 		 * wake up any waiters.
 		 */
-		if (uvmexp.free > uvmexp.reserve_kernel ||
-		    uvmexp.paging == 0) {
+		if (uvm_free() > uvmexp.reserve_kernel || uvmexp.paging == 0) {
+			mutex_spin_enter(&uvmpd_lock);
 			wakeup(&uvmexp.free);
 			uvm_pagedaemon_waiters = 0;
+			mutex_spin_exit(&uvmpd_lock);
 		}
-		mutex_spin_exit(&uvm_fpageqlock);
 
 		/*
 		 * scan done.  if we don't need free memory, we're done.
@@ -382,14 +378,14 @@ uvm_pageout_done(int npages)
 	 * wake up either of pagedaemon or LWPs waiting for it.
 	 */
 
-	mutex_spin_enter(&uvm_fpageqlock);
-	if (uvmexp.free <= uvmexp.reserve_kernel) {
+	mutex_spin_enter(&uvmpd_lock);
+	if (uvm_free() <= uvmexp.reserve_kernel) {
 		wakeup(&uvm.pagedaemon);
-	} else {
+	} else if (uvm_pagedaemon_waiters != 0) {
 		wakeup(&uvmexp.free);
 		uvm_pagedaemon_waiters = 0;
 	}
-	mutex_spin_exit(&uvm_fpageqlock);
+	mutex_spin_exit(&uvmpd_lock);
 }
 
 /*
@@ -714,7 +710,7 @@ uvmpd_scan_queue(void)
 		 * see if we've met the free target.
 		 */
 
-		if (uvmexp.free + uvmexp.paging
+		if (uvm_free() + uvmexp.paging
 #if defined(VMSWAP)
 		    + swapcluster_nused(&swc)
 #endif /* defined(VMSWAP) */
@@ -843,7 +839,7 @@ uvmpd_scan_queue(void)
 		 * free target when all the current pageouts complete.
 		 */
 
-		if (uvmexp.free + uvmexp.paging > uvmexp.freetarg << 2) {
+		if (uvm_free() + uvmexp.paging > uvmexp.freetarg << 2) {
 			mutex_exit(slock);
 			continue;
 		}
@@ -926,7 +922,7 @@ uvmpd_scan_queue(void)
 static void
 uvmpd_scan(void)
 {
-	int swap_shortage, pages_freed;
+	int swap_shortage, pages_freed, fpages;
 	UVMHIST_FUNC("uvmpd_scan"); UVMHIST_CALLED(pdhist);
 
 	uvmexp.pdrevs++;
@@ -950,11 +946,12 @@ uvmpd_scan(void)
 	 */
 
 	swap_shortage = 0;
-	if (uvmexp.free < uvmexp.freetarg &&
+	fpages = uvm_free();
+	if (fpages < uvmexp.freetarg &&
 	    uvmexp.swpginuse >= uvmexp.swpgavail &&
 	    !uvm_swapisfull() &&
 	    pages_freed == 0) {
-		swap_shortage = uvmexp.freetarg - uvmexp.free;
+		swap_shortage = uvmexp.freetarg - fpages;
 	}
 
 	uvmpdpol_balancequeue(swap_shortage);
@@ -964,7 +961,7 @@ uvmpd_scan(void)
 	 * modules.
 	 */
 
-	if (uvmexp.free < uvmexp.freemin) {
+	if (uvm_free() < uvmexp.freemin) {
 		module_thread_kick();
 	}
 }
@@ -1038,19 +1035,17 @@ uvmpd_pool_drain_thread(void *arg)
 	int bufcnt;
 
 	for (;;) {
-		mutex_enter(&uvmpd_pool_drain_lock);
+		mutex_enter(&uvmpd_lock);
 		if (!uvmpd_pool_drain_run) {
-			cv_wait(&uvmpd_pool_drain_cv, &uvmpd_pool_drain_lock);
+			cv_wait(&uvmpd_pool_drain_cv, &uvmpd_lock);
 		}
 		uvmpd_pool_drain_run = false;
-		mutex_exit(&uvmpd_pool_drain_lock);
+		mutex_exit(&uvmpd_lock);
 
 		/*
 		 * kill unused metadata buffers.
 		 */
-		mutex_spin_enter(&uvm_fpageqlock);
-		bufcnt = uvmexp.freetarg - uvmexp.free;
-		mutex_spin_exit(&uvm_fpageqlock);
+		bufcnt = uvmexp.freetarg - uvm_free();
 		if (bufcnt < 0)
 			bufcnt = 0;
 
@@ -1070,8 +1065,8 @@ static void
 uvmpd_pool_drain_wakeup(void)
 {
 
-	mutex_enter(&uvmpd_pool_drain_lock);
+	mutex_enter(&uvmpd_lock);
 	uvmpd_pool_drain_run = true;
 	cv_signal(&uvmpd_pool_drain_cv);
-	mutex_exit(&uvmpd_pool_drain_lock);
+	mutex_exit(&uvmpd_lock);
 }

Index: src/sys/uvm/uvm_pglist.c
diff -u src/sys/uvm/uvm_pglist.c:1.76 src/sys/uvm/uvm_pglist.c:1.77
--- src/sys/uvm/uvm_pglist.c:1.76	Sat Dec 21 14:41:44 2019
+++ src/sys/uvm/uvm_pglist.c	Sat Dec 21 14:50:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_pglist.c,v 1.76 2019/12/21 14:41:44 ad Exp $	*/
+/*	$NetBSD: uvm_pglist.c,v 1.77 2019/12/21 14:50:34 ad Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.76 2019/12/21 14:41:44 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.77 2019/12/21 14:50:34 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -352,8 +352,8 @@ out:
 	 * the pagedaemon.
 	 */
 
-	uvm_kick_pdaemon();
 	mutex_spin_exit(&uvm_fpageqlock);
+	uvm_kick_pdaemon();
 	return (error);
 }
 
@@ -493,8 +493,8 @@ out:
 	 * the pagedaemon.
 	 */
 
-	uvm_kick_pdaemon();
 	mutex_spin_exit(&uvm_fpageqlock);
+	uvm_kick_pdaemon();
 
 	if (error) {
 		if (waitok) {

Reply via email to