Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jan 2018 21:56:22 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r328175 - user/jeff/numa/sys/vm
Message-ID:  <201801192156.w0JLuMh4030826@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Fri Jan 19 21:56:22 2018
New Revision: 328175
URL: https://svnweb.freebsd.org/changeset/base/328175

Log:
  Implement the global vm_wait() and vm_waitpfault().  Document existing
  deficiencies in the design.  Optimize out wakeups.

Modified:
  user/jeff/numa/sys/vm/vm_page.c

Modified: user/jeff/numa/sys/vm/vm_page.c
==============================================================================
--- user/jeff/numa/sys/vm/vm_page.c	Fri Jan 19 21:36:28 2018	(r328174)
+++ user/jeff/numa/sys/vm/vm_page.c	Fri Jan 19 21:56:22 2018	(r328175)
@@ -137,6 +137,9 @@ struct mtx_padalign __exclusive_cache_line pa_lock[PA_
 struct mtx_padalign __exclusive_cache_line vm_domainset_lock;
 domainset_t __exclusive_cache_line vm_min_domains;
 domainset_t __exclusive_cache_line vm_severe_domains;
+static int vm_min_waiters;
+static int vm_severe_waiters;
+static int vm_pageproc_waiters;
 
 
 /*
@@ -2707,14 +2710,18 @@ vm_domain_clear(int domain)
 	if (vmd->vmd_minset && !vm_paging_min(vmd)) {
 		vmd->vmd_minset = 0;
 		DOMAINSET_CLR(domain, &vm_min_domains);
-		if (!vm_page_count_min())
+		if (!vm_page_count_min() && vm_min_waiters) {
+			vm_min_waiters = 0;
 			wakeup(&vm_min_domains);
+		}
 	}
 	if (vmd->vmd_severeset && !vm_paging_severe(vmd)) {
 		vmd->vmd_severeset = 0;
 		DOMAINSET_CLR(domain, &vm_severe_domains);
-		if (!vm_page_count_severe())
+		if (!vm_page_count_severe() && vm_severe_waiters) {
+			vm_severe_waiters = 0;
 			wakeup(&vm_severe_domains);
+		}
 	}
 	mtx_unlock(&vm_domainset_lock);
 }
@@ -2727,8 +2734,10 @@ vm_wait_min(void)
 {
 
 	mtx_lock(&vm_domainset_lock);
-	while (vm_page_count_min())
+	while (vm_page_count_min()) {
+		vm_min_waiters++;
 		msleep(&vm_min_domains, &vm_domainset_lock, PVM, "vmwait", 0);
+	}
 	mtx_unlock(&vm_domainset_lock);
 }
 
@@ -2740,8 +2749,10 @@ vm_wait_severe(void)
 {
 
 	mtx_lock(&vm_domainset_lock);
-	while (vm_page_count_min())
+	while (vm_page_count_min()) {
+		vm_severe_waiters++;
 		msleep(&vm_min_domains, &vm_domainset_lock, PVM, "vmwait", 0);
+	}
 	mtx_unlock(&vm_domainset_lock);
 }
 
@@ -2779,12 +2790,28 @@ vm_wait_domain(int domain)
 void
 vm_wait(void)
 {
-#if 0	/* XXX */
-	mtx_lock(&vm_page_queue_free_mtx);
-	_vm_wait();
-#else
-	pause("vmxxx", 1);
-#endif
+
+	/*
+	 * We use racey wakeup synchronization to avoid expensive global
+	 * locking for the pageproc when sleeping with a non-specific vm_wait.
+	 * To handle this, we only sleep for one tick in this instance.  It
+	 * is expected that most allocations for the pageproc will come from
+	 * kmem or vm_page_grab* which will use the more specific and
+	 * race-free vm_wait_domain().
+	 */
+	if (curproc == pageproc) {
+		mtx_lock(&vm_domainset_lock);
+		vm_pageproc_waiters++;
+		msleep(&vm_pageproc_waiters, &vm_domainset_lock, PVM,
+		    "pageprocwait", 1);
+		mtx_unlock(&vm_domainset_lock);
+	} else
+		/*
+		 * XXX Ideally we would wait only until the allocation could
+		 * be satisfied.  This condition can cause new allocators to
+		 * consume all freed pages while old allocators wait.
+		 */
+		vm_wait_min();
 }
 
 /*
@@ -2835,12 +2862,13 @@ vm_page_alloc_fail(vm_object_t object, int domain, int
 void
 vm_waitpfault(void)
 {
-#if 0	/* XXX */
-	mtx_lock(&vm_page_queue_free_mtx);
-	pagedaemon_wait(PUSER, "pfault");
-#else
-	pause("vmxxx", 1);
-#endif
+
+	mtx_lock(&vm_domainset_lock);
+	while (vm_page_count_min()) {
+		vm_min_waiters++;
+		msleep(&vm_min_domains, &vm_domainset_lock, PUSER, "pfault", 0);
+	}
+	mtx_unlock(&vm_domainset_lock);
 }
 
 struct vm_pagequeue *
@@ -3027,6 +3055,13 @@ vm_page_free_wakeup(int domain)
 	if ((vmd->vmd_minset && !vm_paging_min(vmd)) ||
 	    (vmd->vmd_severeset && !vm_paging_severe(vmd)))
 		vm_domain_clear(domain);
+
+	/* See comments in vm_wait(); */
+	if (vm_pageproc_waiters) {
+		vm_pageproc_waiters = 0;
+		wakeup(&vm_pageproc_waiters);
+	}
+
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801192156.w0JLuMh4030826>