Yet more RCU commits queued for 2.6.37
Subsystems (3)
cover Yet more RCU commits queued for 2.6.37
Hello!
This patchset shows additional patches queued for 2.6.37, over and above those posted at http://lkml.org/lkml/2010/7/14/334 and at http://lkml.org/lkml/2010/8/9/332. These are all trivial fixes. The patches are as follows:
1. Allow kernel debuggers to avoid spurious RCU CPU stall warnings
when restarting from a breakpoint via a new rcu_cpu_stall_reset().
2. Repair code-duplication FIXMEs. This code was temporarily
duplicated to avoid inter-patch dependencies in the RCU tree.
3. Document some additional ways of stalling updates to prevent
call_rcu()-induced OOM situations.
4. Update srcu_read_lock() docbook comment to note that it is
illegal to wait for a given flavor of SRCU grace period while in that same flavor of SRCU read-side critical section.
5. Combine duplicate code, courtesy of a newly refurbished
CONFIG_PREEMPT_RCU symbol. Also convert from macro to static inline function in a couple of places.
6. Apply the TINY_PREEMPT_RCU read-side speedups/fixes to
TREE_PREEMPT_RCU. This update to TINY_PREEMPT_RCU update was posted at http://lkml.org/lkml/2010/8/17/437.
7. Add a comment stating that list_empty() serves the function of
the non-existent list_empty_rcu().
For a testing-only version of this patchset from git, please see:
git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git rcu/testing
Thanx, Paul
b/Documentation/RCU/checklist.txt | 23 ++++++++--- b/include/linux/rculist.h | 9 ++++ b/include/linux/rcupdate.h | 15 +++++++ b/include/linux/rcutiny.h | 4 ++ b/include/linux/rcutree.h | 1 b/include/linux/srcu.h | 7 +++ b/kernel/rcutiny_plugin.h | 4 -- b/kernel/rcutree.c | 20 ++++++++++ b/kernel/rcutree.h | 1 b/kernel/rcutree_plugin.h | 18 +++++++++ include/linux/rcupdate.h | 75 ++++++++++++++++++++++++++++++++++++-- include/linux/rcutiny.h | 58 ----------------------------- include/linux/rcutree.h | 56 ---------------------------- kernel/rcutree.h | 3 - kernel/rcutree_plugin.h | 15 ++----- 15 files changed, 166 insertions(+), 143 deletions(-)
PATCH 1/7 rcu: permit suppressing current grace period's CPU stall warnings
When using a kernel debugger, a long sojourn in the debugger can get you lots of RCU CPU stall warnings once you resume. This might not be helpful, especially if you are using the system console. This patch therefore allows RCU CPU stall warnings to be suppressed, but only for the duration of the current set of grace periods.
This differs from Jason's original patch in that it adds support for tiny RCU and preemptible RCU, and uses a slightly different method for suppressing the RCU CPU stall warning messages.
--- include/linux/rcutiny.h | 4 ++++ include/linux/rcutree.h | 1 + kernel/rcutree.c | 20 ++++++++++++++++++++ kernel/rcutree.h | 1 + kernel/rcutree_plugin.h | 18 ++++++++++++++++++ 5 files changed, 44 insertions(+), 0 deletions(-)
include/linux/rcutiny.h +4 -0
@@ -178,6 +178,10 @@ static inline void rcu_sched_force_quiescent_state(void) { } +static inline void rcu_cpu_stall_reset (void ) +{ +} +#ifdef CONFIG_DEBUG_LOCK_ALLOC extern int rcu_scheduler_active__read_mostly ;
include/linux/rcutree.h +1 -0
@@ -36,6 +36,7 @@ extern void rcu_sched_qs(int cpu);extern void rcu_bh_qs (int cpu);extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu); +extern void rcu_cpu_stall_reset (void );#ifdef CONFIG_TREE_PREEMPT_RCU
kernel/rcutree.c +20 -0
@@ -565,6 +565,22 @@ static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)return NOTIFY_DONE ; } +/** +* rcu_cpu_stall_reset - prevent further stall warnings in current grace period +* +* Set the stall-warning timeout way off into the future, thus preventing +* any RCU CPU stall-warning messages from appearing in the current set of +* RCU grace periods. +* +* The caller must disable hard irqs. +*/ +void rcu_cpu_stall_reset (void ) +{ + rcu_sched_state.jiffies_stall = jiffies +ULONG_MAX /2 ; + rcu_bh_state.jiffies_stall = jiffies +ULONG_MAX /2 ; +rcu_preempt_stall_reset (); +} +static struct notifier_block rcu_panic_block = { .notifier_call = rcu_panic, };
@@ -584,6 +600,10 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) { } +void rcu_cpu_stall_reset (void ) +{ +} +static void __init check_cpu_stall_init (void ) { }
kernel/rcutree.h +1 -0
@@ -372,6 +372,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,#ifdef CONFIG_RCU_CPU_STALL_DETECTOR static void rcu_print_detail_task_stall (struct rcu_state *rsp);static void rcu_print_task_stall (struct rcu_node *rnp); +static void rcu_preempt_stall_reset (void );#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ static void rcu_preempt_check_blocked_tasks (struct rcu_node *rnp);#ifdef CONFIG_HOTPLUG_CPU
kernel/rcutree_plugin.h +18 -0
@@ -417,6 +417,16 @@ static void rcu_print_task_stall(struct rcu_node *rnp) } } +/* +* Suppress preemptible RCU's CPU stall warnings by pushing the +* time of the next stall-warning message comfortably far into the +* future. +*/ +static void rcu_preempt_stall_reset (void ) +{ + rcu_preempt_state.jiffies_stall = jiffies +ULONG_MAX /2 ; +} +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /*
@@ -867,6 +877,14 @@ static void rcu_print_task_stall(struct rcu_node *rnp) { } +/* +* Because preemptible RCU does not exist, there is no need to suppress +* its CPU stall warnings. +*/ +static void rcu_preempt_stall_reset (void ) +{ +} +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /*
Signature · 1 line
1.7.0.6
PATCH 2/7 rcu: repair code-duplication FIXMEs
In reply to Paul E. McKenneyCombine the duplicate definitions of ULONG_CMP_GE(), ULONG_CMP_LT(), and rcu_preempt_depth() into include/linux/rcupdate.h.
--- include/linux/rcupdate.h | 15 +++++++++++++++ include/linux/rcutiny.h | 7 ------- include/linux/rcutree.h | 6 ------ kernel/rcutiny_plugin.h | 4 ---- kernel/rcutree.h | 3 --- 5 files changed, 15 insertions(+), 20 deletions(-)
include/linux/rcupdate.h +15 -0
@@ -47,6 +47,9 @@extern int rcutorture_runnable;/* for sysctl */ #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ +#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b)) +#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) +/** * struct rcu_head - callback structure for use with RCU * @next: next update requests in a list
@@ -66,6 +69,18 @@ extern int sched_expedited_torture_stats(char *page);/* Internal to kernel */ extern void rcu_init (void ); +#ifdef CONFIG_PREEMPT_RCU + +/* +* Defined as a macro as it is a very low level header included from +* areas that don't even know about current. This gives the rcu_read_lock() +* nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other +* types of kernel builds, the rcu_read_lock() nesting depth is unknowable. +*/ +#define rcu_preempt_depth () (current->rcu_read_lock_nesting) + +#endif /* #ifdef CONFIG_PREEMPT_RCU */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU )#include <linux/rcutree.h> #elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU )
include/linux/rcutiny.h +0 -7
@@ -133,13 +133,6 @@ static inline int rcu_needs_cpu(int cpu) return rcu_preempt_needs_cpu(); } -/* -* Defined as macro as it is a very low level header -* included from areas that don't even know about current -* FIXME: combine with include/linux/rcutree.h into rcupdate.h. -*/ -#define rcu_preempt_depth () (current->rcu_read_lock_nesting) -#endif /* #else #ifdef CONFIG_TINY_RCU */ static inline void rcu_note_context_switch (int cpu)
include/linux/rcutree.h +0 -6
@@ -45,12 +45,6 @@ extern void __rcu_read_unlock(void);extern void synchronize_rcu (void );extern void exit_rcu (void ); -/* -* Defined as macro as it is a very low level header -* included from areas that don't even know about current -*/ -#define rcu_preempt_depth () (current->rcu_read_lock_nesting) -#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */ static inline void __rcu_read_lock (void )
kernel/rcutiny_plugin.h +0 -4
@@ -26,10 +26,6 @@#include <linux/delay.h> -/* FIXME: merge with definitions in kernel/rcutree.h. */ -#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b)) -#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/* Global control variables for preemptible RCU. */ struct rcu_preempt_ctrlblk {struct rcu_ctrlblk rcb;/* curtail: ->next ptr of last CB for GP. */
kernel/rcutree.h +0 -3
@@ -272,9 +272,6 @@ struct rcu_data {#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b)) -#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/* * RCU global state, including node hierarchy. This hierarchy is * represented in "heap" form in a dense array. The root (first level)
Signature · 1 line
1.7.0.6
PATCH 3/7 rcu: document ways of stalling updates in low-memory situations
In reply to Paul E. McKenney--- Documentation/RCU/checklist.txt | 23 ++++++++++++++++------- 1 files changed, 16 insertions(+), 7 deletions(-)
Documentation/RCU/checklist.txt +16 -7
@@ -218,13 +218,22 @@ over a rather long period of time, but improvements are always welcome! include: a. Keeping a count of the number of data-structure elements - used by the RCU-protected data structure, including those - waiting for a grace period to elapse. Enforce a limit - on this number, stalling updates as needed to allow - previously deferred frees to complete. - - Alternatively, limit only the number awaiting deferred - free rather than the total number of elements. + used by the RCU-protected data structure, including + those waiting for a grace period to elapse. Enforce a + limit on this number, stalling updates as needed to allow + previously deferred frees to complete. Alternatively, + limit only the number awaiting deferred free rather than + the total number of elements. + + One way to stall the updates is to acquire the update-side + mutex. (Don't try this with a spinlock -- other CPUs + spinning on the lock could prevent the grace period + from ever ending.) Another way to stall the updates + is for the updates to use a wrapper function around + the memory allocator, so that this wrapper function + simulates OOM when there is too much memory awaiting an + RCU grace period. There are of course many other + variations on this theme. b. Limiting update rate. For example, if updates occur only once per hour, then no explicit rate limiting is required,
Signature · 1 line
1.7.0.6
PATCH 4/7 rcu: Upgrade srcu_read_lock() docbook about SRCU grace periods
In reply to Paul E. McKenneyIt is illegal to wait for an SRCU grace period while within the corresponding flavor of SRCU read-side critical section. Therefore, this commit updates the srcu_read_lock() docbook accordingly.
--- include/linux/srcu.h | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-)
include/linux/srcu.h +6 -1
@@ -139,7 +139,12 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)* @sp: srcu_struct in which to register the new reader. * * Enter an SRCU read-side critical section. Note that SRCU read-side -* critical sections may be nested. +* critical sections may be nested. However, it is illegal to +* call anything that waits on an SRCU grace period for the same +* srcu_struct, whether directly or indirectly. Please note that +* one way to indirectly wait on an SRCU grace period is to acquire +* a mutex that is held elsewhere while calling synchronize_srcu() or +* synchronize_srcu_expedited(). */ static inline int srcu_read_lock (struct srcu_struct *sp)__acquires (sp) {
Signature · 1 line
1.7.0.6
PATCH 5/7 rcu: combine duplicate code, courtesy of CONFIG_PREEMPT_RCU
In reply to Paul E. McKenneyThe CONFIG_PREEMPT_RCU kernel configuration parameter was recently re-introduced, but as an indication of the type of RCU (preemptible vs. non-preemptible) instead of as selecting a given implementation. This commit uses CONFIG_PREEMPT_RCU to combine duplicate code from include/linux/rcutiny.h and include/linux/rcutree.h into include/linux/rcupdate.h. This commit also combines a few other pieces of duplicate code that have accumulated.
--- include/linux/rcupdate.h | 75 ++++++++++++++++++++++++++++++++++++++++++++-- include/linux/rcutiny.h | 51 ------------------------------- include/linux/rcutree.h | 50 ------------------------------ kernel/rcutree_plugin.h | 9 ----- 4 files changed, 72 insertions(+), 113 deletions(-)
include/linux/rcupdate.h +72 -3
@@ -61,16 +61,30 @@ struct rcu_head { };/* Exported common interfaces */ +extern void call_rcu_sched (struct rcu_head *head, +void (*func)(struct rcu_head *rcu)); +extern void synchronize_sched (void );extern void rcu_barrier_bh (void );extern void rcu_barrier_sched (void );extern void synchronize_sched_expedited (void );extern int sched_expedited_torture_stats (char *page); -/* Internal to kernel */ -extern void rcu_init (void ); +static inline void __rcu_read_lock_bh (void ) +{ +local_bh_disable (); +} + +static inline void __rcu_read_unlock_bh (void ) +{ +local_bh_enable (); +}#ifdef CONFIG_PREEMPT_RCU +extern void __rcu_read_lock (void ); +extern void __rcu_read_unlock (void ); +void synchronize_rcu (void ); +/* * Defined as a macro as it is a very low level header included from * areas that don't even know about current. This gives the rcu_read_lock()
@@ -79,7 +93,53 @@ extern void rcu_init(void);*/ #define rcu_preempt_depth () (current->rcu_read_lock_nesting) -#endif /* #ifdef CONFIG_PREEMPT_RCU */ +#else /* #ifdef CONFIG_PREEMPT_RCU */ + +static inline void __rcu_read_lock (void ) +{ +preempt_disable (); +} + +static inline void __rcu_read_unlock (void ) +{ +preempt_enable (); +} + +static inline void synchronize_rcu (void ) +{ +synchronize_sched (); +} + +static inline int rcu_preempt_depth (void ) +{ +return 0 ; +} + +#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ + +/* Internal to kernel */ +extern void rcu_init (void ); +extern void rcu_sched_qs (int cpu); +extern void rcu_bh_qs (int cpu); +extern void rcu_check_callbacks (int cpu,int user); +struct notifier_block ; + +#ifdef CONFIG_NO_HZ + +extern void rcu_enter_nohz (void ); +extern void rcu_exit_nohz (void ); + +#else /* #ifdef CONFIG_NO_HZ */ + +static inline void rcu_enter_nohz (void ) +{ +} + +static inline void rcu_exit_nohz (void ) +{ +} + +#endif /* #else #ifdef CONFIG_NO_HZ */ #if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU )#include <linux/rcutree.h>
@@ -626,6 +686,8 @@ struct rcu_synchronize {extern void wakeme_after_rcu (struct rcu_head *head); +#ifdef CONFIG_PREEMPT_RCU +/** * call_rcu() - Queue an RCU callback for invocation after a grace period. * @head: structure to be used for queueing the RCU updates.
@@ -642,6 +704,13 @@ extern void wakeme_after_rcu(struct rcu_head *head);extern void call_rcu (struct rcu_head *head,void (*func)(struct rcu_head *head)); +#else /* #ifdef CONFIG_PREEMPT_RCU */ + +/* In classic RCU, call_rcu() is just call_rcu_sched(). */ +#define call_rcu call_rcu_sched + +#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ +/** * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period. * @head: structure to be used for queueing the RCU updates.
include/linux/rcutiny.h +0 -51
85 lines not on this page · raw message
include/linux/rcutree.h +0 -50
85 lines not on this page · raw message
kernel/rcutree_plugin.h +0 -9
@@ -939,15 +939,6 @@ static void rcu_preempt_process_callbacks(void) }/* -* In classic RCU, call_rcu() is just call_rcu_sched(). -*/ -void call_rcu (struct rcu_head *head,void (*func)(struct rcu_head *rcu)) -{ -call_rcu_sched (head, func); -} -EXPORT_SYMBOL_GPL (call_rcu); - -/* * Wait for an rcu-preempt grace period, but make it happen quickly. * But because preemptable RCU does not exist, map to rcu-sched. */
Signature · 1 line
1.7.0.6
PATCH 6/7 rcu: apply TINY_PREEMPT_RCU read-side speedup to TREE_PREEMPT_RCU
In reply to Paul E. McKenneyReplace one of the ACCESS_ONCE() calls in each of __rcu_read_lock() and __rcu_read_unlock() with barrier() as suggested by Steve Rostedt in order to avoid the potential compiler-optimization-induced bug noted by Mathieu Desnoyers.
--- kernel/rcutree_plugin.h | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
kernel/rcutree_plugin.h +4 -2
@@ -201,7 +201,7 @@ static void rcu_preempt_note_context_switch(int cpu)*/ void __rcu_read_lock (void ) { -ACCESS_ONCE (current->rcu_read_lock_nesting)++; + current->rcu_read_lock_nesting++;barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ }EXPORT_SYMBOL_GPL (__rcu_read_lock);
@@ -344,7 +344,9 @@ void __rcu_read_unlock(void)struct task_struct *t = current;barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ -if (--ACCESS_ONCE (t->rcu_read_lock_nesting) ==0 && + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 &&unlikely (ACCESS_ONCE (t->rcu_read_unlock_special)))rcu_read_unlock_special (t);#ifdef CONFIG_PROVE_LOCKING
Signature · 1 line
1.7.0.6
PATCH 7/7 rcu: add comment stating that list_empty() applies to RCU-protected lists
In reply to Paul E. McKenneyBecause list_empty() does not dereference any RCU-protected pointers, and further does not pass such pointers to the caller (so that the caller does not dereference them either), it is safe to use list_empty() on RCU-protected lists. There is no need for a list_empty_rcu(). This commit adds a comment stating this explicitly.
--- include/linux/rculist.h | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
include/linux/rculist.h +9 -0
@@ -10,6 +10,15 @@#include <linux/rcupdate.h> /* +* Why is there no list_empty_rcu()? Because list_empty() serves this +* purpose. The list_empty() function fetches the RCU-protected pointer +* and compares it to the address of the list head, but neither dereferences +* this pointer itself nor provides this pointer to the caller. Therefore, +* it is not necessary to use rcu_dereference(), so that list_empty() can +* be used anywhere you would want to use a list_empty_rcu(). +*/ + +/* * return the ->next pointer of a list_head in an rcu safe * way, we must not access it directly */
Signature · 1 line
1.7.0.6