• Tejun Heo's avatar
    sched_ext: Make watchdog handle ops.dispatch() looping stall · 0922f54f
    Tejun Heo authored
    The dispatch path retries if the local DSQ is still empty after
    ops.dispatch() either dispatched or consumed a task. This is both out of
    necessity and for convenience. It has to retry because the dispatch path
    might lose the tasks to dequeue while the rq lock is released while trying
    to migrate tasks across CPUs, and the retry mechanism makes ops.dispatch()
    implementation easier as it only needs to make some forward progress each
    iteration.
    
    However, this makes it possible for ops.dispatch() to stall CPUs by
    repeatedly dispatching ineligible tasks. If all CPUs are stalled that way,
    the watchdog or sysrq handler can't run and the system can't be saved. Let's
    address the issue by breaking out of the dispatch loop after 32 iterations.
    
    It is unlikely but not impossible for ops.dispatch() to legitimately go over
    the iteration limit. We want to come back to the dispatch path in such cases
    as not doing so risks stalling the CPU by idling with runnable tasks
    pending. As the previous task is still current in balance_scx(),
    resched_curr() doesn't do anything - it will just get cleared. Let's instead
    use scx_kick_bpf() which will trigger reschedule after switching to the next
    task which will likely be the idle task.
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    Reviewed-by: default avatarDavid Vernet <dvernet@meta.com>
    0922f54f
ext.c 141 KB