SRCU updates
cover SRCU updates
Hello!
This series contains a few SRCU updates:
1. Move rcu_scheduler_starting() from Tiny RCU to Tiny SRCU.
2. Remove obsolete SRCU-C.boot kernel-parameter file
3. Make process_srcu() be static.
4. Provide ordering for CPU not involved in grace period.
Thanx, Paul
------------------------------------------------------------------------
b/include/linux/rcupdate.h | 1 b/include/linux/rcutiny.h | 8 -- b/include/linux/srcutree.h | 2 b/kernel/rcu/srcutiny.c | 8 ++ b/kernel/rcu/srcutree.c | 13 +++ b/kernel/rcu/tiny.c | 2 kernel/rcu/tiny_plugin.h | 47 ------------- tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot | 1 8 files changed, 23 insertions(+), 59 deletions(-)
PATCH 1/4 srcu: Move rcu_scheduler_starting() from Tiny RCU to Tiny SRCU
Other than lockdep support, Tiny RCU has no need for the scheduler status. However, Tiny SRCU will need this to control boot-time behavior independent of lockdep. Therefore, this commit moves rcu_scheduler_starting() from kernel/rcu/tiny_plugin.h to kernel/rcu/srcutiny.c. This in turn allows the complete removal of kernel/rcu/tiny_plugin.h.
--- include/linux/rcupdate.h | 1 + include/linux/rcutiny.h | 8 +++----- kernel/rcu/srcutiny.c | 8 ++++++++ kernel/rcu/tiny.c | 2 -- kernel/rcu/tiny_plugin.h | 47 ----------------------------------------------- 5 files changed, 12 insertions(+), 54 deletions(-) delete mode 100644 kernel/rcu/tiny_plugin.h
include/linux/rcupdate.h +1 -0
@@ -105,6 +105,7 @@ static inline int rcu_preempt_depth(void)/* Internal to kernel */ void rcu_init (void ); +extern int rcu_scheduler_active__read_mostly ;void rcu_sched_qs (void );void rcu_bh_qs (void );void rcu_check_callbacks (int user);
include/linux/rcutiny.h +3 -5
@@ -116,13 +116,11 @@ static inline void rcu_irq_exit_irqson(void) { }static inline void rcu_irq_enter_irqson (void ) { }static inline void rcu_irq_exit (void ) { }static inline void exit_rcu (void ) { } - -#if defined(CONFIG_DEBUG_LOCK_ALLOC ) || defined(CONFIG_SRCU ) -extern int rcu_scheduler_active__read_mostly ; +#ifdef CONFIG_SRCU void rcu_scheduler_starting (void ); -#else /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU) */ +#else /* #ifndef CONFIG_SRCU */ static inline void rcu_scheduler_starting (void ) { } -#endif /* #else #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU) */ +#endif /* #else #ifndef CONFIG_SRCU */ static inline void rcu_end_inkernel_boot (void ) { }static inline bool rcu_is_watching (void ) {return true; }
kernel/rcu/srcutiny.c +8 -0
@@ -33,6 +33,8 @@#include "rcu_segcblist.h" #include "rcu.h" +int rcu_scheduler_active__read_mostly ; +static int init_srcu_struct_fields (struct srcu_struct *sp) { sp->srcu_lock_nesting[0 ] =0 ;
@@ -193,3 +195,9 @@ void synchronize_srcu(struct srcu_struct *sp)destroy_rcu_head_on_stack (&rs.head); }EXPORT_SYMBOL_GPL (synchronize_srcu); + +/* Lockdep diagnostics. */ +void __init rcu_scheduler_starting (void ) +{ + rcu_scheduler_active =RCU_SCHEDULER_RUNNING ; +}
kernel/rcu/tiny.c +0 -2
@@ -56,8 +56,6 @@ static struct rcu_ctrlblk rcu_bh_ctrlblk = { .curtail = &rcu_bh_ctrlblk.rcucblist, }; -#include "tiny_plugin.h" -void rcu_barrier_bh (void ) {wait_rcu_gp (call_rcu_bh);
kernel/rcu/tiny_plugin.h deleted +0 -47
47 lines not on this page · raw message
Signature · 1 line
2.5.2
PATCH 2/4 rcutorture: Remove obsolete SRCU-C.boot
In reply to Paul E. McKenneyClassic SRCU is no more, so this commit removes the corresponding rcutorture boot-parameters file.
--- tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot
tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot deleted +0 -1
@@ -1 +0,0 @@ -rcutorture.torture_type=srcud
Signature · 1 line
2.5.2
PATCH 3/4 srcu: Make process_srcu() be static
In reply to Paul E. McKenneyThe function process_srcu() is not invoked outside of srcutree.c, so this commit makes it static and drops the EXPORT_SYMBOL_GPL().
--- include/linux/srcutree.h | 2 -- kernel/rcu/srcutree.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-)
include/linux/srcutree.h +0 -2
@@ -104,8 +104,6 @@ struct srcu_struct {#define SRCU_STATE_SCAN1 1#define SRCU_STATE_SCAN2 2 -void process_srcu (struct work_struct *work); -#define __SRCU_STRUCT_INIT (name) \ { \ .sda = &name##_srcu_data, \
kernel/rcu/srcutree.c +2 -2
@@ -51,6 +51,7 @@ module_param(counter_wrap_check, ulong, 0444);static void srcu_invoke_callbacks (struct work_struct *work);static void srcu_reschedule (struct srcu_struct *sp,unsigned long delay); +static void process_srcu (struct work_struct *work);/* * Initialize SRCU combining tree. Note that statically allocated
@@ -1194,7 +1195,7 @@ static void srcu_reschedule(struct srcu_struct *sp, unsigned long delay)/* * This is the work-queue function that handles SRCU grace periods. */ -void process_srcu (struct work_struct *work) +static void process_srcu (struct work_struct *work) {struct srcu_struct *sp;
@@ -1203,7 +1204,6 @@ void process_srcu(struct work_struct *work)srcu_advance_state (sp);srcu_reschedule (sp,srcu_get_delay (sp)); } -EXPORT_SYMBOL_GPL (process_srcu); void srcutorture_get_gp_data(enum rcutorture_type test_type, struct srcu_struct *sp, int *flags,
Signature · 1 line
2.5.2
PATCH 4/4 srcu: Provide ordering for CPU not involved in grace period
In reply to Paul E. McKenneyTree RCU guarantees that every online CPU has a memory barrier between any given grace period and any of that CPU's RCU read-side sections that must be ordered against that grace period. Since RCU doesn't always know where read-side critical sections are, the actual implementation guarantees order against prior and subsequent non-idle non-offline code, whether in an RCU read-side critical section or not. As a result, there does not need to be a memory barrier at the end of synchronize_rcu() and friends because the ordering internal to the grace period has ordered every CPU's post-grace-period execution against each CPU's pre-grace-period execution, again for all non-idle online CPUs.
In contrast, SRCU can have non-idle online CPUs that are completely uninvolved in a given SRCU grace period, for example, a CPU that never runs any SRCU read-side critical sections and took no part in the grace-period processing. It is in theory possible for a given synchronize_srcu()'s wakeup to be delivered to a CPU that was completely uninvolved in the prior SRCU grace period, which could mean that the code following that synchronize_srcu() would end up being unordered with respect to both the grace period and any pre-existing SRCU read-side critical sections.
This commit therefore adds an smp_mb() to the end of __synchronize_srcu(), which prevents this scenario from occurring.
--- kernel/rcu/srcutree.c | 9 +++++++++ 1 file changed, 9 insertions(+)
kernel/rcu/srcutree.c +9 -0
@@ -897,6 +897,15 @@ static void __synchronize_srcu(struct srcu_struct *sp, bool do_norm)__call_srcu (sp, &rcu.head, wakeme_after_rcu, do_norm);wait_for_completion (&rcu.completion);destroy_rcu_head_on_stack (&rcu.head); + +/* +* Make sure that later code is ordered after the SRCU grace +* period. This pairs with the raw_spin_lock_irq_rcu_node() +* in srcu_invoke_callbacks(). Unlike Tree RCU, this is needed +* because the current CPU might have been totally uninvolved with +* (and thus unordered against) that grace period. +*/ +smp_mb (); }/**
Signature · 1 line
2.5.2