On Tue, 1 Jun 2010, Luis Claudio R. Goncalves wrote: > oom-kill: give the dying task a higher priority (v5) > > In a system under heavy load it was observed that even after the > oom-killer selects a task to die, the task may take a long time to die. > > Right before sending a SIGKILL to the task selected by the oom-killer > this task has it's priority increased so that it can exit() exit soon, > freeing memory. That is accomplished by: > > /* > * We give our sacrificial lamb high priority and access to > * all the memory it needs. That way it should be able to > * exit() and clear out its resources quickly... > */ > p->rt.time_slice = HZ; > set_tsk_thread_flag(p, TIF_MEMDIE); > > It sounds plausible giving the dying task an even higher priority to be > sure it will be scheduled sooner and free the desired memory. It was > suggested on LKML using SCHED_FIFO:1, the lowest RT priority so that > this task won't interfere with any running RT task. > > If the dying task is already an RT task, leave it untouched. > > Another good suggestion, implemented here, was to avoid boosting the > dying task priority in case of mem_cgroup OOM. > > Signed-off-by: Luis Claudio R. Gonçalves <lclaudio@xxxxxxxx> > > diff --git a/mm/oom_kill.c b/mm/oom_kill.c > index 709aedf..67e18ca 100644 > --- a/mm/oom_kill.c > +++ b/mm/oom_kill.c > @@ -52,6 +52,22 @@ static int has_intersects_mems_allowed(struct task_struct *tsk) > return 0; > } > > +/* > + * If this is a system OOM (not a memcg OOM) and the task selected to be > + * killed is not already running at high (RT) priorities, speed up the > + * recovery by boosting the dying task to the lowest FIFO priority. > + * That helps with the recovery and avoids interfering with RT tasks. > + */ > +static void boost_dying_task_prio(struct task_struct *p, > + struct mem_cgroup *mem) > +{ > + if ((mem == NULL) && !rt_task(p)) { > + struct sched_param param; > + param.sched_priority = 1; > + sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); > + } > +} > + > /** > * badness - calculate a numeric value for how bad this task has been > * @p: task struct of which task we should calculate > @@ -277,8 +293,10 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, > * blocked waiting for another task which itself is waiting > * for memory. Is there a better alternative? > */ > - if (test_tsk_thread_flag(p, TIF_MEMDIE)) > + if (test_tsk_thread_flag(p, TIF_MEMDIE)) { > + boost_dying_task_prio(p, mem); > return ERR_PTR(-1UL); > + } > > /* > * This is in the process of releasing memory so wait for it That's unnecessary, if p already has TIF_MEMDIE set, then boost_dying_task_prio(p) has already been called. > @@ -291,9 +309,10 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, > * Otherwise we could get an easy OOM deadlock. > */ > if (p->flags & PF_EXITING) { > - if (p != current) > + if (p != current) { > + boost_dying_task_prio(p, mem); > return ERR_PTR(-1UL); > - > + } > chosen = p; > *ppoints = ULONG_MAX; > } This has the potential to actually make it harder to free memory if p is waiting to acquire a writelock on mm->mmap_sem in the exit path while the thread holding mm->mmap_sem is trying to run.