Skip to content

Commit

Permalink
simple_lmk: Make reclaim deterministic
Browse files Browse the repository at this point in the history
The 20 ms delay in the reclaim thread is a hacky fudge factor that can
cause Simple LMK to behave wildly differently depending on the
circumstances of when it is invoked. When kswapd doesn't get enough CPU
time to finish up and go back to sleep within 20 ms, Simple LMK performs
superfluous reclaims.

This is suboptimal, so make Simple LMK more deterministic by eliminating
the delay and instead queuing up reclaim requests from kswapd.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
  • Loading branch information
kerneltoast committed Nov 4, 2019
1 parent 1d00279 commit 3383d87
Showing 1 changed file with 25 additions and 55 deletions.
80 changes: 25 additions & 55 deletions simple_lmk.patch
@@ -1,6 +1,6 @@
From e01f0454b9b6d48d1cde813a820cce273c40a739 Mon Sep 17 00:00:00 2001
From c440494d5b6ae7a57e5a87fd72a194f9e887512d Mon Sep 17 00:00:00 2001
From: Sultan Alsawaf <sultan@kerneltoast.com>
Date: Mon, 4 Nov 2019 10:49:21 -0800
Date: Mon, 4 Nov 2019 11:00:41 -0800
Subject: [PATCH] simple_lmk: Introduce Simple Low Memory Killer for Android

This is a complete low memory killer solution for Android that is small
Expand All @@ -20,11 +20,11 @@ Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
---
drivers/android/Kconfig | 44 +++++
drivers/android/Makefile | 1 +
drivers/android/simple_lmk.c | 325 +++++++++++++++++++++++++++++++++++
include/linux/simple_lmk.h | 26 +++
drivers/android/simple_lmk.c | 315 +++++++++++++++++++++++++++++++++++
include/linux/simple_lmk.h | 22 +++
kernel/fork.c | 2 +
mm/vmscan.c | 4 +
6 files changed, 402 insertions(+)
mm/vmscan.c | 2 +
6 files changed, 386 insertions(+)
create mode 100644 drivers/android/simple_lmk.c
create mode 100644 include/linux/simple_lmk.h

Expand Down Expand Up @@ -94,18 +94,17 @@ index 4b7c726bb560..5d4acf08db99 100644
+obj-$(CONFIG_ANDROID_SIMPLE_LMK) += simple_lmk.o
diff --git a/drivers/android/simple_lmk.c b/drivers/android/simple_lmk.c
new file mode 100644
index 000000000000..079281fdcb57
index 000000000000..bce8cf651b81
--- /dev/null
+++ b/drivers/android/simple_lmk.c
@@ -0,0 +1,325 @@
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Sultan Alsawaf <sultan@kerneltoast.com>.
+ */
+
+#define pr_fmt(fmt) "simple_lmk: " fmt
+
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
Expand Down Expand Up @@ -350,36 +349,27 @@ index 000000000000..079281fdcb57
+ sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_max_rt_prio);
+
+ while (1) {
+ wait_event(oom_waitq, atomic_read(&needs_reclaim));
+
+ /*
+ * Kill a batch of processes and wait for their memory to be
+ * freed. After their memory is freed, sleep for 20 ms to give
+ * OOM'd allocations a chance to scavenge for the newly-freed
+ * pages. Rinse and repeat while there are still OOM'd
+ * allocations.
+ */
+ do {
+ scan_and_kill(MIN_FREE_PAGES);
+ msleep(20);
+ } while (atomic_read(&needs_reclaim));
+ wait_event(oom_waitq, atomic_add_unless(&needs_reclaim, -1, 0));
+ scan_and_kill(MIN_FREE_PAGES);
+ }
+
+ return 0;
+}
+
+void simple_lmk_decide_reclaim(int kswapd_priority)
+{
+ if (kswapd_priority != CONFIG_ANDROID_SIMPLE_LMK_AGGRESSION)
+ return;
+
+ if (!atomic_cmpxchg(&needs_reclaim, 0, 1))
+ wake_up(&oom_waitq);
+}
+
+void simple_lmk_stop_reclaim(void)
+{
+ atomic_set(&needs_reclaim, 0);
+ if (kswapd_priority == CONFIG_ANDROID_SIMPLE_LMK_AGGRESSION) {
+ int v, v1;
+
+ for (v = 0;; v = v1) {
+ v1 = atomic_cmpxchg(&needs_reclaim, v, v + 1);
+ if (likely(v1 == v)) {
+ if (!v)
+ wake_up(&oom_waitq);
+ break;
+ }
+ }
+ }
+}
+
+void simple_lmk_mm_freed(struct mm_struct *mm)
Expand Down Expand Up @@ -425,10 +415,10 @@ index 000000000000..079281fdcb57
+module_param_cb(minfree, &simple_lmk_init_ops, NULL, 0200);
diff --git a/include/linux/simple_lmk.h b/include/linux/simple_lmk.h
new file mode 100644
index 000000000000..b0c247f2f2a5
index 000000000000..46cdb389be51
--- /dev/null
+++ b/include/linux/simple_lmk.h
@@ -0,0 +1,26 @@
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Sultan Alsawaf <sultan@kerneltoast.com>.
Expand All @@ -440,15 +430,11 @@ index 000000000000..b0c247f2f2a5
+
+#ifdef CONFIG_ANDROID_SIMPLE_LMK
+void simple_lmk_decide_reclaim(int kswapd_priority);
+void simple_lmk_stop_reclaim(void);
+void simple_lmk_mm_freed(struct mm_struct *mm);
+#else
+static inline void simple_lmk_decide_reclaim(int kswapd_priority)
+{
+}
+static inline void simple_lmk_stop_reclaim(void)
+{
+}
+static inline void simple_lmk_mm_freed(struct mm_struct *mm)
+{
+}
Expand Down Expand Up @@ -476,7 +462,7 @@ index a952249138ba..3afc310ddb47 100644
}

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 96372c657b50..cf69a0777ddf 100644
index 96372c657b50..f4fb2efd66cb 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -46,6 +46,7 @@
Expand All @@ -494,22 +480,6 @@ index 96372c657b50..cf69a0777ddf 100644
+ simple_lmk_decide_reclaim(sc.priority);
sc.nr_reclaimed = 0;

/*
@@ -3475,6 +3477,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order,
/* Try to sleep for a short interval */
if (prepare_kswapd_sleep(pgdat, order, remaining,
balanced_classzone_idx)) {
+ simple_lmk_stop_reclaim();
/*
* Compaction records what page blocks it recently failed to
* isolate pages from and skips them in the future scanning.
@@ -3500,6 +3503,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order,
*/
if (prepare_kswapd_sleep(pgdat, order, remaining,
balanced_classzone_idx)) {
+ simple_lmk_stop_reclaim();
trace_mm_vmscan_kswapd_sleep(pgdat->node_id);

/*
--
2.23.0
Expand Down

0 comments on commit 3383d87

Please sign in to comment.