svn commit: r337714 - head/sys/vm

Konstantin Belousov kib at FreeBSD.org
Mon Aug 13 16:48:48 UTC 2018


Author: kib
Date: Mon Aug 13 16:48:46 2018
New Revision: 337714
URL: https://svnweb.freebsd.org/changeset/base/337714

Log:
  Prevent some parallel swap-ins, rate-limit swapper swap-ins.
  
  If faultin() was called outside swapper (from PHOLD()), do not allow
  swapper to initiate additional swap-ins.  Swapper' initiated swap-ins
  are serialized because they are synchronous and executed in the
  context of the thread0.  With the added limitation, we only allow
  parallel swap-ins from PHOLD(), which is up to PHOLD() users to
  manage, usually they do not need to.
  
  Rate-limit swapper' swap-ins to one in the MAXSLP / 2 seconds
  interval, counting faultin() swapins.
  
  Suggested by:	alc
  Reviewed by:	alc, markj
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks
  Differential revision:	https://reviews.freebsd.org/D16610

Modified:
  head/sys/vm/vm_swapout.c

Modified: head/sys/vm/vm_swapout.c
==============================================================================
--- head/sys/vm/vm_swapout.c	Mon Aug 13 16:26:26 2018	(r337713)
+++ head/sys/vm/vm_swapout.c	Mon Aug 13 16:48:46 2018	(r337714)
@@ -159,6 +159,8 @@ static struct mtx vm_daemon_mtx;
 MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
 
 static int swapped_cnt;
+static int swap_inprogress;	/* Pending swap-ins done outside swapper. */
+static int last_swapin;
 
 static void swapclear(struct proc *);
 static int swapout(struct proc *);
@@ -634,6 +636,8 @@ faultin(struct proc *p)
 		sx_xlock(&allproc_lock);
 		MPASS(swapped_cnt > 0);
 		swapped_cnt--;
+		if (curthread != &thread0)
+			swap_inprogress++;
 		sx_xunlock(&allproc_lock);
 
 		/*
@@ -644,6 +648,13 @@ faultin(struct proc *p)
 		FOREACH_THREAD_IN_PROC(p, td)
 			vm_thread_swapin(td, oom_alloc);
 
+		if (curthread != &thread0) {
+			sx_xlock(&allproc_lock);
+			MPASS(swap_inprogress > 0);
+			swap_inprogress--;
+			last_swapin = ticks;
+			sx_xunlock(&allproc_lock);
+		}
 		PROC_LOCK(p);
 		swapclear(p);
 		p->p_swtick = ticks;
@@ -661,18 +672,17 @@ faultin(struct proc *p)
  */
 
 static struct proc *
-swapper_selector(void)
+swapper_selector(bool wkilled_only)
 {
 	struct proc *p, *res;
 	struct thread *td;
-	int min_flag, ppri, pri, slptime, swtime;
+	int ppri, pri, slptime, swtime;
 
 	sx_assert(&allproc_lock, SA_SLOCKED);
 	if (swapped_cnt == 0)
 		return (NULL);
 	res = NULL;
 	ppri = INT_MIN;
-	min_flag = vm_page_count_min();
 	FOREACH_PROC_IN_SYSTEM(p) {
 		PROC_LOCK(p);
 		if (p->p_state == PRS_NEW || (p->p_flag & (P_SWAPPINGOUT |
@@ -690,7 +700,7 @@ swapper_selector(void)
 			 */
 			return (p);
 		}
-		if (min_flag) {
+		if (wkilled_only) {
 			PROC_UNLOCK(p);
 			continue;
 		}
@@ -721,11 +731,29 @@ swapper_selector(void)
 		}
 		PROC_UNLOCK(p);
 	}
+
 	if (res != NULL)
 		PROC_LOCK(res);
 	return (res);
 }
 
+#define	SWAPIN_INTERVAL	(MAXSLP * hz / 2)
+
+/*
+ * Limit swapper to swap in one non-WKILLED process in MAXSLP/2
+ * interval, assuming that there is:
+ * - no memory shortage;
+ * - no parallel swap-ins;
+ * - no other swap-ins in the current SWAPIN_INTERVAL.
+ */
+static bool
+swapper_wkilled_only(void)
+{
+
+	return (vm_page_count_min() || swap_inprogress > 0 ||
+	    (u_int)(ticks - last_swapin) < SWAPIN_INTERVAL);
+}
+
 void
 swapper(void)
 {
@@ -733,11 +761,11 @@ swapper(void)
 
 	for (;;) {
 		sx_slock(&allproc_lock);
-		p = swapper_selector();
+		p = swapper_selector(swapper_wkilled_only());
 		sx_sunlock(&allproc_lock);
 
 		if (p == NULL) {
-			tsleep(&proc0, PVM, "swapin", MAXSLP * hz / 2);
+			tsleep(&proc0, PVM, "swapin", SWAPIN_INTERVAL);
 		} else {
 			PROC_LOCK_ASSERT(p, MA_OWNED);
 


More information about the svn-src-head mailing list