Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f721347 authored by Charan Teja Reddy's avatar Charan Teja Reddy
Browse files

mm: reorder oom kill logic in should_ulmk_retry()



Current implementation makes a process entered should_ulmk_retry()
after ULMK_TIMEOUT period from the previous kill, for reasons such as
high file cache which causes ignoring psi event, resulting into OOM.

Change-Id: I3d1938d3de8950256fb792471831bf012e5bdd33
Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
parent f9b1a9b7
Loading
Loading
Loading
Loading
+42 −6
Original line number Diff line number Diff line
@@ -90,11 +90,12 @@ module_param(ulmk_dbg_policy, uint, 0644);

static atomic64_t ulmk_wdog_expired = ATOMIC64_INIT(0);
static atomic64_t ulmk_kill_jiffies = ATOMIC64_INIT(INITIAL_JIFFIES);
static atomic64_t ulmk_watchdog_pet_jiffies = ATOMIC64_INIT(INITIAL_JIFFIES);
static unsigned long psi_emergency_jiffies = INITIAL_JIFFIES;
/* Prevents contention on the mutex_trylock in psi_emergency_jiffies */
static DEFINE_MUTEX(ulmk_retry_lock);

static bool ulmk_kill_possible(void)
static bool __maybe_unused ulmk_kill_possible(void)
{
	struct task_struct *tsk;
	bool ret = false;
@@ -129,7 +130,7 @@ static bool ulmk_kill_possible(void)
 */
bool should_ulmk_retry(gfp_t gfp_mask)
{
	unsigned long now, last_kill;
	unsigned long now, last_kill, last_wdog_pet;
	bool ret = true;
	bool wdog_expired, trigger_active;

@@ -155,13 +156,50 @@ bool should_ulmk_retry(gfp_t gfp_mask)

	now = jiffies;
	last_kill = atomic64_read(&ulmk_kill_jiffies);
	last_wdog_pet = atomic64_read(&ulmk_watchdog_pet_jiffies);
	wdog_expired = atomic64_read(&ulmk_wdog_expired);
	trigger_active = psi_is_trigger_active();

	/*
	 * Returning True causes direct reclaim retry and false
	 * causes to take OOM path.
	 * Conditions check is as below:
	 * a) If there is a kill after the previous update of
	 *    psi_emergency_jiffies, then system kills are happening
	 *    properly. Thus update the psi_emergency_jiffies with the
	 *    current time and return true.
	 *
	 * b) If no kill have had happened in the last ULMK_TIMEOUT and
	 *    LMKD also stuck for the last ULMK_TIMEOUT, which then means
	 *    that system kill logic is not responding despite PSI events
	 *    sent from kernel. Return false.
	 *
	 * c) Cond1: trigger = !active && wdog_expired = false:
	 *    Then give a chance to the ULMK by raising emergnecy trigger
	 *    which also registers a watchdog timer with timeout of
	 *    2 * trigger's ->win_size. And thus further process entering
	 *    gets returned with true.
	 *
	 *    Cond2: trigger = active && wdog_expired = true:
	 *    This represents that the previously raised event is not
	 *    consumed by ULMK in 2*HZ timeout. Under this condition we rely
	 *    on OOM killer to select the positive adj task and kill. If
	 *    the OOM killer fails to find a +ve adj task, we return false.
	 *
	 *    Cond3: trigger = !active && wdog_expired = true:
	 *    This is a case of previous events to previous are yet to be
	 *    consumed by ULMK, if triggered, thus only this process is
	 *    asked to raise the trigger and the subsequent ones in the
	 *    triggers ->win.size fall back to OOM.
	 *
	 *    Cond4: trigger = !active && wdog_expired = false:
	 *    ULMK is perfectly working fine.
	 */
	if (time_after(last_kill, psi_emergency_jiffies)) {
		psi_emergency_jiffies = now;
		ret = true;
	} else if (time_after(now, psi_emergency_jiffies + ULMK_TIMEOUT)) {
	} else if (time_after(now, psi_emergency_jiffies + ULMK_TIMEOUT) &&
		   time_after(now, last_wdog_pet + ULMK_TIMEOUT)) {
		ret = false;
	} else if (!trigger_active) {
		BUG_ON(ulmk_dbg_policy & ULMK_DBG_POLICY_TRIGGER);
@@ -172,9 +210,6 @@ bool should_ulmk_retry(gfp_t gfp_mask)
		ret = out_of_memory(&oc);
		mutex_unlock(&oom_lock);
		BUG_ON(!ret && ulmk_dbg_policy & ULMK_DBG_POLICY_POSITIVE_ADJ);
	} else if (!ulmk_kill_possible()) {
		BUG_ON(ulmk_dbg_policy & ULMK_DBG_POLICY_POSITIVE_ADJ);
		ret = false;
	}

	mutex_unlock(&ulmk_retry_lock);
@@ -191,6 +226,7 @@ void ulmk_watchdog_pet(struct timer_list *t)
{
	del_timer_sync(t);
	atomic64_set(&ulmk_wdog_expired, 0);
	atomic64_set(&ulmk_watchdog_pet_jiffies, jiffies);
}

void ulmk_update_last_kill(void)