From e8c7c3807756dc8dd6ff5ea0bf9b6bfad6e980f8 Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sat, 12 Feb 2022 00:06:03 +0530 Subject: [PATCH] sched: walt: take runnable into account for placement descision In case of fully loaded system with spare capacity 0 on all cores, placement logic selects previous cpu of the task for its placement. Update the logic to select cpu which has minimum number of runnables. Also, remove "active_candidate" as we always fallback to least runnable cpu. Change-Id: Ib698969d38dbe7fc7b08451f3c3637aba19a72bc Signed-off-by: Ashay Jaiswal --- kernel/sched/walt/trace.h | 18 ++++++++++++++---- kernel/sched/walt/walt_cfs.c | 32 +++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/kernel/sched/walt/trace.h b/kernel/sched/walt/trace.h index c55d8cbfc218..925529525709 100644 --- a/kernel/sched/walt/trace.h +++ b/kernel/sched/walt/trace.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #undef TRACE_SYSTEM @@ -1099,11 +1100,13 @@ TRACE_EVENT(sched_find_best_target, unsigned long candidates, int most_spare_cap, int order_index, int end_index, - int skip, bool running), + int skip, bool running, + int most_spare_rq_cpu, unsigned int cpu_rq_runnable_cnt), TP_ARGS(tsk, min_util, start_cpu, candidates, most_spare_cap, - order_index, end_index, skip, running), + order_index, end_index, skip, running, + most_spare_rq_cpu, cpu_rq_runnable_cnt), TP_STRUCT__entry( __array(char, comm, TASK_COMM_LEN) @@ -1116,6 +1119,8 @@ TRACE_EVENT(sched_find_best_target, __field(int, end_index) __field(int, skip) __field(bool, running) + __field(int, most_spare_rq_cpu) + __field(unsigned int, cpu_rq_runnable_cnt) ), TP_fast_assign( @@ -1129,9 +1134,11 @@ TRACE_EVENT(sched_find_best_target, __entry->end_index = end_index; __entry->skip = skip; __entry->running = running; + __entry->most_spare_rq_cpu = most_spare_rq_cpu; + __entry->cpu_rq_runnable_cnt = cpu_rq_runnable_cnt; ), - TP_printk("pid=%d comm=%s start_cpu=%d candidates=%#lx most_spare_cap=%d order_index=%d end_index=%d skip=%d running=%d", + TP_printk("pid=%d comm=%s start_cpu=%d candidates=%#lx most_spare_cap=%d order_index=%d end_index=%d skip=%d running=%d min_util=%lu spare_rq_cpu=%d min_runnable=%u", __entry->pid, __entry->comm, __entry->start_cpu, __entry->candidates, @@ -1139,7 +1146,10 @@ TRACE_EVENT(sched_find_best_target, __entry->order_index, __entry->end_index, __entry->skip, - __entry->running) + __entry->running, + __entry->min_util, + __entry->most_spare_rq_cpu, + __entry->cpu_rq_runnable_cnt) ); TRACE_EVENT(sched_enq_deq_task, diff --git a/kernel/sched/walt/walt_cfs.c b/kernel/sched/walt/walt_cfs.c index 4dbd39afbce2..c2bd0d064d18 100644 --- a/kernel/sched/walt/walt_cfs.c +++ b/kernel/sched/walt/walt_cfs.c @@ -227,6 +227,7 @@ static inline bool is_complex_sibling_idle(int cpu) return false; } +#define DIRE_STRAITS_PREV_NR_LIMIT 10 static void walt_find_best_target(struct sched_domain *sd, cpumask_t *candidates, struct task_struct *p, @@ -239,8 +240,9 @@ static void walt_find_best_target(struct sched_domain *sd, int i, start_cpu; long spare_wake_cap, most_spare_wake_cap = 0; int most_spare_cap_cpu = -1; + int least_nr_cpu = -1; + unsigned int cpu_rq_runnable_cnt = UINT_MAX; int prev_cpu = task_cpu(p); - int active_candidate = -1; int order_index = fbt_env->order_index, end_index = fbt_env->end_index; int stop_index = INT_MAX; int cluster; @@ -311,9 +313,6 @@ static void walt_find_best_target(struct sched_domain *sd, if (cpu_halted(i)) continue; - if (active_candidate == -1) - active_candidate = i; - /* * This CPU is the target of an active migration that's * yet to complete. Avoid placing another task on it. @@ -344,6 +343,16 @@ static void walt_find_best_target(struct sched_domain *sd, most_spare_cap_cpu = i; } + /* + * Keep track of runnables for each CPU, if none of the + * CPUs have spare capacity then use CPU with less + * number of runnables. + */ + if (cpu_rq(i)->nr_running < cpu_rq_runnable_cnt) { + cpu_rq_runnable_cnt = cpu_rq(i)->nr_running; + least_nr_cpu = i; + } + /* * Ensure minimum capacity to grant the required boost. * The target CPU can be already at a capacity level higher @@ -455,21 +464,26 @@ static void walt_find_best_target(struct sched_domain *sd, * We have set idle or target as long as they are valid CPUs. * If we don't find either, then we fallback to most_spare_cap, * If we don't find most spare cap, we fallback to prev_cpu, - * provided that the prev_cpu is active. - * If the prev_cpu is not active, we fallback to active_candidate. + * provided that the prev_cpu is active and has less than + * DIRE_STRAITS_PREV_NR_LIMIT runnables otherwise, we fallback to cpu + * with least number of runnables. */ if (unlikely(cpumask_empty(candidates))) { if (most_spare_cap_cpu != -1) cpumask_set_cpu(most_spare_cap_cpu, candidates); - else if (!cpu_active(prev_cpu) && active_candidate != -1) - cpumask_set_cpu(active_candidate, candidates); + else if (cpu_active(prev_cpu) + && (cpu_rq(prev_cpu)->nr_running < DIRE_STRAITS_PREV_NR_LIMIT)) + cpumask_set_cpu(prev_cpu, candidates); + else if (least_nr_cpu != -1) + cpumask_set_cpu(least_nr_cpu, candidates); } out: trace_sched_find_best_target(p, min_task_util, start_cpu, cpumask_bits(candidates)[0], most_spare_cap_cpu, order_index, end_index, - fbt_env->skip_cpu, task_on_rq_queued(p)); + fbt_env->skip_cpu, task_on_rq_queued(p), least_nr_cpu, + cpu_rq_runnable_cnt); } static inline unsigned long