[PATCH 2/4] sched: Return idle task in pick_next_task for offlined CPU

From: Tim Chen
Date: Mon Jul 22 2019 - 19:13:45 EST


There could be races in core scheduler where a CPU is trying to pick
a task for its sibling in core scheduler, when that CPU has just been
offlined. We should not schedule any tasks on the CPU in this case.
Return an idle task in pick_next_task for this situation.

Signed-off-by: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx>
---
kernel/sched/core.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 44399f5434f8..1a132beba3f8 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4154,6 +4154,10 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
int i, j, cpu, occ = 0;
bool need_sync = false;

+ cpu = cpu_of(rq);
+ if (cpu_is_offline(cpu))
+ return idle_sched_class.pick_next_task(rq, prev, rf);
+
if (!sched_core_enabled(rq))
return __pick_next_task(rq, prev, rf);

@@ -4186,7 +4190,6 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
if (!rq->nr_running)
newidle_balance(rq, rf);

- cpu = cpu_of(rq);
smt_mask = cpu_smt_mask(cpu);

/*
@@ -4228,8 +4231,10 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
struct rq *rq_i = cpu_rq(i);
struct task_struct *p;

- if (cpu_is_offline(i))
+ if (cpu_is_offline(i)) {
+ rq_i->core_pick = rq_i->idle;
continue;
+ }

if (rq_i->core_pick)
continue;
--
2.20.1