Skip to content

Commit 462607e

Browse files
rientjestorvalds
authored andcommitted
mm, oom: introduce helper function to process threads during scan
This patch introduces a helper function to process each thread during the iteration over the tasklist. A new return type, enum oom_scan_t, is defined to determine the future behavior of the iteration: - OOM_SCAN_OK: continue scanning the thread and find its badness, - OOM_SCAN_CONTINUE: do not consider this thread for oom kill, it's ineligible, - OOM_SCAN_ABORT: abort the iteration and return, or - OOM_SCAN_SELECT: always select this thread with the highest badness possible. There is no functional change with this patch. This new helper function will be used in the next patch in the memory controller. Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Signed-off-by: David Rientjes <rientjes@google.com> Cc: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Sha Zhengju <handai.szj@taobao.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 62ce1c7 commit 462607e

File tree

1 file changed

+65
-46
lines changed

1 file changed

+65
-46
lines changed

mm/oom_kill.c

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,59 @@ static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
288288
}
289289
#endif
290290

291+
enum oom_scan_t {
292+
OOM_SCAN_OK, /* scan thread and find its badness */
293+
OOM_SCAN_CONTINUE, /* do not consider thread for oom kill */
294+
OOM_SCAN_ABORT, /* abort the iteration and return */
295+
OOM_SCAN_SELECT, /* always select this thread first */
296+
};
297+
298+
static enum oom_scan_t oom_scan_process_thread(struct task_struct *task,
299+
struct mem_cgroup *memcg, unsigned long totalpages,
300+
const nodemask_t *nodemask, bool force_kill)
301+
{
302+
if (task->exit_state)
303+
return OOM_SCAN_CONTINUE;
304+
if (oom_unkillable_task(task, memcg, nodemask))
305+
return OOM_SCAN_CONTINUE;
306+
307+
/*
308+
* This task already has access to memory reserves and is being killed.
309+
* Don't allow any other task to have access to the reserves.
310+
*/
311+
if (test_tsk_thread_flag(task, TIF_MEMDIE)) {
312+
if (unlikely(frozen(task)))
313+
__thaw_task(task);
314+
if (!force_kill)
315+
return OOM_SCAN_ABORT;
316+
}
317+
if (!task->mm)
318+
return OOM_SCAN_CONTINUE;
319+
320+
if (task->flags & PF_EXITING) {
321+
/*
322+
* If task is current and is in the process of releasing memory,
323+
* allow the "kill" to set TIF_MEMDIE, which will allow it to
324+
* access memory reserves. Otherwise, it may stall forever.
325+
*
326+
* The iteration isn't broken here, however, in case other
327+
* threads are found to have already been oom killed.
328+
*/
329+
if (task == current)
330+
return OOM_SCAN_SELECT;
331+
else if (!force_kill) {
332+
/*
333+
* If this task is not being ptraced on exit, then wait
334+
* for it to finish before killing some other task
335+
* unnecessarily.
336+
*/
337+
if (!(task->group_leader->ptrace & PT_TRACE_EXIT))
338+
return OOM_SCAN_ABORT;
339+
}
340+
}
341+
return OOM_SCAN_OK;
342+
}
343+
291344
/*
292345
* Simple selection loop. We chose the process with the highest
293346
* number of 'points'. We expect the caller will lock the tasklist.
@@ -305,53 +358,19 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
305358
do_each_thread(g, p) {
306359
unsigned int points;
307360

308-
if (p->exit_state)
309-
continue;
310-
if (oom_unkillable_task(p, memcg, nodemask))
311-
continue;
312-
313-
/*
314-
* This task already has access to memory reserves and is
315-
* being killed. Don't allow any other task access to the
316-
* memory reserve.
317-
*
318-
* Note: this may have a chance of deadlock if it gets
319-
* blocked waiting for another task which itself is waiting
320-
* for memory. Is there a better alternative?
321-
*/
322-
if (test_tsk_thread_flag(p, TIF_MEMDIE)) {
323-
if (unlikely(frozen(p)))
324-
__thaw_task(p);
325-
if (!force_kill)
326-
return ERR_PTR(-1UL);
327-
}
328-
if (!p->mm)
361+
switch (oom_scan_process_thread(p, memcg, totalpages, nodemask,
362+
force_kill)) {
363+
case OOM_SCAN_SELECT:
364+
chosen = p;
365+
chosen_points = ULONG_MAX;
366+
/* fall through */
367+
case OOM_SCAN_CONTINUE:
329368
continue;
330-
331-
if (p->flags & PF_EXITING) {
332-
/*
333-
* If p is the current task and is in the process of
334-
* releasing memory, we allow the "kill" to set
335-
* TIF_MEMDIE, which will allow it to gain access to
336-
* memory reserves. Otherwise, it may stall forever.
337-
*
338-
* The loop isn't broken here, however, in case other
339-
* threads are found to have already been oom killed.
340-
*/
341-
if (p == current) {
342-
chosen = p;
343-
chosen_points = ULONG_MAX;
344-
} else if (!force_kill) {
345-
/*
346-
* If this task is not being ptraced on exit,
347-
* then wait for it to finish before killing
348-
* some other task unnecessarily.
349-
*/
350-
if (!(p->group_leader->ptrace & PT_TRACE_EXIT))
351-
return ERR_PTR(-1UL);
352-
}
353-
}
354-
369+
case OOM_SCAN_ABORT:
370+
return ERR_PTR(-1UL);
371+
case OOM_SCAN_OK:
372+
break;
373+
};
355374
points = oom_badness(p, memcg, nodemask, totalpages);
356375
if (points > chosen_points) {
357376
chosen = p;

0 commit comments

Comments
 (0)