summaryrefslogtreecommitdiffstats
path: root/mm/oom_kill.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r--mm/oom_kill.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index f0e8cd9edb1a..26ea8636758f 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -647,8 +647,8 @@ static int oom_reaper(void *unused)
647 647
648static void wake_oom_reaper(struct task_struct *tsk) 648static void wake_oom_reaper(struct task_struct *tsk)
649{ 649{
650 /* tsk is already queued? */ 650 /* mm is already queued? */
651 if (tsk == oom_reaper_list || tsk->oom_reaper_list) 651 if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
652 return; 652 return;
653 653
654 get_task_struct(tsk); 654 get_task_struct(tsk);
@@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
975 * still freeing memory. 975 * still freeing memory.
976 */ 976 */
977 read_lock(&tasklist_lock); 977 read_lock(&tasklist_lock);
978
979 /*
980 * The task 'p' might have already exited before reaching here. The
981 * put_task_struct() will free task_struct 'p' while the loop still try
982 * to access the field of 'p', so, get an extra reference.
983 */
984 get_task_struct(p);
978 for_each_thread(p, t) { 985 for_each_thread(p, t) {
979 list_for_each_entry(child, &t->children, sibling) { 986 list_for_each_entry(child, &t->children, sibling) {
980 unsigned int child_points; 987 unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
994 } 1001 }
995 } 1002 }
996 } 1003 }
1004 put_task_struct(p);
997 read_unlock(&tasklist_lock); 1005 read_unlock(&tasklist_lock);
998 1006
999 /* 1007 /*