kernel/sched/walt/halt: drain needs __balance_callbacks

drain_rq_cpu_stop as written, can and will add a call
to the balance_callbacks queue. This is possible with
the below calling sequence

  drain_rq_cpu_stop
  migrate_tasks
  pick_migrate_task
  pick_next_task
  pick_next_task-rt (first==true)
  set_next_task_rt
  rt_queue_push_tasks
  queue_balance_calllback (if rq has pushable tasks)
  --> entry added to balance_callbacks queue.

drain_rq_cpu_stop will release the rq lock and enable
interrupts without performing a balance callback. If
an interrupt which will attempt to acquire the rq
lock happens before this context switches out, the
balance callback will not have happened, and an
attempt to reaquire the rq lock will WARN.

Correct the warn by handling the callbacks prior to
releasing the locks and re-enabling interrupts.

Change-Id: I36f7b20cfaedac556a5a2418a299551bc2c34eb3
Signed-off-by: Stephen Dickey <quic_dickey@quicinc.com>
This commit is contained in:
Stephen Dickey 2022-07-29 12:23:41 -07:00 committed by Sai Harshini Nimmala
parent aca97f0a06
commit f6c65099e9

View File

@ -176,6 +176,8 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf)
rq->stop = stop;
}
void __balance_callbacks(struct rq *rq);
static int drain_rq_cpu_stop(void *data)
{
struct rq *rq = this_rq();
@ -183,6 +185,14 @@ static int drain_rq_cpu_stop(void *data)
rq_lock_irqsave(rq, &rf);
migrate_tasks(rq, &rf);
/*
* service any callbacks that were accumulated, prior to unlocking. such that
* any subsequent calls to rq_lock... will see an rq->balance_callback set to
* the default (0 or balance_push_callback);
*/
__balance_callbacks(rq);
rq_unlock_irqrestore(rq, &rf);
return 0;