android/lowmemorykiller: Wait for memory to be freed

The memory reclaim code needs to give time to the system to
return the memory from a killed process otherwise the memory
reclaim code could run continuously, in multiple threads,
which could starve both the watchdog thread and the thread
which is responsible for returning the memory from the
killed process.

Change-Id: Ieded4bfe038ca936247fa4b638070e979b02eaa1
CRs-fixed: 447740
Signed-off-by: Liam Mark <lmark@codeaurora.org>
This commit is contained in:
Liam Mark 2013-01-25 12:40:18 -08:00 committed by Stephen Boyd
parent 188798b1bf
commit 25f87e504b
1 changed files with 31 additions and 8 deletions

View File

@ -40,6 +40,8 @@
#include <linux/swap.h>
#include <linux/rcupdate.h>
#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/delay.h>
static uint32_t lowmem_debug_level = 1;
static short lowmem_adj[6] = {
@ -135,6 +137,8 @@ static int test_task_flag(struct task_struct *p, int flag)
return 0;
}
static DEFINE_MUTEX(scan_mutex);
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@ -147,11 +151,20 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
int selected_tasksize = 0;
short selected_oom_score_adj;
int array_size = ARRAY_SIZE(lowmem_adj);
int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
int other_file = global_page_state(NR_FILE_PAGES) -
int other_free;
int other_file;
unsigned long nr_to_scan = sc->nr_to_scan;
if (nr_to_scan > 0) {
if (mutex_lock_interruptible(&scan_mutex) < 0)
return 0;
}
other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
if (sc->nr_to_scan > 0 && other_free > other_file) {
if (nr_to_scan > 0 && other_free > other_file) {
/*
* If the number of free pages is going to affect the decision
* of which process is selected then ensure only free pages
@ -171,17 +184,21 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
break;
}
}
if (sc->nr_to_scan > 0)
if (nr_to_scan > 0)
lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %hd\n",
sc->nr_to_scan, sc->gfp_mask, other_free,
nr_to_scan, sc->gfp_mask, other_free,
other_file, min_score_adj);
rem = global_page_state(NR_ACTIVE_ANON) +
global_page_state(NR_ACTIVE_FILE) +
global_page_state(NR_INACTIVE_ANON) +
global_page_state(NR_INACTIVE_FILE);
if (sc->nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
if (nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",
sc->nr_to_scan, sc->gfp_mask, rem);
nr_to_scan, sc->gfp_mask, rem);
if (nr_to_scan > 0)
mutex_unlock(&scan_mutex);
return rem;
}
selected_oom_score_adj = min_score_adj;
@ -197,6 +214,9 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
if (test_task_flag(tsk, TIF_MEMDIE)) {
rcu_read_unlock();
/* give the system time to free up the memory */
msleep_interruptible(20);
mutex_unlock(&scan_mutex);
return 0;
}
}
@ -244,10 +264,13 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
send_sig(SIGKILL, selected, 0);
set_tsk_thread_flag(selected, TIF_MEMDIE);
rem -= selected_tasksize;
/* give the system time to free up the memory */
msleep_interruptible(20);
}
lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
sc->nr_to_scan, sc->gfp_mask, rem);
nr_to_scan, sc->gfp_mask, rem);
rcu_read_unlock();
mutex_unlock(&scan_mutex);
return rem;
}