Commit 39eaf73c authored by Liam Mark's avatar Liam Mark
Browse files

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: default avatarLiam Mark <lmark@codeaurora.org>
parent c0054d24
Loading
Loading
Loading
Loading
+31 −8
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@
#include <linux/sched.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 int lowmem_adj[6] = {
@@ -132,6 +134,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;
@@ -143,11 +147,20 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
	int selected_tasksize = 0;
	int selected_oom_score_adj;
	int array_size = ARRAY_SIZE(lowmem_adj);
	int other_free = global_page_state(NR_FREE_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);
	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
@@ -167,17 +180,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 %d\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;
@@ -193,6 +210,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;
			}
		}
@@ -231,10 +251,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;
}