aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_swapout.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2018-08-13 16:48:46 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2018-08-13 16:48:46 +0000
commitc1344d2bbe832b2755c9f5a44d6fc30e3b7a0ddb (patch)
tree9f9d4b41c484a98a2b56daac35e2dfcd2c5ec21e /sys/vm/vm_swapout.c
parent51f42bad71b9a5aaa55198cf4ce28093fa8ce7d7 (diff)
downloadsrc-c1344d2bbe832b2755c9f5a44d6fc30e3b7a0ddb.tar.gz
src-c1344d2bbe832b2755c9f5a44d6fc30e3b7a0ddb.zip
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
Notes
Notes: svn path=/head/; revision=337714
Diffstat (limited to 'sys/vm/vm_swapout.c')
-rw-r--r--sys/vm/vm_swapout.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/sys/vm/vm_swapout.c b/sys/vm/vm_swapout.c
index 343ff830f0c6..b6a081dcb376 100644
--- a/sys/vm/vm_swapout.c
+++ b/sys/vm/vm_swapout.c
@@ -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);