simple_lmk: Make reclaim deterministic

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>
fourteen
Sultan Alsawaf 5 years ago committed by Jenna
parent bfbd452015
commit f25447ebe2
  1. 38
      drivers/android/simple_lmk.c
  2. 4
      include/linux/simple_lmk.h
  3. 2
      mm/vmscan.c

@ -5,7 +5,6 @@
#define pr_fmt(fmt) "simple_lmk: " fmt
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/mm.h>
#include <linux/moduleparam.h>
@ -250,19 +249,8 @@ static int simple_lmk_reclaim_thread(void *data)
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;
@ -270,16 +258,18 @@ static int simple_lmk_reclaim_thread(void *data)
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)

@ -9,15 +9,11 @@ struct mm_struct;
#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)
{
}

@ -3759,7 +3759,6 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int alloc_order, int reclaim_o
* succeed.
*/
if (prepare_kswapd_sleep(pgdat, reclaim_order, 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.
@ -3796,7 +3795,6 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int alloc_order, int reclaim_o
*/
if (!remaining &&
prepare_kswapd_sleep(pgdat, reclaim_order, classzone_idx)) {
simple_lmk_stop_reclaim();
trace_mm_vmscan_kswapd_sleep(pgdat->node_id);
/*

Loading…
Cancel
Save