aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu/rcutorture.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-01-28 18:29:21 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-02-23 12:01:05 -0500
commit3808dc9fab05913060626d7f0edd0f195cb9dcab (patch)
tree5db578f420dc657197fd34b3a9a2c20bf79e0de3 /kernel/rcu/rcutorture.c
parentf67a33561e6e5463b548219df98130da95f2e4a7 (diff)
rcutorture: Abstract torture_shuffle()
The torture_shuffle() function forces each CPU in turn to go idle periodically in order to check for problems interacting with per-CPU variables and with dyntick-idle mode. Because this sort of debugging is not specific to RCU, this commit abstracts that functionality. This in turn requires abstracting some additional infrastructure. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/rcu/rcutorture.c')
-rw-r--r--kernel/rcu/rcutorture.c124
1 files changed, 15 insertions, 109 deletions
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index a868758a6f9c..0380696f1844 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -106,7 +106,6 @@ static struct task_struct *writer_task;
106static struct task_struct **fakewriter_tasks; 106static struct task_struct **fakewriter_tasks;
107static struct task_struct **reader_tasks; 107static struct task_struct **reader_tasks;
108static struct task_struct *stats_task; 108static struct task_struct *stats_task;
109static struct task_struct *shuffler_task;
110static struct task_struct *stutter_task; 109static struct task_struct *stutter_task;
111static struct task_struct *fqs_task; 110static struct task_struct *fqs_task;
112static struct task_struct *boost_tasks[NR_CPUS]; 111static struct task_struct *boost_tasks[NR_CPUS];
@@ -161,7 +160,6 @@ static int max_online;
161static long n_barrier_attempts; 160static long n_barrier_attempts;
162static long n_barrier_successes; 161static long n_barrier_successes;
163static struct list_head rcu_torture_removed; 162static struct list_head rcu_torture_removed;
164static cpumask_var_t shuffle_tmp_mask;
165 163
166static int stutter_pause_test; 164static int stutter_pause_test;
167 165
@@ -1080,90 +1078,6 @@ rcu_torture_stats(void *arg)
1080 return 0; 1078 return 0;
1081} 1079}
1082 1080
1083static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
1084
1085/* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
1086 * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
1087 */
1088static void rcu_torture_shuffle_tasks(void)
1089{
1090 int i;
1091
1092 cpumask_setall(shuffle_tmp_mask);
1093 get_online_cpus();
1094
1095 /* No point in shuffling if there is only one online CPU (ex: UP) */
1096 if (num_online_cpus() == 1) {
1097 put_online_cpus();
1098 return;
1099 }
1100
1101 if (rcu_idle_cpu != -1)
1102 cpumask_clear_cpu(rcu_idle_cpu, shuffle_tmp_mask);
1103
1104 set_cpus_allowed_ptr(current, shuffle_tmp_mask);
1105
1106 if (reader_tasks) {
1107 for (i = 0; i < nrealreaders; i++)
1108 if (reader_tasks[i])
1109 set_cpus_allowed_ptr(reader_tasks[i],
1110 shuffle_tmp_mask);
1111 }
1112 if (fakewriter_tasks) {
1113 for (i = 0; i < nfakewriters; i++)
1114 if (fakewriter_tasks[i])
1115 set_cpus_allowed_ptr(fakewriter_tasks[i],
1116 shuffle_tmp_mask);
1117 }
1118 if (writer_task)
1119 set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
1120 if (stats_task)
1121 set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
1122 if (stutter_task)
1123 set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
1124 if (fqs_task)
1125 set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
1126 if (shutdown_task)
1127 set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
1128#ifdef CONFIG_HOTPLUG_CPU
1129 if (onoff_task)
1130 set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
1131#endif /* #ifdef CONFIG_HOTPLUG_CPU */
1132 if (stall_task)
1133 set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
1134 if (barrier_cbs_tasks)
1135 for (i = 0; i < n_barrier_cbs; i++)
1136 if (barrier_cbs_tasks[i])
1137 set_cpus_allowed_ptr(barrier_cbs_tasks[i],
1138 shuffle_tmp_mask);
1139 if (barrier_task)
1140 set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
1141
1142 if (rcu_idle_cpu == -1)
1143 rcu_idle_cpu = num_online_cpus() - 1;
1144 else
1145 rcu_idle_cpu--;
1146
1147 put_online_cpus();
1148}
1149
1150/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
1151 * system to become idle at a time and cut off its timer ticks. This is meant
1152 * to test the support for such tickless idle CPU in RCU.
1153 */
1154static int
1155rcu_torture_shuffle(void *arg)
1156{
1157 VERBOSE_TOROUT_STRING("rcu_torture_shuffle task started");
1158 do {
1159 schedule_timeout_interruptible(shuffle_interval * HZ);
1160 rcu_torture_shuffle_tasks();
1161 torture_shutdown_absorb("rcu_torture_shuffle");
1162 } while (!kthread_should_stop());
1163 VERBOSE_TOROUT_STRING("rcu_torture_shuffle task stopping");
1164 return 0;
1165}
1166
1167/* Cause the rcutorture test to "stutter", starting and stopping all 1081/* Cause the rcutorture test to "stutter", starting and stopping all
1168 * threads periodically. 1082 * threads periodically.
1169 */ 1083 */
@@ -1397,6 +1311,7 @@ rcu_torture_onoff_init(void)
1397 onoff_task = NULL; 1311 onoff_task = NULL;
1398 return ret; 1312 return ret;
1399 } 1313 }
1314 torture_shuffle_task_register(onoff_task);
1400 return 0; 1315 return 0;
1401} 1316}
1402 1317
@@ -1468,6 +1383,7 @@ static int __init rcu_torture_stall_init(void)
1468 stall_task = NULL; 1383 stall_task = NULL;
1469 return ret; 1384 return ret;
1470 } 1385 }
1386 torture_shuffle_task_register(stall_task);
1471 return 0; 1387 return 0;
1472} 1388}
1473 1389
@@ -1594,6 +1510,7 @@ static int rcu_torture_barrier_init(void)
1594 barrier_cbs_tasks[i] = NULL; 1510 barrier_cbs_tasks[i] = NULL;
1595 return ret; 1511 return ret;
1596 } 1512 }
1513 torture_shuffle_task_register(barrier_cbs_tasks[i]);
1597 } 1514 }
1598 barrier_task = kthread_run(rcu_torture_barrier, NULL, 1515 barrier_task = kthread_run(rcu_torture_barrier, NULL,
1599 "rcu_torture_barrier"); 1516 "rcu_torture_barrier");
@@ -1602,6 +1519,7 @@ static int rcu_torture_barrier_init(void)
1602 VERBOSE_TOROUT_ERRSTRING("Failed to create rcu_torture_barrier"); 1519 VERBOSE_TOROUT_ERRSTRING("Failed to create rcu_torture_barrier");
1603 barrier_task = NULL; 1520 barrier_task = NULL;
1604 } 1521 }
1522 torture_shuffle_task_register(barrier_task);
1605 return 0; 1523 return 0;
1606} 1524}
1607 1525
@@ -1674,6 +1592,8 @@ rcu_torture_cleanup(void)
1674 fullstop = FULLSTOP_RMMOD; 1592 fullstop = FULLSTOP_RMMOD;
1675 mutex_unlock(&fullstop_mutex); 1593 mutex_unlock(&fullstop_mutex);
1676 unregister_reboot_notifier(&rcutorture_shutdown_nb); 1594 unregister_reboot_notifier(&rcutorture_shutdown_nb);
1595
1596 torture_shuffle_cleanup(); /* Must be first task cleaned up. */
1677 rcu_torture_barrier_cleanup(); 1597 rcu_torture_barrier_cleanup();
1678 rcu_torture_stall_cleanup(); 1598 rcu_torture_stall_cleanup();
1679 if (stutter_task) { 1599 if (stutter_task) {
@@ -1681,12 +1601,6 @@ rcu_torture_cleanup(void)
1681 kthread_stop(stutter_task); 1601 kthread_stop(stutter_task);
1682 } 1602 }
1683 stutter_task = NULL; 1603 stutter_task = NULL;
1684 if (shuffler_task) {
1685 VERBOSE_TOROUT_STRING("Stopping rcu_torture_shuffle task");
1686 kthread_stop(shuffler_task);
1687 free_cpumask_var(shuffle_tmp_mask);
1688 }
1689 shuffler_task = NULL;
1690 1604
1691 if (writer_task) { 1605 if (writer_task) {
1692 VERBOSE_TOROUT_STRING("Stopping rcu_torture_writer task"); 1606 VERBOSE_TOROUT_STRING("Stopping rcu_torture_writer task");
@@ -1904,6 +1818,7 @@ rcu_torture_init(void)
1904 writer_task = NULL; 1818 writer_task = NULL;
1905 goto unwind; 1819 goto unwind;
1906 } 1820 }
1821 torture_shuffle_task_register(writer_task);
1907 wake_up_process(writer_task); 1822 wake_up_process(writer_task);
1908 fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), 1823 fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
1909 GFP_KERNEL); 1824 GFP_KERNEL);
@@ -1922,6 +1837,7 @@ rcu_torture_init(void)
1922 fakewriter_tasks[i] = NULL; 1837 fakewriter_tasks[i] = NULL;
1923 goto unwind; 1838 goto unwind;
1924 } 1839 }
1840 torture_shuffle_task_register(fakewriter_tasks[i]);
1925 } 1841 }
1926 reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]), 1842 reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
1927 GFP_KERNEL); 1843 GFP_KERNEL);
@@ -1940,6 +1856,7 @@ rcu_torture_init(void)
1940 reader_tasks[i] = NULL; 1856 reader_tasks[i] = NULL;
1941 goto unwind; 1857 goto unwind;
1942 } 1858 }
1859 torture_shuffle_task_register(reader_tasks[i]);
1943 } 1860 }
1944 if (stat_interval > 0) { 1861 if (stat_interval > 0) {
1945 VERBOSE_TOROUT_STRING("Creating rcu_torture_stats task"); 1862 VERBOSE_TOROUT_STRING("Creating rcu_torture_stats task");
@@ -1951,26 +1868,12 @@ rcu_torture_init(void)
1951 stats_task = NULL; 1868 stats_task = NULL;
1952 goto unwind; 1869 goto unwind;
1953 } 1870 }
1871 torture_shuffle_task_register(stats_task);
1954 } 1872 }
1955 if (test_no_idle_hz) { 1873 if (test_no_idle_hz) {
1956 rcu_idle_cpu = num_online_cpus() - 1; 1874 firsterr = torture_shuffle_init(shuffle_interval * HZ);
1957 1875 if (firsterr)
1958 if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
1959 firsterr = -ENOMEM;
1960 VERBOSE_TOROUT_ERRSTRING("Failed to alloc mask");
1961 goto unwind; 1876 goto unwind;
1962 }
1963
1964 /* Create the shuffler thread */
1965 shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
1966 "rcu_torture_shuffle");
1967 if (IS_ERR(shuffler_task)) {
1968 free_cpumask_var(shuffle_tmp_mask);
1969 firsterr = PTR_ERR(shuffler_task);
1970 VERBOSE_TOROUT_ERRSTRING("Failed to create shuffler");
1971 shuffler_task = NULL;
1972 goto unwind;
1973 }
1974 } 1877 }
1975 if (stutter < 0) 1878 if (stutter < 0)
1976 stutter = 0; 1879 stutter = 0;
@@ -1984,6 +1887,7 @@ rcu_torture_init(void)
1984 stutter_task = NULL; 1887 stutter_task = NULL;
1985 goto unwind; 1888 goto unwind;
1986 } 1889 }
1890 torture_shuffle_task_register(stutter_task);
1987 } 1891 }
1988 if (fqs_duration < 0) 1892 if (fqs_duration < 0)
1989 fqs_duration = 0; 1893 fqs_duration = 0;
@@ -1997,6 +1901,7 @@ rcu_torture_init(void)
1997 fqs_task = NULL; 1901 fqs_task = NULL;
1998 goto unwind; 1902 goto unwind;
1999 } 1903 }
1904 torture_shuffle_task_register(fqs_task);
2000 } 1905 }
2001 if (test_boost_interval < 1) 1906 if (test_boost_interval < 1)
2002 test_boost_interval = 1; 1907 test_boost_interval = 1;
@@ -2027,6 +1932,7 @@ rcu_torture_init(void)
2027 shutdown_task = NULL; 1932 shutdown_task = NULL;
2028 goto unwind; 1933 goto unwind;
2029 } 1934 }
1935 torture_shuffle_task_register(shutdown_task);
2030 wake_up_process(shutdown_task); 1936 wake_up_process(shutdown_task);
2031 } 1937 }
2032 i = rcu_torture_onoff_init(); 1938 i = rcu_torture_onoff_init();