RCU changes for v3.9
Subsystems (8)
Linus,
Please pull the latest core-rcu-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-rcu-for-linus
HEAD: ac0e32024b8f40987b3db7d2defdc6b5153ba354 Merge branch 'rcu/srcu' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into core/rcu
SRCU changes:
- These include debugging aids, updates that move towards the goal of permitting srcu_read_lock() and srcu_read_unlock() to be used from idle and offline CPUs, and a few small fixes.
Changes to rcutorture and to RCU documentation:
- Posted to LKML at https://lkml.org/lkml/2013/1/26/188
Enhancements to uniprocessor handling in tiny RCU:
- Posted to LKML at https://lkml.org/lkml/2013/1/27/2
Tag RCU callbacks with grace-period number to simplify callback advancement:
- Posted to LKML at https://lkml.org/lkml/2013/1/26/203
Miscellaneous fixes:
- Posted to LKML at https://lkml.org/lkml/2013/1/26/204
Thanks,
Ingo
------------------>
Cody P Schafer (1):
rcu: Correct 'optimized' to 'optimize' in header comment
Dave Hansen (1):
rcu: Consolidate debugging Kconfig options
Frederic Weisbecker (1):
context_tracking: Add comments on interface and internals
Josh Triplett (1):
rcu: Make rcu_is_cpu_rrupt_from_idle helper functions static
Lai Jiangshan (8):
srcu: Simplify __srcu_read_unlock() via this_cpu_dec()
srcu: Add might_sleep() annotation to synchronize_srcu()
srcu: Simple cleanup for cleanup_srcu_struct()
srcu: Remove checks preventing offline CPUs from calling srcu_read_lock()
srcu: Remove checks preventing idle CPUs from calling srcu_read_lock()
srcu: Update synchronize_srcu()'s comments
srcu: Update synchronize_srcu_expedited()'s comments
srcu: use ACCESS_ONCE() to access sp->completed in srcu_read_lock()
Li Zhong (2):
rcu: Use new nesting value for rcu_dyntick trace in rcu_eqs_enter_common
rcu: Remove unused code originally used for context tracking
Paul E. McKenney (10):
tracing: Export trace_clock_local()
rcu: Reduce rcutorture tracing
rcu: Fix blimit type for trace_rcu_batch_start()
rcu: Silence compiler array out-of-bounds false positive
rcu: Tag callback lists with corresponding grace-period number
rcu: Trace callback acceleration
rcu: Remove obsolete Kconfig option from comment
rcu: Provide RCU CPU stall warnings for tiny RCU
rcu: Allow TREE_PREEMPT_RCU on UP systems
rcu: Make rcutorture's shuffler task shuffle recently added tasks
Paul Gortmaker (2):
rcu: Prevent soft-lockup complaints about no-CBs CPUs
rcu: Make rcu_nocb_poll an early_param instead of module_param
Richard Braun (1):
Documentation: Memory barrier semantics of atomic_xchg()
Sasha Levin (1):
rcutorture: Don't compare ptr with 0
Steven Rostedt (1):
rcu: Allow rcutorture to be built at low optimization levels
Documentation/atomic_ops.txt | 2 + Documentation/kernel-parameters.txt | 2 +- Documentation/memory-barriers.txt | 1 + include/linux/rcupdate.h | 15 ++- include/linux/srcu.h | 26 +--- include/trace/events/rcu.h | 31 +++-- init/Kconfig | 12 +- kernel/context_tracking.c | 75 +++++++++-- kernel/rcu.h | 7 + kernel/rcupdate.c | 60 ++++++++- kernel/rcutiny.c | 8 +- kernel/rcutiny_plugin.h | 56 ++++++++ kernel/rcutorture.c | 66 +++++++-- kernel/rcutree.c | 260 +++++++++++++++++++++++++----------- kernel/rcutree.h | 11 +- kernel/rcutree_plugin.h | 13 +- kernel/srcu.c | 37 +++-- kernel/trace/trace_clock.c | 1 + lib/Kconfig.debug | 117 ++++++++-------- 19 files changed, 567 insertions(+), 233 deletions(-)
Documentation/atomic_ops.txt +2 -0
@@ -253,6 +253,8 @@ This performs an atomic exchange operation on the atomic variable v, setting the given new value. It returns the old value that the atomic variable v had just before the operation. +atomic_xchg requires explicit memory barriers around the operation. + int atomic_cmpxchg(atomic_t *v, int old, int new); This performs an atomic compare exchange operation on the atomic value v,
Documentation/kernel-parameters.txt +1 -1
@@ -2438,7 +2438,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. real-time workloads. It can also improve energy efficiency for asymmetric multiprocessors. - rcu_nocbs_poll [KNL,BOOT] + rcu_nocb_poll [KNL,BOOT] Rather than requiring that offloaded CPUs (specified by rcu_nocbs= above) explicitly awaken the corresponding "rcuoN" kthreads,
Documentation/memory-barriers.txt +1 -0
@@ -1685,6 +1685,7 @@ explicit lock operations, described later). These include: xchg(); cmpxchg(); + atomic_xchg(); atomic_cmpxchg(); atomic_inc_return(); atomic_dec_return();
include/linux/rcupdate.h +11 -4
@@ -53,7 +53,10 @@ extern int rcutorture_runnable; /* for sysctl */extern void rcutorture_record_test_transition (void );extern void rcutorture_record_progress (unsigned long vernum);extern void do_trace_rcu_torture_read (char *rcutorturename, -struct rcu_head *rhp); +struct rcu_head *rhp, +unsigned long secs, +unsigned long c_old, +unsigned long c);#else static inline void rcutorture_record_test_transition (void ) {
@@ -63,9 +66,13 @@ static inline void rcutorture_record_progress(unsigned long vernum) }#ifdef CONFIG_RCU_TRACE extern void do_trace_rcu_torture_read (char *rcutorturename, -struct rcu_head *rhp); +struct rcu_head *rhp, +unsigned long secs, +unsigned long c_old, +unsigned long c);#else -#define do_trace_rcu_torture_read (rcutorturename, rhp) do { } while (0) +#define do_trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c) \ + do { } while (0)#endif #endif
@@ -749,7 +756,7 @@ static inline void rcu_preempt_sleep_check(void)* preemptible RCU implementations (TREE_PREEMPT_RCU and TINY_PREEMPT_RCU) * in CONFIG_PREEMPT kernel builds, RCU read-side critical sections may * be preempted, but explicit blocking is illegal. Finally, in preemptible -* RCU implementations in real-time (CONFIG_PREEMPT_RT) kernel builds, +* RCU implementations in real-time (with -rt patchset) kernel builds, * RCU read-side critical sections may be preempted and they may also * block, but only when acquiring spinlocks that are subject to priority * inheritance.
include/linux/srcu.h +3 -23
@@ -151,30 +151,14 @@ void srcu_barrier(struct srcu_struct *sp);* Checks debug_lockdep_rcu_enabled() to prevent false positives during boot * and while lockdep is disabled. * -* Note that if the CPU is in the idle loop from an RCU point of view -* (ie: that we are in the section between rcu_idle_enter() and -* rcu_idle_exit()) then srcu_read_lock_held() returns false even if -* the CPU did an srcu_read_lock(). The reason for this is that RCU -* ignores CPUs that are in such a section, considering these as in -* extended quiescent state, so such a CPU is effectively never in an -* RCU read-side critical section regardless of what RCU primitives it -* invokes. This state of affairs is required --- we need to keep an -* RCU-free window in idle where the CPU may possibly enter into low -* power mode. This way we can notice an extended quiescent state to -* other CPUs that started a grace period. Otherwise we would delay any -* grace period as long as we run in the idle task. -* -* Similarly, we avoid claiming an SRCU read lock held if the current -* CPU is offline. +* Note that SRCU is based on its own statemachine and it doesn't +* relies on normal RCU, it can be called from the CPU which +* is in the idle loop from an RCU point of view or offline. */ static inline int srcu_read_lock_held (struct srcu_struct *sp) {if (!debug_lockdep_rcu_enabled ())return 1 ; -if (rcu_is_cpu_idle ()) -return 0 ; -if (!rcu_lockdep_current_cpu_online ()) -return 0 ;return lock_is_held (&sp->dep_map); }
@@ -236,8 +220,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)int retval =__srcu_read_lock (sp);rcu_lock_acquire (&(sp)->dep_map); -rcu_lockdep_assert (!rcu_is_cpu_idle (), -"srcu_read_lock() used illegally while idle" );return retval; }
@@ -251,8 +233,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)static inline void srcu_read_unlock (struct srcu_struct *sp,int idx)__releases (sp) { -rcu_lockdep_assert (!rcu_is_cpu_idle (), -"srcu_read_unlock() used illegally while idle" );rcu_lock_release (&(sp)->dep_map);__srcu_read_unlock (sp, idx); }
include/trace/events/rcu.h +21 -10
@@ -44,8 +44,10 @@ TRACE_EVENT(rcu_utilization,* of a new grace period or the end of an old grace period ("cpustart" * and "cpuend", respectively), a CPU passing through a quiescent * state ("cpuqs"), a CPU coming online or going offline ("cpuonl" -* and "cpuofl", respectively), and a CPU being kicked for being too -* long in dyntick-idle mode ("kick"). +* and "cpuofl", respectively), a CPU being kicked for being too +* long in dyntick-idle mode ("kick"), a CPU accelerating its new +* callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU +* accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB"). */ TRACE_EVENT(rcu_grace_period,
@@ -393,7 +395,7 @@ TRACE_EVENT(rcu_kfree_callback,*/ TRACE_EVENT(rcu_batch_start, - TP_PROTO(char *rcuname, long qlen_lazy, long qlen, int blimit), + TP_PROTO(char *rcuname, long qlen_lazy, long qlen, long blimit), TP_ARGS(rcuname, qlen_lazy, qlen, blimit),
@@ -401,7 +403,7 @@ TRACE_EVENT(rcu_batch_start, __field(char *, rcuname) __field(long, qlen_lazy) __field(long, qlen) - __field(int, blimit) + __field(long, blimit) ), TP_fast_assign(
@@ -411,7 +413,7 @@ TRACE_EVENT(rcu_batch_start, __entry->blimit = blimit; ), -TP_printk ("%s CBs=%ld/%ld bl=%d" , +TP_printk ("%s CBs=%ld/%ld bl=%ld" , __entry->rcuname, __entry->qlen_lazy, __entry->qlen, __entry->blimit) );
@@ -523,22 +525,30 @@ TRACE_EVENT(rcu_batch_end,*/ TRACE_EVENT (rcu_torture_read, - TP_PROTO(char *rcutorturename, struct rcu_head *rhp), + TP_PROTO(char *rcutorturename, struct rcu_head *rhp, + unsigned long secs, unsigned long c_old, unsigned long c), -TP_ARGS (rcutorturename, rhp), +TP_ARGS (rcutorturename, rhp, secs, c_old, c),TP_STRUCT__entry ( __field(char *, rcutorturename) __field(struct rcu_head *, rhp) + __field(unsigned long, secs) + __field(unsigned long, c_old) + __field(unsigned long, c) ),TP_fast_assign ( __entry->rcutorturename = rcutorturename; __entry->rhp = rhp; + __entry->secs = secs; + __entry->c_old = c_old; + __entry->c = c; ), -TP_printk ("%s torture read %p" , - __entry->rcutorturename, __entry->rhp) +TP_printk ("%s torture read %p %luus c: %lu %lu" , + __entry->rcutorturename, __entry->rhp, + __entry->secs, __entry->c_old, __entry->c) );/*
@@ -608,7 +618,8 @@ TRACE_EVENT(rcu_barrier,#define trace_rcu_invoke_kfree_callback (rcuname, rhp, offset) do { } while (0)#define trace_rcu_batch_end (rcuname, callbacks_invoked, cb, nr, iit, risk) \ do { } while (0) -#define trace_rcu_torture_read (rcutorturename, rhp) do { } while (0) +#define trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c) \ + do { } while (0)#define trace_rcu_barrier (name, s, cpu, cnt, done) do { } while (0)#endif /* #else #ifdef CONFIG_RCU_TRACE */
init/Kconfig +11 -1
@@ -453,7 +453,7 @@ config TREE_RCU config TREE_PREEMPT_RCU bool "Preemptible tree-based hierarchical RCU" - depends on PREEMPT && SMP + depends on PREEMPT help This option selects the RCU implementation that is designed for very large SMP systems with hundreds or
@@ -461,6 +461,8 @@ config TREE_PREEMPT_RCU is also required. It also scales down nicely to smaller systems. + Select this option if you are unsure. + config TINY_RCU bool "UP-only small-memory-footprint RCU" depends on !PREEMPT && !SMP
@@ -486,6 +488,14 @@ config PREEMPT_RCU This option enables preemptible-RCU code that is common between the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations. +config RCU_STALL_COMMON + def_bool ( TREE_RCU || TREE_PREEMPT_RCU || RCU_TRACE ) + help + This option enables RCU CPU stall code that is common between + the TINY and TREE variants of RCU. The purpose is to allow + the tiny variants to disable RCU CPU stall warnings, while + making these warnings mandatory for the tree variants. + config CONTEXT_TRACKING bool
kernel/context_tracking.c +65 -10
122 lines not on this page · raw message
kernel/rcu.h +7 -0
@@ -111,4 +111,11 @@ static inline bool __rcu_reclaim(char *rn, struct rcu_head *head)extern int rcu_expedited; +#ifdef CONFIG_RCU_STALL_COMMON + +extern int rcu_cpu_stall_suppress; +int rcu_jiffies_till_stall_check (void ); + +#endif /* #ifdef CONFIG_RCU_STALL_COMMON */ +#endif /* __LINUX_RCU_H */
kernel/rcupdate.c +57 -3
68 lines not on this page · raw message
kernel/rcutiny.c +5 -3
@@ -51,10 +51,10 @@ static void __call_rcu(struct rcu_head *head,void (*func)(struct rcu_head *rcu), struct rcu_ctrlblk *rcp); -#include "rcutiny_plugin.h" -static long long rcu_dynticks_nesting =DYNTICK_TASK_EXIT_IDLE ; +#include "rcutiny_plugin.h" +/* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ static void rcu_idle_enter_common (long long newval) {
@@ -193,7 +193,7 @@ EXPORT_SYMBOL(rcu_is_cpu_idle);* interrupts don't count, we must be running at the first interrupt * level. */ -int rcu_is_cpu_rrupt_from_idle (void ) +static int rcu_is_cpu_rrupt_from_idle (void ) {return rcu_dynticks_nesting <=1 ; }
@@ -205,6 +205,7 @@ int rcu_is_cpu_rrupt_from_idle(void)*/ static int rcu_qsctr_help (struct rcu_ctrlblk *rcp) { +reset_cpu_stall_ticks (rcp);if (rcp->rcucblist !=NULL && rcp->donetail != rcp->curtail) { rcp->donetail = rcp->curtail;
@@ -251,6 +252,7 @@ void rcu_bh_qs(int cpu)*/ void rcu_check_callbacks (int cpu,int user) { +check_cpu_stalls ();if (user ||rcu_is_cpu_rrupt_from_idle ())rcu_sched_qs (cpu);else if (!in_softirq ())
kernel/rcutiny_plugin.h +56 -0
78 lines not on this page · raw message
kernel/rcutorture.c +54 -12
170 lines not on this page · raw message
kernel/rcutree.c +183 -77
392 lines not on this page · raw message
kernel/rcutree.h +2 -9
@@ -102,10 +102,6 @@ struct rcu_dynticks {/* idle-period nonlazy_posted snapshot. */ int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ -#ifdef CONFIG_RCU_USER_QS -bool ignore_user_qs;/* Treat userspace as extended QS or not */ -bool in_user;/* Is the CPU in userland from RCU POV? */ -#endif };/* RCU's kthread states for tracing. */
@@ -282,6 +278,8 @@ struct rcu_data {*/ struct rcu_head *nxtlist;struct rcu_head **nxttail[RCU_NEXT_SIZE ]; +unsigned long nxtcompleted[RCU_NEXT_SIZE ]; +/* grace periods for sublists. */ long qlen_lazy;/* # of lazy queued callbacks */ long qlen;/* # of queued callbacks, incl lazy */ long qlen_last_fqs_check;
@@ -343,11 +341,6 @@ struct rcu_data {#define RCU_JIFFIES_TILL_FORCE_QS 3/* for rsp->jiffies_force_qs */ -#ifdef CONFIG_PROVE_RCU -#define RCU_STALL_DELAY_DELTA (5 * HZ) -#else -#define RCU_STALL_DELAY_DELTA 0 -#endif #define RCU_STALL_RAT_DELAY 2/* Allow other CPUs time */ /* to take at least one */ /* scheduling clock irq */
kernel/rcutree_plugin.h +10 -3
@@ -40,8 +40,7 @@#ifdef CONFIG_RCU_NOCB_CPU static cpumask_var_t rcu_nocb_mask;/* CPUs to have callbacks offloaded. */ static bool have_rcu_nocb_mask;/* Was rcu_nocb_mask allocated? */ -static bool rcu_nocb_poll;/* Offload kthread are to poll. */ -module_param (rcu_nocb_poll, bool,0444 ); +static bool __read_mostly rcu_nocb_poll;/* Offload kthread are to poll. */ static char __initdata nocb_buf[NR_CPUS *5 ];#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
@@ -2159,6 +2158,13 @@ static int __init rcu_nocb_setup(char *str) }__setup ("rcu_nocbs=" , rcu_nocb_setup); +static int __init parse_rcu_nocb_poll (char *arg) +{ + rcu_nocb_poll =1 ; +return 0 ; +} +early_param ("rcu_nocb_poll" , parse_rcu_nocb_poll); +/* Is the specified CPU a no-CPUs CPU? */ static bool is_nocb_cpu (int cpu) {
@@ -2366,10 +2372,11 @@ static int rcu_nocb_kthread(void *arg)for (;;) {/* If not polling, wait for next batch of callbacks. */ if (!rcu_nocb_poll) -wait_event (rdp->nocb_wq, rdp->nocb_head); +wait_event_interruptible (rdp->nocb_wq, rdp->nocb_head); list =ACCESS_ONCE (rdp->nocb_head);if (!list) {schedule_timeout_interruptible (1 ); +flush_signals (current);continue ; }
kernel/srcu.c +16 -21
@@ -282,12 +282,8 @@ static int srcu_readers_active(struct srcu_struct *sp)*/ void cleanup_srcu_struct (struct srcu_struct *sp) { -int sum; - - sum =srcu_readers_active (sp); -WARN_ON (sum);/* Leakage unless caller handles error. */ -if (sum !=0 ) -return ; +if (WARN_ON (srcu_readers_active (sp))) +return ;/* Leakage unless caller handles error. */ free_percpu (sp->per_cpu_ref); sp->per_cpu_ref =NULL ; }
@@ -302,9 +298,8 @@ int __srcu_read_lock(struct srcu_struct *sp) {int idx; + idx =ACCESS_ONCE (sp->completed) &0x1 ;preempt_disable (); - idx =rcu_dereference_index_check (sp->completed, -rcu_read_lock_sched_held ()) &0x1 ;ACCESS_ONCE (this_cpu_ptr (sp->per_cpu_ref)->c[idx]) +=1 ;smp_mb ();/* B */ /* Avoid leaking the critical section. */ ACCESS_ONCE (this_cpu_ptr (sp->per_cpu_ref)->seq[idx]) +=1 ;
@@ -321,10 +316,8 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);*/ void __srcu_read_unlock (struct srcu_struct *sp,int idx) { -preempt_disable ();smp_mb ();/* C */ /* Avoid leaking the critical section. */ -ACCESS_ONCE (this_cpu_ptr (sp->per_cpu_ref)->c[idx]) -=1 ; -preempt_enable (); +this_cpu_dec (sp->per_cpu_ref->c[idx]); }EXPORT_SYMBOL_GPL (__srcu_read_unlock);
@@ -423,6 +416,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount) !lock_is_held (&rcu_sched_lock_map), "Illegal synchronize_srcu() in same-type SRCU (or RCU) read-side critical section"); +might_sleep ();init_completion (&rcu.completion); head->next =NULL ;
@@ -455,10 +449,12 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)* synchronize_srcu - wait for prior SRCU read-side critical-section completion * @sp: srcu_struct with which to synchronize. * -* Flip the completed counter, and wait for the old count to drain to zero. -* As with classic RCU, the updater must use some separate means of -* synchronizing concurrent updates. Can block; must be called from -* process context. +* Wait for the count to drain to zero of both indexes. To avoid the +* possible starvation of synchronize_srcu(), it waits for the count of +* the index=((->completed & 1) ^ 1) to drain to zero at first, +* and then flip the completed and wait for the count of the other index. +* +* Can block; must be called from process context. * * Note that it is illegal to call synchronize_srcu() from the corresponding * SRCU read-side critical section; doing so will result in deadlock.
@@ -480,12 +476,11 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);* Wait for an SRCU grace period to elapse, but be more aggressive about * spinning rather than blocking when waiting. * -* Note that it is illegal to call this function while holding any lock -* that is acquired by a CPU-hotplug notifier. It is also illegal to call -* synchronize_srcu_expedited() from the corresponding SRCU read-side -* critical section; doing so will result in deadlock. However, it is -* perfectly legal to call synchronize_srcu_expedited() on one srcu_struct -* from some other srcu_struct's read-side critical section, as long as +* Note that it is also illegal to call synchronize_srcu_expedited() +* from the corresponding SRCU read-side critical section; +* doing so will result in deadlock. However, it is perfectly legal +* to call synchronize_srcu_expedited() on one srcu_struct from some +* other srcu_struct's read-side critical section, as long as * the resulting graph of srcu_structs is acyclic. */ void synchronize_srcu_expedited (struct srcu_struct *sp)
kernel/trace/trace_clock.c +1 -0
@@ -44,6 +44,7 @@ u64 notrace trace_clock_local(void)return clock; } +EXPORT_SYMBOL_GPL (trace_clock_local);/* * trace_clock(): 'between' trace clock. Not completely serialized,
lib/Kconfig.debug +61 -56
147 lines not on this page · raw message