Skip to content

Commit 175b45e

Browse files
paulmckrcuBoqun Feng
authored andcommitted
srcu: Use raw spinlocks so call_srcu() can be used under preempt_disable()
Tree SRCU has used non-raw spinlocks for many years, motivated by a desire to avoid unnecessary real-time latency and the absence of any reason to use raw spinlocks. However, the recent use of SRCU in tracing as the underlying implementation of RCU Tasks Trace means that call_srcu() is invoked from preemption-disabled regions of code, which in turn requires that any locks acquired by call_srcu() or its callees must be raw spinlocks. This commit therefore converts SRCU's spinlocks to raw spinlocks. [boqun: Add Fixes tag] Reported-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Fixes: c27cea4 ("rcu: Re-implement RCU Tasks Trace in terms of SRCU-fast") Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Signed-off-by: Boqun Feng <boqun@kernel.org> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
1 parent f338e77 commit 175b45e

3 files changed

Lines changed: 82 additions & 109 deletions

File tree

include/linux/srcutree.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct srcu_data {
3434
/* Values: SRCU_READ_FLAVOR_.* */
3535

3636
/* Update-side state. */
37-
spinlock_t __private lock ____cacheline_internodealigned_in_smp;
37+
raw_spinlock_t __private lock ____cacheline_internodealigned_in_smp;
3838
struct rcu_segcblist srcu_cblist; /* List of callbacks.*/
3939
unsigned long srcu_gp_seq_needed; /* Furthest future GP needed. */
4040
unsigned long srcu_gp_seq_needed_exp; /* Furthest future exp GP. */
@@ -55,7 +55,7 @@ struct srcu_data {
5555
* Node in SRCU combining tree, similar in function to rcu_data.
5656
*/
5757
struct srcu_node {
58-
spinlock_t __private lock;
58+
raw_spinlock_t __private lock;
5959
unsigned long srcu_have_cbs[4]; /* GP seq for children having CBs, but only */
6060
/* if greater than ->srcu_gp_seq. */
6161
unsigned long srcu_data_have_cbs[4]; /* Which srcu_data structs have CBs for given GP? */
@@ -74,7 +74,7 @@ struct srcu_usage {
7474
/* First node at each level. */
7575
int srcu_size_state; /* Small-to-big transition state. */
7676
struct mutex srcu_cb_mutex; /* Serialize CB preparation. */
77-
spinlock_t __private lock; /* Protect counters and size state. */
77+
raw_spinlock_t __private lock; /* Protect counters and size state. */
7878
struct mutex srcu_gp_mutex; /* Serialize GP work. */
7979
unsigned long srcu_gp_seq; /* Grace-period seq #. */
8080
unsigned long srcu_gp_seq_needed; /* Latest gp_seq needed. */
@@ -156,7 +156,7 @@ struct srcu_struct {
156156

157157
#define __SRCU_USAGE_INIT(name) \
158158
{ \
159-
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
159+
.lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \
160160
.srcu_gp_seq = SRCU_GP_SEQ_INITIAL_VAL, \
161161
.srcu_gp_seq_needed = SRCU_GP_SEQ_INITIAL_VAL_WITH_STATE, \
162162
.srcu_gp_seq_needed_exp = SRCU_GP_SEQ_INITIAL_VAL, \

kernel/rcu/rcu.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,15 @@ do { \
502502
___locked; \
503503
})
504504

505+
#define raw_spin_trylock_irqsave_rcu_node(p, flags) \
506+
({ \
507+
bool ___locked = raw_spin_trylock_irqsave(&ACCESS_PRIVATE(p, lock), flags); \
508+
\
509+
if (___locked) \
510+
smp_mb__after_unlock_lock(); \
511+
___locked; \
512+
})
513+
505514
#define raw_lockdep_assert_held_rcu_node(p) \
506515
lockdep_assert_held(&ACCESS_PRIVATE(p, lock))
507516

0 commit comments

Comments
 (0)