The Slow-deboost detector in rcu_torture_one_read() checks for a still- boosted task immediately after the outer rcu_read_unlock() returns. Sub-microsecond checking is unrealistic for any async deboost mechanism (irq_work, softirq dispatch). As, even with a delay in deboosting of just 50us, the check beats it.
Therefore, poll the boost state for up to 500us before declaring the deboost tardy. Signed-off-by: Joel Fernandes <[email protected]> --- kernel/rcu/rcutorture.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index e0bea4039c42..12813b5381d6 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -2601,15 +2601,26 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid) // of arch_irq_work_raise()). On such systems, RCU cannot // guarantee to immediately deboost RCU readers when the outermost // rcu_read_unlock() does not end the full segmented RCU read-side - // critical section. - if (WARN_ON_ONCE(cur_ops->is_task_rcu_boosted && cur_ops->is_task_rcu_boosted() && - preempt_count() == 0 && !irqs_disabled() && - rcu_preempt_depth() == 0) && - READ_ONCE(firsttime) && xchg(&firsttime, 0)) { - nsegs = rtors.rtrsp - rtors.rtseg; - nsegs = clamp_val(nsegs, 0, RCUTORTURE_RDR_MAX_SEGS); - pr_alert("Slow-deboost rcutorture reader segments:\n"); - rcu_torture_dump_read_segs(rtors.rtseg, nsegs); + // critical section. Allow up to 500us for an async deboost + // mechanism (e.g. irq work, timers etc) to fire before + // declaring the deboost tardy. + if (cur_ops->is_task_rcu_boosted && cur_ops->is_task_rcu_boosted() && + preempt_count() == 0 && !irqs_disabled() && + rcu_preempt_depth() == 0) { + int wait_us; + + for (wait_us = 0; wait_us < 500; wait_us += 10) { + udelay(10); + if (!cur_ops->is_task_rcu_boosted()) + break; + } + if (WARN_ON_ONCE(cur_ops->is_task_rcu_boosted()) && + READ_ONCE(firsttime) && xchg(&firsttime, 0)) { + nsegs = rtors.rtrsp - rtors.rtseg; + nsegs = clamp_val(nsegs, 0, RCUTORTURE_RDR_MAX_SEGS); + pr_alert("Slow-deboost rcutorture reader segments:\n"); + rcu_torture_dump_read_segs(rtors.rtseg, nsegs); + } } return true; } -- 2.34.1

