// SPDX-License-Identifier: GPL-2.0-only
/*
 *  linux/mm/oom_kill.c
 *
 *  Copyright (C)  1998,2000  Rik van Riel
 *	Thanks go out to Claus Fischer for some serious inspiration and
 *	for goading me into coding this file...
 *  Copyright (C)  2010  Google, Inc.
 *	Rewritten by David Rientjes
 *
 *  The routines in this file are used to kill a process when
 *  we're seriously out of memory. This gets called from __alloc_pages()
 *  in mm/page_alloc.c when we really run out of memory.
 *
 *  Since we won't call these routines often (on a well-configured
 *  machine) this file will double as a 'coding guide' and a signpost
 *  for newbie kernel hackers. It features several pointers to major
 *  kernel subsystems and hints as to where to find out what things do.
 */

/*
 * Official Linux v6.18: mm/oom_kill.c
 * https://github.com/torvalds/linux/blob/v6.18/mm/oom_kill.c#L766
 * Complete upstream scope, not an elided book-code reconstruction.
 * See GPL-2.0.txt. Not a standalone translation unit.
 */

static void mark_oom_victim(struct task_struct *tsk)
{
	const struct cred *cred;
	struct mm_struct *mm = tsk->mm;

	WARN_ON(oom_killer_disabled);
	/* OOM killer might race with memcg OOM */
	if (test_and_set_tsk_thread_flag(tsk, TIF_MEMDIE))
		return;

	/* oom_mm is bound to the signal struct life time. */
	if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
		mmgrab(tsk->signal->oom_mm);

	/*
	 * Make sure that the process is woken up from uninterruptible sleep
	 * if it is frozen because OOM killer wouldn't be able to free any
	 * memory and livelock. The freezer will thaw the tasks that are OOM
	 * victims regardless of the PM freezing and cgroup freezing states.
	 */
	thaw_process(tsk);
	atomic_inc(&oom_victims);
	cred = get_task_cred(tsk);
	trace_mark_victim(tsk, cred->uid.val);
	put_cred(cred);
}
