]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rcu: Add lockdep checks and kernel-doc header to rcu_softirq_qs()
authorPaul E. McKenney <paulmck@kernel.org>
Tue, 27 Feb 2024 23:07:25 +0000 (15:07 -0800)
committerUladzislau Rezki (Sony) <urezki@gmail.com>
Tue, 9 Apr 2024 13:08:34 +0000 (15:08 +0200)
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 <paulmck@kernel.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Yan Zhai <yan@cloudflare.com>
Cc: <netdev@vger.kernel.org>
Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
kernel/rcu/tree.c

index d9642dd06c2535d9a59682e9b9416d980bd6703c..2795a1457acf7277721b0646db23768d1d989229 100644 (file)
@@ -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);