Skip to contentSkip to conversation

SRCU updates

PATCH New Paul E. McKenney 1 participant 5 messages Jul 24, 2017

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

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(-)
#1 lore raw

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
index f816fc72b51e..55c29e1650b9 100644
@@ -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
index 5becbbccb998..b3dbf9502fd0 100644
@@ -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
index 1a1c1047d2ed..76ac5f50b2c7 100644
@@ -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
index f8488965250f..a64eee0db39e 100644
@@ -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
#2 lore raw

PATCH 2/4 rcutorture: Remove obsolete SRCU-C.boot

In reply to Paul E. McKenney

Classic 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
deleted file mode 100644
index 84a7d51b7481..000000000000
@@ -1 +0,0 @@
-rcutorture.torture_type=srcud
Signature · 1 line
2.5.2
#3 lore raw

PATCH 3/4 srcu: Make process_srcu() be static

In reply to Paul E. McKenney

The 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
index 42973f787e7e..a026a9493bde 100644
@@ -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
index d0ca524bf042..94bd6ed43ea3 100644
@@ -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
#4 lore raw

PATCH 4/4 srcu: Provide ordering for CPU not involved in grace period

In reply to Paul E. McKenney

Tree 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
index 94bd6ed43ea3..c1c0ee3cce3b 100644
@@ -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