aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 14:05:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 14:05:24 -0400
commitb3fd4ea9df2d5c39cd6ce08faf965ed669eb3b56 (patch)
treede45e2aff3106f4fa413ea3f08a7f8c969c0479b
parent462bf234a82ae1ae9d7628f59bc81022591e1348 (diff)
parent7de700e6806cafa30c70bc84478431a11197a5ea (diff)
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU updates from Ingo Molnar: "Main changes: - Torture-test changes, including refactoring of rcutorture and introduction of a vestigial locktorture. - Real-time latency fixes. - Documentation updates. - Miscellaneous fixes" * 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (77 commits) rcu: Provide grace-period piggybacking API rcu: Ensure kernel/rcu/rcu.h can be sourced/used stand-alone rcu: Fix sparse warning for rcu_expedited from kernel/ksysfs.c notifier: Substitute rcu_access_pointer() for rcu_dereference_raw() Documentation/memory-barriers.txt: Clarify release/acquire ordering rcutorture: Save kvm.sh output to log rcutorture: Add a lock_busted to test the test rcutorture: Place kvm-test-1-run.sh output into res directory rcutorture: Rename TREE_RCU-Kconfig.txt locktorture: Add kvm-recheck.sh plug-in for locktorture rcutorture: Gracefully handle NULL cleanup hooks locktorture: Add vestigial locktorture configuration rcutorture: Introduce "rcu" directory level underneath configs rcutorture: Rename kvm-test-1-rcu.sh rcutorture: Remove RCU dependencies from ver_functions.sh API rcutorture: Create CFcommon file for common Kconfig parameters rcutorture: Create config files for scripted test-the-test testing rcutorture: Add an rcu_busted to test the test locktorture: Add a lock-torture kernel module rcutorture: Abstract kvm-recheck.sh ...
-rw-r--r--Documentation/RCU/RTFP.txt149
-rw-r--r--Documentation/RCU/checklist.txt18
-rw-r--r--Documentation/kernel-per-CPU-kthreads.txt13
-rw-r--r--Documentation/memory-barriers.txt137
-rw-r--r--fs/file.c2
-rw-r--r--include/linux/rculist.h17
-rw-r--r--include/linux/rcupdate.h94
-rw-r--r--include/linux/rcutiny.h20
-rw-r--r--include/linux/rcutree.h8
-rw-r--r--include/linux/srcu.h4
-rw-r--r--include/linux/torture.h100
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/ksysfs.c2
-rw-r--r--kernel/locking/Makefile1
-rw-r--r--kernel/locking/locktorture.c452
-rw-r--r--kernel/notifier.c2
-rw-r--r--kernel/rcu/Makefile2
-rw-r--r--kernel/rcu/rcu.h7
-rw-r--r--kernel/rcu/rcutorture.c (renamed from kernel/rcu/torture.c)996
-rw-r--r--kernel/rcu/srcu.c11
-rw-r--r--kernel/rcu/tiny.c8
-rw-r--r--kernel/rcu/tiny_plugin.h4
-rw-r--r--kernel/rcu/tree.c80
-rw-r--r--kernel/rcu/tree.h4
-rw-r--r--kernel/rcu/tree_plugin.h19
-rw-r--r--kernel/rcu/tree_trace.c6
-rw-r--r--kernel/rcu/update.c5
-rw-r--r--kernel/torture.c719
-rw-r--r--lib/Kconfig.debug20
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh1
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh51
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh51
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh13
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh (renamed from tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh)53
-rw-r--r--tools/testing/selftests/rcutorture/bin/kvm.sh276
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/BUSTED6
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFLIST1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFcommon2
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK016
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh43
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/BUSTED7
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFcommon2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N (renamed from tools/testing/selftests/rcutorture/configs/SRCU-N)3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot (renamed from tools/testing/selftests/rcutorture/configs/SRCU-N.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-P (renamed from tools/testing/selftests/rcutorture/configs/SRCU-P)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot (renamed from tools/testing/selftests/rcutorture/configs/SRCU-P.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY01 (renamed from tools/testing/selftests/rcutorture/configs/TINY01)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY02 (renamed from tools/testing/selftests/rcutorture/configs/TINY02)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01 (renamed from tools/testing/selftests/rcutorture/configs/TREE01)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE01.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE02 (renamed from tools/testing/selftests/rcutorture/configs/TREE02)3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE03 (renamed from tools/testing/selftests/rcutorture/configs/TREE03)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04 (renamed from tools/testing/selftests/rcutorture/configs/TREE04)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE04.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05 (renamed from tools/testing/selftests/rcutorture/configs/TREE05)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE05.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE06 (renamed from tools/testing/selftests/rcutorture/configs/TREE06)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE07 (renamed from tools/testing/selftests/rcutorture/configs/TREE07)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08 (renamed from tools/testing/selftests/rcutorture/configs/TREE08)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08-T (renamed from tools/testing/selftests/rcutorture/configs/TREE08-T)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE09 (renamed from tools/testing/selftests/rcutorture/configs/TREE09)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v0.0/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh)22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.12/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.3/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/ver_functions.sh)28
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.5/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh)23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh)26
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt (renamed from tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt)0
137 files changed, 2454 insertions, 1078 deletions
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 273e654d7d08..2f0fcb2112d2 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -31,6 +31,14 @@ has lapsed, so this approach may be used in non-GPL software, if desired.
31(In contrast, implementation of RCU is permitted only in software licensed 31(In contrast, implementation of RCU is permitted only in software licensed
32under either GPL or LGPL. Sorry!!!) 32under either GPL or LGPL. Sorry!!!)
33 33
34In 1987, Rashid et al. described lazy TLB-flush [RichardRashid87a].
35At first glance, this has nothing to do with RCU, but nevertheless
36this paper helped inspire the update-side batching used in the later
37RCU implementation in DYNIX/ptx. In 1988, Barbara Liskov published
38a description of Argus that noted that use of out-of-date values can
39be tolerated in some situations. Thus, this paper provides some early
40theoretical justification for use of stale data.
41
34In 1990, Pugh [Pugh90] noted that explicitly tracking which threads 42In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
35were reading a given data structure permitted deferred free to operate 43were reading a given data structure permitted deferred free to operate
36in the presence of non-terminating threads. However, this explicit 44in the presence of non-terminating threads. However, this explicit
@@ -41,11 +49,11 @@ providing a fine-grained locking design, however, it would be interesting
41to see how much of the performance advantage reported in 1990 remains 49to see how much of the performance advantage reported in 1990 remains
42today. 50today.
43 51
44At about this same time, Adams [Adams91] described ``chaotic relaxation'', 52At about this same time, Andrews [Andrews91textbook] described ``chaotic
45where the normal barriers between successive iterations of convergent 53relaxation'', where the normal barriers between successive iterations
46numerical algorithms are relaxed, so that iteration $n$ might use 54of convergent numerical algorithms are relaxed, so that iteration $n$
47data from iteration $n-1$ or even $n-2$. This introduces error, 55might use data from iteration $n-1$ or even $n-2$. This introduces
48which typically slows convergence and thus increases the number of 56error, which typically slows convergence and thus increases the number of
49iterations required. However, this increase is sometimes more than made 57iterations required. However, this increase is sometimes more than made
50up for by a reduction in the number of expensive barrier operations, 58up for by a reduction in the number of expensive barrier operations,
51which are otherwise required to synchronize the threads at the end 59which are otherwise required to synchronize the threads at the end
@@ -55,7 +63,8 @@ is thus inapplicable to most data structures in operating-system kernels.
55 63
56In 1992, Henry (now Alexia) Massalin completed a dissertation advising 64In 1992, Henry (now Alexia) Massalin completed a dissertation advising
57parallel programmers to defer processing when feasible to simplify 65parallel programmers to defer processing when feasible to simplify
58synchronization. RCU makes extremely heavy use of this advice. 66synchronization [HMassalinPhD]. RCU makes extremely heavy use of
67this advice.
59 68
60In 1993, Jacobson [Jacobson93] verbally described what is perhaps the 69In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
61simplest deferred-free technique: simply waiting a fixed amount of time 70simplest deferred-free technique: simply waiting a fixed amount of time
@@ -90,27 +99,29 @@ mechanism, which is quite similar to RCU [Gamsa99]. These operating
90systems made pervasive use of RCU in place of "existence locks", which 99systems made pervasive use of RCU in place of "existence locks", which
91greatly simplifies locking hierarchies and helps avoid deadlocks. 100greatly simplifies locking hierarchies and helps avoid deadlocks.
92 101
932001 saw the first RCU presentation involving Linux [McKenney01a] 102The year 2000 saw an email exchange that would likely have
94at OLS. The resulting abundance of RCU patches was presented the 103led to yet another independent invention of something like RCU
95following year [McKenney02a], and use of RCU in dcache was first 104[RustyRussell2000a,RustyRussell2000b]. Instead, 2001 saw the first
96described that same year [Linder02a]. 105RCU presentation involving Linux [McKenney01a] at OLS. The resulting
106abundance of RCU patches was presented the following year [McKenney02a],
107and use of RCU in dcache was first described that same year [Linder02a].
97 108
98Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer" 109Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
99techniques that defer the destruction of data structures to simplify 110techniques that defer the destruction of data structures to simplify
100non-blocking synchronization (wait-free synchronization, lock-free 111non-blocking synchronization (wait-free synchronization, lock-free
101synchronization, and obstruction-free synchronization are all examples of 112synchronization, and obstruction-free synchronization are all examples of
102non-blocking synchronization). In particular, this technique eliminates 113non-blocking synchronization). The corresponding journal article appeared
103locking, reduces contention, reduces memory latency for readers, and 114in 2004 [MagedMichael04a]. This technique eliminates locking, reduces
104parallelizes pipeline stalls and memory latency for writers. However, 115contention, reduces memory latency for readers, and parallelizes pipeline
105these techniques still impose significant read-side overhead in the 116stalls and memory latency for writers. However, these techniques still
106form of memory barriers. Researchers at Sun worked along similar lines 117impose significant read-side overhead in the form of memory barriers.
107in the same timeframe [HerlihyLM02]. These techniques can be thought 118Researchers at Sun worked along similar lines in the same timeframe
108of as inside-out reference counts, where the count is represented by the 119[HerlihyLM02]. These techniques can be thought of as inside-out reference
109number of hazard pointers referencing a given data structure rather than 120counts, where the count is represented by the number of hazard pointers
110the more conventional counter field within the data structure itself. 121referencing a given data structure rather than the more conventional
111The key advantage of inside-out reference counts is that they can be 122counter field within the data structure itself. The key advantage
112stored in immortal variables, thus allowing races between access and 123of inside-out reference counts is that they can be stored in immortal
113deletion to be avoided. 124variables, thus allowing races between access and deletion to be avoided.
114 125
115By the same token, RCU can be thought of as a "bulk reference count", 126By the same token, RCU can be thought of as a "bulk reference count",
116where some form of reference counter covers all reference by a given CPU 127where some form of reference counter covers all reference by a given CPU
@@ -123,8 +134,10 @@ can be thought of in other terms as well.
123 134
124In 2003, the K42 group described how RCU could be used to create 135In 2003, the K42 group described how RCU could be used to create
125hot-pluggable implementations of operating-system functions [Appavoo03a]. 136hot-pluggable implementations of operating-system functions [Appavoo03a].
126Later that year saw a paper describing an RCU implementation of System 137Later that year saw a paper describing an RCU implementation
127V IPC [Arcangeli03], and an introduction to RCU in Linux Journal 138of System V IPC [Arcangeli03] (following up on a suggestion by
139Hugh Dickins [Dickins02a] and an implementation by Mingming Cao
140[MingmingCao2002IPCRCU]), and an introduction to RCU in Linux Journal
128[McKenney03a]. 141[McKenney03a].
129 142
1302004 has seen a Linux-Journal article on use of RCU in dcache 1432004 has seen a Linux-Journal article on use of RCU in dcache
@@ -383,6 +396,21 @@ for Programming Languages and Operating Systems}"
383} 396}
384} 397}
385 398
399@phdthesis{HMassalinPhD
400,author="H. Massalin"
401,title="Synthesis: An Efficient Implementation of Fundamental Operating
402System Services"
403,school="Columbia University"
404,address="New York, NY"
405,year="1992"
406,annotation={
407 Mondo optimizing compiler.
408 Wait-free stuff.
409 Good advice: defer work to avoid synchronization. See page 90
410 (PDF page 106), Section 5.4, fourth bullet point.
411}
412}
413
386@unpublished{Jacobson93 414@unpublished{Jacobson93
387,author="Van Jacobson" 415,author="Van Jacobson"
388,title="Avoid Read-Side Locking Via Delayed Free" 416,title="Avoid Read-Side Locking Via Delayed Free"
@@ -671,6 +699,20 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
671[Viewed October 18, 2004]" 699[Viewed October 18, 2004]"
672} 700}
673 701
702@conference{Michael02b
703,author="Maged M. Michael"
704,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
705,Year="2002"
706,Month="August"
707,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
708Symposium on Parallel
709Algorithms and Architecture}"
710,pages="73-82"
711,annotation={
712Like the title says...
713}
714}
715
674@Conference{Linder02a 716@Conference{Linder02a
675,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni" 717,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
676,Title="Scalability of the Directory Entry Cache" 718,Title="Scalability of the Directory Entry Cache"
@@ -727,6 +769,24 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
727} 769}
728} 770}
729 771
772@conference{Michael02a
773,author="Maged M. Michael"
774,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
775Reads and Writes"
776,Year="2002"
777,Month="August"
778,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
779Symposium on Principles of Distributed Computing}"
780,pages="21-30"
781,annotation={
782 Each thread keeps an array of pointers to items that it is
783 currently referencing. Sort of an inside-out garbage collection
784 mechanism, but one that requires the accessing code to explicitly
785 state its needs. Also requires read-side memory barriers on
786 most architectures.
787}
788}
789
730@unpublished{Dickins02a 790@unpublished{Dickins02a
731,author="Hugh Dickins" 791,author="Hugh Dickins"
732,title="Use RCU for System-V IPC" 792,title="Use RCU for System-V IPC"
@@ -735,6 +795,17 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
735,note="private communication" 795,note="private communication"
736} 796}
737 797
798@InProceedings{HerlihyLM02
799,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
800,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
801Lock-Free Data Structures"
802,booktitle={Proceedings of 16\textsuperscript{th} International
803Symposium on Distributed Computing}
804,year=2002
805,month="October"
806,pages="339-353"
807}
808
738@unpublished{Sarma02b 809@unpublished{Sarma02b
739,Author="Dipankar Sarma" 810,Author="Dipankar Sarma"
740,Title="Some dcache\_rcu benchmark numbers" 811,Title="Some dcache\_rcu benchmark numbers"
@@ -749,6 +820,19 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
749} 820}
750} 821}
751 822
823@unpublished{MingmingCao2002IPCRCU
824,Author="Mingming Cao"
825,Title="[PATCH]updated ipc lock patch"
826,month="October"
827,year="2002"
828,note="Available:
829\url{https://lkml.org/lkml/2002/10/24/262}
830[Viewed February 15, 2014]"
831,annotation={
832 Mingming Cao's patch to introduce RCU to SysV IPC.
833}
834}
835
752@unpublished{LinusTorvalds2003a 836@unpublished{LinusTorvalds2003a
753,Author="Linus Torvalds" 837,Author="Linus Torvalds"
754,Title="Re: {[PATCH]} small fixes in brlock.h" 838,Title="Re: {[PATCH]} small fixes in brlock.h"
@@ -982,6 +1066,23 @@ Realtime Applications"
982} 1066}
983} 1067}
984 1068
1069@article{MagedMichael04a
1070,author="Maged M. Michael"
1071,title="Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects"
1072,Year="2004"
1073,Month="June"
1074,journal="IEEE Transactions on Parallel and Distributed Systems"
1075,volume="15"
1076,number="6"
1077,pages="491-504"
1078,url="Available:
1079\url{http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf}
1080[Viewed March 1, 2005]"
1081,annotation={
1082 New canonical hazard-pointer citation.
1083}
1084}
1085
985@phdthesis{PaulEdwardMcKenneyPhD 1086@phdthesis{PaulEdwardMcKenneyPhD
986,author="Paul E. McKenney" 1087,author="Paul E. McKenney"
987,title="Exploiting Deferred Destruction: 1088,title="Exploiting Deferred Destruction:
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 91266193b8f4..9d10d1db16a5 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -256,10 +256,10 @@ over a rather long period of time, but improvements are always welcome!
256 variations on this theme. 256 variations on this theme.
257 257
258 b. Limiting update rate. For example, if updates occur only 258 b. Limiting update rate. For example, if updates occur only
259 once per hour, then no explicit rate limiting is required, 259 once per hour, then no explicit rate limiting is
260 unless your system is already badly broken. The dcache 260 required, unless your system is already badly broken.
261 subsystem takes this approach -- updates are guarded 261 Older versions of the dcache subsystem take this approach,
262 by a global lock, limiting their rate. 262 guarding updates with a global lock, limiting their rate.
263 263
264 c. Trusted update -- if updates can only be done manually by 264 c. Trusted update -- if updates can only be done manually by
265 superuser or some other trusted user, then it might not 265 superuser or some other trusted user, then it might not
@@ -268,7 +268,8 @@ over a rather long period of time, but improvements are always welcome!
268 the machine. 268 the machine.
269 269
270 d. Use call_rcu_bh() rather than call_rcu(), in order to take 270 d. Use call_rcu_bh() rather than call_rcu(), in order to take
271 advantage of call_rcu_bh()'s faster grace periods. 271 advantage of call_rcu_bh()'s faster grace periods. (This
272 is only a partial solution, though.)
272 273
273 e. Periodically invoke synchronize_rcu(), permitting a limited 274 e. Periodically invoke synchronize_rcu(), permitting a limited
274 number of updates per grace period. 275 number of updates per grace period.
@@ -276,6 +277,13 @@ over a rather long period of time, but improvements are always welcome!
276 The same cautions apply to call_rcu_bh(), call_rcu_sched(), 277 The same cautions apply to call_rcu_bh(), call_rcu_sched(),
277 call_srcu(), and kfree_rcu(). 278 call_srcu(), and kfree_rcu().
278 279
280 Note that although these primitives do take action to avoid memory
281 exhaustion when any given CPU has too many callbacks, a determined
282 user could still exhaust memory. This is especially the case
283 if a system with a large number of CPUs has been configured to
284 offload all of its RCU callbacks onto a single CPU, or if the
285 system has relatively little free memory.
286
2799. All RCU list-traversal primitives, which include 2879. All RCU list-traversal primitives, which include
280 rcu_dereference(), list_for_each_entry_rcu(), and 288 rcu_dereference(), list_for_each_entry_rcu(), and
281 list_for_each_safe_rcu(), must be either within an RCU read-side 289 list_for_each_safe_rcu(), must be either within an RCU read-side
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index 827104fb9364..f3cd299fcc41 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -162,7 +162,18 @@ Purpose: Execute workqueue requests
162To reduce its OS jitter, do any of the following: 162To reduce its OS jitter, do any of the following:
1631. Run your workload at a real-time priority, which will allow 1631. Run your workload at a real-time priority, which will allow
164 preempting the kworker daemons. 164 preempting the kworker daemons.
1652. Do any of the following needed to avoid jitter that your 1652. A given workqueue can be made visible in the sysfs filesystem
166 by passing the WQ_SYSFS to that workqueue's alloc_workqueue().
167 Such a workqueue can be confined to a given subset of the
168 CPUs using the /sys/devices/virtual/workqueue/*/cpumask sysfs
169 files. The set of WQ_SYSFS workqueues can be displayed using
170 "ls sys/devices/virtual/workqueue". That said, the workqueues
171 maintainer would like to caution people against indiscriminately
172 sprinkling WQ_SYSFS across all the workqueues. The reason for
173 caution is that it is easy to add WQ_SYSFS, but because sysfs is
174 part of the formal user/kernel API, it can be nearly impossible
175 to remove it, even if its addition was a mistake.
1763. Do any of the following needed to avoid jitter that your
166 application cannot tolerate: 177 application cannot tolerate:
167 a. Build your kernel with CONFIG_SLUB=y rather than 178 a. Build your kernel with CONFIG_SLUB=y rather than
168 CONFIG_SLAB=y, thus avoiding the slab allocator's periodic 179 CONFIG_SLAB=y, thus avoiding the slab allocator's periodic
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 102dc19c4119..11c1d2049662 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -608,26 +608,30 @@ as follows:
608 b = p; /* BUG: Compiler can reorder!!! */ 608 b = p; /* BUG: Compiler can reorder!!! */
609 do_something(); 609 do_something();
610 610
611The solution is again ACCESS_ONCE(), which preserves the ordering between 611The solution is again ACCESS_ONCE() and barrier(), which preserves the
612the load from variable 'a' and the store to variable 'b': 612ordering between the load from variable 'a' and the store to variable 'b':
613 613
614 q = ACCESS_ONCE(a); 614 q = ACCESS_ONCE(a);
615 if (q) { 615 if (q) {
616 barrier();
616 ACCESS_ONCE(b) = p; 617 ACCESS_ONCE(b) = p;
617 do_something(); 618 do_something();
618 } else { 619 } else {
620 barrier();
619 ACCESS_ONCE(b) = p; 621 ACCESS_ONCE(b) = p;
620 do_something_else(); 622 do_something_else();
621 } 623 }
622 624
623You could also use barrier() to prevent the compiler from moving 625The initial ACCESS_ONCE() is required to prevent the compiler from
624the stores to variable 'b', but barrier() would not prevent the 626proving the value of 'a', and the pair of barrier() invocations are
625compiler from proving to itself that a==1 always, so ACCESS_ONCE() 627required to prevent the compiler from pulling the two identical stores
626is also needed. 628to 'b' out from the legs of the "if" statement.
627 629
628It is important to note that control dependencies absolutely require a 630It is important to note that control dependencies absolutely require a
629a conditional. For example, the following "optimized" version of 631a conditional. For example, the following "optimized" version of
630the above example breaks ordering: 632the above example breaks ordering, which is why the barrier() invocations
633are absolutely required if you have identical stores in both legs of
634the "if" statement:
631 635
632 q = ACCESS_ONCE(a); 636 q = ACCESS_ONCE(a);
633 ACCESS_ONCE(b) = p; /* BUG: No ordering vs. load from a!!! */ 637 ACCESS_ONCE(b) = p; /* BUG: No ordering vs. load from a!!! */
@@ -643,9 +647,11 @@ It is of course legal for the prior load to be part of the conditional,
643for example, as follows: 647for example, as follows:
644 648
645 if (ACCESS_ONCE(a) > 0) { 649 if (ACCESS_ONCE(a) > 0) {
650 barrier();
646 ACCESS_ONCE(b) = q / 2; 651 ACCESS_ONCE(b) = q / 2;
647 do_something(); 652 do_something();
648 } else { 653 } else {
654 barrier();
649 ACCESS_ONCE(b) = q / 3; 655 ACCESS_ONCE(b) = q / 3;
650 do_something_else(); 656 do_something_else();
651 } 657 }
@@ -659,9 +665,11 @@ the needed conditional. For example:
659 665
660 q = ACCESS_ONCE(a); 666 q = ACCESS_ONCE(a);
661 if (q % MAX) { 667 if (q % MAX) {
668 barrier();
662 ACCESS_ONCE(b) = p; 669 ACCESS_ONCE(b) = p;
663 do_something(); 670 do_something();
664 } else { 671 } else {
672 barrier();
665 ACCESS_ONCE(b) = p; 673 ACCESS_ONCE(b) = p;
666 do_something_else(); 674 do_something_else();
667 } 675 }
@@ -723,8 +731,13 @@ In summary:
723 use smb_rmb(), smp_wmb(), or, in the case of prior stores and 731 use smb_rmb(), smp_wmb(), or, in the case of prior stores and
724 later loads, smp_mb(). 732 later loads, smp_mb().
725 733
734 (*) If both legs of the "if" statement begin with identical stores
735 to the same variable, a barrier() statement is required at the
736 beginning of each leg of the "if" statement.
737
726 (*) Control dependencies require at least one run-time conditional 738 (*) Control dependencies require at least one run-time conditional
727 between the prior load and the subsequent store. If the compiler 739 between the prior load and the subsequent store, and this
740 conditional must involve the prior load. If the compiler
728 is able to optimize the conditional away, it will have also 741 is able to optimize the conditional away, it will have also
729 optimized away the ordering. Careful use of ACCESS_ONCE() can 742 optimized away the ordering. Careful use of ACCESS_ONCE() can
730 help to preserve the needed conditional. 743 help to preserve the needed conditional.
@@ -1249,6 +1262,23 @@ The ACCESS_ONCE() function can prevent any number of optimizations that,
1249while perfectly safe in single-threaded code, can be fatal in concurrent 1262while perfectly safe in single-threaded code, can be fatal in concurrent
1250code. Here are some examples of these sorts of optimizations: 1263code. Here are some examples of these sorts of optimizations:
1251 1264
1265 (*) The compiler is within its rights to reorder loads and stores
1266 to the same variable, and in some cases, the CPU is within its
1267 rights to reorder loads to the same variable. This means that
1268 the following code:
1269
1270 a[0] = x;
1271 a[1] = x;
1272
1273 Might result in an older value of x stored in a[1] than in a[0].
1274 Prevent both the compiler and the CPU from doing this as follows:
1275
1276 a[0] = ACCESS_ONCE(x);
1277 a[1] = ACCESS_ONCE(x);
1278
1279 In short, ACCESS_ONCE() provides cache coherence for accesses from
1280 multiple CPUs to a single variable.
1281
1252 (*) The compiler is within its rights to merge successive loads from 1282 (*) The compiler is within its rights to merge successive loads from
1253 the same variable. Such merging can cause the compiler to "optimize" 1283 the same variable. Such merging can cause the compiler to "optimize"
1254 the following code: 1284 the following code:
@@ -1644,12 +1674,12 @@ for each construct. These operations all imply certain barriers:
1644 Memory operations issued after the ACQUIRE will be completed after the 1674 Memory operations issued after the ACQUIRE will be completed after the
1645 ACQUIRE operation has completed. 1675 ACQUIRE operation has completed.
1646 1676
1647 Memory operations issued before the ACQUIRE may be completed after the 1677 Memory operations issued before the ACQUIRE may be completed after
1648 ACQUIRE operation has completed. An smp_mb__before_spinlock(), combined 1678 the ACQUIRE operation has completed. An smp_mb__before_spinlock(),
1649 with a following ACQUIRE, orders prior loads against subsequent stores and 1679 combined with a following ACQUIRE, orders prior loads against
1650 stores and prior stores against subsequent stores. Note that this is 1680 subsequent loads and stores and also orders prior stores against
1651 weaker than smp_mb()! The smp_mb__before_spinlock() primitive is free on 1681 subsequent stores. Note that this is weaker than smp_mb()! The
1652 many architectures. 1682 smp_mb__before_spinlock() primitive is free on many architectures.
1653 1683
1654 (2) RELEASE operation implication: 1684 (2) RELEASE operation implication:
1655 1685
@@ -1694,24 +1724,21 @@ may occur as:
1694 1724
1695 ACQUIRE M, STORE *B, STORE *A, RELEASE M 1725 ACQUIRE M, STORE *B, STORE *A, RELEASE M
1696 1726
1697This same reordering can of course occur if the lock's ACQUIRE and RELEASE are 1727When the ACQUIRE and RELEASE are a lock acquisition and release,
1698to the same lock variable, but only from the perspective of another CPU not 1728respectively, this same reordering can occur if the lock's ACQUIRE and
1699holding that lock. 1729RELEASE are to the same lock variable, but only from the perspective of
1700 1730another CPU not holding that lock. In short, a ACQUIRE followed by an
1701In short, a RELEASE followed by an ACQUIRE may -not- be assumed to be a full 1731RELEASE may -not- be assumed to be a full memory barrier.
1702memory barrier because it is possible for a preceding RELEASE to pass a 1732
1703later ACQUIRE from the viewpoint of the CPU, but not from the viewpoint 1733Similarly, the reverse case of a RELEASE followed by an ACQUIRE does not
1704of the compiler. Note that deadlocks cannot be introduced by this 1734imply a full memory barrier. If it is necessary for a RELEASE-ACQUIRE
1705interchange because if such a deadlock threatened, the RELEASE would 1735pair to produce a full barrier, the ACQUIRE can be followed by an
1706simply complete. 1736smp_mb__after_unlock_lock() invocation. This will produce a full barrier
1707 1737if either (a) the RELEASE and the ACQUIRE are executed by the same
1708If it is necessary for a RELEASE-ACQUIRE pair to produce a full barrier, the 1738CPU or task, or (b) the RELEASE and ACQUIRE act on the same variable.
1709ACQUIRE can be followed by an smp_mb__after_unlock_lock() invocation. This 1739The smp_mb__after_unlock_lock() primitive is free on many architectures.
1710will produce a full barrier if either (a) the RELEASE and the ACQUIRE are 1740Without smp_mb__after_unlock_lock(), the CPU's execution of the critical
1711executed by the same CPU or task, or (b) the RELEASE and ACQUIRE act on the 1741sections corresponding to the RELEASE and the ACQUIRE can cross, so that:
1712same variable. The smp_mb__after_unlock_lock() primitive is free on many
1713architectures. Without smp_mb__after_unlock_lock(), the critical sections
1714corresponding to the RELEASE and the ACQUIRE can cross:
1715 1742
1716 *A = a; 1743 *A = a;
1717 RELEASE M 1744 RELEASE M
@@ -1722,7 +1749,36 @@ could occur as:
1722 1749
1723 ACQUIRE N, STORE *B, STORE *A, RELEASE M 1750 ACQUIRE N, STORE *B, STORE *A, RELEASE M
1724 1751
1725With smp_mb__after_unlock_lock(), they cannot, so that: 1752It might appear that this reordering could introduce a deadlock.
1753However, this cannot happen because if such a deadlock threatened,
1754the RELEASE would simply complete, thereby avoiding the deadlock.
1755
1756 Why does this work?
1757
1758 One key point is that we are only talking about the CPU doing
1759 the reordering, not the compiler. If the compiler (or, for
1760 that matter, the developer) switched the operations, deadlock
1761 -could- occur.
1762
1763 But suppose the CPU reordered the operations. In this case,
1764 the unlock precedes the lock in the assembly code. The CPU
1765 simply elected to try executing the later lock operation first.
1766 If there is a deadlock, this lock operation will simply spin (or
1767 try to sleep, but more on that later). The CPU will eventually
1768 execute the unlock operation (which preceded the lock operation
1769 in the assembly code), which will unravel the potential deadlock,
1770 allowing the lock operation to succeed.
1771
1772 But what if the lock is a sleeplock? In that case, the code will
1773 try to enter the scheduler, where it will eventually encounter
1774 a memory barrier, which will force the earlier unlock operation
1775 to complete, again unraveling the deadlock. There might be
1776 a sleep-unlock race, but the locking primitive needs to resolve
1777 such races properly in any case.
1778
1779With smp_mb__after_unlock_lock(), the two critical sections cannot overlap.
1780For example, with the following code, the store to *A will always be
1781seen by other CPUs before the store to *B:
1726 1782
1727 *A = a; 1783 *A = a;
1728 RELEASE M 1784 RELEASE M
@@ -1730,13 +1786,18 @@ With smp_mb__after_unlock_lock(), they cannot, so that:
1730 smp_mb__after_unlock_lock(); 1786 smp_mb__after_unlock_lock();
1731 *B = b; 1787 *B = b;
1732 1788
1733will always occur as either of the following: 1789The operations will always occur in one of the following orders:
1734 1790
1735 STORE *A, RELEASE, ACQUIRE, STORE *B 1791 STORE *A, RELEASE, ACQUIRE, smp_mb__after_unlock_lock(), STORE *B
1736 STORE *A, ACQUIRE, RELEASE, STORE *B 1792 STORE *A, ACQUIRE, RELEASE, smp_mb__after_unlock_lock(), STORE *B
1793 ACQUIRE, STORE *A, RELEASE, smp_mb__after_unlock_lock(), STORE *B
1737 1794
1738If the RELEASE and ACQUIRE were instead both operating on the same lock 1795If the RELEASE and ACQUIRE were instead both operating on the same lock
1739variable, only the first of these two alternatives can occur. 1796variable, only the first of these alternatives can occur. In addition,
1797the more strongly ordered systems may rule out some of the above orders.
1798But in any case, as noted earlier, the smp_mb__after_unlock_lock()
1799ensures that the store to *A will always be seen as happening before
1800the store to *B.
1740 1801
1741Locks and semaphores may not provide any guarantee of ordering on UP compiled 1802Locks and semaphores may not provide any guarantee of ordering on UP compiled
1742systems, and so cannot be counted on in such a situation to actually achieve 1803systems, and so cannot be counted on in such a situation to actually achieve
@@ -2757,7 +2818,7 @@ in that order, but, without intervention, the sequence may have almost any
2757combination of elements combined or discarded, provided the program's view of 2818combination of elements combined or discarded, provided the program's view of
2758the world remains consistent. Note that ACCESS_ONCE() is -not- optional 2819the world remains consistent. Note that ACCESS_ONCE() is -not- optional
2759in the above example, as there are architectures where a given CPU might 2820in the above example, as there are architectures where a given CPU might
2760interchange successive loads to the same location. On such architectures, 2821reorder successive loads to the same location. On such architectures,
2761ACCESS_ONCE() does whatever is necessary to prevent this, for example, on 2822ACCESS_ONCE() does whatever is necessary to prevent this, for example, on
2762Itanium the volatile casts used by ACCESS_ONCE() cause GCC to emit the 2823Itanium the volatile casts used by ACCESS_ONCE() cause GCC to emit the
2763special ld.acq and st.rel instructions that prevent such reordering. 2824special ld.acq and st.rel instructions that prevent such reordering.
diff --git a/fs/file.c b/fs/file.c
index eb56a13dab3e..b61293badfb1 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -497,7 +497,7 @@ repeat:
497 error = fd; 497 error = fd;
498#if 1 498#if 1
499 /* Sanity check */ 499 /* Sanity check */
500 if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { 500 if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
501 printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); 501 printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
502 rcu_assign_pointer(fdt->fd[fd], NULL); 502 rcu_assign_pointer(fdt->fd[fd], NULL);
503 } 503 }
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index dbaf99084112..8183b46fbaa2 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list,
247 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). 247 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
248 */ 248 */
249#define list_entry_rcu(ptr, type, member) \ 249#define list_entry_rcu(ptr, type, member) \
250 ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \ 250({ \
251 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ 251 typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
252 }) 252 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
253})
253 254
254/** 255/**
255 * Where are list_empty_rcu() and list_first_entry_rcu()? 256 * Where are list_empty_rcu() and list_first_entry_rcu()?
@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list,
285 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). 286 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
286 */ 287 */
287#define list_first_or_null_rcu(ptr, type, member) \ 288#define list_first_or_null_rcu(ptr, type, member) \
288 ({struct list_head *__ptr = (ptr); \ 289({ \
289 struct list_head *__next = ACCESS_ONCE(__ptr->next); \ 290 struct list_head *__ptr = (ptr); \
290 likely(__ptr != __next) ? \ 291 struct list_head *__next = ACCESS_ONCE(__ptr->next); \
291 list_entry_rcu(__next, type, member) : NULL; \ 292 likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
292 }) 293})
293 294
294/** 295/**
295 * list_for_each_entry_rcu - iterate over rcu list of given type 296 * list_for_each_entry_rcu - iterate over rcu list of given type
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index adff3c99dcaa..00a7fd61b3c6 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2001 18 * Copyright IBM Corporation, 2001
19 * 19 *
@@ -44,7 +44,9 @@
44#include <linux/debugobjects.h> 44#include <linux/debugobjects.h>
45#include <linux/bug.h> 45#include <linux/bug.h>
46#include <linux/compiler.h> 46#include <linux/compiler.h>
47#include <asm/barrier.h>
47 48
49extern int rcu_expedited; /* for sysctl */
48#ifdef CONFIG_RCU_TORTURE_TEST 50#ifdef CONFIG_RCU_TORTURE_TEST
49extern int rcutorture_runnable; /* for sysctl */ 51extern int rcutorture_runnable; /* for sysctl */
50#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ 52#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void)
479 do { \ 481 do { \
480 rcu_preempt_sleep_check(); \ 482 rcu_preempt_sleep_check(); \
481 rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ 483 rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \
482 "Illegal context switch in RCU-bh" \ 484 "Illegal context switch in RCU-bh read-side critical section"); \
483 " read-side critical section"); \
484 rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \ 485 rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \
485 "Illegal context switch in RCU-sched"\ 486 "Illegal context switch in RCU-sched read-side critical section"); \
486 " read-side critical section"); \
487 } while (0) 487 } while (0)
488 488
489#else /* #ifdef CONFIG_PROVE_RCU */ 489#else /* #ifdef CONFIG_PROVE_RCU */
@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void)
510#endif /* #else #ifdef __CHECKER__ */ 510#endif /* #else #ifdef __CHECKER__ */
511 511
512#define __rcu_access_pointer(p, space) \ 512#define __rcu_access_pointer(p, space) \
513 ({ \ 513({ \
514 typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ 514 typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
515 rcu_dereference_sparse(p, space); \ 515 rcu_dereference_sparse(p, space); \
516 ((typeof(*p) __force __kernel *)(_________p1)); \ 516 ((typeof(*p) __force __kernel *)(_________p1)); \
517 }) 517})
518#define __rcu_dereference_check(p, c, space) \ 518#define __rcu_dereference_check(p, c, space) \
519 ({ \ 519({ \
520 typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ 520 typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
521 rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \ 521 rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \
522 " usage"); \ 522 rcu_dereference_sparse(p, space); \
523 rcu_dereference_sparse(p, space); \ 523 smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
524 smp_read_barrier_depends(); \ 524 ((typeof(*p) __force __kernel *)(_________p1)); \
525 ((typeof(*p) __force __kernel *)(_________p1)); \ 525})
526 })
527#define __rcu_dereference_protected(p, c, space) \ 526#define __rcu_dereference_protected(p, c, space) \
528 ({ \ 527({ \
529 rcu_lockdep_assert(c, "suspicious rcu_dereference_protected()" \ 528 rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \
530 " usage"); \ 529 rcu_dereference_sparse(p, space); \
531 rcu_dereference_sparse(p, space); \ 530 ((typeof(*p) __force __kernel *)(p)); \
532 ((typeof(*p) __force __kernel *)(p)); \ 531})
533 })
534 532
535#define __rcu_access_index(p, space) \ 533#define __rcu_access_index(p, space) \
536 ({ \ 534({ \
537 typeof(p) _________p1 = ACCESS_ONCE(p); \ 535 typeof(p) _________p1 = ACCESS_ONCE(p); \
538 rcu_dereference_sparse(p, space); \ 536 rcu_dereference_sparse(p, space); \
539 (_________p1); \ 537 (_________p1); \
540 }) 538})
541#define __rcu_dereference_index_check(p, c) \ 539#define __rcu_dereference_index_check(p, c) \
542 ({ \ 540({ \
543 typeof(p) _________p1 = ACCESS_ONCE(p); \ 541 typeof(p) _________p1 = ACCESS_ONCE(p); \
544 rcu_lockdep_assert(c, \ 542 rcu_lockdep_assert(c, \
545 "suspicious rcu_dereference_index_check()" \ 543 "suspicious rcu_dereference_index_check() usage"); \
546 " usage"); \ 544 smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
547 smp_read_barrier_depends(); \ 545 (_________p1); \
548 (_________p1); \ 546})
549 })
550 547
551/** 548/**
552 * RCU_INITIALIZER() - statically initialize an RCU-protected global variable 549 * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void)
585 * please be careful when making changes to rcu_assign_pointer() and the 582 * please be careful when making changes to rcu_assign_pointer() and the
586 * other macros that it invokes. 583 * other macros that it invokes.
587 */ 584 */
588#define rcu_assign_pointer(p, v) \ 585#define rcu_assign_pointer(p, v) smp_store_release(&p, RCU_INITIALIZER(v))
589 do { \
590 smp_wmb(); \
591 ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
592 } while (0)
593
594 586
595/** 587/**
596 * rcu_access_pointer() - fetch RCU pointer with no dereferencing 588 * rcu_access_pointer() - fetch RCU pointer with no dereferencing
@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
1015#define kfree_rcu(ptr, rcu_head) \ 1007#define kfree_rcu(ptr, rcu_head) \
1016 __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) 1008 __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
1017 1009
1018#ifdef CONFIG_RCU_NOCB_CPU 1010#if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL)
1011static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
1012{
1013 *delta_jiffies = ULONG_MAX;
1014 return 0;
1015}
1016#endif /* #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) */
1017
1018#if defined(CONFIG_RCU_NOCB_CPU_ALL)
1019static inline bool rcu_is_nocb_cpu(int cpu) { return true; }
1020#elif defined(CONFIG_RCU_NOCB_CPU)
1019bool rcu_is_nocb_cpu(int cpu); 1021bool rcu_is_nocb_cpu(int cpu);
1020#else 1022#else
1021static inline bool rcu_is_nocb_cpu(int cpu) { return false; } 1023static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
1022#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ 1024#endif
1023 1025
1024 1026
1025/* Only for use by adaptive-ticks code. */ 1027/* Only for use by adaptive-ticks code. */
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 6f01771b571c..425c659d54e5 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2008 18 * Copyright IBM Corporation, 2008
19 * 19 *
@@ -27,6 +27,16 @@
27 27
28#include <linux/cache.h> 28#include <linux/cache.h>
29 29
30static inline unsigned long get_state_synchronize_rcu(void)
31{
32 return 0;
33}
34
35static inline void cond_synchronize_rcu(unsigned long oldstate)
36{
37 might_sleep();
38}
39
30static inline void rcu_barrier_bh(void) 40static inline void rcu_barrier_bh(void)
31{ 41{
32 wait_rcu_gp(call_rcu_bh); 42 wait_rcu_gp(call_rcu_bh);
@@ -68,12 +78,6 @@ static inline void kfree_call_rcu(struct rcu_head *head,
68 call_rcu(head, func); 78 call_rcu(head, func);
69} 79}
70 80
71static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
72{
73 *delta_jiffies = ULONG_MAX;
74 return 0;
75}
76
77static inline void rcu_note_context_switch(int cpu) 81static inline void rcu_note_context_switch(int cpu)
78{ 82{
79 rcu_sched_qs(cpu); 83 rcu_sched_qs(cpu);
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 72137ee8c603..a59ca05fd4e3 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2008 18 * Copyright IBM Corporation, 2008
19 * 19 *
@@ -31,7 +31,9 @@
31#define __LINUX_RCUTREE_H 31#define __LINUX_RCUTREE_H
32 32
33void rcu_note_context_switch(int cpu); 33void rcu_note_context_switch(int cpu);
34#ifndef CONFIG_RCU_NOCB_CPU_ALL
34int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); 35int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
36#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
35void rcu_cpu_stall_reset(void); 37void rcu_cpu_stall_reset(void);
36 38
37/* 39/*
@@ -74,6 +76,8 @@ static inline void synchronize_rcu_bh_expedited(void)
74void rcu_barrier(void); 76void rcu_barrier(void);
75void rcu_barrier_bh(void); 77void rcu_barrier_bh(void);
76void rcu_barrier_sched(void); 78void rcu_barrier_sched(void);
79unsigned long get_state_synchronize_rcu(void);
80void cond_synchronize_rcu(unsigned long oldstate);
77 81
78extern unsigned long rcutorture_testseq; 82extern unsigned long rcutorture_testseq;
79extern unsigned long rcutorture_vernum; 83extern unsigned long rcutorture_vernum;
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 9b058eecd403..a2783cb5d275 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright (C) IBM Corporation, 2006 18 * Copyright (C) IBM Corporation, 2006
19 * Copyright (C) Fujitsu, 2012 19 * Copyright (C) Fujitsu, 2012
diff --git a/include/linux/torture.h b/include/linux/torture.h
new file mode 100644
index 000000000000..b2e2b468e511
--- /dev/null
+++ b/include/linux/torture.h
@@ -0,0 +1,100 @@
1/*
2 * Common functions for in-kernel torture tests.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * Copyright IBM Corporation, 2014
19 *
20 * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
21 */
22
23#ifndef __LINUX_TORTURE_H
24#define __LINUX_TORTURE_H
25
26#include <linux/types.h>
27#include <linux/cache.h>
28#include <linux/spinlock.h>
29#include <linux/threads.h>
30#include <linux/cpumask.h>
31#include <linux/seqlock.h>
32#include <linux/lockdep.h>
33#include <linux/completion.h>
34#include <linux/debugobjects.h>
35#include <linux/bug.h>
36#include <linux/compiler.h>
37
38/* Definitions for a non-string torture-test module parameter. */
39#define torture_param(type, name, init, msg) \
40 static type name = init; \
41 module_param(name, type, 0444); \
42 MODULE_PARM_DESC(name, msg);
43
44#define TORTURE_FLAG "-torture:"
45#define TOROUT_STRING(s) \
46 pr_alert("%s" TORTURE_FLAG s "\n", torture_type)
47#define VERBOSE_TOROUT_STRING(s) \
48 do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0)
49#define VERBOSE_TOROUT_ERRSTRING(s) \
50 do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
51
52/* Definitions for a non-string torture-test module parameter. */
53#define torture_parm(type, name, init, msg) \
54 static type name = init; \
55 module_param(name, type, 0444); \
56 MODULE_PARM_DESC(name, msg);
57
58/* Definitions for online/offline exerciser. */
59int torture_onoff_init(long ooholdoff, long oointerval);
60char *torture_onoff_stats(char *page);
61bool torture_onoff_failures(void);
62
63/* Low-rider random number generator. */
64struct torture_random_state {
65 unsigned long trs_state;
66 long trs_count;
67};
68#define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 }
69unsigned long torture_random(struct torture_random_state *trsp);
70
71/* Task shuffler, which causes CPUs to occasionally go idle. */
72void torture_shuffle_task_register(struct task_struct *tp);
73int torture_shuffle_init(long shuffint);
74
75/* Test auto-shutdown handling. */
76void torture_shutdown_absorb(const char *title);
77int torture_shutdown_init(int ssecs, void (*cleanup)(void));
78
79/* Task stuttering, which forces load/no-load transitions. */
80void stutter_wait(const char *title);
81int torture_stutter_init(int s);
82
83/* Initialization and cleanup. */
84void torture_init_begin(char *ttype, bool v, int *runnable);
85void torture_init_end(void);
86bool torture_cleanup(void);
87bool torture_must_stop(void);
88bool torture_must_stop_irq(void);
89void torture_kthread_stopping(char *title);
90int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
91 char *f, struct task_struct **tp);
92void _torture_stop_kthread(char *m, struct task_struct **tp);
93
94#define torture_create_kthread(n, arg, tp) \
95 _torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
96 "Failed to create " #n, &(tp))
97#define torture_stop_kthread(n, tp) \
98 _torture_stop_kthread("Stopping " #n " task", &(tp))
99
100#endif /* __LINUX_TORTURE_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index bc010ee272b6..5c0e7666811d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_PADATA) += padata.o
93obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 93obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
94obj-$(CONFIG_JUMP_LABEL) += jump_label.o 94obj-$(CONFIG_JUMP_LABEL) += jump_label.o
95obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o 95obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
96obj-$(CONFIG_TORTURE_TEST) += torture.o
96 97
97$(obj)/configs.o: $(obj)/config_data.h 98$(obj)/configs.o: $(obj)/config_data.h
98 99
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index d945a949760f..e660964086e2 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -19,6 +19,8 @@
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/capability.h> 20#include <linux/capability.h>
21 21
22#include <linux/rcupdate.h> /* rcu_expedited */
23
22#define KERNEL_ATTR_RO(_name) \ 24#define KERNEL_ATTR_RO(_name) \
23static struct kobj_attribute _name##_attr = __ATTR_RO(_name) 25static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
24 26
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 2a9ee96ecf00..306a76b51e0f 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
23obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o 23obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
24obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o 24obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
25obj-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o 25obj-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o
26obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
new file mode 100644
index 000000000000..f26b1a18e34e
--- /dev/null
+++ b/kernel/locking/locktorture.c
@@ -0,0 +1,452 @@
1/*
2 * Module-based torture test facility for locking
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * Copyright (C) IBM Corporation, 2014
19 *
20 * Author: Paul E. McKenney <paulmck@us.ibm.com>
21 * Based on kernel/rcu/torture.c.
22 */
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/kthread.h>
28#include <linux/err.h>
29#include <linux/spinlock.h>
30#include <linux/smp.h>
31#include <linux/interrupt.h>
32#include <linux/sched.h>
33#include <linux/atomic.h>
34#include <linux/bitops.h>
35#include <linux/completion.h>
36#include <linux/moduleparam.h>
37#include <linux/percpu.h>
38#include <linux/notifier.h>
39#include <linux/reboot.h>
40#include <linux/freezer.h>
41#include <linux/cpu.h>
42#include <linux/delay.h>
43#include <linux/stat.h>
44#include <linux/slab.h>
45#include <linux/trace_clock.h>
46#include <asm/byteorder.h>
47#include <linux/torture.h>
48
49MODULE_LICENSE("GPL");
50MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>");
51
52torture_param(int, nwriters_stress, -1,
53 "Number of write-locking stress-test threads");
54torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
55torture_param(int, onoff_interval, 0,
56 "Time between CPU hotplugs (s), 0=disable");
57torture_param(int, shuffle_interval, 3,
58 "Number of jiffies between shuffles, 0=disable");
59torture_param(int, shutdown_secs, 0, "Shutdown time (j), <= zero to disable.");
60torture_param(int, stat_interval, 60,
61 "Number of seconds between stats printk()s");
62torture_param(int, stutter, 5, "Number of jiffies to run/halt test, 0=disable");
63torture_param(bool, verbose, true,
64 "Enable verbose debugging printk()s");
65
66static char *torture_type = "spin_lock";
67module_param(torture_type, charp, 0444);
68MODULE_PARM_DESC(torture_type,
69 "Type of lock to torture (spin_lock, spin_lock_irq, ...)");
70
71static atomic_t n_lock_torture_errors;
72
73static struct task_struct *stats_task;
74static struct task_struct **writer_tasks;
75
76static int nrealwriters_stress;
77static bool lock_is_write_held;
78
79struct lock_writer_stress_stats {
80 long n_write_lock_fail;
81 long n_write_lock_acquired;
82};
83static struct lock_writer_stress_stats *lwsa;
84
85#if defined(MODULE) || defined(CONFIG_LOCK_TORTURE_TEST_RUNNABLE)
86#define LOCKTORTURE_RUNNABLE_INIT 1
87#else
88#define LOCKTORTURE_RUNNABLE_INIT 0
89#endif
90int locktorture_runnable = LOCKTORTURE_RUNNABLE_INIT;
91module_param(locktorture_runnable, int, 0444);
92MODULE_PARM_DESC(locktorture_runnable, "Start locktorture at boot");
93
94/* Forward reference. */
95static void lock_torture_cleanup(void);
96
97/*
98 * Operations vector for selecting different types of tests.
99 */
100struct lock_torture_ops {
101 void (*init)(void);
102 int (*writelock)(void);
103 void (*write_delay)(struct torture_random_state *trsp);
104 void (*writeunlock)(void);
105 unsigned long flags;
106 const char *name;
107};
108
109static struct lock_torture_ops *cur_ops;
110
111/*
112 * Definitions for lock torture testing.
113 */
114
115static int torture_lock_busted_write_lock(void)
116{
117 return 0; /* BUGGY, do not use in real life!!! */
118}
119
120static void torture_lock_busted_write_delay(struct torture_random_state *trsp)
121{
122 const unsigned long longdelay_us = 100;
123
124 /* We want a long delay occasionally to force massive contention. */
125 if (!(torture_random(trsp) %
126 (nrealwriters_stress * 2000 * longdelay_us)))
127 mdelay(longdelay_us);
128#ifdef CONFIG_PREEMPT
129 if (!(torture_random(trsp) % (nrealwriters_stress * 20000)))
130 preempt_schedule(); /* Allow test to be preempted. */
131#endif
132}
133
134static void torture_lock_busted_write_unlock(void)
135{
136 /* BUGGY, do not use in real life!!! */
137}
138
139static struct lock_torture_ops lock_busted_ops = {
140 .writelock = torture_lock_busted_write_lock,
141 .write_delay = torture_lock_busted_write_delay,
142 .writeunlock = torture_lock_busted_write_unlock,
143 .name = "lock_busted"
144};
145
146static DEFINE_SPINLOCK(torture_spinlock);
147
148static int torture_spin_lock_write_lock(void) __acquires(torture_spinlock)
149{
150 spin_lock(&torture_spinlock);
151 return 0;
152}
153
154static void torture_spin_lock_write_delay(struct torture_random_state *trsp)
155{
156 const unsigned long shortdelay_us = 2;
157 const unsigned long longdelay_us = 100;
158
159 /* We want a short delay mostly to emulate likely code, and
160 * we want a long delay occasionally to force massive contention.
161 */
162 if (!(torture_random(trsp) %
163 (nrealwriters_stress * 2000 * longdelay_us)))
164 mdelay(longdelay_us);
165 if (!(torture_random(trsp) %
166 (nrealwriters_stress * 2 * shortdelay_us)))
167 udelay(shortdelay_us);
168#ifdef CONFIG_PREEMPT
169 if (!(torture_random(trsp) % (nrealwriters_stress * 20000)))
170 preempt_schedule(); /* Allow test to be preempted. */
171#endif
172}
173
174static void torture_spin_lock_write_unlock(void) __releases(torture_spinlock)
175{
176 spin_unlock(&torture_spinlock);
177}
178
179static struct lock_torture_ops spin_lock_ops = {
180 .writelock = torture_spin_lock_write_lock,
181 .write_delay = torture_spin_lock_write_delay,
182 .writeunlock = torture_spin_lock_write_unlock,
183 .name = "spin_lock"
184};
185
186static int torture_spin_lock_write_lock_irq(void)
187__acquires(torture_spinlock_irq)
188{
189 unsigned long flags;
190
191 spin_lock_irqsave(&torture_spinlock, flags);
192 cur_ops->flags = flags;
193 return 0;
194}
195
196static void torture_lock_spin_write_unlock_irq(void)
197__releases(torture_spinlock)
198{
199 spin_unlock_irqrestore(&torture_spinlock, cur_ops->flags);
200}
201
202static struct lock_torture_ops spin_lock_irq_ops = {
203 .writelock = torture_spin_lock_write_lock_irq,
204 .write_delay = torture_spin_lock_write_delay,
205 .writeunlock = torture_lock_spin_write_unlock_irq,
206 .name = "spin_lock_irq"
207};
208
209/*
210 * Lock torture writer kthread. Repeatedly acquires and releases
211 * the lock, checking for duplicate acquisitions.
212 */
213static int lock_torture_writer(void *arg)
214{
215 struct lock_writer_stress_stats *lwsp = arg;
216 static DEFINE_TORTURE_RANDOM(rand);
217
218 VERBOSE_TOROUT_STRING("lock_torture_writer task started");
219 set_user_nice(current, 19);
220
221 do {
222 schedule_timeout_uninterruptible(1);
223 cur_ops->writelock();
224 if (WARN_ON_ONCE(lock_is_write_held))
225 lwsp->n_write_lock_fail++;
226 lock_is_write_held = 1;
227 lwsp->n_write_lock_acquired++;
228 cur_ops->write_delay(&rand);
229 lock_is_write_held = 0;
230 cur_ops->writeunlock();
231 stutter_wait("lock_torture_writer");
232 } while (!torture_must_stop());
233 torture_kthread_stopping("lock_torture_writer");
234 return 0;
235}
236
237/*
238 * Create an lock-torture-statistics message in the specified buffer.
239 */
240static void lock_torture_printk(char *page)
241{
242 bool fail = 0;
243 int i;
244 long max = 0;
245 long min = lwsa[0].n_write_lock_acquired;
246 long long sum = 0;
247
248 for (i = 0; i < nrealwriters_stress; i++) {
249 if (lwsa[i].n_write_lock_fail)
250 fail = true;
251 sum += lwsa[i].n_write_lock_acquired;
252 if (max < lwsa[i].n_write_lock_fail)
253 max = lwsa[i].n_write_lock_fail;
254 if (min > lwsa[i].n_write_lock_fail)
255 min = lwsa[i].n_write_lock_fail;
256 }
257 page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
258 page += sprintf(page,
259 "Writes: Total: %lld Max/Min: %ld/%ld %s Fail: %d %s\n",
260 sum, max, min, max / 2 > min ? "???" : "",
261 fail, fail ? "!!!" : "");
262 if (fail)
263 atomic_inc(&n_lock_torture_errors);
264}
265
266/*
267 * Print torture statistics. Caller must ensure that there is only one
268 * call to this function at a given time!!! This is normally accomplished
269 * by relying on the module system to only have one copy of the module
270 * loaded, and then by giving the lock_torture_stats kthread full control
271 * (or the init/cleanup functions when lock_torture_stats thread is not
272 * running).
273 */
274static void lock_torture_stats_print(void)
275{
276 int size = nrealwriters_stress * 200 + 8192;
277 char *buf;
278
279 buf = kmalloc(size, GFP_KERNEL);
280 if (!buf) {
281 pr_err("lock_torture_stats_print: Out of memory, need: %d",
282 size);
283 return;
284 }
285 lock_torture_printk(buf);
286 pr_alert("%s", buf);
287 kfree(buf);
288}
289
290/*
291 * Periodically prints torture statistics, if periodic statistics printing
292 * was specified via the stat_interval module parameter.
293 *
294 * No need to worry about fullstop here, since this one doesn't reference
295 * volatile state or register callbacks.
296 */
297static int lock_torture_stats(void *arg)
298{
299 VERBOSE_TOROUT_STRING("lock_torture_stats task started");
300 do {
301 schedule_timeout_interruptible(stat_interval * HZ);
302 lock_torture_stats_print();
303 torture_shutdown_absorb("lock_torture_stats");
304 } while (!torture_must_stop());
305 torture_kthread_stopping("lock_torture_stats");
306 return 0;
307}
308
309static inline void
310lock_torture_print_module_parms(struct lock_torture_ops *cur_ops,
311 const char *tag)
312{
313 pr_alert("%s" TORTURE_FLAG
314 "--- %s: nwriters_stress=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n",
315 torture_type, tag, nrealwriters_stress, stat_interval, verbose,
316 shuffle_interval, stutter, shutdown_secs,
317 onoff_interval, onoff_holdoff);
318}
319
320static void lock_torture_cleanup(void)
321{
322 int i;
323
324 if (torture_cleanup())
325 return;
326
327 if (writer_tasks) {
328 for (i = 0; i < nrealwriters_stress; i++)
329 torture_stop_kthread(lock_torture_writer,
330 writer_tasks[i]);
331 kfree(writer_tasks);
332 writer_tasks = NULL;
333 }
334
335 torture_stop_kthread(lock_torture_stats, stats_task);
336 lock_torture_stats_print(); /* -After- the stats thread is stopped! */
337
338 if (atomic_read(&n_lock_torture_errors))
339 lock_torture_print_module_parms(cur_ops,
340 "End of test: FAILURE");
341 else if (torture_onoff_failures())
342 lock_torture_print_module_parms(cur_ops,
343 "End of test: LOCK_HOTPLUG");
344 else
345 lock_torture_print_module_parms(cur_ops,
346 "End of test: SUCCESS");
347}
348
349static int __init lock_torture_init(void)
350{
351 int i;
352 int firsterr = 0;
353 static struct lock_torture_ops *torture_ops[] = {
354 &lock_busted_ops, &spin_lock_ops, &spin_lock_irq_ops,
355 };
356
357 torture_init_begin(torture_type, verbose, &locktorture_runnable);
358
359 /* Process args and tell the world that the torturer is on the job. */
360 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
361 cur_ops = torture_ops[i];
362 if (strcmp(torture_type, cur_ops->name) == 0)
363 break;
364 }
365 if (i == ARRAY_SIZE(torture_ops)) {
366 pr_alert("lock-torture: invalid torture type: \"%s\"\n",
367 torture_type);
368 pr_alert("lock-torture types:");
369 for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
370 pr_alert(" %s", torture_ops[i]->name);
371 pr_alert("\n");
372 torture_init_end();
373 return -EINVAL;
374 }
375 if (cur_ops->init)
376 cur_ops->init(); /* no "goto unwind" prior to this point!!! */
377
378 if (nwriters_stress >= 0)
379 nrealwriters_stress = nwriters_stress;
380 else
381 nrealwriters_stress = 2 * num_online_cpus();
382 lock_torture_print_module_parms(cur_ops, "Start of test");
383
384 /* Initialize the statistics so that each run gets its own numbers. */
385
386 lock_is_write_held = 0;
387 lwsa = kmalloc(sizeof(*lwsa) * nrealwriters_stress, GFP_KERNEL);
388 if (lwsa == NULL) {
389 VERBOSE_TOROUT_STRING("lwsa: Out of memory");
390 firsterr = -ENOMEM;
391 goto unwind;
392 }
393 for (i = 0; i < nrealwriters_stress; i++) {
394 lwsa[i].n_write_lock_fail = 0;
395 lwsa[i].n_write_lock_acquired = 0;
396 }
397
398 /* Start up the kthreads. */
399
400 if (onoff_interval > 0) {
401 firsterr = torture_onoff_init(onoff_holdoff * HZ,
402 onoff_interval * HZ);
403 if (firsterr)
404 goto unwind;
405 }
406 if (shuffle_interval > 0) {
407 firsterr = torture_shuffle_init(shuffle_interval);
408 if (firsterr)
409 goto unwind;
410 }
411 if (shutdown_secs > 0) {
412 firsterr = torture_shutdown_init(shutdown_secs,
413 lock_torture_cleanup);
414 if (firsterr)
415 goto unwind;
416 }
417 if (stutter > 0) {
418 firsterr = torture_stutter_init(stutter);
419 if (firsterr)
420 goto unwind;
421 }
422
423 writer_tasks = kzalloc(nrealwriters_stress * sizeof(writer_tasks[0]),
424 GFP_KERNEL);
425 if (writer_tasks == NULL) {
426 VERBOSE_TOROUT_ERRSTRING("writer_tasks: Out of memory");
427 firsterr = -ENOMEM;
428 goto unwind;
429 }
430 for (i = 0; i < nrealwriters_stress; i++) {
431 firsterr = torture_create_kthread(lock_torture_writer, &lwsa[i],
432 writer_tasks[i]);
433 if (firsterr)
434 goto unwind;
435 }
436 if (stat_interval > 0) {
437 firsterr = torture_create_kthread(lock_torture_stats, NULL,
438 stats_task);
439 if (firsterr)
440 goto unwind;
441 }
442 torture_init_end();
443 return 0;
444
445unwind:
446 torture_init_end();
447 lock_torture_cleanup();
448 return firsterr;
449}
450
451module_init(lock_torture_init);
452module_exit(lock_torture_cleanup);
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 2d5cc4ccff7f..db4c8b08a50c 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -309,7 +309,7 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
309 * racy then it does not matter what the result of the test 309 * racy then it does not matter what the result of the test
310 * is, we re-check the list after having taken the lock anyway: 310 * is, we re-check the list after having taken the lock anyway:
311 */ 311 */
312 if (rcu_dereference_raw(nh->head)) { 312 if (rcu_access_pointer(nh->head)) {
313 down_read(&nh->rwsem); 313 down_read(&nh->rwsem);
314 ret = notifier_call_chain(&nh->head, val, v, nr_to_call, 314 ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
315 nr_calls); 315 nr_calls);
diff --git a/kernel/rcu/Makefile b/kernel/rcu/Makefile
index 01e9ec37a3e3..807ccfbf69b3 100644
--- a/kernel/rcu/Makefile
+++ b/kernel/rcu/Makefile
@@ -1,5 +1,5 @@
1obj-y += update.o srcu.o 1obj-y += update.o srcu.o
2obj-$(CONFIG_RCU_TORTURE_TEST) += torture.o 2obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
3obj-$(CONFIG_TREE_RCU) += tree.o 3obj-$(CONFIG_TREE_RCU) += tree.o
4obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o 4obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o
5obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o 5obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index 79c3877e9c5b..bfda2726ca45 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2011 18 * Copyright IBM Corporation, 2011
19 * 19 *
@@ -23,6 +23,7 @@
23#ifndef __LINUX_RCU_H 23#ifndef __LINUX_RCU_H
24#define __LINUX_RCU_H 24#define __LINUX_RCU_H
25 25
26#include <trace/events/rcu.h>
26#ifdef CONFIG_RCU_TRACE 27#ifdef CONFIG_RCU_TRACE
27#define RCU_TRACE(stmt) stmt 28#define RCU_TRACE(stmt) stmt
28#else /* #ifdef CONFIG_RCU_TRACE */ 29#else /* #ifdef CONFIG_RCU_TRACE */
@@ -116,8 +117,6 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
116 } 117 }
117} 118}
118 119
119extern int rcu_expedited;
120
121#ifdef CONFIG_RCU_STALL_COMMON 120#ifdef CONFIG_RCU_STALL_COMMON
122 121
123extern int rcu_cpu_stall_suppress; 122extern int rcu_cpu_stall_suppress;
diff --git a/kernel/rcu/torture.c b/kernel/rcu/rcutorture.c
index 732f8ae3086a..f59d48597dde 100644
--- a/kernel/rcu/torture.c
+++ b/kernel/rcu/rcutorture.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright (C) IBM Corporation, 2005, 2006 18 * Copyright (C) IBM Corporation, 2005, 2006
19 * 19 *
@@ -48,110 +48,58 @@
48#include <linux/slab.h> 48#include <linux/slab.h>
49#include <linux/trace_clock.h> 49#include <linux/trace_clock.h>
50#include <asm/byteorder.h> 50#include <asm/byteorder.h>
51#include <linux/torture.h>
51 52
52MODULE_LICENSE("GPL"); 53MODULE_LICENSE("GPL");
53MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>"); 54MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
54 55
55MODULE_ALIAS("rcutorture"); 56
56#ifdef MODULE_PARAM_PREFIX 57torture_param(int, fqs_duration, 0,
57#undef MODULE_PARAM_PREFIX 58 "Duration of fqs bursts (us), 0 to disable");
58#endif 59torture_param(int, fqs_holdoff, 0, "Holdoff time within fqs bursts (us)");
59#define MODULE_PARAM_PREFIX "rcutorture." 60torture_param(int, fqs_stutter, 3, "Wait time between fqs bursts (s)");
60 61torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
61static int fqs_duration; 62torture_param(bool, gp_normal, false,
62module_param(fqs_duration, int, 0444); 63 "Use normal (non-expedited) GP wait primitives");
63MODULE_PARM_DESC(fqs_duration, "Duration of fqs bursts (us), 0 to disable"); 64torture_param(int, irqreader, 1, "Allow RCU readers from irq handlers");
64static int fqs_holdoff; 65torture_param(int, n_barrier_cbs, 0,
65module_param(fqs_holdoff, int, 0444); 66 "# of callbacks/kthreads for barrier testing");
66MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)"); 67torture_param(int, nfakewriters, 4, "Number of RCU fake writer threads");
67static int fqs_stutter = 3; 68torture_param(int, nreaders, -1, "Number of RCU reader threads");
68module_param(fqs_stutter, int, 0444); 69torture_param(int, object_debug, 0,
69MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)"); 70 "Enable debug-object double call_rcu() testing");
70static bool gp_exp; 71torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
71module_param(gp_exp, bool, 0444); 72torture_param(int, onoff_interval, 0,
72MODULE_PARM_DESC(gp_exp, "Use expedited GP wait primitives"); 73 "Time between CPU hotplugs (s), 0=disable");
73static bool gp_normal; 74torture_param(int, shuffle_interval, 3, "Number of seconds between shuffles");
74module_param(gp_normal, bool, 0444); 75torture_param(int, shutdown_secs, 0, "Shutdown time (s), <= zero to disable.");
75MODULE_PARM_DESC(gp_normal, "Use normal (non-expedited) GP wait primitives"); 76torture_param(int, stall_cpu, 0, "Stall duration (s), zero to disable.");
76static int irqreader = 1; 77torture_param(int, stall_cpu_holdoff, 10,
77module_param(irqreader, int, 0444); 78 "Time to wait before starting stall (s).");
78MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers"); 79torture_param(int, stat_interval, 60,
79static int n_barrier_cbs; 80 "Number of seconds between stats printk()s");
80module_param(n_barrier_cbs, int, 0444); 81torture_param(int, stutter, 5, "Number of seconds to run/halt test");
81MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing"); 82torture_param(int, test_boost, 1, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
82static int nfakewriters = 4; 83torture_param(int, test_boost_duration, 4,
83module_param(nfakewriters, int, 0444); 84 "Duration of each boost test, seconds.");
84MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads"); 85torture_param(int, test_boost_interval, 7,
85static int nreaders = -1; 86 "Interval between boost tests, seconds.");
86module_param(nreaders, int, 0444); 87torture_param(bool, test_no_idle_hz, true,
87MODULE_PARM_DESC(nreaders, "Number of RCU reader threads"); 88 "Test support for tickless idle CPUs");
88static int object_debug; 89torture_param(bool, verbose, true,
89module_param(object_debug, int, 0444); 90 "Enable verbose debugging printk()s");
90MODULE_PARM_DESC(object_debug, "Enable debug-object double call_rcu() testing"); 91
91static int onoff_holdoff;
92module_param(onoff_holdoff, int, 0444);
93MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
94static int onoff_interval;
95module_param(onoff_interval, int, 0444);
96MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
97static int shuffle_interval = 3;
98module_param(shuffle_interval, int, 0444);
99MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
100static int shutdown_secs;
101module_param(shutdown_secs, int, 0444);
102MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), <= zero to disable.");
103static int stall_cpu;
104module_param(stall_cpu, int, 0444);
105MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
106static int stall_cpu_holdoff = 10;
107module_param(stall_cpu_holdoff, int, 0444);
108MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
109static int stat_interval = 60;
110module_param(stat_interval, int, 0644);
111MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
112static int stutter = 5;
113module_param(stutter, int, 0444);
114MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
115static int test_boost = 1;
116module_param(test_boost, int, 0444);
117MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
118static int test_boost_duration = 4;
119module_param(test_boost_duration, int, 0444);
120MODULE_PARM_DESC(test_boost_duration, "Duration of each boost test, seconds.");
121static int test_boost_interval = 7;
122module_param(test_boost_interval, int, 0444);
123MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
124static bool test_no_idle_hz = true;
125module_param(test_no_idle_hz, bool, 0444);
126MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
127static char *torture_type = "rcu"; 92static char *torture_type = "rcu";
128module_param(torture_type, charp, 0444); 93module_param(torture_type, charp, 0444);
129MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)"); 94MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)");
130static bool verbose;
131module_param(verbose, bool, 0444);
132MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
133
134#define TORTURE_FLAG "-torture:"
135#define PRINTK_STRING(s) \
136 do { pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
137#define VERBOSE_PRINTK_STRING(s) \
138 do { if (verbose) pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
139#define VERBOSE_PRINTK_ERRSTRING(s) \
140 do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
141 95
142static int nrealreaders; 96static int nrealreaders;
143static struct task_struct *writer_task; 97static struct task_struct *writer_task;
144static struct task_struct **fakewriter_tasks; 98static struct task_struct **fakewriter_tasks;
145static struct task_struct **reader_tasks; 99static struct task_struct **reader_tasks;
146static struct task_struct *stats_task; 100static struct task_struct *stats_task;
147static struct task_struct *shuffler_task;
148static struct task_struct *stutter_task;
149static struct task_struct *fqs_task; 101static struct task_struct *fqs_task;
150static struct task_struct *boost_tasks[NR_CPUS]; 102static struct task_struct *boost_tasks[NR_CPUS];
151static struct task_struct *shutdown_task;
152#ifdef CONFIG_HOTPLUG_CPU
153static struct task_struct *onoff_task;
154#endif /* #ifdef CONFIG_HOTPLUG_CPU */
155static struct task_struct *stall_task; 103static struct task_struct *stall_task;
156static struct task_struct **barrier_cbs_tasks; 104static struct task_struct **barrier_cbs_tasks;
157static struct task_struct *barrier_task; 105static struct task_struct *barrier_task;
@@ -170,10 +118,10 @@ static struct rcu_torture __rcu *rcu_torture_current;
170static unsigned long rcu_torture_current_version; 118static unsigned long rcu_torture_current_version;
171static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN]; 119static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
172static DEFINE_SPINLOCK(rcu_torture_lock); 120static DEFINE_SPINLOCK(rcu_torture_lock);
173static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = 121static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
174 { 0 }; 122 rcu_torture_count) = { 0 };
175static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = 123static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
176 { 0 }; 124 rcu_torture_batch) = { 0 };
177static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1]; 125static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
178static atomic_t n_rcu_torture_alloc; 126static atomic_t n_rcu_torture_alloc;
179static atomic_t n_rcu_torture_alloc_fail; 127static atomic_t n_rcu_torture_alloc_fail;
@@ -186,22 +134,9 @@ static long n_rcu_torture_boost_rterror;
186static long n_rcu_torture_boost_failure; 134static long n_rcu_torture_boost_failure;
187static long n_rcu_torture_boosts; 135static long n_rcu_torture_boosts;
188static long n_rcu_torture_timers; 136static long n_rcu_torture_timers;
189static long n_offline_attempts;
190static long n_offline_successes;
191static unsigned long sum_offline;
192static int min_offline = -1;
193static int max_offline;
194static long n_online_attempts;
195static long n_online_successes;
196static unsigned long sum_online;
197static int min_online = -1;
198static int max_online;
199static long n_barrier_attempts; 137static long n_barrier_attempts;
200static long n_barrier_successes; 138static long n_barrier_successes;
201static struct list_head rcu_torture_removed; 139static struct list_head rcu_torture_removed;
202static cpumask_var_t shuffle_tmp_mask;
203
204static int stutter_pause_test;
205 140
206#if defined(MODULE) || defined(CONFIG_RCU_TORTURE_TEST_RUNNABLE) 141#if defined(MODULE) || defined(CONFIG_RCU_TORTURE_TEST_RUNNABLE)
207#define RCUTORTURE_RUNNABLE_INIT 1 142#define RCUTORTURE_RUNNABLE_INIT 1
@@ -232,7 +167,6 @@ static u64 notrace rcu_trace_clock_local(void)
232} 167}
233#endif /* #else #ifdef CONFIG_RCU_TRACE */ 168#endif /* #else #ifdef CONFIG_RCU_TRACE */
234 169
235static unsigned long shutdown_time; /* jiffies to system shutdown. */
236static unsigned long boost_starttime; /* jiffies of next boost test start. */ 170static unsigned long boost_starttime; /* jiffies of next boost test start. */
237DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */ 171DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
238 /* and boost task create/destroy. */ 172 /* and boost task create/destroy. */
@@ -242,51 +176,6 @@ static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
242static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */ 176static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
243static DECLARE_WAIT_QUEUE_HEAD(barrier_wq); 177static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
244 178
245/* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */
246
247#define FULLSTOP_DONTSTOP 0 /* Normal operation. */
248#define FULLSTOP_SHUTDOWN 1 /* System shutdown with rcutorture running. */
249#define FULLSTOP_RMMOD 2 /* Normal rmmod of rcutorture. */
250static int fullstop = FULLSTOP_RMMOD;
251/*
252 * Protect fullstop transitions and spawning of kthreads.
253 */
254static DEFINE_MUTEX(fullstop_mutex);
255
256/* Forward reference. */
257static void rcu_torture_cleanup(void);
258
259/*
260 * Detect and respond to a system shutdown.
261 */
262static int
263rcutorture_shutdown_notify(struct notifier_block *unused1,
264 unsigned long unused2, void *unused3)
265{
266 mutex_lock(&fullstop_mutex);
267 if (fullstop == FULLSTOP_DONTSTOP)
268 fullstop = FULLSTOP_SHUTDOWN;
269 else
270 pr_warn(/* but going down anyway, so... */
271 "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
272 mutex_unlock(&fullstop_mutex);
273 return NOTIFY_DONE;
274}
275
276/*
277 * Absorb kthreads into a kernel function that won't return, so that
278 * they won't ever access module text or data again.
279 */
280static void rcutorture_shutdown_absorb(const char *title)
281{
282 if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
283 pr_notice(
284 "rcutorture thread %s parking due to system shutdown\n",
285 title);
286 schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
287 }
288}
289
290/* 179/*
291 * Allocate an element from the rcu_tortures pool. 180 * Allocate an element from the rcu_tortures pool.
292 */ 181 */
@@ -320,44 +209,6 @@ rcu_torture_free(struct rcu_torture *p)
320 spin_unlock_bh(&rcu_torture_lock); 209 spin_unlock_bh(&rcu_torture_lock);
321} 210}
322 211
323struct rcu_random_state {
324 unsigned long rrs_state;
325 long rrs_count;
326};
327
328#define RCU_RANDOM_MULT 39916801 /* prime */
329#define RCU_RANDOM_ADD 479001701 /* prime */
330#define RCU_RANDOM_REFRESH 10000
331
332#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 }
333
334/*
335 * Crude but fast random-number generator. Uses a linear congruential
336 * generator, with occasional help from cpu_clock().
337 */
338static unsigned long
339rcu_random(struct rcu_random_state *rrsp)
340{
341 if (--rrsp->rrs_count < 0) {
342 rrsp->rrs_state += (unsigned long)local_clock();
343 rrsp->rrs_count = RCU_RANDOM_REFRESH;
344 }
345 rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD;
346 return swahw32(rrsp->rrs_state);
347}
348
349static void
350rcu_stutter_wait(const char *title)
351{
352 while (stutter_pause_test || !rcutorture_runnable) {
353 if (rcutorture_runnable)
354 schedule_timeout_interruptible(1);
355 else
356 schedule_timeout_interruptible(round_jiffies_relative(HZ));
357 rcutorture_shutdown_absorb(title);
358 }
359}
360
361/* 212/*
362 * Operations vector for selecting different types of tests. 213 * Operations vector for selecting different types of tests.
363 */ 214 */
@@ -365,7 +216,7 @@ rcu_stutter_wait(const char *title)
365struct rcu_torture_ops { 216struct rcu_torture_ops {
366 void (*init)(void); 217 void (*init)(void);
367 int (*readlock)(void); 218 int (*readlock)(void);
368 void (*read_delay)(struct rcu_random_state *rrsp); 219 void (*read_delay)(struct torture_random_state *rrsp);
369 void (*readunlock)(int idx); 220 void (*readunlock)(int idx);
370 int (*completed)(void); 221 int (*completed)(void);
371 void (*deferred_free)(struct rcu_torture *p); 222 void (*deferred_free)(struct rcu_torture *p);
@@ -392,7 +243,7 @@ static int rcu_torture_read_lock(void) __acquires(RCU)
392 return 0; 243 return 0;
393} 244}
394 245
395static void rcu_read_delay(struct rcu_random_state *rrsp) 246static void rcu_read_delay(struct torture_random_state *rrsp)
396{ 247{
397 const unsigned long shortdelay_us = 200; 248 const unsigned long shortdelay_us = 200;
398 const unsigned long longdelay_ms = 50; 249 const unsigned long longdelay_ms = 50;
@@ -401,12 +252,13 @@ static void rcu_read_delay(struct rcu_random_state *rrsp)
401 * period, and we want a long delay occasionally to trigger 252 * period, and we want a long delay occasionally to trigger
402 * force_quiescent_state. */ 253 * force_quiescent_state. */
403 254
404 if (!(rcu_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) 255 if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms)))
405 mdelay(longdelay_ms); 256 mdelay(longdelay_ms);
406 if (!(rcu_random(rrsp) % (nrealreaders * 2 * shortdelay_us))) 257 if (!(torture_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
407 udelay(shortdelay_us); 258 udelay(shortdelay_us);
408#ifdef CONFIG_PREEMPT 259#ifdef CONFIG_PREEMPT
409 if (!preempt_count() && !(rcu_random(rrsp) % (nrealreaders * 20000))) 260 if (!preempt_count() &&
261 !(torture_random(rrsp) % (nrealreaders * 20000)))
410 preempt_schedule(); /* No QS if preempt_disable() in effect */ 262 preempt_schedule(); /* No QS if preempt_disable() in effect */
411#endif 263#endif
412} 264}
@@ -427,7 +279,7 @@ rcu_torture_cb(struct rcu_head *p)
427 int i; 279 int i;
428 struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu); 280 struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
429 281
430 if (fullstop != FULLSTOP_DONTSTOP) { 282 if (torture_must_stop_irq()) {
431 /* Test is ending, just drop callbacks on the floor. */ 283 /* Test is ending, just drop callbacks on the floor. */
432 /* The next initialization will pick up the pieces. */ 284 /* The next initialization will pick up the pieces. */
433 return; 285 return;
@@ -520,6 +372,48 @@ static struct rcu_torture_ops rcu_bh_ops = {
520}; 372};
521 373
522/* 374/*
375 * Don't even think about trying any of these in real life!!!
376 * The names includes "busted", and they really means it!
377 * The only purpose of these functions is to provide a buggy RCU
378 * implementation to make sure that rcutorture correctly emits
379 * buggy-RCU error messages.
380 */
381static void rcu_busted_torture_deferred_free(struct rcu_torture *p)
382{
383 /* This is a deliberate bug for testing purposes only! */
384 rcu_torture_cb(&p->rtort_rcu);
385}
386
387static void synchronize_rcu_busted(void)
388{
389 /* This is a deliberate bug for testing purposes only! */
390}
391
392static void
393call_rcu_busted(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
394{
395 /* This is a deliberate bug for testing purposes only! */
396 func(head);
397}
398
399static struct rcu_torture_ops rcu_busted_ops = {
400 .init = rcu_sync_torture_init,
401 .readlock = rcu_torture_read_lock,
402 .read_delay = rcu_read_delay, /* just reuse rcu's version. */
403 .readunlock = rcu_torture_read_unlock,
404 .completed = rcu_no_completed,
405 .deferred_free = rcu_busted_torture_deferred_free,
406 .sync = synchronize_rcu_busted,
407 .exp_sync = synchronize_rcu_busted,
408 .call = call_rcu_busted,
409 .cb_barrier = NULL,
410 .fqs = NULL,
411 .stats = NULL,
412 .irq_capable = 1,
413 .name = "rcu_busted"
414};
415
416/*
523 * Definitions for srcu torture testing. 417 * Definitions for srcu torture testing.
524 */ 418 */
525 419
@@ -530,7 +424,7 @@ static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
530 return srcu_read_lock(&srcu_ctl); 424 return srcu_read_lock(&srcu_ctl);
531} 425}
532 426
533static void srcu_read_delay(struct rcu_random_state *rrsp) 427static void srcu_read_delay(struct torture_random_state *rrsp)
534{ 428{
535 long delay; 429 long delay;
536 const long uspertick = 1000000 / HZ; 430 const long uspertick = 1000000 / HZ;
@@ -538,7 +432,8 @@ static void srcu_read_delay(struct rcu_random_state *rrsp)
538 432
539 /* We want there to be long-running readers, but not all the time. */ 433 /* We want there to be long-running readers, but not all the time. */
540 434
541 delay = rcu_random(rrsp) % (nrealreaders * 2 * longdelay * uspertick); 435 delay = torture_random(rrsp) %
436 (nrealreaders * 2 * longdelay * uspertick);
542 if (!delay) 437 if (!delay)
543 schedule_timeout_interruptible(longdelay); 438 schedule_timeout_interruptible(longdelay);
544 else 439 else
@@ -677,12 +572,12 @@ static int rcu_torture_boost(void *arg)
677 struct rcu_boost_inflight rbi = { .inflight = 0 }; 572 struct rcu_boost_inflight rbi = { .inflight = 0 };
678 struct sched_param sp; 573 struct sched_param sp;
679 574
680 VERBOSE_PRINTK_STRING("rcu_torture_boost started"); 575 VERBOSE_TOROUT_STRING("rcu_torture_boost started");
681 576
682 /* Set real-time priority. */ 577 /* Set real-time priority. */
683 sp.sched_priority = 1; 578 sp.sched_priority = 1;
684 if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) { 579 if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) {
685 VERBOSE_PRINTK_STRING("rcu_torture_boost RT prio failed!"); 580 VERBOSE_TOROUT_STRING("rcu_torture_boost RT prio failed!");
686 n_rcu_torture_boost_rterror++; 581 n_rcu_torture_boost_rterror++;
687 } 582 }
688 583
@@ -693,9 +588,8 @@ static int rcu_torture_boost(void *arg)
693 oldstarttime = boost_starttime; 588 oldstarttime = boost_starttime;
694 while (ULONG_CMP_LT(jiffies, oldstarttime)) { 589 while (ULONG_CMP_LT(jiffies, oldstarttime)) {
695 schedule_timeout_interruptible(oldstarttime - jiffies); 590 schedule_timeout_interruptible(oldstarttime - jiffies);
696 rcu_stutter_wait("rcu_torture_boost"); 591 stutter_wait("rcu_torture_boost");
697 if (kthread_should_stop() || 592 if (torture_must_stop())
698 fullstop != FULLSTOP_DONTSTOP)
699 goto checkwait; 593 goto checkwait;
700 } 594 }
701 595
@@ -710,15 +604,14 @@ static int rcu_torture_boost(void *arg)
710 call_rcu(&rbi.rcu, rcu_torture_boost_cb); 604 call_rcu(&rbi.rcu, rcu_torture_boost_cb);
711 if (jiffies - call_rcu_time > 605 if (jiffies - call_rcu_time >
712 test_boost_duration * HZ - HZ / 2) { 606 test_boost_duration * HZ - HZ / 2) {
713 VERBOSE_PRINTK_STRING("rcu_torture_boost boosting failed"); 607 VERBOSE_TOROUT_STRING("rcu_torture_boost boosting failed");
714 n_rcu_torture_boost_failure++; 608 n_rcu_torture_boost_failure++;
715 } 609 }
716 call_rcu_time = jiffies; 610 call_rcu_time = jiffies;
717 } 611 }
718 cond_resched(); 612 cond_resched();
719 rcu_stutter_wait("rcu_torture_boost"); 613 stutter_wait("rcu_torture_boost");
720 if (kthread_should_stop() || 614 if (torture_must_stop())
721 fullstop != FULLSTOP_DONTSTOP)
722 goto checkwait; 615 goto checkwait;
723 } 616 }
724 617
@@ -742,16 +635,17 @@ static int rcu_torture_boost(void *arg)
742 } 635 }
743 636
744 /* Go do the stutter. */ 637 /* Go do the stutter. */
745checkwait: rcu_stutter_wait("rcu_torture_boost"); 638checkwait: stutter_wait("rcu_torture_boost");
746 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 639 } while (!torture_must_stop());
747 640
748 /* Clean up and exit. */ 641 /* Clean up and exit. */
749 VERBOSE_PRINTK_STRING("rcu_torture_boost task stopping"); 642 while (!kthread_should_stop() || rbi.inflight) {
750 rcutorture_shutdown_absorb("rcu_torture_boost"); 643 torture_shutdown_absorb("rcu_torture_boost");
751 while (!kthread_should_stop() || rbi.inflight)
752 schedule_timeout_uninterruptible(1); 644 schedule_timeout_uninterruptible(1);
645 }
753 smp_mb(); /* order accesses to ->inflight before stack-frame death. */ 646 smp_mb(); /* order accesses to ->inflight before stack-frame death. */
754 destroy_rcu_head_on_stack(&rbi.rcu); 647 destroy_rcu_head_on_stack(&rbi.rcu);
648 torture_kthread_stopping("rcu_torture_boost");
755 return 0; 649 return 0;
756} 650}
757 651
@@ -766,7 +660,7 @@ rcu_torture_fqs(void *arg)
766 unsigned long fqs_resume_time; 660 unsigned long fqs_resume_time;
767 int fqs_burst_remaining; 661 int fqs_burst_remaining;
768 662
769 VERBOSE_PRINTK_STRING("rcu_torture_fqs task started"); 663 VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
770 do { 664 do {
771 fqs_resume_time = jiffies + fqs_stutter * HZ; 665 fqs_resume_time = jiffies + fqs_stutter * HZ;
772 while (ULONG_CMP_LT(jiffies, fqs_resume_time) && 666 while (ULONG_CMP_LT(jiffies, fqs_resume_time) &&
@@ -780,12 +674,9 @@ rcu_torture_fqs(void *arg)
780 udelay(fqs_holdoff); 674 udelay(fqs_holdoff);
781 fqs_burst_remaining -= fqs_holdoff; 675 fqs_burst_remaining -= fqs_holdoff;
782 } 676 }
783 rcu_stutter_wait("rcu_torture_fqs"); 677 stutter_wait("rcu_torture_fqs");
784 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 678 } while (!torture_must_stop());
785 VERBOSE_PRINTK_STRING("rcu_torture_fqs task stopping"); 679 torture_kthread_stopping("rcu_torture_fqs");
786 rcutorture_shutdown_absorb("rcu_torture_fqs");
787 while (!kthread_should_stop())
788 schedule_timeout_uninterruptible(1);
789 return 0; 680 return 0;
790} 681}
791 682
@@ -802,9 +693,9 @@ rcu_torture_writer(void *arg)
802 struct rcu_torture *rp; 693 struct rcu_torture *rp;
803 struct rcu_torture *rp1; 694 struct rcu_torture *rp1;
804 struct rcu_torture *old_rp; 695 struct rcu_torture *old_rp;
805 static DEFINE_RCU_RANDOM(rand); 696 static DEFINE_TORTURE_RANDOM(rand);
806 697
807 VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); 698 VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
808 set_user_nice(current, 19); 699 set_user_nice(current, 19);
809 700
810 do { 701 do {
@@ -813,7 +704,7 @@ rcu_torture_writer(void *arg)
813 if (rp == NULL) 704 if (rp == NULL)
814 continue; 705 continue;
815 rp->rtort_pipe_count = 0; 706 rp->rtort_pipe_count = 0;
816 udelay(rcu_random(&rand) & 0x3ff); 707 udelay(torture_random(&rand) & 0x3ff);
817 old_rp = rcu_dereference_check(rcu_torture_current, 708 old_rp = rcu_dereference_check(rcu_torture_current,
818 current == writer_task); 709 current == writer_task);
819 rp->rtort_mbtest = 1; 710 rp->rtort_mbtest = 1;
@@ -826,7 +717,7 @@ rcu_torture_writer(void *arg)
826 atomic_inc(&rcu_torture_wcount[i]); 717 atomic_inc(&rcu_torture_wcount[i]);
827 old_rp->rtort_pipe_count++; 718 old_rp->rtort_pipe_count++;
828 if (gp_normal == gp_exp) 719 if (gp_normal == gp_exp)
829 exp = !!(rcu_random(&rand) & 0x80); 720 exp = !!(torture_random(&rand) & 0x80);
830 else 721 else
831 exp = gp_exp; 722 exp = gp_exp;
832 if (!exp) { 723 if (!exp) {
@@ -852,12 +743,9 @@ rcu_torture_writer(void *arg)
852 } 743 }
853 } 744 }
854 rcutorture_record_progress(++rcu_torture_current_version); 745 rcutorture_record_progress(++rcu_torture_current_version);
855 rcu_stutter_wait("rcu_torture_writer"); 746 stutter_wait("rcu_torture_writer");
856 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 747 } while (!torture_must_stop());
857 VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); 748 torture_kthread_stopping("rcu_torture_writer");
858 rcutorture_shutdown_absorb("rcu_torture_writer");
859 while (!kthread_should_stop())
860 schedule_timeout_uninterruptible(1);
861 return 0; 749 return 0;
862} 750}
863 751
@@ -868,19 +756,19 @@ rcu_torture_writer(void *arg)
868static int 756static int
869rcu_torture_fakewriter(void *arg) 757rcu_torture_fakewriter(void *arg)
870{ 758{
871 DEFINE_RCU_RANDOM(rand); 759 DEFINE_TORTURE_RANDOM(rand);
872 760
873 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started"); 761 VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task started");
874 set_user_nice(current, 19); 762 set_user_nice(current, 19);
875 763
876 do { 764 do {
877 schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10); 765 schedule_timeout_uninterruptible(1 + torture_random(&rand)%10);
878 udelay(rcu_random(&rand) & 0x3ff); 766 udelay(torture_random(&rand) & 0x3ff);
879 if (cur_ops->cb_barrier != NULL && 767 if (cur_ops->cb_barrier != NULL &&
880 rcu_random(&rand) % (nfakewriters * 8) == 0) { 768 torture_random(&rand) % (nfakewriters * 8) == 0) {
881 cur_ops->cb_barrier(); 769 cur_ops->cb_barrier();
882 } else if (gp_normal == gp_exp) { 770 } else if (gp_normal == gp_exp) {
883 if (rcu_random(&rand) & 0x80) 771 if (torture_random(&rand) & 0x80)
884 cur_ops->sync(); 772 cur_ops->sync();
885 else 773 else
886 cur_ops->exp_sync(); 774 cur_ops->exp_sync();
@@ -889,13 +777,10 @@ rcu_torture_fakewriter(void *arg)
889 } else { 777 } else {
890 cur_ops->exp_sync(); 778 cur_ops->exp_sync();
891 } 779 }
892 rcu_stutter_wait("rcu_torture_fakewriter"); 780 stutter_wait("rcu_torture_fakewriter");
893 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 781 } while (!torture_must_stop());
894 782
895 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); 783 torture_kthread_stopping("rcu_torture_fakewriter");
896 rcutorture_shutdown_absorb("rcu_torture_fakewriter");
897 while (!kthread_should_stop())
898 schedule_timeout_uninterruptible(1);
899 return 0; 784 return 0;
900} 785}
901 786
@@ -921,7 +806,7 @@ static void rcu_torture_timer(unsigned long unused)
921 int idx; 806 int idx;
922 int completed; 807 int completed;
923 int completed_end; 808 int completed_end;
924 static DEFINE_RCU_RANDOM(rand); 809 static DEFINE_TORTURE_RANDOM(rand);
925 static DEFINE_SPINLOCK(rand_lock); 810 static DEFINE_SPINLOCK(rand_lock);
926 struct rcu_torture *p; 811 struct rcu_torture *p;
927 int pipe_count; 812 int pipe_count;
@@ -980,13 +865,13 @@ rcu_torture_reader(void *arg)
980 int completed; 865 int completed;
981 int completed_end; 866 int completed_end;
982 int idx; 867 int idx;
983 DEFINE_RCU_RANDOM(rand); 868 DEFINE_TORTURE_RANDOM(rand);
984 struct rcu_torture *p; 869 struct rcu_torture *p;
985 int pipe_count; 870 int pipe_count;
986 struct timer_list t; 871 struct timer_list t;
987 unsigned long long ts; 872 unsigned long long ts;
988 873
989 VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); 874 VERBOSE_TOROUT_STRING("rcu_torture_reader task started");
990 set_user_nice(current, 19); 875 set_user_nice(current, 19);
991 if (irqreader && cur_ops->irq_capable) 876 if (irqreader && cur_ops->irq_capable)
992 setup_timer_on_stack(&t, rcu_torture_timer, 0); 877 setup_timer_on_stack(&t, rcu_torture_timer, 0);
@@ -1034,14 +919,11 @@ rcu_torture_reader(void *arg)
1034 preempt_enable(); 919 preempt_enable();
1035 cur_ops->readunlock(idx); 920 cur_ops->readunlock(idx);
1036 schedule(); 921 schedule();
1037 rcu_stutter_wait("rcu_torture_reader"); 922 stutter_wait("rcu_torture_reader");
1038 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 923 } while (!torture_must_stop());
1039 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
1040 rcutorture_shutdown_absorb("rcu_torture_reader");
1041 if (irqreader && cur_ops->irq_capable) 924 if (irqreader && cur_ops->irq_capable)
1042 del_timer_sync(&t); 925 del_timer_sync(&t);
1043 while (!kthread_should_stop()) 926 torture_kthread_stopping("rcu_torture_reader");
1044 schedule_timeout_uninterruptible(1);
1045 return 0; 927 return 0;
1046} 928}
1047 929
@@ -1083,13 +965,7 @@ rcu_torture_printk(char *page)
1083 n_rcu_torture_boost_failure, 965 n_rcu_torture_boost_failure,
1084 n_rcu_torture_boosts, 966 n_rcu_torture_boosts,
1085 n_rcu_torture_timers); 967 n_rcu_torture_timers);
1086 page += sprintf(page, 968 page = torture_onoff_stats(page);
1087 "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
1088 n_online_successes, n_online_attempts,
1089 n_offline_successes, n_offline_attempts,
1090 min_online, max_online,
1091 min_offline, max_offline,
1092 sum_online, sum_offline, HZ);
1093 page += sprintf(page, "barrier: %ld/%ld:%ld", 969 page += sprintf(page, "barrier: %ld/%ld:%ld",
1094 n_barrier_successes, 970 n_barrier_successes,
1095 n_barrier_attempts, 971 n_barrier_attempts,
@@ -1150,123 +1026,17 @@ rcu_torture_stats_print(void)
1150/* 1026/*
1151 * Periodically prints torture statistics, if periodic statistics printing 1027 * Periodically prints torture statistics, if periodic statistics printing
1152 * was specified via the stat_interval module parameter. 1028 * was specified via the stat_interval module parameter.
1153 *
1154 * No need to worry about fullstop here, since this one doesn't reference
1155 * volatile state or register callbacks.
1156 */ 1029 */
1157static int 1030static int
1158rcu_torture_stats(void *arg) 1031rcu_torture_stats(void *arg)
1159{ 1032{
1160 VERBOSE_PRINTK_STRING("rcu_torture_stats task started"); 1033 VERBOSE_TOROUT_STRING("rcu_torture_stats task started");
1161 do { 1034 do {
1162 schedule_timeout_interruptible(stat_interval * HZ); 1035 schedule_timeout_interruptible(stat_interval * HZ);
1163 rcu_torture_stats_print(); 1036 rcu_torture_stats_print();
1164 rcutorture_shutdown_absorb("rcu_torture_stats"); 1037 torture_shutdown_absorb("rcu_torture_stats");
1165 } while (!kthread_should_stop()); 1038 } while (!torture_must_stop());
1166 VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping"); 1039 torture_kthread_stopping("rcu_torture_stats");
1167 return 0;
1168}
1169
1170static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
1171
1172/* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
1173 * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
1174 */
1175static void rcu_torture_shuffle_tasks(void)
1176{
1177 int i;
1178
1179 cpumask_setall(shuffle_tmp_mask);
1180 get_online_cpus();
1181
1182 /* No point in shuffling if there is only one online CPU (ex: UP) */
1183 if (num_online_cpus() == 1) {
1184 put_online_cpus();
1185 return;
1186 }
1187
1188 if (rcu_idle_cpu != -1)
1189 cpumask_clear_cpu(rcu_idle_cpu, shuffle_tmp_mask);
1190
1191 set_cpus_allowed_ptr(current, shuffle_tmp_mask);
1192
1193 if (reader_tasks) {
1194 for (i = 0; i < nrealreaders; i++)
1195 if (reader_tasks[i])
1196 set_cpus_allowed_ptr(reader_tasks[i],
1197 shuffle_tmp_mask);
1198 }
1199 if (fakewriter_tasks) {
1200 for (i = 0; i < nfakewriters; i++)
1201 if (fakewriter_tasks[i])
1202 set_cpus_allowed_ptr(fakewriter_tasks[i],
1203 shuffle_tmp_mask);
1204 }
1205 if (writer_task)
1206 set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
1207 if (stats_task)
1208 set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
1209 if (stutter_task)
1210 set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
1211 if (fqs_task)
1212 set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
1213 if (shutdown_task)
1214 set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
1215#ifdef CONFIG_HOTPLUG_CPU
1216 if (onoff_task)
1217 set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
1218#endif /* #ifdef CONFIG_HOTPLUG_CPU */
1219 if (stall_task)
1220 set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
1221 if (barrier_cbs_tasks)
1222 for (i = 0; i < n_barrier_cbs; i++)
1223 if (barrier_cbs_tasks[i])
1224 set_cpus_allowed_ptr(barrier_cbs_tasks[i],
1225 shuffle_tmp_mask);
1226 if (barrier_task)
1227 set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
1228
1229 if (rcu_idle_cpu == -1)
1230 rcu_idle_cpu = num_online_cpus() - 1;
1231 else
1232 rcu_idle_cpu--;
1233
1234 put_online_cpus();
1235}
1236
1237/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
1238 * system to become idle at a time and cut off its timer ticks. This is meant
1239 * to test the support for such tickless idle CPU in RCU.
1240 */
1241static int
1242rcu_torture_shuffle(void *arg)
1243{
1244 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task started");
1245 do {
1246 schedule_timeout_interruptible(shuffle_interval * HZ);
1247 rcu_torture_shuffle_tasks();
1248 rcutorture_shutdown_absorb("rcu_torture_shuffle");
1249 } while (!kthread_should_stop());
1250 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
1251 return 0;
1252}
1253
1254/* Cause the rcutorture test to "stutter", starting and stopping all
1255 * threads periodically.
1256 */
1257static int
1258rcu_torture_stutter(void *arg)
1259{
1260 VERBOSE_PRINTK_STRING("rcu_torture_stutter task started");
1261 do {
1262 schedule_timeout_interruptible(stutter * HZ);
1263 stutter_pause_test = 1;
1264 if (!kthread_should_stop())
1265 schedule_timeout_interruptible(stutter * HZ);
1266 stutter_pause_test = 0;
1267 rcutorture_shutdown_absorb("rcu_torture_stutter");
1268 } while (!kthread_should_stop());
1269 VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
1270 return 0; 1040 return 0;
1271} 1041}
1272 1042
@@ -1293,10 +1063,6 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
1293 onoff_interval, onoff_holdoff); 1063 onoff_interval, onoff_holdoff);
1294} 1064}
1295 1065
1296static struct notifier_block rcutorture_shutdown_nb = {
1297 .notifier_call = rcutorture_shutdown_notify,
1298};
1299
1300static void rcutorture_booster_cleanup(int cpu) 1066static void rcutorture_booster_cleanup(int cpu)
1301{ 1067{
1302 struct task_struct *t; 1068 struct task_struct *t;
@@ -1304,14 +1070,12 @@ static void rcutorture_booster_cleanup(int cpu)
1304 if (boost_tasks[cpu] == NULL) 1070 if (boost_tasks[cpu] == NULL)
1305 return; 1071 return;
1306 mutex_lock(&boost_mutex); 1072 mutex_lock(&boost_mutex);
1307 VERBOSE_PRINTK_STRING("Stopping rcu_torture_boost task");
1308 t = boost_tasks[cpu]; 1073 t = boost_tasks[cpu];
1309 boost_tasks[cpu] = NULL; 1074 boost_tasks[cpu] = NULL;
1310 mutex_unlock(&boost_mutex); 1075 mutex_unlock(&boost_mutex);
1311 1076
1312 /* This must be outside of the mutex, otherwise deadlock! */ 1077 /* This must be outside of the mutex, otherwise deadlock! */
1313 kthread_stop(t); 1078 torture_stop_kthread(rcu_torture_boost, t);
1314 boost_tasks[cpu] = NULL;
1315} 1079}
1316 1080
1317static int rcutorture_booster_init(int cpu) 1081static int rcutorture_booster_init(int cpu)
@@ -1323,13 +1087,13 @@ static int rcutorture_booster_init(int cpu)
1323 1087
1324 /* Don't allow time recalculation while creating a new task. */ 1088 /* Don't allow time recalculation while creating a new task. */
1325 mutex_lock(&boost_mutex); 1089 mutex_lock(&boost_mutex);
1326 VERBOSE_PRINTK_STRING("Creating rcu_torture_boost task"); 1090 VERBOSE_TOROUT_STRING("Creating rcu_torture_boost task");
1327 boost_tasks[cpu] = kthread_create_on_node(rcu_torture_boost, NULL, 1091 boost_tasks[cpu] = kthread_create_on_node(rcu_torture_boost, NULL,
1328 cpu_to_node(cpu), 1092 cpu_to_node(cpu),
1329 "rcu_torture_boost"); 1093 "rcu_torture_boost");
1330 if (IS_ERR(boost_tasks[cpu])) { 1094 if (IS_ERR(boost_tasks[cpu])) {
1331 retval = PTR_ERR(boost_tasks[cpu]); 1095 retval = PTR_ERR(boost_tasks[cpu]);
1332 VERBOSE_PRINTK_STRING("rcu_torture_boost task create failed"); 1096 VERBOSE_TOROUT_STRING("rcu_torture_boost task create failed");
1333 n_rcu_torture_boost_ktrerror++; 1097 n_rcu_torture_boost_ktrerror++;
1334 boost_tasks[cpu] = NULL; 1098 boost_tasks[cpu] = NULL;
1335 mutex_unlock(&boost_mutex); 1099 mutex_unlock(&boost_mutex);
@@ -1342,175 +1106,6 @@ static int rcutorture_booster_init(int cpu)
1342} 1106}
1343 1107
1344/* 1108/*
1345 * Cause the rcutorture test to shutdown the system after the test has
1346 * run for the time specified by the shutdown_secs module parameter.
1347 */
1348static int
1349rcu_torture_shutdown(void *arg)
1350{
1351 long delta;
1352 unsigned long jiffies_snap;
1353
1354 VERBOSE_PRINTK_STRING("rcu_torture_shutdown task started");
1355 jiffies_snap = ACCESS_ONCE(jiffies);
1356 while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
1357 !kthread_should_stop()) {
1358 delta = shutdown_time - jiffies_snap;
1359 if (verbose)
1360 pr_alert("%s" TORTURE_FLAG
1361 "rcu_torture_shutdown task: %lu jiffies remaining\n",
1362 torture_type, delta);
1363 schedule_timeout_interruptible(delta);
1364 jiffies_snap = ACCESS_ONCE(jiffies);
1365 }
1366 if (kthread_should_stop()) {
1367 VERBOSE_PRINTK_STRING("rcu_torture_shutdown task stopping");
1368 return 0;
1369 }
1370
1371 /* OK, shut down the system. */
1372
1373 VERBOSE_PRINTK_STRING("rcu_torture_shutdown task shutting down system");
1374 shutdown_task = NULL; /* Avoid self-kill deadlock. */
1375 rcu_torture_cleanup(); /* Get the success/failure message. */
1376 kernel_power_off(); /* Shut down the system. */
1377 return 0;
1378}
1379
1380#ifdef CONFIG_HOTPLUG_CPU
1381
1382/*
1383 * Execute random CPU-hotplug operations at the interval specified
1384 * by the onoff_interval.
1385 */
1386static int
1387rcu_torture_onoff(void *arg)
1388{
1389 int cpu;
1390 unsigned long delta;
1391 int maxcpu = -1;
1392 DEFINE_RCU_RANDOM(rand);
1393 int ret;
1394 unsigned long starttime;
1395
1396 VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
1397 for_each_online_cpu(cpu)
1398 maxcpu = cpu;
1399 WARN_ON(maxcpu < 0);
1400 if (onoff_holdoff > 0) {
1401 VERBOSE_PRINTK_STRING("rcu_torture_onoff begin holdoff");
1402 schedule_timeout_interruptible(onoff_holdoff * HZ);
1403 VERBOSE_PRINTK_STRING("rcu_torture_onoff end holdoff");
1404 }
1405 while (!kthread_should_stop()) {
1406 cpu = (rcu_random(&rand) >> 4) % (maxcpu + 1);
1407 if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
1408 if (verbose)
1409 pr_alert("%s" TORTURE_FLAG
1410 "rcu_torture_onoff task: offlining %d\n",
1411 torture_type, cpu);
1412 starttime = jiffies;
1413 n_offline_attempts++;
1414 ret = cpu_down(cpu);
1415 if (ret) {
1416 if (verbose)
1417 pr_alert("%s" TORTURE_FLAG
1418 "rcu_torture_onoff task: offline %d failed: errno %d\n",
1419 torture_type, cpu, ret);
1420 } else {
1421 if (verbose)
1422 pr_alert("%s" TORTURE_FLAG
1423 "rcu_torture_onoff task: offlined %d\n",
1424 torture_type, cpu);
1425 n_offline_successes++;
1426 delta = jiffies - starttime;
1427 sum_offline += delta;
1428 if (min_offline < 0) {
1429 min_offline = delta;
1430 max_offline = delta;
1431 }
1432 if (min_offline > delta)
1433 min_offline = delta;
1434 if (max_offline < delta)
1435 max_offline = delta;
1436 }
1437 } else if (cpu_is_hotpluggable(cpu)) {
1438 if (verbose)
1439 pr_alert("%s" TORTURE_FLAG
1440 "rcu_torture_onoff task: onlining %d\n",
1441 torture_type, cpu);
1442 starttime = jiffies;
1443 n_online_attempts++;
1444 ret = cpu_up(cpu);
1445 if (ret) {
1446 if (verbose)
1447 pr_alert("%s" TORTURE_FLAG
1448 "rcu_torture_onoff task: online %d failed: errno %d\n",
1449 torture_type, cpu, ret);
1450 } else {
1451 if (verbose)
1452 pr_alert("%s" TORTURE_FLAG
1453 "rcu_torture_onoff task: onlined %d\n",
1454 torture_type, cpu);
1455 n_online_successes++;
1456 delta = jiffies - starttime;
1457 sum_online += delta;
1458 if (min_online < 0) {
1459 min_online = delta;
1460 max_online = delta;
1461 }
1462 if (min_online > delta)
1463 min_online = delta;
1464 if (max_online < delta)
1465 max_online = delta;
1466 }
1467 }
1468 schedule_timeout_interruptible(onoff_interval * HZ);
1469 }
1470 VERBOSE_PRINTK_STRING("rcu_torture_onoff task stopping");
1471 return 0;
1472}
1473
1474static int
1475rcu_torture_onoff_init(void)
1476{
1477 int ret;
1478
1479 if (onoff_interval <= 0)
1480 return 0;
1481 onoff_task = kthread_run(rcu_torture_onoff, NULL, "rcu_torture_onoff");
1482 if (IS_ERR(onoff_task)) {
1483 ret = PTR_ERR(onoff_task);
1484 onoff_task = NULL;
1485 return ret;
1486 }
1487 return 0;
1488}
1489
1490static void rcu_torture_onoff_cleanup(void)
1491{
1492 if (onoff_task == NULL)
1493 return;
1494 VERBOSE_PRINTK_STRING("Stopping rcu_torture_onoff task");
1495 kthread_stop(onoff_task);
1496 onoff_task = NULL;
1497}
1498
1499#else /* #ifdef CONFIG_HOTPLUG_CPU */
1500
1501static int
1502rcu_torture_onoff_init(void)
1503{
1504 return 0;
1505}
1506
1507static void rcu_torture_onoff_cleanup(void)
1508{
1509}
1510
1511#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
1512
1513/*
1514 * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then 1109 * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
1515 * induces a CPU stall for the time specified by stall_cpu. 1110 * induces a CPU stall for the time specified by stall_cpu.
1516 */ 1111 */
@@ -1518,11 +1113,11 @@ static int rcu_torture_stall(void *args)
1518{ 1113{
1519 unsigned long stop_at; 1114 unsigned long stop_at;
1520 1115
1521 VERBOSE_PRINTK_STRING("rcu_torture_stall task started"); 1116 VERBOSE_TOROUT_STRING("rcu_torture_stall task started");
1522 if (stall_cpu_holdoff > 0) { 1117 if (stall_cpu_holdoff > 0) {
1523 VERBOSE_PRINTK_STRING("rcu_torture_stall begin holdoff"); 1118 VERBOSE_TOROUT_STRING("rcu_torture_stall begin holdoff");
1524 schedule_timeout_interruptible(stall_cpu_holdoff * HZ); 1119 schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
1525 VERBOSE_PRINTK_STRING("rcu_torture_stall end holdoff"); 1120 VERBOSE_TOROUT_STRING("rcu_torture_stall end holdoff");
1526 } 1121 }
1527 if (!kthread_should_stop()) { 1122 if (!kthread_should_stop()) {
1528 stop_at = get_seconds() + stall_cpu; 1123 stop_at = get_seconds() + stall_cpu;
@@ -1536,7 +1131,7 @@ static int rcu_torture_stall(void *args)
1536 rcu_read_unlock(); 1131 rcu_read_unlock();
1537 pr_alert("rcu_torture_stall end.\n"); 1132 pr_alert("rcu_torture_stall end.\n");
1538 } 1133 }
1539 rcutorture_shutdown_absorb("rcu_torture_stall"); 1134 torture_shutdown_absorb("rcu_torture_stall");
1540 while (!kthread_should_stop()) 1135 while (!kthread_should_stop())
1541 schedule_timeout_interruptible(10 * HZ); 1136 schedule_timeout_interruptible(10 * HZ);
1542 return 0; 1137 return 0;
@@ -1545,27 +1140,9 @@ static int rcu_torture_stall(void *args)
1545/* Spawn CPU-stall kthread, if stall_cpu specified. */ 1140/* Spawn CPU-stall kthread, if stall_cpu specified. */
1546static int __init rcu_torture_stall_init(void) 1141static int __init rcu_torture_stall_init(void)
1547{ 1142{
1548 int ret;
1549
1550 if (stall_cpu <= 0) 1143 if (stall_cpu <= 0)
1551 return 0; 1144 return 0;
1552 stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall"); 1145 return torture_create_kthread(rcu_torture_stall, NULL, stall_task);
1553 if (IS_ERR(stall_task)) {
1554 ret = PTR_ERR(stall_task);
1555 stall_task = NULL;
1556 return ret;
1557 }
1558 return 0;
1559}
1560
1561/* Clean up after the CPU-stall kthread, if one was spawned. */
1562static void rcu_torture_stall_cleanup(void)
1563{
1564 if (stall_task == NULL)
1565 return;
1566 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
1567 kthread_stop(stall_task);
1568 stall_task = NULL;
1569} 1146}
1570 1147
1571/* Callback function for RCU barrier testing. */ 1148/* Callback function for RCU barrier testing. */
@@ -1583,28 +1160,24 @@ static int rcu_torture_barrier_cbs(void *arg)
1583 struct rcu_head rcu; 1160 struct rcu_head rcu;
1584 1161
1585 init_rcu_head_on_stack(&rcu); 1162 init_rcu_head_on_stack(&rcu);
1586 VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task started"); 1163 VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task started");
1587 set_user_nice(current, 19); 1164 set_user_nice(current, 19);
1588 do { 1165 do {
1589 wait_event(barrier_cbs_wq[myid], 1166 wait_event(barrier_cbs_wq[myid],
1590 (newphase = 1167 (newphase =
1591 ACCESS_ONCE(barrier_phase)) != lastphase || 1168 ACCESS_ONCE(barrier_phase)) != lastphase ||
1592 kthread_should_stop() || 1169 torture_must_stop());
1593 fullstop != FULLSTOP_DONTSTOP);
1594 lastphase = newphase; 1170 lastphase = newphase;
1595 smp_mb(); /* ensure barrier_phase load before ->call(). */ 1171 smp_mb(); /* ensure barrier_phase load before ->call(). */
1596 if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) 1172 if (torture_must_stop())
1597 break; 1173 break;
1598 cur_ops->call(&rcu, rcu_torture_barrier_cbf); 1174 cur_ops->call(&rcu, rcu_torture_barrier_cbf);
1599 if (atomic_dec_and_test(&barrier_cbs_count)) 1175 if (atomic_dec_and_test(&barrier_cbs_count))
1600 wake_up(&barrier_wq); 1176 wake_up(&barrier_wq);
1601 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 1177 } while (!torture_must_stop());
1602 VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task stopping");
1603 rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
1604 while (!kthread_should_stop())
1605 schedule_timeout_interruptible(1);
1606 cur_ops->cb_barrier(); 1178 cur_ops->cb_barrier();
1607 destroy_rcu_head_on_stack(&rcu); 1179 destroy_rcu_head_on_stack(&rcu);
1180 torture_kthread_stopping("rcu_torture_barrier_cbs");
1608 return 0; 1181 return 0;
1609} 1182}
1610 1183
@@ -1613,7 +1186,7 @@ static int rcu_torture_barrier(void *arg)
1613{ 1186{
1614 int i; 1187 int i;
1615 1188
1616 VERBOSE_PRINTK_STRING("rcu_torture_barrier task starting"); 1189 VERBOSE_TOROUT_STRING("rcu_torture_barrier task starting");
1617 do { 1190 do {
1618 atomic_set(&barrier_cbs_invoked, 0); 1191 atomic_set(&barrier_cbs_invoked, 0);
1619 atomic_set(&barrier_cbs_count, n_barrier_cbs); 1192 atomic_set(&barrier_cbs_count, n_barrier_cbs);
@@ -1623,9 +1196,8 @@ static int rcu_torture_barrier(void *arg)
1623 wake_up(&barrier_cbs_wq[i]); 1196 wake_up(&barrier_cbs_wq[i]);
1624 wait_event(barrier_wq, 1197 wait_event(barrier_wq,
1625 atomic_read(&barrier_cbs_count) == 0 || 1198 atomic_read(&barrier_cbs_count) == 0 ||
1626 kthread_should_stop() || 1199 torture_must_stop());
1627 fullstop != FULLSTOP_DONTSTOP); 1200 if (torture_must_stop())
1628 if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
1629 break; 1201 break;
1630 n_barrier_attempts++; 1202 n_barrier_attempts++;
1631 cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */ 1203 cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */
@@ -1635,11 +1207,8 @@ static int rcu_torture_barrier(void *arg)
1635 } 1207 }
1636 n_barrier_successes++; 1208 n_barrier_successes++;
1637 schedule_timeout_interruptible(HZ / 10); 1209 schedule_timeout_interruptible(HZ / 10);
1638 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 1210 } while (!torture_must_stop());
1639 VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping"); 1211 torture_kthread_stopping("rcu_torture_barrier");
1640 rcutorture_shutdown_absorb("rcu_torture_barrier");
1641 while (!kthread_should_stop())
1642 schedule_timeout_interruptible(1);
1643 return 0; 1212 return 0;
1644} 1213}
1645 1214
@@ -1672,24 +1241,13 @@ static int rcu_torture_barrier_init(void)
1672 return -ENOMEM; 1241 return -ENOMEM;
1673 for (i = 0; i < n_barrier_cbs; i++) { 1242 for (i = 0; i < n_barrier_cbs; i++) {
1674 init_waitqueue_head(&barrier_cbs_wq[i]); 1243 init_waitqueue_head(&barrier_cbs_wq[i]);
1675 barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs, 1244 ret = torture_create_kthread(rcu_torture_barrier_cbs,
1676 (void *)(long)i, 1245 (void *)(long)i,
1677 "rcu_torture_barrier_cbs"); 1246 barrier_cbs_tasks[i]);
1678 if (IS_ERR(barrier_cbs_tasks[i])) { 1247 if (ret)
1679 ret = PTR_ERR(barrier_cbs_tasks[i]);
1680 VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier_cbs");
1681 barrier_cbs_tasks[i] = NULL;
1682 return ret; 1248 return ret;
1683 }
1684 } 1249 }
1685 barrier_task = kthread_run(rcu_torture_barrier, NULL, 1250 return torture_create_kthread(rcu_torture_barrier, NULL, barrier_task);
1686 "rcu_torture_barrier");
1687 if (IS_ERR(barrier_task)) {
1688 ret = PTR_ERR(barrier_task);
1689 VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier");
1690 barrier_task = NULL;
1691 }
1692 return 0;
1693} 1251}
1694 1252
1695/* Clean up after RCU barrier testing. */ 1253/* Clean up after RCU barrier testing. */
@@ -1697,19 +1255,11 @@ static void rcu_torture_barrier_cleanup(void)
1697{ 1255{
1698 int i; 1256 int i;
1699 1257
1700 if (barrier_task != NULL) { 1258 torture_stop_kthread(rcu_torture_barrier, barrier_task);
1701 VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier task");
1702 kthread_stop(barrier_task);
1703 barrier_task = NULL;
1704 }
1705 if (barrier_cbs_tasks != NULL) { 1259 if (barrier_cbs_tasks != NULL) {
1706 for (i = 0; i < n_barrier_cbs; i++) { 1260 for (i = 0; i < n_barrier_cbs; i++)
1707 if (barrier_cbs_tasks[i] != NULL) { 1261 torture_stop_kthread(rcu_torture_barrier_cbs,
1708 VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier_cbs task"); 1262 barrier_cbs_tasks[i]);
1709 kthread_stop(barrier_cbs_tasks[i]);
1710 barrier_cbs_tasks[i] = NULL;
1711 }
1712 }
1713 kfree(barrier_cbs_tasks); 1263 kfree(barrier_cbs_tasks);
1714 barrier_cbs_tasks = NULL; 1264 barrier_cbs_tasks = NULL;
1715 } 1265 }
@@ -1747,90 +1297,42 @@ rcu_torture_cleanup(void)
1747{ 1297{
1748 int i; 1298 int i;
1749 1299
1750 mutex_lock(&fullstop_mutex);
1751 rcutorture_record_test_transition(); 1300 rcutorture_record_test_transition();
1752 if (fullstop == FULLSTOP_SHUTDOWN) { 1301 if (torture_cleanup()) {
1753 pr_warn(/* but going down anyway, so... */
1754 "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
1755 mutex_unlock(&fullstop_mutex);
1756 schedule_timeout_uninterruptible(10);
1757 if (cur_ops->cb_barrier != NULL) 1302 if (cur_ops->cb_barrier != NULL)
1758 cur_ops->cb_barrier(); 1303 cur_ops->cb_barrier();
1759 return; 1304 return;
1760 } 1305 }
1761 fullstop = FULLSTOP_RMMOD;
1762 mutex_unlock(&fullstop_mutex);
1763 unregister_reboot_notifier(&rcutorture_shutdown_nb);
1764 rcu_torture_barrier_cleanup();
1765 rcu_torture_stall_cleanup();
1766 if (stutter_task) {
1767 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
1768 kthread_stop(stutter_task);
1769 }
1770 stutter_task = NULL;
1771 if (shuffler_task) {
1772 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
1773 kthread_stop(shuffler_task);
1774 free_cpumask_var(shuffle_tmp_mask);
1775 }
1776 shuffler_task = NULL;
1777 1306
1778 if (writer_task) { 1307 rcu_torture_barrier_cleanup();
1779 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); 1308 torture_stop_kthread(rcu_torture_stall, stall_task);
1780 kthread_stop(writer_task); 1309 torture_stop_kthread(rcu_torture_writer, writer_task);
1781 }
1782 writer_task = NULL;
1783 1310
1784 if (reader_tasks) { 1311 if (reader_tasks) {
1785 for (i = 0; i < nrealreaders; i++) { 1312 for (i = 0; i < nrealreaders; i++)
1786 if (reader_tasks[i]) { 1313 torture_stop_kthread(rcu_torture_reader,
1787 VERBOSE_PRINTK_STRING( 1314 reader_tasks[i]);
1788 "Stopping rcu_torture_reader task");
1789 kthread_stop(reader_tasks[i]);
1790 }
1791 reader_tasks[i] = NULL;
1792 }
1793 kfree(reader_tasks); 1315 kfree(reader_tasks);
1794 reader_tasks = NULL;
1795 } 1316 }
1796 rcu_torture_current = NULL; 1317 rcu_torture_current = NULL;
1797 1318
1798 if (fakewriter_tasks) { 1319 if (fakewriter_tasks) {
1799 for (i = 0; i < nfakewriters; i++) { 1320 for (i = 0; i < nfakewriters; i++) {
1800 if (fakewriter_tasks[i]) { 1321 torture_stop_kthread(rcu_torture_fakewriter,
1801 VERBOSE_PRINTK_STRING( 1322 fakewriter_tasks[i]);
1802 "Stopping rcu_torture_fakewriter task");
1803 kthread_stop(fakewriter_tasks[i]);
1804 }
1805 fakewriter_tasks[i] = NULL;
1806 } 1323 }
1807 kfree(fakewriter_tasks); 1324 kfree(fakewriter_tasks);
1808 fakewriter_tasks = NULL; 1325 fakewriter_tasks = NULL;
1809 } 1326 }
1810 1327
1811 if (stats_task) { 1328 torture_stop_kthread(rcu_torture_stats, stats_task);
1812 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task"); 1329 torture_stop_kthread(rcu_torture_fqs, fqs_task);
1813 kthread_stop(stats_task);
1814 }
1815 stats_task = NULL;
1816
1817 if (fqs_task) {
1818 VERBOSE_PRINTK_STRING("Stopping rcu_torture_fqs task");
1819 kthread_stop(fqs_task);
1820 }
1821 fqs_task = NULL;
1822 if ((test_boost == 1 && cur_ops->can_boost) || 1330 if ((test_boost == 1 && cur_ops->can_boost) ||
1823 test_boost == 2) { 1331 test_boost == 2) {
1824 unregister_cpu_notifier(&rcutorture_cpu_nb); 1332 unregister_cpu_notifier(&rcutorture_cpu_nb);
1825 for_each_possible_cpu(i) 1333 for_each_possible_cpu(i)
1826 rcutorture_booster_cleanup(i); 1334 rcutorture_booster_cleanup(i);
1827 } 1335 }
1828 if (shutdown_task != NULL) {
1829 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shutdown task");
1830 kthread_stop(shutdown_task);
1831 }
1832 shutdown_task = NULL;
1833 rcu_torture_onoff_cleanup();
1834 1336
1835 /* Wait for all RCU callbacks to fire. */ 1337 /* Wait for all RCU callbacks to fire. */
1836 1338
@@ -1841,8 +1343,7 @@ rcu_torture_cleanup(void)
1841 1343
1842 if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error) 1344 if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
1843 rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE"); 1345 rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
1844 else if (n_online_successes != n_online_attempts || 1346 else if (torture_onoff_failures())
1845 n_offline_successes != n_offline_attempts)
1846 rcu_torture_print_module_parms(cur_ops, 1347 rcu_torture_print_module_parms(cur_ops,
1847 "End of test: RCU_HOTPLUG"); 1348 "End of test: RCU_HOTPLUG");
1848 else 1349 else
@@ -1911,12 +1412,11 @@ rcu_torture_init(void)
1911 int i; 1412 int i;
1912 int cpu; 1413 int cpu;
1913 int firsterr = 0; 1414 int firsterr = 0;
1914 int retval;
1915 static struct rcu_torture_ops *torture_ops[] = { 1415 static struct rcu_torture_ops *torture_ops[] = {
1916 &rcu_ops, &rcu_bh_ops, &srcu_ops, &sched_ops, 1416 &rcu_ops, &rcu_bh_ops, &rcu_busted_ops, &srcu_ops, &sched_ops,
1917 }; 1417 };
1918 1418
1919 mutex_lock(&fullstop_mutex); 1419 torture_init_begin(torture_type, verbose, &rcutorture_runnable);
1920 1420
1921 /* Process args and tell the world that the torturer is on the job. */ 1421 /* Process args and tell the world that the torturer is on the job. */
1922 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { 1422 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
@@ -1931,7 +1431,7 @@ rcu_torture_init(void)
1931 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) 1431 for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
1932 pr_alert(" %s", torture_ops[i]->name); 1432 pr_alert(" %s", torture_ops[i]->name);
1933 pr_alert("\n"); 1433 pr_alert("\n");
1934 mutex_unlock(&fullstop_mutex); 1434 torture_init_end();
1935 return -EINVAL; 1435 return -EINVAL;
1936 } 1436 }
1937 if (cur_ops->fqs == NULL && fqs_duration != 0) { 1437 if (cur_ops->fqs == NULL && fqs_duration != 0) {
@@ -1946,7 +1446,6 @@ rcu_torture_init(void)
1946 else 1446 else
1947 nrealreaders = 2 * num_online_cpus(); 1447 nrealreaders = 2 * num_online_cpus();
1948 rcu_torture_print_module_parms(cur_ops, "Start of test"); 1448 rcu_torture_print_module_parms(cur_ops, "Start of test");
1949 fullstop = FULLSTOP_DONTSTOP;
1950 1449
1951 /* Set up the freelist. */ 1450 /* Set up the freelist. */
1952 1451
@@ -1982,108 +1481,61 @@ rcu_torture_init(void)
1982 1481
1983 /* Start up the kthreads. */ 1482 /* Start up the kthreads. */
1984 1483
1985 VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task"); 1484 firsterr = torture_create_kthread(rcu_torture_writer, NULL,
1986 writer_task = kthread_create(rcu_torture_writer, NULL, 1485 writer_task);
1987 "rcu_torture_writer"); 1486 if (firsterr)
1988 if (IS_ERR(writer_task)) {
1989 firsterr = PTR_ERR(writer_task);
1990 VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
1991 writer_task = NULL;
1992 goto unwind; 1487 goto unwind;
1993 }
1994 wake_up_process(writer_task);
1995 fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), 1488 fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
1996 GFP_KERNEL); 1489 GFP_KERNEL);
1997 if (fakewriter_tasks == NULL) { 1490 if (fakewriter_tasks == NULL) {
1998 VERBOSE_PRINTK_ERRSTRING("out of memory"); 1491 VERBOSE_TOROUT_ERRSTRING("out of memory");
1999 firsterr = -ENOMEM; 1492 firsterr = -ENOMEM;
2000 goto unwind; 1493 goto unwind;
2001 } 1494 }
2002 for (i = 0; i < nfakewriters; i++) { 1495 for (i = 0; i < nfakewriters; i++) {
2003 VERBOSE_PRINTK_STRING("Creating rcu_torture_fakewriter task"); 1496 firsterr = torture_create_kthread(rcu_torture_fakewriter,
2004 fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, NULL, 1497 NULL, fakewriter_tasks[i]);
2005 "rcu_torture_fakewriter"); 1498 if (firsterr)
2006 if (IS_ERR(fakewriter_tasks[i])) {
2007 firsterr = PTR_ERR(fakewriter_tasks[i]);
2008 VERBOSE_PRINTK_ERRSTRING("Failed to create fakewriter");
2009 fakewriter_tasks[i] = NULL;
2010 goto unwind; 1499 goto unwind;
2011 }
2012 } 1500 }
2013 reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]), 1501 reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
2014 GFP_KERNEL); 1502 GFP_KERNEL);
2015 if (reader_tasks == NULL) { 1503 if (reader_tasks == NULL) {
2016 VERBOSE_PRINTK_ERRSTRING("out of memory"); 1504 VERBOSE_TOROUT_ERRSTRING("out of memory");
2017 firsterr = -ENOMEM; 1505 firsterr = -ENOMEM;
2018 goto unwind; 1506 goto unwind;
2019 } 1507 }
2020 for (i = 0; i < nrealreaders; i++) { 1508 for (i = 0; i < nrealreaders; i++) {
2021 VERBOSE_PRINTK_STRING("Creating rcu_torture_reader task"); 1509 firsterr = torture_create_kthread(rcu_torture_reader, NULL,
2022 reader_tasks[i] = kthread_run(rcu_torture_reader, NULL, 1510 reader_tasks[i]);
2023 "rcu_torture_reader"); 1511 if (firsterr)
2024 if (IS_ERR(reader_tasks[i])) {
2025 firsterr = PTR_ERR(reader_tasks[i]);
2026 VERBOSE_PRINTK_ERRSTRING("Failed to create reader");
2027 reader_tasks[i] = NULL;
2028 goto unwind; 1512 goto unwind;
2029 }
2030 } 1513 }
2031 if (stat_interval > 0) { 1514 if (stat_interval > 0) {
2032 VERBOSE_PRINTK_STRING("Creating rcu_torture_stats task"); 1515 firsterr = torture_create_kthread(rcu_torture_stats, NULL,
2033 stats_task = kthread_run(rcu_torture_stats, NULL, 1516 stats_task);
2034 "rcu_torture_stats"); 1517 if (firsterr)
2035 if (IS_ERR(stats_task)) {
2036 firsterr = PTR_ERR(stats_task);
2037 VERBOSE_PRINTK_ERRSTRING("Failed to create stats");
2038 stats_task = NULL;
2039 goto unwind; 1518 goto unwind;
2040 }
2041 } 1519 }
2042 if (test_no_idle_hz) { 1520 if (test_no_idle_hz) {
2043 rcu_idle_cpu = num_online_cpus() - 1; 1521 firsterr = torture_shuffle_init(shuffle_interval * HZ);
2044 1522 if (firsterr)
2045 if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
2046 firsterr = -ENOMEM;
2047 VERBOSE_PRINTK_ERRSTRING("Failed to alloc mask");
2048 goto unwind;
2049 }
2050
2051 /* Create the shuffler thread */
2052 shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
2053 "rcu_torture_shuffle");
2054 if (IS_ERR(shuffler_task)) {
2055 free_cpumask_var(shuffle_tmp_mask);
2056 firsterr = PTR_ERR(shuffler_task);
2057 VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
2058 shuffler_task = NULL;
2059 goto unwind; 1523 goto unwind;
2060 }
2061 } 1524 }
2062 if (stutter < 0) 1525 if (stutter < 0)
2063 stutter = 0; 1526 stutter = 0;
2064 if (stutter) { 1527 if (stutter) {
2065 /* Create the stutter thread */ 1528 firsterr = torture_stutter_init(stutter * HZ);
2066 stutter_task = kthread_run(rcu_torture_stutter, NULL, 1529 if (firsterr)
2067 "rcu_torture_stutter");
2068 if (IS_ERR(stutter_task)) {
2069 firsterr = PTR_ERR(stutter_task);
2070 VERBOSE_PRINTK_ERRSTRING("Failed to create stutter");
2071 stutter_task = NULL;
2072 goto unwind; 1530 goto unwind;
2073 }
2074 } 1531 }
2075 if (fqs_duration < 0) 1532 if (fqs_duration < 0)
2076 fqs_duration = 0; 1533 fqs_duration = 0;
2077 if (fqs_duration) { 1534 if (fqs_duration) {
2078 /* Create the stutter thread */ 1535 /* Create the fqs thread */
2079 fqs_task = kthread_run(rcu_torture_fqs, NULL, 1536 torture_create_kthread(rcu_torture_fqs, NULL, fqs_task);
2080 "rcu_torture_fqs"); 1537 if (firsterr)
2081 if (IS_ERR(fqs_task)) {
2082 firsterr = PTR_ERR(fqs_task);
2083 VERBOSE_PRINTK_ERRSTRING("Failed to create fqs");
2084 fqs_task = NULL;
2085 goto unwind; 1538 goto unwind;
2086 }
2087 } 1539 }
2088 if (test_boost_interval < 1) 1540 if (test_boost_interval < 1)
2089 test_boost_interval = 1; 1541 test_boost_interval = 1;
@@ -2097,49 +1549,31 @@ rcu_torture_init(void)
2097 for_each_possible_cpu(i) { 1549 for_each_possible_cpu(i) {
2098 if (cpu_is_offline(i)) 1550 if (cpu_is_offline(i))
2099 continue; /* Heuristic: CPU can go offline. */ 1551 continue; /* Heuristic: CPU can go offline. */
2100 retval = rcutorture_booster_init(i); 1552 firsterr = rcutorture_booster_init(i);
2101 if (retval < 0) { 1553 if (firsterr)
2102 firsterr = retval;
2103 goto unwind; 1554 goto unwind;
2104 }
2105 } 1555 }
2106 } 1556 }
2107 if (shutdown_secs > 0) { 1557 firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
2108 shutdown_time = jiffies + shutdown_secs * HZ; 1558 if (firsterr)
2109 shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
2110 "rcu_torture_shutdown");
2111 if (IS_ERR(shutdown_task)) {
2112 firsterr = PTR_ERR(shutdown_task);
2113 VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown");
2114 shutdown_task = NULL;
2115 goto unwind;
2116 }
2117 wake_up_process(shutdown_task);
2118 }
2119 i = rcu_torture_onoff_init();
2120 if (i != 0) {
2121 firsterr = i;
2122 goto unwind; 1559 goto unwind;
2123 } 1560 firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
2124 register_reboot_notifier(&rcutorture_shutdown_nb); 1561 if (firsterr)
2125 i = rcu_torture_stall_init();
2126 if (i != 0) {
2127 firsterr = i;
2128 goto unwind; 1562 goto unwind;
2129 } 1563 firsterr = rcu_torture_stall_init();
2130 retval = rcu_torture_barrier_init(); 1564 if (firsterr)
2131 if (retval != 0) { 1565 goto unwind;
2132 firsterr = retval; 1566 firsterr = rcu_torture_barrier_init();
1567 if (firsterr)
2133 goto unwind; 1568 goto unwind;
2134 }
2135 if (object_debug) 1569 if (object_debug)
2136 rcu_test_debug_objects(); 1570 rcu_test_debug_objects();
2137 rcutorture_record_test_transition(); 1571 rcutorture_record_test_transition();
2138 mutex_unlock(&fullstop_mutex); 1572 torture_init_end();
2139 return 0; 1573 return 0;
2140 1574
2141unwind: 1575unwind:
2142 mutex_unlock(&fullstop_mutex); 1576 torture_init_end();
2143 rcu_torture_cleanup(); 1577 rcu_torture_cleanup();
2144 return firsterr; 1578 return firsterr;
2145} 1579}
diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c
index 3318d8284384..c639556f3fa0 100644
--- a/kernel/rcu/srcu.c
+++ b/kernel/rcu/srcu.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright (C) IBM Corporation, 2006 18 * Copyright (C) IBM Corporation, 2006
19 * Copyright (C) Fujitsu, 2012 19 * Copyright (C) Fujitsu, 2012
@@ -36,8 +36,6 @@
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/srcu.h> 37#include <linux/srcu.h>
38 38
39#include <trace/events/rcu.h>
40
41#include "rcu.h" 39#include "rcu.h"
42 40
43/* 41/*
@@ -398,7 +396,7 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
398 rcu_batch_queue(&sp->batch_queue, head); 396 rcu_batch_queue(&sp->batch_queue, head);
399 if (!sp->running) { 397 if (!sp->running) {
400 sp->running = true; 398 sp->running = true;
401 schedule_delayed_work(&sp->work, 0); 399 queue_delayed_work(system_power_efficient_wq, &sp->work, 0);
402 } 400 }
403 spin_unlock_irqrestore(&sp->queue_lock, flags); 401 spin_unlock_irqrestore(&sp->queue_lock, flags);
404} 402}
@@ -674,7 +672,8 @@ static void srcu_reschedule(struct srcu_struct *sp)
674 } 672 }
675 673
676 if (pending) 674 if (pending)
677 schedule_delayed_work(&sp->work, SRCU_INTERVAL); 675 queue_delayed_work(system_power_efficient_wq,
676 &sp->work, SRCU_INTERVAL);
678} 677}
679 678
680/* 679/*
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index 1254f312d024..d9efcc13008c 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2008 18 * Copyright IBM Corporation, 2008
19 * 19 *
@@ -37,10 +37,6 @@
37#include <linux/prefetch.h> 37#include <linux/prefetch.h>
38#include <linux/ftrace_event.h> 38#include <linux/ftrace_event.h>
39 39
40#ifdef CONFIG_RCU_TRACE
41#include <trace/events/rcu.h>
42#endif /* #else #ifdef CONFIG_RCU_TRACE */
43
44#include "rcu.h" 40#include "rcu.h"
45 41
46/* Forward declarations for tiny_plugin.h. */ 42/* Forward declarations for tiny_plugin.h. */
diff --git a/kernel/rcu/tiny_plugin.h b/kernel/rcu/tiny_plugin.h
index 280d06cae352..431528520562 100644
--- a/kernel/rcu/tiny_plugin.h
+++ b/kernel/rcu/tiny_plugin.h
@@ -14,8 +14,8 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, you can access it online at
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 * 19 *
20 * Copyright (c) 2010 Linaro 20 * Copyright (c) 2010 Linaro
21 * 21 *
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b3d116cd072d..0c47e300210a 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2008 18 * Copyright IBM Corporation, 2008
19 * 19 *
@@ -58,8 +58,6 @@
58#include <linux/suspend.h> 58#include <linux/suspend.h>
59 59
60#include "tree.h" 60#include "tree.h"
61#include <trace/events/rcu.h>
62
63#include "rcu.h" 61#include "rcu.h"
64 62
65MODULE_ALIAS("rcutree"); 63MODULE_ALIAS("rcutree");
@@ -837,7 +835,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
837 * to the next. Only do this for the primary flavor of RCU. 835 * to the next. Only do this for the primary flavor of RCU.
838 */ 836 */
839 if (rdp->rsp == rcu_state && 837 if (rdp->rsp == rcu_state &&
840 ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) { 838 ULONG_CMP_GE(jiffies, rdp->rsp->jiffies_resched)) {
841 rdp->rsp->jiffies_resched += 5; 839 rdp->rsp->jiffies_resched += 5;
842 resched_cpu(rdp->cpu); 840 resched_cpu(rdp->cpu);
843 } 841 }
@@ -847,7 +845,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
847 845
848static void record_gp_stall_check_time(struct rcu_state *rsp) 846static void record_gp_stall_check_time(struct rcu_state *rsp)
849{ 847{
850 unsigned long j = ACCESS_ONCE(jiffies); 848 unsigned long j = jiffies;
851 unsigned long j1; 849 unsigned long j1;
852 850
853 rsp->gp_start = j; 851 rsp->gp_start = j;
@@ -1005,7 +1003,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
1005 1003
1006 if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp)) 1004 if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp))
1007 return; 1005 return;
1008 j = ACCESS_ONCE(jiffies); 1006 j = jiffies;
1009 1007
1010 /* 1008 /*
1011 * Lots of memory barriers to reject false positives. 1009 * Lots of memory barriers to reject false positives.
@@ -1423,13 +1421,14 @@ static int rcu_gp_init(struct rcu_state *rsp)
1423 1421
1424 /* Advance to a new grace period and initialize state. */ 1422 /* Advance to a new grace period and initialize state. */
1425 record_gp_stall_check_time(rsp); 1423 record_gp_stall_check_time(rsp);
1426 smp_wmb(); /* Record GP times before starting GP. */ 1424 /* Record GP times before starting GP, hence smp_store_release(). */
1427 rsp->gpnum++; 1425 smp_store_release(&rsp->gpnum, rsp->gpnum + 1);
1428 trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); 1426 trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
1429 raw_spin_unlock_irq(&rnp->lock); 1427 raw_spin_unlock_irq(&rnp->lock);
1430 1428
1431 /* Exclude any concurrent CPU-hotplug operations. */ 1429 /* Exclude any concurrent CPU-hotplug operations. */
1432 mutex_lock(&rsp->onoff_mutex); 1430 mutex_lock(&rsp->onoff_mutex);
1431 smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */
1433 1432
1434 /* 1433 /*
1435 * Set the quiescent-state-needed bits in all the rcu_node 1434 * Set the quiescent-state-needed bits in all the rcu_node
@@ -1557,10 +1556,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
1557 } 1556 }
1558 rnp = rcu_get_root(rsp); 1557 rnp = rcu_get_root(rsp);
1559 raw_spin_lock_irq(&rnp->lock); 1558 raw_spin_lock_irq(&rnp->lock);
1560 smp_mb__after_unlock_lock(); 1559 smp_mb__after_unlock_lock(); /* Order GP before ->completed update. */
1561 rcu_nocb_gp_set(rnp, nocb); 1560 rcu_nocb_gp_set(rnp, nocb);
1562 1561
1563 rsp->completed = rsp->gpnum; /* Declare grace period done. */ 1562 /* Declare grace period done. */
1563 ACCESS_ONCE(rsp->completed) = rsp->gpnum;
1564 trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); 1564 trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end"));
1565 rsp->fqs_state = RCU_GP_IDLE; 1565 rsp->fqs_state = RCU_GP_IDLE;
1566 rdp = this_cpu_ptr(rsp->rda); 1566 rdp = this_cpu_ptr(rsp->rda);
@@ -2304,7 +2304,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
2304 if (rnp_old != NULL) 2304 if (rnp_old != NULL)
2305 raw_spin_unlock(&rnp_old->fqslock); 2305 raw_spin_unlock(&rnp_old->fqslock);
2306 if (ret) { 2306 if (ret) {
2307 rsp->n_force_qs_lh++; 2307 ACCESS_ONCE(rsp->n_force_qs_lh)++;
2308 return; 2308 return;
2309 } 2309 }
2310 rnp_old = rnp; 2310 rnp_old = rnp;
@@ -2316,7 +2316,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
2316 smp_mb__after_unlock_lock(); 2316 smp_mb__after_unlock_lock();
2317 raw_spin_unlock(&rnp_old->fqslock); 2317 raw_spin_unlock(&rnp_old->fqslock);
2318 if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { 2318 if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
2319 rsp->n_force_qs_lh++; 2319 ACCESS_ONCE(rsp->n_force_qs_lh)++;
2320 raw_spin_unlock_irqrestore(&rnp_old->lock, flags); 2320 raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
2321 return; /* Someone beat us to it. */ 2321 return; /* Someone beat us to it. */
2322 } 2322 }
@@ -2639,6 +2639,58 @@ void synchronize_rcu_bh(void)
2639} 2639}
2640EXPORT_SYMBOL_GPL(synchronize_rcu_bh); 2640EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
2641 2641
2642/**
2643 * get_state_synchronize_rcu - Snapshot current RCU state
2644 *
2645 * Returns a cookie that is used by a later call to cond_synchronize_rcu()
2646 * to determine whether or not a full grace period has elapsed in the
2647 * meantime.
2648 */
2649unsigned long get_state_synchronize_rcu(void)
2650{
2651 /*
2652 * Any prior manipulation of RCU-protected data must happen
2653 * before the load from ->gpnum.
2654 */
2655 smp_mb(); /* ^^^ */
2656
2657 /*
2658 * Make sure this load happens before the purportedly
2659 * time-consuming work between get_state_synchronize_rcu()
2660 * and cond_synchronize_rcu().
2661 */
2662 return smp_load_acquire(&rcu_state->gpnum);
2663}
2664EXPORT_SYMBOL_GPL(get_state_synchronize_rcu);
2665
2666/**
2667 * cond_synchronize_rcu - Conditionally wait for an RCU grace period
2668 *
2669 * @oldstate: return value from earlier call to get_state_synchronize_rcu()
2670 *
2671 * If a full RCU grace period has elapsed since the earlier call to
2672 * get_state_synchronize_rcu(), just return. Otherwise, invoke
2673 * synchronize_rcu() to wait for a full grace period.
2674 *
2675 * Yes, this function does not take counter wrap into account. But
2676 * counter wrap is harmless. If the counter wraps, we have waited for
2677 * more than 2 billion grace periods (and way more on a 64-bit system!),
2678 * so waiting for one additional grace period should be just fine.
2679 */
2680void cond_synchronize_rcu(unsigned long oldstate)
2681{
2682 unsigned long newstate;
2683
2684 /*
2685 * Ensure that this load happens before any RCU-destructive
2686 * actions the caller might carry out after we return.
2687 */
2688 newstate = smp_load_acquire(&rcu_state->completed);
2689 if (ULONG_CMP_GE(oldstate, newstate))
2690 synchronize_rcu();
2691}
2692EXPORT_SYMBOL_GPL(cond_synchronize_rcu);
2693
2642static int synchronize_sched_expedited_cpu_stop(void *data) 2694static int synchronize_sched_expedited_cpu_stop(void *data)
2643{ 2695{
2644 /* 2696 /*
@@ -2880,7 +2932,7 @@ static int rcu_pending(int cpu)
2880 * non-NULL, store an indication of whether all callbacks are lazy. 2932 * non-NULL, store an indication of whether all callbacks are lazy.
2881 * (If there are no callbacks, all of them are deemed to be lazy.) 2933 * (If there are no callbacks, all of them are deemed to be lazy.)
2882 */ 2934 */
2883static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy) 2935static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
2884{ 2936{
2885 bool al = true; 2937 bool al = true;
2886 bool hc = false; 2938 bool hc = false;
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 8c19873f1ac9..75dc3c39a02a 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -13,8 +13,8 @@
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, you can access it online at
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * http://www.gnu.org/licenses/gpl-2.0.html.
18 * 18 *
19 * Copyright IBM Corporation, 2008 19 * Copyright IBM Corporation, 2008
20 * 20 *
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 6e2ef4b2b920..962d1d589929 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -14,8 +14,8 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, you can access it online at
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 * 19 *
20 * Copyright Red Hat, 2009 20 * Copyright Red Hat, 2009
21 * Copyright IBM Corporation, 2009 21 * Copyright IBM Corporation, 2009
@@ -1586,11 +1586,13 @@ static void rcu_prepare_kthreads(int cpu)
1586 * Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs 1586 * Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs
1587 * any flavor of RCU. 1587 * any flavor of RCU.
1588 */ 1588 */
1589#ifndef CONFIG_RCU_NOCB_CPU_ALL
1589int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) 1590int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
1590{ 1591{
1591 *delta_jiffies = ULONG_MAX; 1592 *delta_jiffies = ULONG_MAX;
1592 return rcu_cpu_has_callbacks(cpu, NULL); 1593 return rcu_cpu_has_callbacks(cpu, NULL);
1593} 1594}
1595#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
1594 1596
1595/* 1597/*
1596 * Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up 1598 * Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up
@@ -1656,7 +1658,7 @@ extern int tick_nohz_active;
1656 * only if it has been awhile since the last time we did so. Afterwards, 1658 * only if it has been awhile since the last time we did so. Afterwards,
1657 * if there are any callbacks ready for immediate invocation, return true. 1659 * if there are any callbacks ready for immediate invocation, return true.
1658 */ 1660 */
1659static bool rcu_try_advance_all_cbs(void) 1661static bool __maybe_unused rcu_try_advance_all_cbs(void)
1660{ 1662{
1661 bool cbs_ready = false; 1663 bool cbs_ready = false;
1662 struct rcu_data *rdp; 1664 struct rcu_data *rdp;
@@ -1696,6 +1698,7 @@ static bool rcu_try_advance_all_cbs(void)
1696 * 1698 *
1697 * The caller must have disabled interrupts. 1699 * The caller must have disabled interrupts.
1698 */ 1700 */
1701#ifndef CONFIG_RCU_NOCB_CPU_ALL
1699int rcu_needs_cpu(int cpu, unsigned long *dj) 1702int rcu_needs_cpu(int cpu, unsigned long *dj)
1700{ 1703{
1701 struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); 1704 struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
@@ -1726,6 +1729,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
1726 } 1729 }
1727 return 0; 1730 return 0;
1728} 1731}
1732#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
1729 1733
1730/* 1734/*
1731 * Prepare a CPU for idle from an RCU perspective. The first major task 1735 * Prepare a CPU for idle from an RCU perspective. The first major task
@@ -1739,6 +1743,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
1739 */ 1743 */
1740static void rcu_prepare_for_idle(int cpu) 1744static void rcu_prepare_for_idle(int cpu)
1741{ 1745{
1746#ifndef CONFIG_RCU_NOCB_CPU_ALL
1742 struct rcu_data *rdp; 1747 struct rcu_data *rdp;
1743 struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); 1748 struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
1744 struct rcu_node *rnp; 1749 struct rcu_node *rnp;
@@ -1790,6 +1795,7 @@ static void rcu_prepare_for_idle(int cpu)
1790 rcu_accelerate_cbs(rsp, rnp, rdp); 1795 rcu_accelerate_cbs(rsp, rnp, rdp);
1791 raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ 1796 raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
1792 } 1797 }
1798#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
1793} 1799}
1794 1800
1795/* 1801/*
@@ -1799,11 +1805,12 @@ static void rcu_prepare_for_idle(int cpu)
1799 */ 1805 */
1800static void rcu_cleanup_after_idle(int cpu) 1806static void rcu_cleanup_after_idle(int cpu)
1801{ 1807{
1802 1808#ifndef CONFIG_RCU_NOCB_CPU_ALL
1803 if (rcu_is_nocb_cpu(cpu)) 1809 if (rcu_is_nocb_cpu(cpu))
1804 return; 1810 return;
1805 if (rcu_try_advance_all_cbs()) 1811 if (rcu_try_advance_all_cbs())
1806 invoke_rcu_core(); 1812 invoke_rcu_core();
1813#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
1807} 1814}
1808 1815
1809/* 1816/*
@@ -2101,6 +2108,7 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
2101 init_waitqueue_head(&rnp->nocb_gp_wq[1]); 2108 init_waitqueue_head(&rnp->nocb_gp_wq[1]);
2102} 2109}
2103 2110
2111#ifndef CONFIG_RCU_NOCB_CPU_ALL
2104/* Is the specified CPU a no-CPUs CPU? */ 2112/* Is the specified CPU a no-CPUs CPU? */
2105bool rcu_is_nocb_cpu(int cpu) 2113bool rcu_is_nocb_cpu(int cpu)
2106{ 2114{
@@ -2108,6 +2116,7 @@ bool rcu_is_nocb_cpu(int cpu)
2108 return cpumask_test_cpu(cpu, rcu_nocb_mask); 2116 return cpumask_test_cpu(cpu, rcu_nocb_mask);
2109 return false; 2117 return false;
2110} 2118}
2119#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
2111 2120
2112/* 2121/*
2113 * Enqueue the specified string of rcu_head structures onto the specified 2122 * Enqueue the specified string of rcu_head structures onto the specified
@@ -2893,7 +2902,7 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
2893 * CPU unless the grace period has extended for too long. 2902 * CPU unless the grace period has extended for too long.
2894 * 2903 *
2895 * This code relies on the fact that all NO_HZ_FULL CPUs are also 2904 * This code relies on the fact that all NO_HZ_FULL CPUs are also
2896 * CONFIG_RCU_NOCB_CPUs. 2905 * CONFIG_RCU_NOCB_CPU CPUs.
2897 */ 2906 */
2898static bool rcu_nohz_full_cpu(struct rcu_state *rsp) 2907static bool rcu_nohz_full_cpu(struct rcu_state *rsp)
2899{ 2908{
diff --git a/kernel/rcu/tree_trace.c b/kernel/rcu/tree_trace.c
index 4def475336d4..5cdc62e1beeb 100644
--- a/kernel/rcu/tree_trace.c
+++ b/kernel/rcu/tree_trace.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2008 18 * Copyright IBM Corporation, 2008
19 * 19 *
@@ -273,7 +273,7 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
273 seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", 273 seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
274 rsp->n_force_qs, rsp->n_force_qs_ngp, 274 rsp->n_force_qs, rsp->n_force_qs_ngp,
275 rsp->n_force_qs - rsp->n_force_qs_ngp, 275 rsp->n_force_qs - rsp->n_force_qs_ngp,
276 rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen); 276 ACCESS_ONCE(rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen);
277 for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) { 277 for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
278 if (rnp->level != level) { 278 if (rnp->level != level) {
279 seq_puts(m, "\n"); 279 seq_puts(m, "\n");
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index c54609faf233..4c0a9b0af469 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -12,8 +12,8 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, you can access it online at
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 * 17 *
18 * Copyright IBM Corporation, 2001 18 * Copyright IBM Corporation, 2001
19 * 19 *
@@ -49,7 +49,6 @@
49#include <linux/module.h> 49#include <linux/module.h>
50 50
51#define CREATE_TRACE_POINTS 51#define CREATE_TRACE_POINTS
52#include <trace/events/rcu.h>
53 52
54#include "rcu.h" 53#include "rcu.h"
55 54
diff --git a/kernel/torture.c b/kernel/torture.c
new file mode 100644
index 000000000000..acc9afc2f26e
--- /dev/null
+++ b/kernel/torture.c
@@ -0,0 +1,719 @@
1/*
2 * Common functions for in-kernel torture tests.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * Copyright (C) IBM Corporation, 2014
19 *
20 * Author: Paul E. McKenney <paulmck@us.ibm.com>
21 * Based on kernel/rcu/torture.c.
22 */
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/kthread.h>
28#include <linux/err.h>
29#include <linux/spinlock.h>
30#include <linux/smp.h>
31#include <linux/interrupt.h>
32#include <linux/sched.h>
33#include <linux/atomic.h>
34#include <linux/bitops.h>
35#include <linux/completion.h>
36#include <linux/moduleparam.h>
37#include <linux/percpu.h>
38#include <linux/notifier.h>
39#include <linux/reboot.h>
40#include <linux/freezer.h>
41#include <linux/cpu.h>
42#include <linux/delay.h>
43#include <linux/stat.h>
44#include <linux/slab.h>
45#include <linux/trace_clock.h>
46#include <asm/byteorder.h>
47#include <linux/torture.h>
48
49MODULE_LICENSE("GPL");
50MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>");
51
52static char *torture_type;
53static bool verbose;
54
55/* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */
56#define FULLSTOP_DONTSTOP 0 /* Normal operation. */
57#define FULLSTOP_SHUTDOWN 1 /* System shutdown with torture running. */
58#define FULLSTOP_RMMOD 2 /* Normal rmmod of torture. */
59static int fullstop = FULLSTOP_RMMOD;
60static DEFINE_MUTEX(fullstop_mutex);
61static int *torture_runnable;
62
63#ifdef CONFIG_HOTPLUG_CPU
64
65/*
66 * Variables for online-offline handling. Only present if CPU hotplug
67 * is enabled, otherwise does nothing.
68 */
69
70static struct task_struct *onoff_task;
71static long onoff_holdoff;
72static long onoff_interval;
73static long n_offline_attempts;
74static long n_offline_successes;
75static unsigned long sum_offline;
76static int min_offline = -1;
77static int max_offline;
78static long n_online_attempts;
79static long n_online_successes;
80static unsigned long sum_online;
81static int min_online = -1;
82static int max_online;
83
84/*
85 * Execute random CPU-hotplug operations at the interval specified
86 * by the onoff_interval.
87 */
88static int
89torture_onoff(void *arg)
90{
91 int cpu;
92 unsigned long delta;
93 int maxcpu = -1;
94 DEFINE_TORTURE_RANDOM(rand);
95 int ret;
96 unsigned long starttime;
97
98 VERBOSE_TOROUT_STRING("torture_onoff task started");
99 for_each_online_cpu(cpu)
100 maxcpu = cpu;
101 WARN_ON(maxcpu < 0);
102 if (onoff_holdoff > 0) {
103 VERBOSE_TOROUT_STRING("torture_onoff begin holdoff");
104 schedule_timeout_interruptible(onoff_holdoff);
105 VERBOSE_TOROUT_STRING("torture_onoff end holdoff");
106 }
107 while (!torture_must_stop()) {
108 cpu = (torture_random(&rand) >> 4) % (maxcpu + 1);
109 if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
110 if (verbose)
111 pr_alert("%s" TORTURE_FLAG
112 "torture_onoff task: offlining %d\n",
113 torture_type, cpu);
114 starttime = jiffies;
115 n_offline_attempts++;
116 ret = cpu_down(cpu);
117 if (ret) {
118 if (verbose)
119 pr_alert("%s" TORTURE_FLAG
120 "torture_onoff task: offline %d failed: errno %d\n",
121 torture_type, cpu, ret);
122 } else {
123 if (verbose)
124 pr_alert("%s" TORTURE_FLAG
125 "torture_onoff task: offlined %d\n",
126 torture_type, cpu);
127 n_offline_successes++;
128 delta = jiffies - starttime;
129 sum_offline += delta;
130 if (min_offline < 0) {
131 min_offline = delta;
132 max_offline = delta;
133 }
134 if (min_offline > delta)
135 min_offline = delta;
136 if (max_offline < delta)
137 max_offline = delta;
138 }
139 } else if (cpu_is_hotpluggable(cpu)) {
140 if (verbose)
141 pr_alert("%s" TORTURE_FLAG
142 "torture_onoff task: onlining %d\n",
143 torture_type, cpu);
144 starttime = jiffies;
145 n_online_attempts++;
146 ret = cpu_up(cpu);
147 if (ret) {
148 if (verbose)
149 pr_alert("%s" TORTURE_FLAG
150 "torture_onoff task: online %d failed: errno %d\n",
151 torture_type, cpu, ret);
152 } else {
153 if (verbose)
154 pr_alert("%s" TORTURE_FLAG
155 "torture_onoff task: onlined %d\n",
156 torture_type, cpu);
157 n_online_successes++;
158 delta = jiffies - starttime;
159 sum_online += delta;
160 if (min_online < 0) {
161 min_online = delta;
162 max_online = delta;
163 }
164 if (min_online > delta)
165 min_online = delta;
166 if (max_online < delta)
167 max_online = delta;
168 }
169 }
170 schedule_timeout_interruptible(onoff_interval);
171 }
172 torture_kthread_stopping("torture_onoff");
173 return 0;
174}
175
176#endif /* #ifdef CONFIG_HOTPLUG_CPU */
177
178/*
179 * Initiate online-offline handling.
180 */
181int torture_onoff_init(long ooholdoff, long oointerval)
182{
183 int ret = 0;
184
185#ifdef CONFIG_HOTPLUG_CPU
186 onoff_holdoff = ooholdoff;
187 onoff_interval = oointerval;
188 if (onoff_interval <= 0)
189 return 0;
190 ret = torture_create_kthread(torture_onoff, NULL, onoff_task);
191#endif /* #ifdef CONFIG_HOTPLUG_CPU */
192 return ret;
193}
194EXPORT_SYMBOL_GPL(torture_onoff_init);
195
196/*
197 * Clean up after online/offline testing.
198 */
199static void torture_onoff_cleanup(void)
200{
201#ifdef CONFIG_HOTPLUG_CPU
202 if (onoff_task == NULL)
203 return;
204 VERBOSE_TOROUT_STRING("Stopping torture_onoff task");
205 kthread_stop(onoff_task);
206 onoff_task = NULL;
207#endif /* #ifdef CONFIG_HOTPLUG_CPU */
208}
209EXPORT_SYMBOL_GPL(torture_onoff_cleanup);
210
211/*
212 * Print online/offline testing statistics.
213 */
214char *torture_onoff_stats(char *page)
215{
216#ifdef CONFIG_HOTPLUG_CPU
217 page += sprintf(page,
218 "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
219 n_online_successes, n_online_attempts,
220 n_offline_successes, n_offline_attempts,
221 min_online, max_online,
222 min_offline, max_offline,
223 sum_online, sum_offline, HZ);
224#endif /* #ifdef CONFIG_HOTPLUG_CPU */
225 return page;
226}
227EXPORT_SYMBOL_GPL(torture_onoff_stats);
228
229/*
230 * Were all the online/offline operations successful?
231 */
232bool torture_onoff_failures(void)
233{
234#ifdef CONFIG_HOTPLUG_CPU
235 return n_online_successes != n_online_attempts ||
236 n_offline_successes != n_offline_attempts;
237#else /* #ifdef CONFIG_HOTPLUG_CPU */
238 return false;
239#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
240}
241EXPORT_SYMBOL_GPL(torture_onoff_failures);
242
243#define TORTURE_RANDOM_MULT 39916801 /* prime */
244#define TORTURE_RANDOM_ADD 479001701 /* prime */
245#define TORTURE_RANDOM_REFRESH 10000
246
247/*
248 * Crude but fast random-number generator. Uses a linear congruential
249 * generator, with occasional help from cpu_clock().
250 */
251unsigned long
252torture_random(struct torture_random_state *trsp)
253{
254 if (--trsp->trs_count < 0) {
255 trsp->trs_state += (unsigned long)local_clock();
256 trsp->trs_count = TORTURE_RANDOM_REFRESH;
257 }
258 trsp->trs_state = trsp->trs_state * TORTURE_RANDOM_MULT +
259 TORTURE_RANDOM_ADD;
260 return swahw32(trsp->trs_state);
261}
262EXPORT_SYMBOL_GPL(torture_random);
263
264/*
265 * Variables for shuffling. The idea is to ensure that each CPU stays
266 * idle for an extended period to test interactions with dyntick idle,
267 * as well as interactions with any per-CPU varibles.
268 */
269struct shuffle_task {
270 struct list_head st_l;
271 struct task_struct *st_t;
272};
273
274static long shuffle_interval; /* In jiffies. */
275static struct task_struct *shuffler_task;
276static cpumask_var_t shuffle_tmp_mask;
277static int shuffle_idle_cpu; /* Force all torture tasks off this CPU */
278static struct list_head shuffle_task_list = LIST_HEAD_INIT(shuffle_task_list);
279static DEFINE_MUTEX(shuffle_task_mutex);
280
281/*
282 * Register a task to be shuffled. If there is no memory, just splat
283 * and don't bother registering.
284 */
285void torture_shuffle_task_register(struct task_struct *tp)
286{
287 struct shuffle_task *stp;
288
289 if (WARN_ON_ONCE(tp == NULL))
290 return;
291 stp = kmalloc(sizeof(*stp), GFP_KERNEL);
292 if (WARN_ON_ONCE(stp == NULL))
293 return;
294 stp->st_t = tp;
295 mutex_lock(&shuffle_task_mutex);
296 list_add(&stp->st_l, &shuffle_task_list);
297 mutex_unlock(&shuffle_task_mutex);
298}
299EXPORT_SYMBOL_GPL(torture_shuffle_task_register);
300
301/*
302 * Unregister all tasks, for example, at the end of the torture run.
303 */
304static void torture_shuffle_task_unregister_all(void)
305{
306 struct shuffle_task *stp;
307 struct shuffle_task *p;
308
309 mutex_lock(&shuffle_task_mutex);
310 list_for_each_entry_safe(stp, p, &shuffle_task_list, st_l) {
311 list_del(&stp->st_l);
312 kfree(stp);
313 }
314 mutex_unlock(&shuffle_task_mutex);
315}
316
317/* Shuffle tasks such that we allow shuffle_idle_cpu to become idle.
318 * A special case is when shuffle_idle_cpu = -1, in which case we allow
319 * the tasks to run on all CPUs.
320 */
321static void torture_shuffle_tasks(void)
322{
323 struct shuffle_task *stp;
324
325 cpumask_setall(shuffle_tmp_mask);
326 get_online_cpus();
327
328 /* No point in shuffling if there is only one online CPU (ex: UP) */
329 if (num_online_cpus() == 1) {
330 put_online_cpus();
331 return;
332 }
333
334 /* Advance to the next CPU. Upon overflow, don't idle any CPUs. */
335 shuffle_idle_cpu = cpumask_next(shuffle_idle_cpu, shuffle_tmp_mask);
336 if (shuffle_idle_cpu >= nr_cpu_ids)
337 shuffle_idle_cpu = -1;
338 if (shuffle_idle_cpu != -1) {
339 cpumask_clear_cpu(shuffle_idle_cpu, shuffle_tmp_mask);
340 if (cpumask_empty(shuffle_tmp_mask)) {
341 put_online_cpus();
342 return;
343 }
344 }
345
346 mutex_lock(&shuffle_task_mutex);
347 list_for_each_entry(stp, &shuffle_task_list, st_l)
348 set_cpus_allowed_ptr(stp->st_t, shuffle_tmp_mask);
349 mutex_unlock(&shuffle_task_mutex);
350
351 put_online_cpus();
352}
353
354/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
355 * system to become idle at a time and cut off its timer ticks. This is meant
356 * to test the support for such tickless idle CPU in RCU.
357 */
358static int torture_shuffle(void *arg)
359{
360 VERBOSE_TOROUT_STRING("torture_shuffle task started");
361 do {
362 schedule_timeout_interruptible(shuffle_interval);
363 torture_shuffle_tasks();
364 torture_shutdown_absorb("torture_shuffle");
365 } while (!torture_must_stop());
366 torture_kthread_stopping("torture_shuffle");
367 return 0;
368}
369
370/*
371 * Start the shuffler, with shuffint in jiffies.
372 */
373int torture_shuffle_init(long shuffint)
374{
375 shuffle_interval = shuffint;
376
377 shuffle_idle_cpu = -1;
378
379 if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
380 VERBOSE_TOROUT_ERRSTRING("Failed to alloc mask");
381 return -ENOMEM;
382 }
383
384 /* Create the shuffler thread */
385 return torture_create_kthread(torture_shuffle, NULL, shuffler_task);
386}
387EXPORT_SYMBOL_GPL(torture_shuffle_init);
388
389/*
390 * Stop the shuffling.
391 */
392static void torture_shuffle_cleanup(void)
393{
394 torture_shuffle_task_unregister_all();
395 if (shuffler_task) {
396 VERBOSE_TOROUT_STRING("Stopping torture_shuffle task");
397 kthread_stop(shuffler_task);
398 free_cpumask_var(shuffle_tmp_mask);
399 }
400 shuffler_task = NULL;
401}
402EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
403
404/*
405 * Variables for auto-shutdown. This allows "lights out" torture runs
406 * to be fully scripted.
407 */
408static int shutdown_secs; /* desired test duration in seconds. */
409static struct task_struct *shutdown_task;
410static unsigned long shutdown_time; /* jiffies to system shutdown. */
411static void (*torture_shutdown_hook)(void);
412
413/*
414 * Absorb kthreads into a kernel function that won't return, so that
415 * they won't ever access module text or data again.
416 */
417void torture_shutdown_absorb(const char *title)
418{
419 while (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
420 pr_notice("torture thread %s parking due to system shutdown\n",
421 title);
422 schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
423 }
424}
425EXPORT_SYMBOL_GPL(torture_shutdown_absorb);
426
427/*
428 * Cause the torture test to shutdown the system after the test has
429 * run for the time specified by the shutdown_secs parameter.
430 */
431static int torture_shutdown(void *arg)
432{
433 long delta;
434 unsigned long jiffies_snap;
435
436 VERBOSE_TOROUT_STRING("torture_shutdown task started");
437 jiffies_snap = jiffies;
438 while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
439 !torture_must_stop()) {
440 delta = shutdown_time - jiffies_snap;
441 if (verbose)
442 pr_alert("%s" TORTURE_FLAG
443 "torture_shutdown task: %lu jiffies remaining\n",
444 torture_type, delta);
445 schedule_timeout_interruptible(delta);
446 jiffies_snap = jiffies;
447 }
448 if (torture_must_stop()) {
449 torture_kthread_stopping("torture_shutdown");
450 return 0;
451 }
452
453 /* OK, shut down the system. */
454
455 VERBOSE_TOROUT_STRING("torture_shutdown task shutting down system");
456 shutdown_task = NULL; /* Avoid self-kill deadlock. */
457 if (torture_shutdown_hook)
458 torture_shutdown_hook();
459 else
460 VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping.");
461 kernel_power_off(); /* Shut down the system. */
462 return 0;
463}
464
465/*
466 * Start up the shutdown task.
467 */
468int torture_shutdown_init(int ssecs, void (*cleanup)(void))
469{
470 int ret = 0;
471
472 shutdown_secs = ssecs;
473 torture_shutdown_hook = cleanup;
474 if (shutdown_secs > 0) {
475 shutdown_time = jiffies + shutdown_secs * HZ;
476 ret = torture_create_kthread(torture_shutdown, NULL,
477 shutdown_task);
478 }
479 return ret;
480}
481EXPORT_SYMBOL_GPL(torture_shutdown_init);
482
483/*
484 * Detect and respond to a system shutdown.
485 */
486static int torture_shutdown_notify(struct notifier_block *unused1,
487 unsigned long unused2, void *unused3)
488{
489 mutex_lock(&fullstop_mutex);
490 if (ACCESS_ONCE(fullstop) == FULLSTOP_DONTSTOP) {
491 VERBOSE_TOROUT_STRING("Unscheduled system shutdown detected");
492 ACCESS_ONCE(fullstop) = FULLSTOP_SHUTDOWN;
493 } else {
494 pr_warn("Concurrent rmmod and shutdown illegal!\n");
495 }
496 mutex_unlock(&fullstop_mutex);
497 return NOTIFY_DONE;
498}
499
500static struct notifier_block torture_shutdown_nb = {
501 .notifier_call = torture_shutdown_notify,
502};
503
504/*
505 * Shut down the shutdown task. Say what??? Heh! This can happen if
506 * the torture module gets an rmmod before the shutdown time arrives. ;-)
507 */
508static void torture_shutdown_cleanup(void)
509{
510 unregister_reboot_notifier(&torture_shutdown_nb);
511 if (shutdown_task != NULL) {
512 VERBOSE_TOROUT_STRING("Stopping torture_shutdown task");
513 kthread_stop(shutdown_task);
514 }
515 shutdown_task = NULL;
516}
517
518/*
519 * Variables for stuttering, which means to periodically pause and
520 * restart testing in order to catch bugs that appear when load is
521 * suddenly applied to or removed from the system.
522 */
523static struct task_struct *stutter_task;
524static int stutter_pause_test;
525static int stutter;
526
527/*
528 * Block until the stutter interval ends. This must be called periodically
529 * by all running kthreads that need to be subject to stuttering.
530 */
531void stutter_wait(const char *title)
532{
533 while (ACCESS_ONCE(stutter_pause_test) ||
534 (torture_runnable && !ACCESS_ONCE(*torture_runnable))) {
535 if (stutter_pause_test)
536 schedule_timeout_interruptible(1);
537 else
538 schedule_timeout_interruptible(round_jiffies_relative(HZ));
539 torture_shutdown_absorb(title);
540 }
541}
542EXPORT_SYMBOL_GPL(stutter_wait);
543
544/*
545 * Cause the torture test to "stutter", starting and stopping all
546 * threads periodically.
547 */
548static int torture_stutter(void *arg)
549{
550 VERBOSE_TOROUT_STRING("torture_stutter task started");
551 do {
552 if (!torture_must_stop()) {
553 schedule_timeout_interruptible(stutter);
554 ACCESS_ONCE(stutter_pause_test) = 1;
555 }
556 if (!torture_must_stop())
557 schedule_timeout_interruptible(stutter);
558 ACCESS_ONCE(stutter_pause_test) = 0;
559 torture_shutdown_absorb("torture_stutter");
560 } while (!torture_must_stop());
561 torture_kthread_stopping("torture_stutter");
562 return 0;
563}
564
565/*
566 * Initialize and kick off the torture_stutter kthread.
567 */
568int torture_stutter_init(int s)
569{
570 int ret;
571
572 stutter = s;
573 ret = torture_create_kthread(torture_stutter, NULL, stutter_task);
574 return ret;
575}
576EXPORT_SYMBOL_GPL(torture_stutter_init);
577
578/*
579 * Cleanup after the torture_stutter kthread.
580 */
581static void torture_stutter_cleanup(void)
582{
583 if (!stutter_task)
584 return;
585 VERBOSE_TOROUT_STRING("Stopping torture_stutter task");
586 kthread_stop(stutter_task);
587 stutter_task = NULL;
588}
589
590/*
591 * Initialize torture module. Please note that this is -not- invoked via
592 * the usual module_init() mechanism, but rather by an explicit call from
593 * the client torture module. This call must be paired with a later
594 * torture_init_end().
595 *
596 * The runnable parameter points to a flag that controls whether or not
597 * the test is currently runnable. If there is no such flag, pass in NULL.
598 */
599void __init torture_init_begin(char *ttype, bool v, int *runnable)
600{
601 mutex_lock(&fullstop_mutex);
602 torture_type = ttype;
603 verbose = v;
604 torture_runnable = runnable;
605 fullstop = FULLSTOP_DONTSTOP;
606
607}
608EXPORT_SYMBOL_GPL(torture_init_begin);
609
610/*
611 * Tell the torture module that initialization is complete.
612 */
613void __init torture_init_end(void)
614{
615 mutex_unlock(&fullstop_mutex);
616 register_reboot_notifier(&torture_shutdown_nb);
617}
618EXPORT_SYMBOL_GPL(torture_init_end);
619
620/*
621 * Clean up torture module. Please note that this is -not- invoked via
622 * the usual module_exit() mechanism, but rather by an explicit call from
623 * the client torture module. Returns true if a race with system shutdown
624 * is detected, otherwise, all kthreads started by functions in this file
625 * will be shut down.
626 *
627 * This must be called before the caller starts shutting down its own
628 * kthreads.
629 */
630bool torture_cleanup(void)
631{
632 mutex_lock(&fullstop_mutex);
633 if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
634 pr_warn("Concurrent rmmod and shutdown illegal!\n");
635 mutex_unlock(&fullstop_mutex);
636 schedule_timeout_uninterruptible(10);
637 return true;
638 }
639 ACCESS_ONCE(fullstop) = FULLSTOP_RMMOD;
640 mutex_unlock(&fullstop_mutex);
641 torture_shutdown_cleanup();
642 torture_shuffle_cleanup();
643 torture_stutter_cleanup();
644 torture_onoff_cleanup();
645 return false;
646}
647EXPORT_SYMBOL_GPL(torture_cleanup);
648
649/*
650 * Is it time for the current torture test to stop?
651 */
652bool torture_must_stop(void)
653{
654 return torture_must_stop_irq() || kthread_should_stop();
655}
656EXPORT_SYMBOL_GPL(torture_must_stop);
657
658/*
659 * Is it time for the current torture test to stop? This is the irq-safe
660 * version, hence no check for kthread_should_stop().
661 */
662bool torture_must_stop_irq(void)
663{
664 return ACCESS_ONCE(fullstop) != FULLSTOP_DONTSTOP;
665}
666EXPORT_SYMBOL_GPL(torture_must_stop_irq);
667
668/*
669 * Each kthread must wait for kthread_should_stop() before returning from
670 * its top-level function, otherwise segfaults ensue. This function
671 * prints a "stopping" message and waits for kthread_should_stop(), and
672 * should be called from all torture kthreads immediately prior to
673 * returning.
674 */
675void torture_kthread_stopping(char *title)
676{
677 if (verbose)
678 VERBOSE_TOROUT_STRING(title);
679 while (!kthread_should_stop()) {
680 torture_shutdown_absorb(title);
681 schedule_timeout_uninterruptible(1);
682 }
683}
684EXPORT_SYMBOL_GPL(torture_kthread_stopping);
685
686/*
687 * Create a generic torture kthread that is immediately runnable. If you
688 * need the kthread to be stopped so that you can do something to it before
689 * it starts, you will need to open-code your own.
690 */
691int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
692 char *f, struct task_struct **tp)
693{
694 int ret = 0;
695
696 VERBOSE_TOROUT_STRING(m);
697 *tp = kthread_run(fn, arg, s);
698 if (IS_ERR(*tp)) {
699 ret = PTR_ERR(*tp);
700 VERBOSE_TOROUT_ERRSTRING(f);
701 *tp = NULL;
702 }
703 torture_shuffle_task_register(*tp);
704 return ret;
705}
706EXPORT_SYMBOL_GPL(_torture_create_kthread);
707
708/*
709 * Stop a generic kthread, emitting a message.
710 */
711void _torture_stop_kthread(char *m, struct task_struct **tp)
712{
713 if (*tp == NULL)
714 return;
715 VERBOSE_TOROUT_STRING(m);
716 kthread_stop(*tp);
717 *tp = NULL;
718}
719EXPORT_SYMBOL_GPL(_torture_stop_kthread);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a48abeac753f..dd7f8858188a 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -980,6 +980,21 @@ config DEBUG_LOCKING_API_SELFTESTS
980 The following locking APIs are covered: spinlocks, rwlocks, 980 The following locking APIs are covered: spinlocks, rwlocks,
981 mutexes and rwsems. 981 mutexes and rwsems.
982 982
983config LOCK_TORTURE_TEST
984 tristate "torture tests for locking"
985 depends on DEBUG_KERNEL
986 select TORTURE_TEST
987 default n
988 help
989 This option provides a kernel module that runs torture tests
990 on kernel locking primitives. The kernel module may be built
991 after the fact on the running kernel to be tested, if desired.
992
993 Say Y here if you want kernel locking-primitive torture tests
994 to be built into the kernel.
995 Say M if you want these torture tests to build as a module.
996 Say N if you are unsure.
997
983endmenu # lock debugging 998endmenu # lock debugging
984 999
985config TRACE_IRQFLAGS 1000config TRACE_IRQFLAGS
@@ -1141,9 +1156,14 @@ config SPARSE_RCU_POINTER
1141 1156
1142 Say N if you are unsure. 1157 Say N if you are unsure.
1143 1158
1159config TORTURE_TEST
1160 tristate
1161 default n
1162
1144config RCU_TORTURE_TEST 1163config RCU_TORTURE_TEST
1145 tristate "torture tests for RCU" 1164 tristate "torture tests for RCU"
1146 depends on DEBUG_KERNEL 1165 depends on DEBUG_KERNEL
1166 select TORTURE_TEST
1147 default n 1167 default n
1148 help 1168 help
1149 This option provides a kernel module that runs torture tests 1169 This option provides a kernel module that runs torture tests
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index 587561d7c035..9b17e810ddc3 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -96,6 +96,7 @@ identify_qemu () {
96 echo qemu-system-ppc64 96 echo qemu-system-ppc64
97 else 97 else
98 echo Cannot figure out what qemu command to use! 1>&2 98 echo Cannot figure out what qemu command to use! 1>&2
99 echo file $1 output: $u
99 # Usually this will be one of /usr/bin/qemu-system-* 100 # Usually this will be one of /usr/bin/qemu-system-*
100 # Use RCU_QEMU_CMD environment variable or appropriate 101 # Use RCU_QEMU_CMD environment variable or appropriate
101 # argument to top-level script. 102 # argument to top-level script.
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
new file mode 100755
index 000000000000..829186e19eb1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
@@ -0,0 +1,51 @@
1#!/bin/bash
2#
3# Analyze a given results directory for locktorture progress.
4#
5# Usage: sh kvm-recheck-lock.sh resdir
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, you can access it online at
19# http://www.gnu.org/licenses/gpl-2.0.html.
20#
21# Copyright (C) IBM Corporation, 2014
22#
23# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24
25i="$1"
26if test -d $i
27then
28 :
29else
30 echo Unreadable results directory: $i
31 exit 1
32fi
33
34configfile=`echo $i | sed -e 's/^.*\///'`
35ncs=`grep "Writes: Total:" $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* Total: //' -e 's/ .*$//'`
36if test -z "$ncs"
37then
38 echo $configfile
39else
40 title="$configfile ------- $ncs acquisitions/releases"
41 dur=`sed -e 's/^.* locktorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
42 if test -z "$dur"
43 then
44 :
45 else
46 ncsps=`awk -v ncs=$ncs -v dur=$dur '
47 BEGIN { print ncs / dur }' < /dev/null`
48 title="$title ($ncsps per second)"
49 fi
50 echo $title
51fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
new file mode 100755
index 000000000000..d75b1dc5ae53
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
@@ -0,0 +1,51 @@
1#!/bin/bash
2#
3# Analyze a given results directory for rcutorture progress.
4#
5# Usage: sh kvm-recheck-rcu.sh resdir
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, you can access it online at
19# http://www.gnu.org/licenses/gpl-2.0.html.
20#
21# Copyright (C) IBM Corporation, 2014
22#
23# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24
25i="$1"
26if test -d $i
27then
28 :
29else
30 echo Unreadable results directory: $i
31 exit 1
32fi
33
34configfile=`echo $i | sed -e 's/^.*\///'`
35ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'`
36if test -z "$ngps"
37then
38 echo $configfile
39else
40 title="$configfile ------- $ngps grace periods"
41 dur=`sed -e 's/^.* rcutorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
42 if test -z "$dur"
43 then
44 :
45 else
46 ngpsps=`awk -v ngps=$ngps -v dur=$dur '
47 BEGIN { print ngps / dur }' < /dev/null`
48 title="$title ($ngpsps per second)"
49 fi
50 echo $title
51fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
index baef09f3469b..a44daaa259a9 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
@@ -1,6 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2# 2#
3# Given the results directories for previous KVM runs of rcutorture, 3# Given the results directories for previous KVM-based torture runs,
4# check the build and console output for errors. Given a directory 4# check the build and console output for errors. Given a directory
5# containing results directories, this recursively checks them all. 5# containing results directories, this recursively checks them all.
6# 6#
@@ -27,11 +27,18 @@
27PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH 27PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
28for rd in "$@" 28for rd in "$@"
29do 29do
30 firsttime=1
30 dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u` 31 dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u`
31 for i in $dirs 32 for i in $dirs
32 do 33 do
33 configfile=`echo $i | sed -e 's/^.*\///'` 34 if test -n "$firsttime"
34 echo $configfile 35 then
36 firsttime=""
37 resdir=`echo $i | sed -e 's,/$,,' -e 's,/[^/]*$,,'`
38 head -1 $resdir/log
39 fi
40 TORTURE_SUITE="`cat $i/../TORTURE_SUITE`"
41 kvm-recheck-${TORTURE_SUITE}.sh $i
35 configcheck.sh $i/.config $i/ConfigFragment 42 configcheck.sh $i/.config $i/ConfigFragment
36 parse-build.sh $i/Make.out $configfile 43 parse-build.sh $i/Make.out $configfile
37 parse-rcutorture.sh $i/console.log $configfile 44 parse-rcutorture.sh $i/console.log $configfile
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 151b23788935..94b28bb37d36 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -6,15 +6,15 @@
6# Execute this in the source tree. Do not run it as a background task 6# Execute this in the source tree. Do not run it as a background task
7# because qemu does not seem to like that much. 7# because qemu does not seem to like that much.
8# 8#
9# Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs 9# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
10# 10#
11# qemu-args defaults to "" -- you will want "-nographic" if running headless. 11# qemu-args defaults to "-nographic", along with arguments specifying the
12# bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0" 12# number of CPUs and other options generated from
13# "initcall_debug debug rcutorture.stat_interval=15" 13# the underlying CPU architecture.
14# "rcutorture.shutdown_secs=$((minutes * 60))" 14# boot_args defaults to value returned by the per_version_boot_params
15# "rcutorture.rcutorture_runnable=1" 15# shell function.
16# 16#
17# Anything you specify for either qemu-args or bootargs is appended to 17# Anything you specify for either qemu-args or boot_args is appended to
18# the default values. The "-smp" value is deduced from the contents of 18# the default values. The "-smp" value is deduced from the contents of
19# the config fragment. 19# the config fragment.
20# 20#
@@ -40,32 +40,34 @@
40 40
41grace=120 41grace=120
42 42
43T=/tmp/kvm-test-1-rcu.sh.$$ 43T=/tmp/kvm-test-1-run.sh.$$
44trap 'rm -rf $T' 0 44trap 'rm -rf $T' 0
45 45
46. $KVM/bin/functions.sh 46. $KVM/bin/functions.sh
47. $KVPATH/ver_functions.sh 47. $KVPATH/ver_functions.sh
48 48
49config_template=${1} 49config_template=${1}
50config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
50title=`echo $config_template | sed -e 's/^.*\///'` 51title=`echo $config_template | sed -e 's/^.*\///'`
51builddir=${2} 52builddir=${2}
52if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" 53if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
53then 54then
54 echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it" 55 echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it"
55 exit 1 56 exit 1
56fi 57fi
57resdir=${3} 58resdir=${3}
58if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" 59if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
59then 60then
60 echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it" 61 echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it"
61 exit 1 62 exit 1
62fi 63fi
63cp $config_template $resdir/ConfigFragment 64cp $config_template $resdir/ConfigFragment
64echo ' ---' `date`: Starting build 65echo ' ---' `date`: Starting build
65echo ' ---' Kconfig fragment at: $config_template >> $resdir/log 66echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
66cat << '___EOF___' >> $T 67if test -r "$config_dir/CFcommon"
67CONFIG_RCU_TORTURE_TEST=y 68then
68___EOF___ 69 cat < $config_dir/CFcommon >> $T
70fi
69# Optimizations below this point 71# Optimizations below this point
70# CONFIG_USB=n 72# CONFIG_USB=n
71# CONFIG_SECURITY=n 73# CONFIG_SECURITY=n
@@ -96,11 +98,23 @@ then
96 cp $builddir/.config $resdir 98 cp $builddir/.config $resdir
97 cp $builddir/arch/x86/boot/bzImage $resdir 99 cp $builddir/arch/x86/boot/bzImage $resdir
98 parse-build.sh $resdir/Make.out $title 100 parse-build.sh $resdir/Make.out $title
101 if test -f $builddir.wait
102 then
103 mv $builddir.wait $builddir.ready
104 fi
99else 105else
100 cp $builddir/Make*.out $resdir 106 cp $builddir/Make*.out $resdir
101 echo Build failed, not running KVM, see $resdir. 107 echo Build failed, not running KVM, see $resdir.
108 if test -f $builddir.wait
109 then
110 mv $builddir.wait $builddir.ready
111 fi
102 exit 1 112 exit 1
103fi 113fi
114while test -f $builddir.ready
115do
116 sleep 1
117done
104minutes=$4 118minutes=$4
105seconds=$(($minutes * 60)) 119seconds=$(($minutes * 60))
106qemu_args=$5 120qemu_args=$5
@@ -111,9 +125,10 @@ kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
111echo ' ---' `date`: Starting kernel 125echo ' ---' `date`: Starting kernel
112 126
113# Determine the appropriate flavor of qemu command. 127# Determine the appropriate flavor of qemu command.
114QEMU="`identify_qemu $builddir/vmlinux.o`" 128QEMU="`identify_qemu $builddir/vmlinux`"
115 129
116# Generate -smp qemu argument. 130# Generate -smp qemu argument.
131qemu_args="-nographic $qemu_args"
117cpu_count=`configNR_CPUS.sh $config_template` 132cpu_count=`configNR_CPUS.sh $config_template`
118vcpus=`identify_qemu_vcpus` 133vcpus=`identify_qemu_vcpus`
119if test $cpu_count -gt $vcpus 134if test $cpu_count -gt $vcpus
@@ -133,12 +148,8 @@ qemu_append="`identify_qemu_append "$QEMU"`"
133 148
134# Pull in Kconfig-fragment boot parameters 149# Pull in Kconfig-fragment boot parameters
135boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" 150boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
136# Generate CPU-hotplug boot parameters 151# Generate kernel-version-specific boot parameters
137boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`" 152boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`"
138# Generate rcu_barrier() boot parameter
139boot_args="`rcutorture_param_n_barrier_cbs "$boot_args"`"
140# Pull in standard rcutorture boot arguments
141boot_args="$boot_args rcutorture.stat_interval=15 rcutorture.shutdown_secs=$seconds rcutorture.rcutorture_runnable=1"
142 153
143echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 154echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
144if test -n "$RCU_BUILDONLY" 155if test -n "$RCU_BUILDONLY"
@@ -188,5 +199,5 @@ then
188fi 199fi
189 200
190cp $builddir/console.log $resdir 201cp $builddir/console.log $resdir
191parse-rcutorture.sh $resdir/console.log $title 202parse-${TORTURE_SUITE}torture.sh $resdir/console.log $title
192parse-console.sh $resdir/console.log $title 203parse-console.sh $resdir/console.log $title
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 1b7923bf6a70..5a78cbf55f06 100644
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -30,14 +30,21 @@
30scriptname=$0 30scriptname=$0
31args="$*" 31args="$*"
32 32
33T=/tmp/kvm.sh.$$
34trap 'rm -rf $T' 0
35mkdir $T
36
33dur=30 37dur=30
38dryrun=""
34KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM 39KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
35PATH=${KVM}/bin:$PATH; export PATH 40PATH=${KVM}/bin:$PATH; export PATH
36builddir="${KVM}/b1" 41builddir="${KVM}/b1"
37RCU_INITRD="$KVM/initrd"; export RCU_INITRD 42RCU_INITRD="$KVM/initrd"; export RCU_INITRD
38RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG 43RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
44TORTURE_SUITE=rcu
39resdir="" 45resdir=""
40configs="" 46configs=""
47cpus=0
41ds=`date +%Y.%m.%d-%H:%M:%S` 48ds=`date +%Y.%m.%d-%H:%M:%S`
42kversion="" 49kversion=""
43 50
@@ -49,7 +56,9 @@ usage () {
49 echo " --builddir absolute-pathname" 56 echo " --builddir absolute-pathname"
50 echo " --buildonly" 57 echo " --buildonly"
51 echo " --configs \"config-file list\"" 58 echo " --configs \"config-file list\""
59 echo " --cpus N"
52 echo " --datestamp string" 60 echo " --datestamp string"
61 echo " --dryrun sched|script"
53 echo " --duration minutes" 62 echo " --duration minutes"
54 echo " --interactive" 63 echo " --interactive"
55 echo " --kmake-arg kernel-make-arguments" 64 echo " --kmake-arg kernel-make-arguments"
@@ -58,8 +67,9 @@ usage () {
58 echo " --no-initrd" 67 echo " --no-initrd"
59 echo " --qemu-args qemu-system-..." 68 echo " --qemu-args qemu-system-..."
60 echo " --qemu-cmd qemu-system-..." 69 echo " --qemu-cmd qemu-system-..."
61 echo " --results absolute-pathname"
62 echo " --relbuilddir relative-pathname" 70 echo " --relbuilddir relative-pathname"
71 echo " --results absolute-pathname"
72 echo " --torture rcu"
63 exit 1 73 exit 1
64} 74}
65 75
@@ -85,11 +95,21 @@ do
85 configs="$2" 95 configs="$2"
86 shift 96 shift
87 ;; 97 ;;
98 --cpus)
99 checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--'
100 cpus=$2
101 shift
102 ;;
88 --datestamp) 103 --datestamp)
89 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' 104 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
90 ds=$2 105 ds=$2
91 shift 106 shift
92 ;; 107 ;;
108 --dryrun)
109 checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--'
110 dryrun=$2
111 shift
112 ;;
93 --duration) 113 --duration)
94 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' 114 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
95 dur=$2 115 dur=$2
@@ -138,6 +158,11 @@ do
138 resdir=$2 158 resdir=$2
139 shift 159 shift
140 ;; 160 ;;
161 --torture)
162 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--'
163 TORTURE_SUITE=$2
164 shift
165 ;;
141 *) 166 *)
142 echo Unknown argument $1 167 echo Unknown argument $1
143 usage 168 usage
@@ -146,7 +171,7 @@ do
146 shift 171 shift
147done 172done
148 173
149CONFIGFRAG=${KVM}/configs; export CONFIGFRAG 174CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
150KVPATH=${CONFIGFRAG}/$kversion; export KVPATH 175KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
151 176
152if test -z "$configs" 177if test -z "$configs"
@@ -157,54 +182,231 @@ fi
157if test -z "$resdir" 182if test -z "$resdir"
158then 183then
159 resdir=$KVM/res 184 resdir=$KVM/res
160 if ! test -e $resdir 185fi
161 then 186
162 mkdir $resdir || : 187if test "$dryrun" = ""
163 fi 188then
164else
165 if ! test -e $resdir 189 if ! test -e $resdir
166 then 190 then
167 mkdir -p "$resdir" || : 191 mkdir -p "$resdir" || :
168 fi 192 fi
169fi 193 mkdir $resdir/$ds
170mkdir $resdir/$ds
171touch $resdir/$ds/log
172echo $scriptname $args >> $resdir/$ds/log
173 194
174pwd > $resdir/$ds/testid.txt 195 # Be noisy only if running the script.
175if test -d .git 196 echo Results directory: $resdir/$ds
176then 197 echo $scriptname $args
177 git status >> $resdir/$ds/testid.txt 198
178 git rev-parse HEAD >> $resdir/$ds/testid.txt 199 touch $resdir/$ds/log
179fi 200 echo $scriptname $args >> $resdir/$ds/log
180builddir=$KVM/b1 201 echo ${TORTURE_SUITE} > $resdir/$ds/TORTURE_SUITE
181if ! test -e $builddir 202
182then 203 pwd > $resdir/$ds/testid.txt
183 mkdir $builddir || : 204 if test -d .git
205 then
206 git status >> $resdir/$ds/testid.txt
207 git rev-parse HEAD >> $resdir/$ds/testid.txt
208 fi
184fi 209fi
185 210
211# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus.
212touch $T/cfgcpu
186for CF in $configs 213for CF in $configs
187do 214do
188 # Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ... 215 if test -f "$CONFIGFRAG/$kversion/$CF"
189 rd=$resdir/$ds/$CF
190 if test -d "${rd}"
191 then 216 then
192 n="`ls -d "${rd}"* | grep '\.[0-9]\+$' | 217 echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu
193 sed -e 's/^.*\.\([0-9]\+\)/\1/' | 218 else
194 sort -k1n | tail -1`" 219 echo "The --configs file $CF does not exist, terminating."
195 if test -z "$n" 220 exit 1
196 then
197 rd="${rd}.2"
198 else
199 n="`expr $n + 1`"
200 rd="${rd}.${n}"
201 fi
202 fi 221 fi
203 mkdir "${rd}"
204 echo Results directory: $rd
205 kvm-test-1-rcu.sh $CONFIGFRAG/$kversion/$CF $builddir $rd $dur "-nographic $RCU_QEMU_ARG" "rcutorture.test_no_idle_hz=1 rcutorture.verbose=1 $RCU_BOOTARGS"
206done 222done
223sort -k2nr $T/cfgcpu > $T/cfgcpu.sort
224
225# Use a greedy bin-packing algorithm, sorting the list accordingly.
226awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus '
227BEGIN {
228 njobs = 0;
229}
230
231{
232 # Read file of tests and corresponding required numbers of CPUs.
233 cf[njobs] = $1;
234 cpus[njobs] = $2;
235 njobs++;
236}
237
238END {
239 alldone = 0;
240 batch = 0;
241 nc = -1;
242
243 # Each pass through the following loop creates on test batch
244 # that can be executed concurrently given ncpus. Note that a
245 # given test that requires more than the available CPUs will run in
246 # their own batch. Such tests just have to make do with what
247 # is available.
248 while (nc != ncpus) {
249 batch++;
250 nc = ncpus;
251
252 # Each pass through the following loop considers one
253 # test for inclusion in the current batch.
254 for (i = 0; i < njobs; i++) {
255 if (done[i])
256 continue; # Already part of a batch.
257 if (nc >= cpus[i] || nc == ncpus) {
258
259 # This test fits into the current batch.
260 done[i] = batch;
261 nc -= cpus[i];
262 if (nc <= 0)
263 break; # Too-big test in its own batch.
264 }
265 }
266 }
267
268 # Dump out the tests in batch order.
269 for (b = 1; b <= batch; b++)
270 for (i = 0; i < njobs; i++)
271 if (done[i] == b)
272 print cf[i], cpus[i];
273}'
274
275# Generate a script to execute the tests in appropriate batches.
276cat << ___EOF___ > $T/script
277TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
278___EOF___
279awk < $T/cfgcpu.pack \
280 -v CONFIGDIR="$CONFIGFRAG/$kversion/" \
281 -v KVM="$KVM" \
282 -v ncpus=$cpus \
283 -v rd=$resdir/$ds/ \
284 -v dur=$dur \
285 -v RCU_QEMU_ARG=$RCU_QEMU_ARG \
286 -v RCU_BOOTARGS=$RCU_BOOTARGS \
287'BEGIN {
288 i = 0;
289}
290
291{
292 cf[i] = $1;
293 cpus[i] = $2;
294 i++;
295}
296
297# Dump out the scripting required to run one test batch.
298function dump(first, pastlast)
299{
300 print "echo ----Start batch: `date`";
301 print "echo ----Start batch: `date` >> " rd "/log";
302 jn=1
303 for (j = first; j < pastlast; j++) {
304 builddir=KVM "/b" jn
305 cpusr[jn] = cpus[j];
306 if (cfrep[cf[j]] == "") {
307 cfr[jn] = cf[j];
308 cfrep[cf[j]] = 1;
309 } else {
310 cfrep[cf[j]]++;
311 cfr[jn] = cf[j] "." cfrep[cf[j]];
312 }
313 if (cpusr[jn] > ncpus && ncpus != 0)
314 ovf = "(!)";
315 else
316 ovf = "";
317 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
318 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` >> " rd "/log";
319 print "rm -f " builddir ".*";
320 print "touch " builddir ".wait";
321 print "mkdir " builddir " > /dev/null 2>&1 || :";
322 print "mkdir " rd cfr[jn] " || :";
323 print "kvm-test-1-run.sh " CONFIGDIR cf[j], builddir, rd cfr[jn], dur " \"" RCU_QEMU_ARG "\" \"" RCU_BOOTARGS "\" > " rd cfr[jn] "/kvm-test-1-run.sh.out 2>&1 &"
324 print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date`";
325 print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` >> " rd "/log";
326 print "while test -f " builddir ".wait"
327 print "do"
328 print "\tsleep 1"
329 print "done"
330 print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date`";
331 print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` >> " rd "/log";
332 jn++;
333 }
334 for (j = 1; j < jn; j++) {
335 builddir=KVM "/b" j
336 print "rm -f " builddir ".ready"
337 print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`";
338 print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
339 }
340 print "wait"
341 print "echo ---- All kernel runs complete. `date`";
342 print "echo ---- All kernel runs complete. `date` >> " rd "/log";
343 for (j = 1; j < jn; j++) {
344 builddir=KVM "/b" j
345 print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results:";
346 print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: >> " rd "/log";
347 print "cat " rd cfr[j] "/kvm-test-1-run.sh.out";
348 print "cat " rd cfr[j] "/kvm-test-1-run.sh.out >> " rd "/log";
349 }
350}
351
352END {
353 njobs = i;
354 nc = ncpus;
355 first = 0;
356
357 # Each pass through the following loop considers one test.
358 for (i = 0; i < njobs; i++) {
359 if (ncpus == 0) {
360 # Sequential test specified, each test its own batch.
361 dump(i, i + 1);
362 first = i;
363 } else if (nc < cpus[i] && i != 0) {
364 # Out of CPUs, dump out a batch.
365 dump(first, i);
366 first = i;
367 nc = ncpus;
368 }
369 # Account for the CPUs needed by the current test.
370 nc -= cpus[i];
371 }
372 # Dump the last batch.
373 if (ncpus != 0)
374 dump(first, i);
375}' >> $T/script
376
377if test "$dryrun" = script
378then
379 # Dump out the script, but define the environment variables that
380 # it needs to run standalone.
381 echo CONFIGFRAG="$CONFIGFRAG; export CONFIGFRAG"
382 echo KVM="$KVM; export KVM"
383 echo KVPATH="$KVPATH; export KVPATH"
384 echo PATH="$PATH; export PATH"
385 echo RCU_BUILDONLY="$RCU_BUILDONLY; export RCU_BUILDONLY"
386 echo RCU_INITRD="$RCU_INITRD; export RCU_INITRD"
387 echo RCU_KMAKE_ARG="$RCU_KMAKE_ARG; export RCU_KMAKE_ARG"
388 echo RCU_QEMU_CMD="$RCU_QEMU_CMD; export RCU_QEMU_CMD"
389 echo RCU_QEMU_INTERACTIVE="$RCU_QEMU_INTERACTIVE; export RCU_QEMU_INTERACTIVE"
390 echo RCU_QEMU_MAC="$RCU_QEMU_MAC; export RCU_QEMU_MAC"
391 echo "mkdir -p "$resdir" || :"
392 echo "mkdir $resdir/$ds"
393 cat $T/script
394 exit 0
395elif test "$dryrun" = sched
396then
397 # Extract the test run schedule from the script.
398 egrep 'start batch|Starting build\.' $T/script |
399 sed -e 's/:.*$//' -e 's/^echo //'
400 exit 0
401else
402 # Not a dryru, so run the script.
403 sh $T/script
404fi
405
207# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier 406# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier
208 407
408echo
409echo
209echo " --- `date` Test summary:" 410echo " --- `date` Test summary:"
411echo Results directory: $resdir/$ds
210kvm-recheck.sh $resdir/$ds 412kvm-recheck.sh $resdir/$ds
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED b/tools/testing/selftests/rcutorture/configs/lock/BUSTED
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
new file mode 100644
index 000000000000..6386c15e9770
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
@@ -0,0 +1 @@
locktorture.torture_type=lock_busted
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
new file mode 100644
index 000000000000..a061b22d1892
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
@@ -0,0 +1 @@
LOCK01
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFcommon b/tools/testing/selftests/rcutorture/configs/lock/CFcommon
new file mode 100644
index 000000000000..e372dc269254
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFcommon
@@ -0,0 +1,2 @@
1CONFIG_LOCK_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK01 b/tools/testing/selftests/rcutorture/configs/lock/LOCK01
new file mode 100644
index 000000000000..a9625e3d6cd9
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK01
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=8
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
new file mode 100644
index 000000000000..9746ea1cd6c7
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
@@ -0,0 +1,43 @@
1#!/bin/bash
2#
3# Kernel-version-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2014
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# locktorture_param_onoff bootparam-string config-file
24#
25# Adds onoff locktorture module parameters to kernels having it.
26locktorture_param_onoff () {
27 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
28 then
29 echo CPU-hotplug kernel, adding locktorture onoff. 1>&2
30 echo locktorture.onoff_interval=3 locktorture.onoff_holdoff=30
31 fi
32}
33
34# per_version_boot_params bootparam-string config-file seconds
35#
36# Adds per-version torture-module parameters to kernels supporting them.
37per_version_boot_params () {
38 echo $1 `locktorture_param_onoff "$1" "$2"` \
39 locktorture.stat_interval=15 \
40 locktorture.shutdown_secs=$3 \
41 locktorture.locktorture_runnable=1 \
42 locktorture.verbose=1
43}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
new file mode 100644
index 000000000000..48d8a245c7fa
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
@@ -0,0 +1,7 @@
1CONFIG_RCU_TRACE=n
2CONFIG_SMP=y
3CONFIG_NR_CPUS=4
4CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=n
6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
new file mode 100644
index 000000000000..6804f9dcfc1b
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
@@ -0,0 +1 @@
rcutorture.torture_type=rcu_busted
diff --git a/tools/testing/selftests/rcutorture/configs/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index cd3d29cb0a47..cd3d29cb0a47 100644
--- a/tools/testing/selftests/rcutorture/configs/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
new file mode 100644
index 000000000000..d2d2a86139db
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
@@ -0,0 +1,2 @@
1CONFIG_RCU_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
index 10a0e27f4c75..9fbb41b9b314 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-N
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
@@ -1,8 +1,7 @@
1CONFIG_RCU_TRACE=n 1CONFIG_RCU_TRACE=n
2CONFIG_SMP=y 2CONFIG_SMP=y
3CONFIG_NR_CPUS=8 3CONFIG_NR_CPUS=4
4CONFIG_HOTPLUG_CPU=y 4CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=y 5CONFIG_PREEMPT_NONE=y
6CONFIG_PREEMPT_VOLUNTARY=n 6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=n 7CONFIG_PREEMPT=n
8CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot
index 238bfe3bd0cc..238bfe3bd0cc 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
index 6650e00c6d91..4b6f272dba27 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-P
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
@@ -5,4 +5,3 @@ CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=n 5CONFIG_PREEMPT_NONE=n
6CONFIG_PREEMPT_VOLUNTARY=n 6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=y 7CONFIG_PREEMPT=y
8CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot
index 238bfe3bd0cc..238bfe3bd0cc 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
index 0c2823f21712..0a63e073a00c 100644
--- a/tools/testing/selftests/rcutorture/configs/TINY01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=n
10CONFIG_DEBUG_LOCK_ALLOC=n 10CONFIG_DEBUG_LOCK_ALLOC=n
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=n 12CONFIG_PREEMPT_COUNT=n
13CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index e5072d7528b6..f4feaee40776 100644
--- a/tools/testing/selftests/rcutorture/configs/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=y
10CONFIG_DEBUG_LOCK_ALLOC=y 10CONFIG_DEBUG_LOCK_ALLOC=y
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=y 12CONFIG_PREEMPT_COUNT=y
13CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index 141119a00044..9c827ec59a97 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
20CONFIG_RCU_CPU_STALL_VERBOSE=n 20CONFIG_RCU_CPU_STALL_VERBOSE=n
21CONFIG_RCU_BOOST=n 21CONFIG_RCU_BOOST=n
22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
23CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
index 0fc8a3428938..0fc8a3428938 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE01.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index 2d4d09608528..1a777b5f68b5 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -7,7 +7,7 @@ CONFIG_PREEMPT=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=n 10CONFIG_RCU_FAST_NO_HZ=n
11CONFIG_RCU_TRACE=n 11CONFIG_RCU_TRACE=n
12CONFIG_HOTPLUG_CPU=n 12CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n 13CONFIG_SUSPEND=n
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=y 23CONFIG_RCU_CPU_STALL_VERBOSE=y
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index a47de5be8a04..c1f111c1561b 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_VERBOSE=n
20CONFIG_RCU_BOOST=y 20CONFIG_RCU_BOOST=y
21CONFIG_RCU_BOOST_PRIO=2 21CONFIG_RCU_BOOST_PRIO=2
22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
23CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 8d839b86a1d5..7dbd27ce17a4 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=n
22CONFIG_RCU_CPU_STALL_INFO=y 22CONFIG_RCU_CPU_STALL_INFO=y
23CONFIG_RCU_CPU_STALL_VERBOSE=y 23CONFIG_RCU_CPU_STALL_VERBOSE=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
25CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
index 0fc8a3428938..0fc8a3428938 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE04.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index b5ba72ea25cb..d0f32e574743 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=y
22CONFIG_RCU_CPU_STALL_INFO=n 22CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
25CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
index 3b42b8b033cd..3b42b8b033cd 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE05.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index 7c95ab48d29f..2e477dfb9c57 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -23,4 +23,3 @@ CONFIG_PROVE_RCU_DELAY=n
23CONFIG_RCU_CPU_STALL_INFO=n 23CONFIG_RCU_CPU_STALL_INFO=n
24CONFIG_RCU_CPU_STALL_VERBOSE=n 24CONFIG_RCU_CPU_STALL_VERBOSE=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 1467404bdec1..042f86ef362a 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -21,4 +21,3 @@ CONFIG_PROVE_RCU_DELAY=n
21CONFIG_RCU_CPU_STALL_INFO=y 21CONFIG_RCU_CPU_STALL_INFO=y
22CONFIG_RCU_CPU_STALL_VERBOSE=n 22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
24CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
index 7d097a61ac2a..3438cee1e3c5 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
index 442c4e450ab3..bf4523d3e44c 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE08-T
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
index 0d1ec0d3dfee..81e4f7c0bf0b 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE09
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
@@ -18,4 +18,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
18CONFIG_RCU_CPU_STALL_VERBOSE=n 18CONFIG_RCU_CPU_STALL_VERBOSE=n
19CONFIG_RCU_BOOST=n 19CONFIG_RCU_BOOST=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
index d3ef873eb6e7..d3ef873eb6e7 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
index f72402d7c13d..f72402d7c13d 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
index e8052539af54..5ace37a89780 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
@@ -20,16 +20,14 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcutorture_param_n_barrier_cbs bootparam-string 23# per_version_boot_params bootparam-string config-file seconds
24# 24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it. 25# Adds per-version torture-module parameters to kernels supporting them.
26rcutorture_param_n_barrier_cbs () { 26# Which old kernels do not.
27 echo $1 27per_version_boot_params () {
28} 28 echo rcutorture.stat_interval=15 \
29 29 rcutorture.shutdown_secs=$3 \
30# rcutorture_param_onoff bootparam-string config-file 30 rcutorture.rcutorture_runnable=1 \
31# 31 rcutorture.test_no_idle_hz=1 \
32# Adds onoff rcutorture module parameters to kernels having it. 32 rcutorture.verbose=1
33rcutorture_param_onoff () {
34 echo $1
35} 33}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
index da4cbc668f2a..da4cbc668f2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
index 0ccc36d72738..0ccc36d72738 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
index 3f640cf84973..3f640cf84973 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
index 285da2dd8ac3..285da2dd8ac3 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
index f4c9175828bf..f4c9175828bf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
index 77a8c5b75763..77a8c5b75763 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
index 0eecebc6e95f..0eecebc6e95f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
index 0eecebc6e95f..0eecebc6e95f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
index 588bc70420cd..588bc70420cd 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
index 5e40eadea777..bae55692ce6e 100644
--- a/tools/testing/selftests/rcutorture/configs/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
@@ -20,18 +20,6 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcutorture_param_n_barrier_cbs bootparam-string
24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
26rcutorture_param_n_barrier_cbs () {
27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then
29 echo $1
30 else
31 echo $1 rcutorture.n_barrier_cbs=4
32 fi
33}
34
35# rcutorture_param_onoff bootparam-string config-file 23# rcutorture_param_onoff bootparam-string config-file
36# 24#
37# Adds onoff rcutorture module parameters to kernels having it. 25# Adds onoff rcutorture module parameters to kernels having it.
@@ -39,8 +27,18 @@ rcutorture_param_onoff () {
39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 27 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
40 then 28 then
41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 29 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
42 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 30 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
43 else
44 echo $1
45 fi 31 fi
46} 32}
33
34# per_version_boot_params bootparam-string config-file seconds
35#
36# Adds per-version torture-module parameters to kernels supporting them.
37per_version_boot_params () {
38 echo $1 `rcutorture_param_onoff "$1" "$2"` \
39 rcutorture.stat_interval=15 \
40 rcutorture.shutdown_secs=$3 \
41 rcutorture.rcutorture_runnable=1 \
42 rcutorture.test_no_idle_hz=1 \
43 rcutorture.verbose=1
44}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
index 6a5f13aab44d..8977d8d31b19 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
@@ -26,9 +26,9 @@
26rcutorture_param_n_barrier_cbs () { 26rcutorture_param_n_barrier_cbs () {
27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs" 27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then 28 then
29 echo $1 29 :
30 else 30 else
31 echo $1 rcutorture.n_barrier_cbs=4 31 echo rcutorture.n_barrier_cbs=4
32 fi 32 fi
33} 33}
34 34
@@ -38,9 +38,20 @@ rcutorture_param_n_barrier_cbs () {
38rcutorture_param_onoff () { 38rcutorture_param_onoff () {
39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
40 then 40 then
41 echo CPU-hotplug kernel, adding rcutorture onoff. 41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
42 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 42 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
43 else
44 echo $1
45 fi 43 fi
46} 44}
45
46# per_version_boot_params bootparam-string config-file seconds
47#
48# Adds per-version torture-module parameters to kernels supporting them.
49per_version_boot_params () {
50 echo $1 `rcutorture_param_onoff "$1" "$2"` \
51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1
57}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
index c37432f3572c..8977d8d31b19 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
@@ -24,7 +24,12 @@
24# 24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it. 25# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
26rcutorture_param_n_barrier_cbs () { 26rcutorture_param_n_barrier_cbs () {
27 echo $1 27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then
29 :
30 else
31 echo rcutorture.n_barrier_cbs=4
32 fi
28} 33}
29 34
30# rcutorture_param_onoff bootparam-string config-file 35# rcutorture_param_onoff bootparam-string config-file
@@ -33,9 +38,20 @@ rcutorture_param_n_barrier_cbs () {
33rcutorture_param_onoff () { 38rcutorture_param_onoff () {
34 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
35 then 40 then
36 echo CPU-hotplug kernel, adding rcutorture onoff. 41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
37 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 42 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
38 else
39 echo $1
40 fi 43 fi
41} 44}
45
46# per_version_boot_params bootparam-string config-file seconds
47#
48# Adds per-version torture-module parameters to kernels supporting them.
49per_version_boot_params () {
50 echo $1 `rcutorture_param_onoff "$1" "$2"` \
51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1
57}
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index adbb76cffb49..adbb76cffb49 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt