[tip: sched/core] sched/rt: cpupri_find: Trigger a full search as fallback

From: tip-bot2 for Qais Yousef
Date: Fri Mar 20 2020 - 08:58:28 EST


The following commit has been merged into the sched/core branch of tip:

Commit-ID: e94f80f6c49020008e6fa0f3d4b806b8595d17d8
Gitweb: https://git.kernel.org/tip/e94f80f6c49020008e6fa0f3d4b806b8595d17d8
Author: Qais Yousef <qais.yousef@xxxxxxx>
AuthorDate: Thu, 05 Mar 2020 10:24:50
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Fri, 20 Mar 2020 13:06:20 +01:00

sched/rt: cpupri_find: Trigger a full search as fallback

If we failed to find a fitting CPU, in cpupri_find(), we only fallback
to the level we found a hit at.

But Steve suggested to fallback to a second full scan instead as this
could be a better effort.

https://lore.kernel.org/lkml/20200304135404.146c56eb@xxxxxxxxxxxxxxxxxx/

We trigger the 2nd search unconditionally since the argument about
triggering a full search is that the recorded fall back level might have
become empty by then. Which means storing any data about what happened
would be meaningless and stale.

I had a humble try at timing it and it seemed okay for the small 6 CPUs
system I was running on

https://lore.kernel.org/lkml/20200305124324.42x6ehjxbnjkklnh@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

On large system this second full scan could be expensive. But there are
no users outside capacity awareness for this fitness function at the
moment. Heterogeneous systems tend to be small with 8cores in total.

Suggested-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
Signed-off-by: Qais Yousef <qais.yousef@xxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Steven Rostedt (VMware) <rostedt@xxxxxxxxxxx>
Link: https://lkml.kernel.org/r/20200310142219.syxzn5ljpdxqtbgx@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
---
kernel/sched/cpupri.c | 29 ++++++-----------------------
1 file changed, 6 insertions(+), 23 deletions(-)

diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
index dd3f16d..0033731 100644
--- a/kernel/sched/cpupri.c
+++ b/kernel/sched/cpupri.c
@@ -122,8 +122,7 @@ int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
bool (*fitness_fn)(struct task_struct *p, int cpu))
{
int task_pri = convert_prio(p->prio);
- int best_unfit_idx = -1;
- int idx = 0, cpu;
+ int idx, cpu;

BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);

@@ -145,31 +144,15 @@ int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
* If no CPU at the current priority can fit the task
* continue looking
*/
- if (cpumask_empty(lowest_mask)) {
- /*
- * Store our fallback priority in case we
- * didn't find a fitting CPU
- */
- if (best_unfit_idx == -1)
- best_unfit_idx = idx;
-
+ if (cpumask_empty(lowest_mask))
continue;
- }

return 1;
}

/*
- * If we failed to find a fitting lowest_mask, make sure we fall back
- * to the last known unfitting lowest_mask.
- *
- * Note that the map of the recorded idx might have changed since then,
- * so we must ensure to do the full dance to make sure that level still
- * holds a valid lowest_mask.
- *
- * As per above, the map could have been concurrently emptied while we
- * were busy searching for a fitting lowest_mask at the other priority
- * levels.
+ * If we failed to find a fitting lowest_mask, kick off a new search
+ * but without taking into account any fitness criteria this time.
*
* This rule favours honouring priority over fitting the task in the
* correct CPU (Capacity Awareness being the only user now).
@@ -184,8 +167,8 @@ int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
* must do proper RT planning to avoid overloading the system if they
* really care.
*/
- if (best_unfit_idx != -1)
- return __cpupri_find(cp, p, lowest_mask, best_unfit_idx);
+ if (fitness_fn)
+ return cpupri_find(cp, p, lowest_mask);

return 0;
}