RCU changes for v4.2
Subsystems (14)
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: 085c789783f5f95c253740d3d0a1659ec5ff32a8 Merge branch 'for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into core/rcu
- Continued initialization/Kconfig updates: hide most Kconfig options from unsuspecting users. There's now a single high level configuration option:
*
* RCU Subsystem
*
Make expert-level adjustments to RCU configuration (RCU_EXPERT) [N/y/?] (NEW)
Which if answered in the negative, leaves us with a single interactive configuration option:
Offload RCU callback processing from boot-selected CPUs (RCU_NOCB_CPU) [N/y/?] (NEW)
All the rest of the RCU options are configured automatically. Later on we'll remove this single leftover configuration option as well.
- Remove all uses of RCU-protected array indexes: replace the rcu_[access|dereference]_index_check() APIs with READ_ONCE() and rcu_lockdep_assert().
- RCU CPU-hotplug cleanups.
- Updates to Tiny RCU: a race fix and further code shrinkage.
- RCU torture-testing updates: fixes, speedups, cleanups and documentation updates.
- Miscellaneous fixes.
- Documentation updates.
Thanks,
Ingo
------------------>
Alexey Kodanev (1):
locktorture: fix deadlock in 'rw_lock_irq' type
Joe Perches (1):
rcu: tree_plugin: Use bool function return values of true/false not 1/0
Milos Vyletel (1):
documentation: State that rcu_dereference() reloads pointer
Nicholas Mc Guire (1):
rcu: Change function declaration to bool
Nicolas Iooss (1):
rcu: Make rcu_*_data variables static
Patrick Daly (1):
rcu: Fix missing task information during rcu-preempt stall
Paul E. McKenney (50):
rcu: Convert ACCESS_ONCE() to READ_ONCE() and WRITE_ONCE()
mce: Stop using array-index-based RCU primitives
rcu: Eliminate array-index-based RCU primitives
documentation: RCU-protected array indexes no longer supported
mce: mce_chrdev_write() can be static
documentation: Update rcu_dereference.txt based on WG21 discussions
rcu: Convert from rcu_preempt_state to *rcu_state_p
rcu: Eliminate a few RCU_BOOST #ifdefs in favor of IS_ENABLED()
rcu: Tell the compiler that rcu_state_p is immutable
rcu: Create an immutable rcu_data_p pointer to default rcu_data structure
rcu: Eliminate a few CONFIG_RCU_NOCB_CPU_ALL #ifdefs
rcu: Force wakeup of rcu_gp_kthread at grace-period end
powerpc: Fix smp_mb__before_spinlock()
rcu: Add more debug info on "kthread starved" RCU CPU stall warnings
smp: Make control dependencies work on Alpha, improve documentation
rcu: Make synchronize_sched_expedited() call wait_rcu_gp()
rcu: Eliminate HOTPLUG_CPU #ifdef in favor of IS_ENABLED()
rcu: Adjust ->lock acquisition for tasks no longer migrating
rcu: Remove dead code from force_qs_rnp()
rcu: Remove redundant offline check
rcu: Correctly initialize ->rcu_qs_ctr_snap at online time
cpu: Handle smpboot_unpark_threads() uniformly
rcu: Modulate grace-period slow init to normalize delay
rcu: Shut up spurious gcc uninitialized-variable warning
rcu: Provide diagnostic option to slow down grace-period scans
rcu: Directly drive TASKS_RCU from Kconfig
rcu: Directly drive RCU_USER_QS from Kconfig
rcu: Convert CONFIG_RCU_FANOUT_EXACT to boot parameter
rcu: Enable diagnostic dump of rcu_node combining tree
rcu: Create RCU_EXPERT Kconfig and hide booleans behind it
rcu: Break dependency of RCU_FANOUT_LEAF on RCU_FANOUT
rcu: Make RCU able to tolerate undefined CONFIG_RCU_FANOUT
rcu: Make RCU able to tolerate undefined CONFIG_RCU_FANOUT_LEAF
rcu: Make RCU able to tolerate undefined CONFIG_RCU_KTHREAD_PRIO
rcu: Conditionally compile RCU's eqs warnings
rcu: Further shrink Tiny RCU by making empty functions static inlines
rcutorture: Test both RCU-sched and RCU-bh for Tiny RCU
rcu: Correctly handle non-empty Tiny RCU callback list with none ready
rcutorture: Exchange TREE03 and TREE04 geometries
rcutorture: Exchange TREE03 and TREE08 NR_CPUS, speed up CPU hotplug
rcutorture: Allow negative values of nreaders to oversubscribe
locktorture: Change longdelay_us to longdelay_ms
rcutorture: Replace barriers with smp_store_release() and smp_load_acquire()
rcutorture: Test SRCU cleanup code path
rcutorture: TASKS_RCU set directly, so don't explicitly set it
rcutorture: Update configuration fragments for rcutree.rcu_fanout_exact
rcutorture: Make rcutorture scripts force RCU_EXPERT
rcutorture: Update TREE_RCU-kconfig.txt
rcutorture: Display "make oldconfig" errors
rcutorture: Allow repetition factors in Kconfig-fragment lists
Paul Gortmaker (1):
cpu: Remove new instance of __cpuinit that crept back in
Pranith Kumar (1):
rcu: Remove prompt for RCU implementation
Will Deacon (1):
documentation: memory-barriers: Fix smp_mb__before_spinlock() semantics
Ying Xue (1):
rculist: Fix another sparse warning
Documentation/RCU/arrayRCU.txt | 20 +- Documentation/RCU/lockdep.txt | 10 - Documentation/RCU/rcu_dereference.txt | 38 +-- Documentation/RCU/whatisRCU.txt | 6 +- Documentation/kernel-parameters.txt | 33 +- Documentation/memory-barriers.txt | 62 ++-- arch/powerpc/include/asm/barrier.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 15 +- include/linux/compiler.h | 16 + include/linux/rculist.h | 10 +- include/linux/rcupdate.h | 70 +--- include/linux/rcutiny.h | 16 + include/linux/rcutree.h | 7 +- include/linux/spinlock.h | 2 +- init/Kconfig | 72 ++-- kernel/cpu.c | 4 +- kernel/events/ring_buffer.c | 2 +- kernel/locking/locktorture.c | 14 +- kernel/rcu/rcutorture.c | 103 ++++-- kernel/rcu/srcu.c | 10 +- kernel/rcu/tiny.c | 38 +-- kernel/rcu/tiny_plugin.h | 12 +- kernel/rcu/tree.c | 365 ++++++++++++--------- kernel/rcu/tree.h | 35 +- kernel/rcu/tree_plugin.h | 216 ++++++------ kernel/rcu/tree_trace.c | 6 +- kernel/rcu/update.c | 30 +- kernel/torture.c | 26 +- lib/Kconfig.debug | 66 +++- .../testing/selftests/rcutorture/bin/configinit.sh | 2 +- .../selftests/rcutorture/bin/kvm-recheck.sh | 4 + tools/testing/selftests/rcutorture/bin/kvm.sh | 25 +- .../selftests/rcutorture/configs/rcu/CFcommon | 2 + .../selftests/rcutorture/configs/rcu/SRCU-N | 1 + .../selftests/rcutorture/configs/rcu/SRCU-P | 1 + .../selftests/rcutorture/configs/rcu/SRCU-P.boot | 2 +- .../selftests/rcutorture/configs/rcu/TASKS01 | 5 +- .../selftests/rcutorture/configs/rcu/TASKS02 | 1 - .../selftests/rcutorture/configs/rcu/TASKS03 | 2 +- .../selftests/rcutorture/configs/rcu/TINY02 | 2 +- .../selftests/rcutorture/configs/rcu/TINY02.boot | 1 + .../selftests/rcutorture/configs/rcu/TREE01 | 1 + .../selftests/rcutorture/configs/rcu/TREE02 | 2 +- .../selftests/rcutorture/configs/rcu/TREE02-T | 1 - .../selftests/rcutorture/configs/rcu/TREE03 | 8 +- .../selftests/rcutorture/configs/rcu/TREE03.boot | 1 + .../selftests/rcutorture/configs/rcu/TREE04 | 8 +- .../selftests/rcutorture/configs/rcu/TREE05 | 4 +- .../selftests/rcutorture/configs/rcu/TREE06 | 4 +- .../selftests/rcutorture/configs/rcu/TREE06.boot | 1 + .../selftests/rcutorture/configs/rcu/TREE07 | 4 +- .../selftests/rcutorture/configs/rcu/TREE08 | 6 +- .../selftests/rcutorture/configs/rcu/TREE08-T | 1 - .../selftests/rcutorture/configs/rcu/TREE08-T.boot | 1 + .../selftests/rcutorture/configs/rcu/TREE08.boot | 1 + .../selftests/rcutorture/configs/rcu/TREE09 | 1 + .../selftests/rcutorture/doc/TREE_RCU-kconfig.txt | 36 +- 57 files changed, 809 insertions(+), 624 deletions(-) create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/TREE08-T.boot
Documentation/RCU/arrayRCU.txt +16 -4
@@ -10,7 +10,19 @@ Although RCU is more commonly used to protect linked lists, it can 3. Resizeable Arrays -Each of these situations are discussed below. +Each of these three situations involves an RCU-protected pointer to an +array that is separately indexed. It might be tempting to consider use +of RCU to instead protect the index into an array, however, this use +case is -not- supported. The problem with RCU-protected indexes into +arrays is that compilers can play way too many optimization games with +integers, which means that the rules governing handling of these indexes +are far more trouble than they are worth. If RCU-protected indexes into +arrays prove to be particularly valuable (which they have not thus far), +explicit cooperation from the compiler will be required to permit them +to be safely used. + +That aside, each of the three RCU-protected pointer situations are +described in the following sections. Situation 1: Hash Tables
@@ -36,9 +48,9 @@ Quick Quiz: Why is it so important that updates be rare when Situation 3: Resizeable Arrays Use of RCU for resizeable arrays is demonstrated by the grow_ary() -function used by the System V IPC code. The array is used to map from -semaphore, message-queue, and shared-memory IDs to the data structure -that represents the corresponding IPC construct. The grow_ary() +function formerly used by the System V IPC code. The array is used +to map from semaphore, message-queue, and shared-memory IDs to the data +structure that represents the corresponding IPC construct. The grow_ary() function does not acquire any locks; instead its caller must hold the ids->sem semaphore.
Documentation/RCU/lockdep.txt +0 -10
@@ -47,11 +47,6 @@ In addition, a separate kernel config parameter CONFIG_PROVE_RCU enables Use explicit check expression "c" along with srcu_read_lock_held()(). This is useful in code that is invoked by both SRCU readers and updaters. - rcu_dereference_index_check(p, c): - Use explicit check expression "c", but the caller - must supply one of the rcu_read_lock_held() functions. - This is useful in code that uses RCU-protected arrays - that is invoked by both RCU readers and updaters. rcu_dereference_raw(p): Don't check. (Use sparingly, if at all.) rcu_dereference_protected(p, c):
@@ -64,11 +59,6 @@ In addition, a separate kernel config parameter CONFIG_PROVE_RCU enables but retain the compiler constraints that prevent duplicating or coalescsing. This is useful when when testing the value of the pointer itself, for example, against NULL. - rcu_access_index(idx): - Return the value of the index and omit all barriers, but - retain the compiler constraints that prevent duplicating - or coalescsing. This is useful when when testing the - value of the index itself, for example, against -1. The rcu_dereference_check() check expression can be any boolean expression, but would normally include a lockdep expression. However,
Documentation/RCU/rcu_dereference.txt +17 -21
@@ -25,17 +25,6 @@ o You must use one of the rcu_dereference() family of primitives for an example where the compiler can in fact deduce the exact value of the pointer, and thus cause misordering. -o Do not use single-element RCU-protected arrays. The compiler - is within its right to assume that the value of an index into - such an array must necessarily evaluate to zero. The compiler - could then substitute the constant zero for the computation, so - that the array index no longer depended on the value returned - by rcu_dereference(). If the array index no longer depends - on rcu_dereference(), then both the compiler and the CPU - are within their rights to order the array access before the - rcu_dereference(), which can cause the array access to return - garbage. - o Avoid cancellation when using the "+" and "-" infix arithmetic operators. For example, for a given variable "x", avoid "(x-x)". There are similar arithmetic pitfalls from other
@@ -76,14 +65,15 @@ o Do not use the results from the boolean "&&" and "||" when dereferencing. For example, the following (rather improbable) code is buggy: - int a[2]; - int index; - int force_zero_index = 1; + int *p; + int *q; ... - r1 = rcu_dereference(i1) - r2 = a[r1 && force_zero_index]; /* BUGGY!!! */ + p = rcu_dereference(gp) + q = &global_q; + q += p != &oom_p1 && p != &oom_p2; + r1 = *q; /* BUGGY!!! */ The reason this is buggy is that "&&" and "||" are often compiled using branches. While weak-memory machines such as ARM or PowerPC
@@ -94,14 +84,15 @@ o Do not use the results from relational operators ("==", "!=", ">", ">=", "<", or "<=") when dereferencing. For example, the following (quite strange) code is buggy: - int a[2]; - int index; - int flip_index = 0; + int *p; + int *q; ... - r1 = rcu_dereference(i1) - r2 = a[r1 != flip_index]; /* BUGGY!!! */ + p = rcu_dereference(gp) + q = &global_q; + q += p > &oom_p; + r1 = *q; /* BUGGY!!! */ As before, the reason this is buggy is that relational operators are often compiled using branches. And as before, although
@@ -193,6 +184,11 @@ o Be very careful about comparing pointers obtained from pointer. Note that the volatile cast in rcu_dereference() will normally prevent the compiler from knowing too much. + However, please note that if the compiler knows that the + pointer takes on only one of two values, a not-equal + comparison will provide exactly the information that the + compiler needs to deduce the value of the pointer. + o Disable any value-speculation optimizations that your compiler might provide, especially if you are making use of feedback-based optimizations that take data collected from prior runs. Such
Documentation/RCU/whatisRCU.txt +3 -3
@@ -256,7 +256,9 @@ rcu_dereference() If you are going to be fetching multiple fields from the RCU-protected structure, using the local variable is of course preferred. Repeated rcu_dereference() calls look - ugly and incur unnecessary overhead on Alpha CPUs. + ugly, do not guarantee that the same pointer will be returned + if an update happened while in the critical section, and incur + unnecessary overhead on Alpha CPUs. Note that the value returned by rcu_dereference() is valid only within the enclosing RCU read-side critical section.
@@ -879,9 +881,7 @@ SRCU: Initialization/cleanup All: lockdep-checked RCU-protected pointer access - rcu_access_index rcu_access_pointer - rcu_dereference_index_check rcu_dereference_raw rcu_lockdep_assert rcu_sleep_check
Documentation/kernel-parameters.txt +30 -3
@@ -2992,11 +2992,34 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Set maximum number of finished RCU callbacks to process in one batch. + rcutree.dump_tree= [KNL] + Dump the structure of the rcu_node combining tree + out at early boot. This is used for diagnostic + purposes, to verify correct tree setup. + + rcutree.gp_cleanup_delay= [KNL] + Set the number of jiffies to delay each step of + RCU grace-period cleanup. This only has effect + when CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP is set. + rcutree.gp_init_delay= [KNL] Set the number of jiffies to delay each step of RCU grace-period initialization. This only has - effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT is - set. + effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT + is set. + + rcutree.gp_preinit_delay= [KNL] + Set the number of jiffies to delay each step of + RCU grace-period pre-initialization, that is, + the propagation of recent CPU-hotplug changes up + the rcu_node combining tree. This only has effect + when CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT is set. + + rcutree.rcu_fanout_exact= [KNL] + Disable autobalancing of the rcu_node combining + tree. This is used by rcutorture, and might + possibly be useful for architectures having high + cache-to-cache transfer latencies. rcutree.rcu_fanout_leaf= [KNL] Increase the number of CPUs assigned to each
@@ -3101,7 +3124,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. test, hence the "fake". rcutorture.nreaders= [KNL] - Set number of RCU readers. + Set number of RCU readers. The value -1 selects + N-1, where N is the number of CPUs. A value + "n" less than -1 selects N-n-2, where N is again + the number of CPUs. For example, -2 selects N + (the number of CPUs), -3 selects N+1, and so on. rcutorture.object_debug= [KNL] Enable debug-object double-call_rcu() testing.
Documentation/memory-barriers.txt +36 -26
151 lines not on this page · raw message
arch/powerpc/include/asm/barrier.h +1 -0
@@ -89,5 +89,6 @@ do { \#define smp_mb__before_atomic () smp_mb()#define smp_mb__after_atomic () smp_mb() +#define smp_mb__before_spinlock () smp_mb()#endif /* _ASM_POWERPC_BARRIER_H */
arch/x86/kernel/cpu/mcheck/mce.c +9 -6
@@ -53,9 +53,12 @@static DEFINE_MUTEX (mce_chrdev_read_mutex);#define rcu_dereference_check_mce (p) \ - rcu_dereference_index_check((p), \ - rcu_read_lock_sched_held() || \ - lockdep_is_held(&mce_chrdev_read_mutex)) +({ \ + rcu_lockdep_assert(rcu_read_lock_sched_held() || \ + lockdep_is_held(&mce_chrdev_read_mutex), \ + "suspicious rcu_dereference_check_mce() usage"); \ + smp_load_acquire(&(p)); \ +})#define CREATE_TRACE_POINTS #include <trace/events/mce.h>
@@ -1887,7 +1890,7 @@ static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,static unsigned int mce_chrdev_poll (struct file *file,poll_table *wait) {poll_wait (file, &mce_chrdev_wait, wait); -if (rcu_access_index (mcelog.next)) +if (READ_ONCE (mcelog.next))return POLLIN |POLLRDNORM ;if (!mce_apei_read_done &&apei_check_mce ())return POLLIN |POLLRDNORM ;
@@ -1932,8 +1935,8 @@ void register_mce_write_callback(ssize_t (*fn)(struct file *filp, }EXPORT_SYMBOL_GPL (register_mce_write_callback); -ssize_t mce_chrdev_write (struct file *filp,const char __user *ubuf, -size_t usize,loff_t *off) +static ssize_t mce_chrdev_write (struct file *filp,const char __user *ubuf, +size_t usize,loff_t *off) {if (mce_write)return mce_write (filp, ubuf, usize, off);
include/linux/compiler.h +16 -0
@@ -252,6 +252,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s#define WRITE_ONCE (x, val) \ ({ typeof(x) __val = (val); __write_once_size(&(x), &__val, sizeof(__val)); __val; }) +/** +* READ_ONCE_CTRL - Read a value heading a control dependency +* @x: The value to be read, heading the control dependency +* +* Control dependencies are tricky. See Documentation/memory-barriers.txt +* for important information on how to use them. Note that in many cases, +* use of smp_load_acquire() will be much simpler. Control dependencies +* should be avoided except on the hottest of hotpaths. +*/ +#define READ_ONCE_CTRL(x) \ +({ \ + typeof(x) __val = READ_ONCE(x); \ + smp_read_barrier_depends(); /* Enforce control dependency. */ \ + __val; \ +}) +#endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */
include/linux/rculist.h +5 -5
@@ -29,8 +29,8 @@*/ static inline void INIT_LIST_HEAD_RCU (struct list_head *list) { -ACCESS_ONCE (list->next) = list; -ACCESS_ONCE (list->prev) = list; +WRITE_ONCE (list->next, list); +WRITE_ONCE (list->prev, list); }/*
@@ -288,7 +288,7 @@ static inline void list_splice_init_rcu(struct list_head *list,#define list_first_or_null_rcu (ptr, type, member) \ ({ \ struct list_head *__ptr = (ptr); \ - struct list_head *__next = ACCESS_ONCE(__ptr->next); \ + struct list_head *__next = READ_ONCE(__ptr->next); \ likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \ })
@@ -549,8 +549,8 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n,*/ #define hlist_for_each_entry_from_rcu (pos, member) \ for (; pos; \ - pos = hlist_entry_safe(rcu_dereference((pos)->member.next),\ - typeof(*(pos)), member)) + pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu( \ + &(pos)->member)), typeof(*(pos)), member))#endif /* __KERNEL__ */ #endif
include/linux/rcupdate.h +8 -62
128 lines not on this page · raw message
include/linux/rcutiny.h +16 -0
@@ -159,6 +159,22 @@ static inline void rcu_cpu_stall_reset(void) { } +static inline void rcu_idle_enter (void ) +{ +} + +static inline void rcu_idle_exit (void ) +{ +} + +static inline void rcu_irq_enter (void ) +{ +} + +static inline void rcu_irq_exit (void ) +{ +} +static inline void exit_rcu (void ) { }
include/linux/rcutree.h +5 -2
@@ -31,9 +31,7 @@#define __LINUX_RCUTREE_Hvoid rcu_note_context_switch (void ); -#ifndef CONFIG_RCU_NOCB_CPU_ALL int rcu_needs_cpu (unsigned long *delta_jiffies); -#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */ void rcu_cpu_stall_reset (void );/*
@@ -93,6 +91,11 @@ void rcu_force_quiescent_state(void);void rcu_bh_force_quiescent_state (void );void rcu_sched_force_quiescent_state (void ); +void rcu_idle_enter (void ); +void rcu_idle_exit (void ); +void rcu_irq_enter (void ); +void rcu_irq_exit (void ); +void exit_rcu (void );void rcu_scheduler_starting (void );
include/linux/spinlock.h +1 -1
@@ -120,7 +120,7 @@ do { \/* * Despite its name it doesn't necessarily has to be a full barrier. * It should only guarantee that a STORE before the critical section -* can not be reordered with a LOAD inside this section. +* can not be reordered with LOADs and STOREs inside this section. * spin_lock() is the one-way barrier, this LOAD can not escape out * of the region. So the default implementation simply ensures that * a STORE can not move into the critical section, smp_wmb() should
init/Kconfig +29 -43
153 lines not on this page · raw message
kernel/cpu.c +2 -2
@@ -398,7 +398,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) err =__stop_machine (take_cpu_down, &tcd_param,cpumask_of (cpu));if (err) {/* CPU didn't die: tell everyone. Can't complain. */ -smpboot_unpark_threads (cpu);cpu_notify_nofail (CPU_DOWN_FAILED | mod, hcpu); goto out_release; }
@@ -463,6 +462,7 @@ static int smpboot_thread_call(struct notifier_block *nfb,switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_DOWN_FAILED :case CPU_ONLINE :smpboot_unpark_threads (cpu);break ;
@@ -479,7 +479,7 @@ static struct notifier_block smpboot_thread_notifier = { .priority = CPU_PRI_SMPBOOT, }; -void __cpuinit smpboot_thread_init (void ) +void smpboot_thread_init (void ) {register_cpu_notifier (&smpboot_thread_notifier); }
kernel/events/ring_buffer.c +1 -1
@@ -141,7 +141,7 @@ int perf_output_begin(struct perf_output_handle *handle,perf_output_get_handle (handle); do { - tail = ACCESS_ONCE(rb->user_page->data_tail); + tail = READ_ONCE_CTRL(rb->user_page->data_tail); offset = head = local_read(&rb->head); if (!rb->overwrite && unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))
kernel/locking/locktorture.c +7 -7
@@ -122,12 +122,12 @@ static int torture_lock_busted_write_lock(void)static void torture_lock_busted_write_delay (struct torture_random_state *trsp) { -const unsigned long longdelay_us =100 ; +const unsigned long longdelay_ms =100 ;/* We want a long delay occasionally to force massive contention. */ if (!(torture_random (trsp) % - (cxt.nrealwriters_stress *2000 * longdelay_us))) -mdelay (longdelay_us); + (cxt.nrealwriters_stress *2000 * longdelay_ms))) +mdelay (longdelay_ms);#ifdef CONFIG_PREEMPT if (!(torture_random (trsp) % (cxt.nrealwriters_stress *20000 )))preempt_schedule ();/* Allow test to be preempted. */
@@ -160,14 +160,14 @@ static int torture_spin_lock_write_lock(void) __acquires(torture_spinlock)static void torture_spin_lock_write_delay (struct torture_random_state *trsp) {const unsigned long shortdelay_us =2 ; -const unsigned long longdelay_us =100 ; +const unsigned long longdelay_ms =100 ;/* We want a short delay mostly to emulate likely code, and * we want a long delay occasionally to force massive contention. */ if (!(torture_random (trsp) % - (cxt.nrealwriters_stress *2000 * longdelay_us))) -mdelay (longdelay_us); + (cxt.nrealwriters_stress *2000 * longdelay_ms))) +mdelay (longdelay_ms);if (!(torture_random (trsp) % (cxt.nrealwriters_stress *2 * shortdelay_us)))udelay (shortdelay_us);
@@ -309,7 +309,7 @@ static int torture_rwlock_read_lock_irq(void) __acquires(torture_rwlock)static void torture_rwlock_read_unlock_irq (void )__releases (torture_rwlock) { -write_unlock_irqrestore (&torture_rwlock, cxt.cur_ops->flags); +read_unlock_irqrestore (&torture_rwlock, cxt.cur_ops->flags); }static struct lock_torture_ops rw_lock_irq_ops = {
kernel/rcu/rcutorture.c +72 -31
237 lines not on this page · raw message
kernel/rcu/srcu.c +5 -5
@@ -151,7 +151,7 @@ static unsigned long srcu_readers_seq_idx(struct srcu_struct *sp, int idx)unsigned long t;for_each_possible_cpu (cpu) { - t =ACCESS_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->seq[idx]); + t =READ_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->seq[idx]); sum += t; }return sum;
@@ -168,7 +168,7 @@ static unsigned long srcu_readers_active_idx(struct srcu_struct *sp, int idx)unsigned long t;for_each_possible_cpu (cpu) { - t =ACCESS_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[idx]); + t =READ_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[idx]); sum += t; }return sum;
@@ -265,8 +265,8 @@ static int srcu_readers_active(struct srcu_struct *sp)unsigned long sum =0 ;for_each_possible_cpu (cpu) { - sum +=ACCESS_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[0 ]); - sum +=ACCESS_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[1 ]); + sum +=READ_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[0 ]); + sum +=READ_ONCE (per_cpu_ptr (sp->per_cpu_ref, cpu)->c[1 ]); }return sum; }
@@ -296,7 +296,7 @@ int __srcu_read_lock(struct srcu_struct *sp) {int idx; - idx =ACCESS_ONCE (sp->completed) &0x1 ; + idx =READ_ONCE (sp->completed) &0x1 ;preempt_disable ();__this_cpu_inc (sp->per_cpu_ref->c[idx]);smp_mb ();/* B */ /* Avoid leaking the critical section. */
kernel/rcu/tiny.c +5 -33
@@ -49,39 +49,6 @@ static void __call_rcu(struct rcu_head *head,#include "tiny_plugin.h" -/* -* Enter idle, which is an extended quiescent state if we have fully -* entered that mode. -*/ -void rcu_idle_enter (void ) -{ -} -EXPORT_SYMBOL_GPL (rcu_idle_enter); - -/* -* Exit an interrupt handler towards idle. -*/ -void rcu_irq_exit (void ) -{ -} -EXPORT_SYMBOL_GPL (rcu_irq_exit); - -/* -* Exit idle, so that we are no longer in an extended quiescent state. -*/ -void rcu_idle_exit (void ) -{ -} -EXPORT_SYMBOL_GPL (rcu_idle_exit); - -/* -* Enter an interrupt handler, moving away from idle. -*/ -void rcu_irq_enter (void ) -{ -} -EXPORT_SYMBOL_GPL (rcu_irq_enter); -#if defined(CONFIG_DEBUG_LOCK_ALLOC ) || defined(CONFIG_RCU_TRACE )/*
@@ -170,6 +137,11 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)/* Move the ready-to-invoke callbacks to a local list. */ local_irq_save (flags); +if (rcp->donetail == &rcp->rcucblist) { +/* No callbacks ready, so just leave. */ +local_irq_restore (flags); +return ; + }RCU_TRACE (trace_rcu_batch_start (rcp->name,0 , rcp->qlen,-1 )); list = rcp->rcucblist; rcp->rcucblist = *rcp->donetail;
kernel/rcu/tiny_plugin.h +7 -5
@@ -144,16 +144,17 @@ static void check_cpu_stall(struct rcu_ctrlblk *rcp)return ; rcp->ticks_this_gp++; j = jiffies; - js =ACCESS_ONCE (rcp->jiffies_stall); + js =READ_ONCE (rcp->jiffies_stall);if (rcp->rcucblist &&ULONG_CMP_GE (j, js)) {pr_err ("INFO: %s stall on CPU (%lu ticks this GP) idle=%llx (t=%lu jiffies q=%ld)\n" , rcp->name, rcp->ticks_this_gp,DYNTICK_TASK_EXIT_IDLE , jiffies - rcp->gp_start, rcp->qlen);dump_stack (); -ACCESS_ONCE (rcp->jiffies_stall) = jiffies + -3 *rcu_jiffies_till_stall_check () +3 ; +WRITE_ONCE (rcp->jiffies_stall, + jiffies +3 *rcu_jiffies_till_stall_check () +3 ); }else if (ULONG_CMP_GE (j, js)) { -ACCESS_ONCE (rcp->jiffies_stall) = jiffies +rcu_jiffies_till_stall_check (); +WRITE_ONCE (rcp->jiffies_stall, + jiffies +rcu_jiffies_till_stall_check ()); } }
@@ -161,7 +162,8 @@ static void reset_cpu_stall_ticks(struct rcu_ctrlblk *rcp) { rcp->ticks_this_gp =0 ; rcp->gp_start = jiffies; -ACCESS_ONCE (rcp->jiffies_stall) = jiffies +rcu_jiffies_till_stall_check (); +WRITE_ONCE (rcp->jiffies_stall, + jiffies +rcu_jiffies_till_stall_check ()); }static void check_cpu_stalls (void )
kernel/rcu/tree.c +212 -153
950 lines not on this page · raw message
kernel/rcu/tree.h +26 -9
@@ -35,11 +35,33 @@* In practice, this did work well going from three levels to four. * Of course, your mileage may vary. */ +#define MAX_RCU_LVLS 4 -#define RCU_FANOUT_1 (CONFIG_RCU_FANOUT_LEAF) -#define RCU_FANOUT_2 (RCU_FANOUT_1 * CONFIG_RCU_FANOUT) -#define RCU_FANOUT_3 (RCU_FANOUT_2 * CONFIG_RCU_FANOUT) -#define RCU_FANOUT_4 (RCU_FANOUT_3 * CONFIG_RCU_FANOUT) + +#ifdef CONFIG_RCU_FANOUT +#define RCU_FANOUT CONFIG_RCU_FANOUT +#else /* #ifdef CONFIG_RCU_FANOUT */ +# ifdef CONFIG_64BIT +# define RCU_FANOUT 64 +# else +# define RCU_FANOUT 32 +# endif +#endif /* #else #ifdef CONFIG_RCU_FANOUT */ + +#ifdef CONFIG_RCU_FANOUT_LEAF +#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF +#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */ +# ifdef CONFIG_64BIT +# define RCU_FANOUT_LEAF 64 +# else +# define RCU_FANOUT_LEAF 32 +# endif +#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */ + +#define RCU_FANOUT_1 (RCU_FANOUT_LEAF) +#define RCU_FANOUT_2 (RCU_FANOUT_1 * RCU_FANOUT) +#define RCU_FANOUT_3 (RCU_FANOUT_2 * RCU_FANOUT) +#define RCU_FANOUT_4 (RCU_FANOUT_3 * RCU_FANOUT)#if NR_CPUS <=RCU_FANOUT_1 # define RCU_NUM_LVLS 1
@@ -170,7 +192,6 @@ struct rcu_node {/* if there is no such task. If there */ /* is no current expedited grace period, */ /* then there can cannot be any such task. */ -#ifdef CONFIG_RCU_BOOST struct list_head *boost_tasks;/* Pointer to first task that needs to be */ /* priority boosted, or NULL if no priority */
@@ -208,7 +229,6 @@ struct rcu_node {unsigned long n_balk_nos;/* Refused to boost: not sure why, though. */ /* This can happen due to race conditions. */ -#endif /* #ifdef CONFIG_RCU_BOOST */ #ifdef CONFIG_RCU_NOCB_CPU wait_queue_head_t nocb_gp_wq[2 ];/* Place for rcu_nocb_kthread() to wait GP. */
@@ -519,14 +539,11 @@ extern struct list_head rcu_struct_flavors;* RCU implementation internal declarations: */ extern struct rcu_state rcu_sched_state; -DECLARE_PER_CPU(struct rcu_data, rcu_sched_data);extern struct rcu_state rcu_bh_state; -DECLARE_PER_CPU(struct rcu_data, rcu_bh_data);#ifdef CONFIG_PREEMPT_RCU extern struct rcu_state rcu_preempt_state; -DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);#endif /* #ifdef CONFIG_PREEMPT_RCU */ #ifdef CONFIG_RCU_BOOST
kernel/rcu/tree_plugin.h +113 -103
635 lines not on this page · raw message
kernel/rcu/tree_trace.c +3 -3
@@ -277,7 +277,7 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)seq_printf (m,"nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n" , rsp->n_force_qs, rsp->n_force_qs_ngp, rsp->n_force_qs - rsp->n_force_qs_ngp, -ACCESS_ONCE (rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen); +READ_ONCE (rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen);for (rnp = &rsp->node[0 ]; rnp - &rsp->node[0 ] < rcu_num_nodes; rnp++) {if (rnp->level != level) {seq_puts (m,"\n" );
@@ -323,8 +323,8 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)struct rcu_node *rnp = &rsp->node[0 ];raw_spin_lock_irqsave (&rnp->lock, flags); - completed =ACCESS_ONCE (rsp->completed); - gpnum =ACCESS_ONCE (rsp->gpnum); + completed =READ_ONCE (rsp->completed); + gpnum =READ_ONCE (rsp->gpnum);if (completed == gpnum) gpage =0 ;else
kernel/rcu/update.c +15 -15
@@ -150,14 +150,14 @@ void __rcu_read_unlock(void)barrier ();/* critical section before exit code. */ t->rcu_read_lock_nesting =INT_MIN ;barrier ();/* assign before ->rcu_read_unlock_special load */ -if (unlikely (ACCESS_ONCE (t->rcu_read_unlock_special.s))) +if (unlikely (READ_ONCE (t->rcu_read_unlock_special.s)))rcu_read_unlock_special (t);barrier ();/* ->rcu_read_unlock_special load before assign */ t->rcu_read_lock_nesting =0 ; }#ifdef CONFIG_PROVE_LOCKING { -int rrln =ACCESS_ONCE (t->rcu_read_lock_nesting); +int rrln =READ_ONCE (t->rcu_read_lock_nesting);WARN_ON_ONCE (rrln <0 && rrln >INT_MIN /2 ); }
@@ -389,17 +389,17 @@ module_param(rcu_cpu_stall_timeout, int, 0644);int rcu_jiffies_till_stall_check (void ) { -int till_stall_check =ACCESS_ONCE (rcu_cpu_stall_timeout); +int till_stall_check =READ_ONCE (rcu_cpu_stall_timeout);/* * Limit check must be consistent with the Kconfig limits * for CONFIG_RCU_CPU_STALL_TIMEOUT. */ if (till_stall_check <3 ) { -ACCESS_ONCE (rcu_cpu_stall_timeout) =3 ; +WRITE_ONCE (rcu_cpu_stall_timeout,3 ); till_stall_check =3 ; }else if (till_stall_check >300 ) { -ACCESS_ONCE (rcu_cpu_stall_timeout) =300 ; +WRITE_ONCE (rcu_cpu_stall_timeout,300 ); till_stall_check =300 ; }return till_stall_check *HZ +RCU_STALL_DELAY_DELTA ;
@@ -550,12 +550,12 @@ static void check_holdout_task(struct task_struct *t, {int cpu; -if (!ACCESS_ONCE (t->rcu_tasks_holdout) || - t->rcu_tasks_nvcsw !=ACCESS_ONCE (t->nvcsw) || - !ACCESS_ONCE (t->on_rq) || +if (!READ_ONCE (t->rcu_tasks_holdout) || + t->rcu_tasks_nvcsw !=READ_ONCE (t->nvcsw) || + !READ_ONCE (t->on_rq) || (IS_ENABLED (CONFIG_NO_HZ_FULL ) && !is_idle_task (t) && t->rcu_tasks_idle_cpu >=0 )) { -ACCESS_ONCE (t->rcu_tasks_holdout) = false; +WRITE_ONCE (t->rcu_tasks_holdout, false);list_del_init (&t->rcu_tasks_holdout_list);put_task_struct (t);return ;
@@ -639,11 +639,11 @@ static int __noreturn rcu_tasks_kthread(void *arg)*/ rcu_read_lock ();for_each_process_thread (g, t) { -if (t != current &&ACCESS_ONCE (t->on_rq) && +if (t != current &&READ_ONCE (t->on_rq) && !is_idle_task (t)) {get_task_struct (t); - t->rcu_tasks_nvcsw =ACCESS_ONCE (t->nvcsw); -ACCESS_ONCE (t->rcu_tasks_holdout) = true; + t->rcu_tasks_nvcsw =READ_ONCE (t->nvcsw); +WRITE_ONCE (t->rcu_tasks_holdout, true);list_add (&t->rcu_tasks_holdout_list, &rcu_tasks_holdouts); }
@@ -672,7 +672,7 @@ static int __noreturn rcu_tasks_kthread(void *arg)struct task_struct *t1;schedule_timeout_interruptible (HZ ); - rtst =ACCESS_ONCE (rcu_task_stall_timeout); + rtst =READ_ONCE (rcu_task_stall_timeout); needreport = rtst >0 &&time_after (jiffies, lastreport + rtst);if (needreport)
@@ -728,7 +728,7 @@ static void rcu_spawn_tasks_kthread(void)static struct task_struct *rcu_tasks_kthread_ptr;struct task_struct *t; -if (ACCESS_ONCE (rcu_tasks_kthread_ptr)) { +if (READ_ONCE (rcu_tasks_kthread_ptr)) {smp_mb ();/* Ensure caller sees full kthread. */ return ; }
@@ -740,7 +740,7 @@ static void rcu_spawn_tasks_kthread(void) t =kthread_run (rcu_tasks_kthread,NULL ,"rcu_tasks_kthread" );BUG_ON (IS_ERR (t));smp_mb ();/* Ensure others see full kthread. */ -ACCESS_ONCE (rcu_tasks_kthread_ptr) = t; +WRITE_ONCE (rcu_tasks_kthread_ptr, t);mutex_unlock (&rcu_tasks_kthread_mutex); }
kernel/torture.c +13 -13
@@ -409,7 +409,7 @@ static void (*torture_shutdown_hook)(void);*/ void torture_shutdown_absorb (const char *title) { -while (ACCESS_ONCE (fullstop) ==FULLSTOP_SHUTDOWN ) { +while (READ_ONCE (fullstop) ==FULLSTOP_SHUTDOWN ) {pr_notice ("torture thread %s parking due to system shutdown\n" , title);schedule_timeout_uninterruptible (MAX_SCHEDULE_TIMEOUT );
@@ -480,9 +480,9 @@ static int torture_shutdown_notify(struct notifier_block *unused1, unsigned long unused2, void *unused3) { mutex_lock(&fullstop_mutex); -if (ACCESS_ONCE (fullstop) ==FULLSTOP_DONTSTOP ) { +if (READ_ONCE (fullstop) ==FULLSTOP_DONTSTOP ) {VERBOSE_TOROUT_STRING ("Unscheduled system shutdown detected" ); -ACCESS_ONCE (fullstop) =FULLSTOP_SHUTDOWN ; +WRITE_ONCE (fullstop,FULLSTOP_SHUTDOWN ); }else {pr_warn ("Concurrent rmmod and shutdown illegal!\n" ); }
@@ -523,13 +523,13 @@ static int stutter;*/ void stutter_wait (const char *title) { -while (ACCESS_ONCE (stutter_pause_test) || - (torture_runnable && !ACCESS_ONCE (*torture_runnable))) { +while (READ_ONCE (stutter_pause_test) || + (torture_runnable && !READ_ONCE (*torture_runnable))) {if (stutter_pause_test) -if (ACCESS_ONCE (stutter_pause_test) ==1 ) +if (READ_ONCE (stutter_pause_test) ==1 )schedule_timeout_interruptible (1 );else -while (ACCESS_ONCE (stutter_pause_test)) +while (READ_ONCE (stutter_pause_test))cond_resched ();else schedule_timeout_interruptible (round_jiffies_relative (HZ ));
@@ -549,14 +549,14 @@ static int torture_stutter(void *arg)if (!torture_must_stop ()) {if (stutter >1 ) {schedule_timeout_interruptible (stutter -1 ); -ACCESS_ONCE (stutter_pause_test) =2 ; +WRITE_ONCE (stutter_pause_test,2 ); }schedule_timeout_interruptible (1 ); -ACCESS_ONCE (stutter_pause_test) =1 ; +WRITE_ONCE (stutter_pause_test,1 ); }if (!torture_must_stop ())schedule_timeout_interruptible (stutter); -ACCESS_ONCE (stutter_pause_test) =0 ; +WRITE_ONCE (stutter_pause_test,0 );torture_shutdown_absorb ("torture_stutter" ); }while (!torture_must_stop ());torture_kthread_stopping ("torture_stutter" );
@@ -642,13 +642,13 @@ EXPORT_SYMBOL_GPL(torture_init_end);bool torture_cleanup_begin (void ) {mutex_lock (&fullstop_mutex); -if (ACCESS_ONCE (fullstop) ==FULLSTOP_SHUTDOWN ) { +if (READ_ONCE (fullstop) ==FULLSTOP_SHUTDOWN ) {pr_warn ("Concurrent rmmod and shutdown illegal!\n" );mutex_unlock (&fullstop_mutex);schedule_timeout_uninterruptible (10 );
Lines of this file are not shown. View the raw message.
lib/Kconfig.debug +64 -2
66 lines not on this page · raw message
tools/testing/selftests/rcutorture/bin/configinit.sh +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/bin/kvm-recheck.sh +4 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/bin/kvm.sh +19 -6
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/CFcommon +2 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/SRCU-N +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/SRCU-P +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TASKS01 +3 -2
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TASKS02 +0 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TASKS03 +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TINY02 +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE01 +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE02 +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE02-T +0 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE03 +4 -4
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot new file +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE04 +4 -4
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE05 +2 -2
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE06 +2 -2
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE07 +2 -2
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE08 +3 -3
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE08-T +0 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE08-T.boot new file +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/configs/rcu/TREE09 +1 -0
Lines of this file are not shown. View the raw message.
tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt +13 -23
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/
Part of the diff is not shown here. View the raw message.