From: Paul E. McKenney Date: Tue, 27 Feb 2024 23:07:25 +0000 (-0800) Subject: rcu: Add lockdep checks and kernel-doc header to rcu_softirq_qs() X-Git-Tag: v6.10-rc1~234^2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3183059ad82a0daa8292daf43c325bac57daceb5;p=thirdparty%2Fkernel%2Flinux.git rcu: Add lockdep checks and kernel-doc header to rcu_softirq_qs() There is some indications that rcu_softirq_qs() might be more generally used than anticipated. This commit therefore adds some lockdep assertions and some cautionary tales in a new kernel-doc header. Link: https://lore.kernel.org/all/Zd4DXTyCf17lcTfq@debian.debian/ Signed-off-by: Paul E. McKenney Cc: Eric Dumazet Cc: Jakub Kicinski Cc: "David S. Miller" Cc: Yan Zhai Cc: Signed-off-by: Uladzislau Rezki (Sony) --- diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index d9642dd06c253..2795a1457acf7 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -240,8 +240,36 @@ static long rcu_get_n_cbs_cpu(int cpu) return 0; } +/** + * rcu_softirq_qs - Provide a set of RCU quiescent states in softirq processing + * + * Mark a quiescent state for RCU, Tasks RCU, and Tasks Trace RCU. + * This is a special-purpose function to be used in the softirq + * infrastructure and perhaps the occasional long-running softirq + * handler. + * + * Note that from RCU's viewpoint, a call to rcu_softirq_qs() is + * equivalent to momentarily completely enabling preemption. For + * example, given this code:: + * + * local_bh_disable(); + * do_something(); + * rcu_softirq_qs(); // A + * do_something_else(); + * local_bh_enable(); // B + * + * A call to synchronize_rcu() that began concurrently with the + * call to do_something() would be guaranteed to wait only until + * execution reached statement A. Without that rcu_softirq_qs(), + * that same synchronize_rcu() would instead be guaranteed to wait + * until execution reached statement B. + */ void rcu_softirq_qs(void) { + RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || + lock_is_held(&rcu_lock_map) || + lock_is_held(&rcu_sched_lock_map), + "Illegal rcu_softirq_qs() in RCU read-side critical section"); rcu_qs(); rcu_preempt_deferred_qs(current); rcu_tasks_qs(current, false);