Skip to content

Commit 058e877

Browse files
committed
rcu: Update lockdep while in RCU read-side critical section
With Ankur's lazy-/auto-preemption patches applied and with a lazy-preemptible kernel in combination with a non-preemptible RCU, lockdep sometimes complains about context switches within RCU read-side critical sections. This is a false positive due to rcu_read_unlock() updating lockdep state too late: __release(RCU); __rcu_read_unlock(); // Context switch here results in lockdep false positive!!! rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */ Although this complaint could also happen with preemptible RCU in a preemptible kernel, the odds of that happening aer quite low. In constrast, with non-preemptible RCU, a long critical section has a high probability of performing a context switch from the preempt_enable() in __rcu_read_unlock(). The fix is straightforward, just move the rcu_lock_release() within rcu_read_unlock() to obtain the reverse order from that of rcu_read_lock(): rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */ __release(RCU); __rcu_read_unlock(); This commit makes this change. Co-developed-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Frederic Weisbecker <frederic@kernel.org> Co-developed-by: Joel Fernandes (Google) <joel@joelfernandes.org> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org> Co-developed-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> Reviewed-by: Paul E. McKenney <paulmck@kernel.org> Cc: Ankur Arora <ankur.a.arora@oracle.com> Cc: Thomas Gleixner <tglx@linutronix.de>
1 parent 3183059 commit 058e877

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

include/linux/rcupdate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,9 +809,9 @@ static inline void rcu_read_unlock(void)
809809
{
810810
RCU_LOCKDEP_WARN(!rcu_is_watching(),
811811
"rcu_read_unlock() used illegally while idle");
812+
rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */
812813
__release(RCU);
813814
__rcu_read_unlock();
814-
rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */
815815
}
816816

817817
/**

0 commit comments

Comments
 (0)