android/lowmemorykiller: Ignore tasks with freed mm
A killed task can stay in the task list long after its memory has been returned to the system, therefore ignore any tasks whose mm struct has been freed. Change-Id: I76394b203b4ab2312437c839976f0ecb7b6dde4e CRs-fixed: 450383 Signed-off-by: Liam Mark <lmark@codeaurora.org>
This commit is contained in:
committed by
Iliyan Malchev
parent
8eb221e7d3
commit
19ac1a8740
@@ -153,7 +153,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
||||
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
||||
#define TIF_RESTORE_SIGMASK 20
|
||||
#define TIF_SECCOMP 21
|
||||
|
||||
#define TIF_MM_RELEASED 22 /* task MM has been released */
|
||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
|
||||
@@ -283,6 +283,10 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
|
||||
if (tsk->flags & PF_KTHREAD)
|
||||
continue;
|
||||
|
||||
/* if task no longer has any memory ignore it */
|
||||
if (test_task_flag(tsk, TIF_MM_RELEASED))
|
||||
continue;
|
||||
|
||||
if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
|
||||
if (test_task_flag(tsk, TIF_MEMDIE)) {
|
||||
rcu_read_unlock();
|
||||
@@ -327,12 +331,14 @@ 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;
|
||||
rcu_read_unlock();
|
||||
/* give the system time to free up the memory */
|
||||
msleep_interruptible(20);
|
||||
}
|
||||
} else
|
||||
rcu_read_unlock();
|
||||
|
||||
lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
|
||||
nr_to_scan, sc->gfp_mask, rem);
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&scan_mutex);
|
||||
return rem;
|
||||
}
|
||||
|
||||
@@ -2304,7 +2304,7 @@ static inline void mmdrop(struct mm_struct * mm)
|
||||
}
|
||||
|
||||
/* mmput gets rid of the mappings and all user-space */
|
||||
extern void mmput(struct mm_struct *);
|
||||
extern int mmput(struct mm_struct *);
|
||||
/* Grab a reference to a task's mm, if it is not already going away */
|
||||
extern struct mm_struct *get_task_mm(struct task_struct *task);
|
||||
/*
|
||||
|
||||
@@ -639,6 +639,7 @@ static void exit_mm(struct task_struct * tsk)
|
||||
{
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
struct core_state *core_state;
|
||||
int mm_released;
|
||||
|
||||
mm_release(tsk, mm);
|
||||
if (!mm)
|
||||
@@ -683,7 +684,10 @@ static void exit_mm(struct task_struct * tsk)
|
||||
enter_lazy_tlb(mm, current);
|
||||
task_unlock(tsk);
|
||||
mm_update_next_owner(mm);
|
||||
mmput(mm);
|
||||
|
||||
mm_released = mmput(mm);
|
||||
if (mm_released)
|
||||
set_tsk_thread_flag(tsk, TIF_MM_RELEASED);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -581,8 +581,9 @@ EXPORT_SYMBOL_GPL(__mmdrop);
|
||||
/*
|
||||
* Decrement the use count and release all resources for an mm.
|
||||
*/
|
||||
void mmput(struct mm_struct *mm)
|
||||
int mmput(struct mm_struct *mm)
|
||||
{
|
||||
int mm_freed = 0;
|
||||
might_sleep();
|
||||
|
||||
if (atomic_dec_and_test(&mm->mm_users)) {
|
||||
@@ -600,7 +601,9 @@ void mmput(struct mm_struct *mm)
|
||||
if (mm->binfmt)
|
||||
module_put(mm->binfmt->module);
|
||||
mmdrop(mm);
|
||||
mm_freed = 1;
|
||||
}
|
||||
return mm_freed;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mmput);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user