[PATCH v3 12/14] rcutorture: tighten boost-WARN to exclude any implicit-reader context

Joel Fernandes <[email protected]>
Newsgroups org.kernel.vger.rcu,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The Slow-deboost WARN_ON_ONCE in rcu_torture_one_read() currently uses
only the handler-context predicates to decide whether the calling
context is "safe" to assert immediate deboosting:

    !in_serving_softirq() && !in_hardirq() && !in_nmi()

They do NOT exclude several other contexts in which the task is still
holding an implicit RCU read-side critical section.

  1. local_bh_disable()-but-not-in-softirq.

  2. preempt_disable()-held.

  3. irqs_disabled().

  4. rcu_preempt_depth() > 0.

The current predicate set lets the WARN fire while these implicit
readers are still active, which is a false positive: the user-visible
"tardy deboost" finding becomes ambiguous between an actual
deferred-QS bug and a valid caller still inside an implicit-reader
section.

Replace the three handler-only predicates with the following which
covers everything.

    preempt_count() == 0 && !irqs_disabled() && rcu_preempt_depth() == 0

Note that we only check in contexts where rcu_read_unlock_special() deboosts
synchronously, i.e. where it is not inside an implicit RCU read-side
critical section. This matches rcu_read_unlock_special()'s own gate
and rcu_flavor_sched_clock_irq()'s:
 "rcu_preempt_depth() > 0 || (preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK))".

Also note, in PREEMPT_RT, softirqs always run under local_bh_disable(),
which itself takes rcu_read_lock() to satisfy RCU's bottom-half
requirement (see softirq.c) — so rcu_preempt_depth() is non-zero
throughout any RT softirq thus making in_serving_softirq() redundant.

Signed-off-by: Joel Fernandes <[email protected]>
---
 kernel/rcu/rcutorture.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 13e0eec1e1ce..e0bea4039c42 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -2603,7 +2603,8 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
 	// 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() &&
-			 !in_serving_softirq() && !in_hardirq() && !in_nmi()) &&
+			 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);
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.