sched_ext: Fix exit_cpu accuracy for lockup paths

handle_lockup() uses raw_smp_processor_id() for exit_cpu, which is wrong
for two paths:

- scx_hardlockup_irq_workfn() has the hung CPU in a local variable but
  irq_work may run elsewhere. Pass the local cpu explicitly.
- scx_rcu_cpu_stall() records the detector CPU rather than the stalled
  one. Pass -1 for now. The next patch fixes this properly.

Signed-off-by: Cheng-Yang Chou <yphbchou0911@gmail.com>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Cheng-Yang Chou 2026-06-10 23:26:55 +08:00 committed by Tejun Heo
parent a5cc43414b
commit da428d572e
2 changed files with 9 additions and 8 deletions

View File

@ -5092,6 +5092,7 @@ bool scx_allow_ttwu_queue(const struct task_struct *p)
/**
* handle_lockup - sched_ext common lockup handler
* @exit_cpu: CPU to record in exit_info. Pass the stalled/hung CPU, not current.
* @fmt: format string
*
* Called on system stall or lockup condition and initiates abort of sched_ext
@ -5101,7 +5102,7 @@ bool scx_allow_ttwu_queue(const struct task_struct *p)
* resolve the lockup. %false if sched_ext is not enabled or abort was already
* initiated by someone else.
*/
static __printf(1, 2) bool handle_lockup(const char *fmt, ...)
static __printf(2, 3) bool handle_lockup(int exit_cpu, const char *fmt, ...)
{
struct scx_sched *sch;
va_list args;
@ -5117,7 +5118,7 @@ static __printf(1, 2) bool handle_lockup(const char *fmt, ...)
case SCX_ENABLING:
case SCX_ENABLED:
va_start(args, fmt);
ret = scx_verror(sch, fmt, args);
ret = scx_vexit(sch, SCX_EXIT_ERROR, 0, exit_cpu, fmt, args);
va_end(args);
return ret;
default:
@ -5139,7 +5140,7 @@ static __printf(1, 2) bool handle_lockup(const char *fmt, ...)
*/
bool scx_rcu_cpu_stall(void)
{
return handle_lockup("RCU CPU stall detected!");
return handle_lockup(-1, "RCU CPU stall detected!");
}
/**
@ -5154,11 +5155,13 @@ bool scx_rcu_cpu_stall(void)
*/
void scx_softlockup(u32 dur_s)
{
if (!handle_lockup("soft lockup - CPU %d stuck for %us", smp_processor_id(), dur_s))
int cpu = smp_processor_id();
if (!handle_lockup(cpu, "soft lockup - CPU %d stuck for %us", cpu, dur_s))
return;
printk_deferred(KERN_ERR "sched_ext: Soft lockup - CPU %d stuck for %us, disabling BPF scheduler\n",
smp_processor_id(), dur_s);
cpu, dur_s);
}
/*
@ -5173,7 +5176,7 @@ static void scx_hardlockup_irq_workfn(struct irq_work *work)
{
int cpu = atomic_xchg(&scx_hardlockup_cpu, -1);
if (cpu >= 0 && handle_lockup("hard lockup - CPU %d", cpu))
if (cpu >= 0 && handle_lockup(cpu, "hard lockup - CPU %d", cpu))
printk_deferred(KERN_ERR "sched_ext: Hard lockup - CPU %d, disabling BPF scheduler\n",
cpu);
}

View File

@ -1543,8 +1543,6 @@ __printf(5, 6) bool __scx_exit(struct scx_sched *sch, enum scx_exit_kind kind,
__scx_exit(sch, kind, exit_code, raw_smp_processor_id(), fmt, ##args)
#define scx_error(sch, fmt, args...) \
scx_exit((sch), SCX_EXIT_ERROR, 0, fmt, ##args)
#define scx_verror(sch, fmt, args) \
scx_vexit((sch), SCX_EXIT_ERROR, 0, raw_smp_processor_id(), fmt, args)
/*
* Return the rq currently locked from an scx callback, or NULL if no rq is