aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-02-20 20:51:45 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-04-30 13:48:18 -0400
commitfae4b54f28f034d228fa3bfc98858c698b64e89c (patch)
tree1259258956ba9d30eba6360083214e145ec19813
parent37e377d2823e03528cb64f435d7c0e30b1c668eb (diff)
rcu: Introduce rcutorture testing for rcu_barrier()
Although rcutorture does invoke rcu_barrier() and friends, it cannot really be called a torture test given that it invokes them only once at the end of the test. This commit therefore introduces heavy-duty rcutorture testing for rcu_barrier(), which may be carried out concurrently with normal rcutorture testing. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--Documentation/RCU/torture.txt15
-rw-r--r--kernel/rcutorture.c194
2 files changed, 200 insertions, 9 deletions
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index 375d3fb71437..4ddf3913fd8c 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -47,6 +47,16 @@ irqreader Says to invoke RCU readers from irq level. This is currently
47 permit this. (Or, more accurately, variants of RCU that do 47 permit this. (Or, more accurately, variants of RCU that do
48 -not- permit this know to ignore this variable.) 48 -not- permit this know to ignore this variable.)
49 49
50n_barrier_cbs If this is nonzero, RCU barrier testing will be conducted,
51 in which case n_barrier_cbs specifies the number of
52 RCU callbacks (and corresponding kthreads) to use for
53 this testing. The value cannot be negative. If you
54 specify this to be non-zero when torture_type indicates a
55 synchronous RCU implementation (one for which a member of
56 the synchronize_rcu() rather than the call_rcu() family is
57 used -- see the documentation for torture_type below), an
58 error will be reported and no testing will be carried out.
59
50nfakewriters This is the number of RCU fake writer threads to run. Fake 60nfakewriters This is the number of RCU fake writer threads to run. Fake
51 writer threads repeatedly use the synchronous "wait for 61 writer threads repeatedly use the synchronous "wait for
52 current readers" function of the interface selected by 62 current readers" function of the interface selected by
@@ -188,7 +198,7 @@ OUTPUT
188The statistics output is as follows: 198The statistics output is as follows:
189 199
190 rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4 200 rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
191 rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767 201 rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
192 rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0 202 rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0
193 rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0 203 rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0
194 rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0 204 rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
@@ -230,6 +240,9 @@ o "rtmbe": A non-zero value indicates that rcutorture believes that
230 rcu_assign_pointer() and rcu_dereference() are not working 240 rcu_assign_pointer() and rcu_dereference() are not working
231 correctly. This value should be zero. 241 correctly. This value should be zero.
232 242
243o "rtbe": A non-zero value indicates that one of the rcu_barrier()
244 family of functions is not working correctly.
245
233o "rtbke": rcutorture was unable to create the real-time kthreads 246o "rtbke": rcutorture was unable to create the real-time kthreads
234 used to force RCU priority inversion. This value should be zero. 247 used to force RCU priority inversion. This value should be zero.
235 248
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 1463a0636443..8cd262b41499 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -64,6 +64,7 @@ static int irqreader = 1; /* RCU readers from irq (timers). */
64static int fqs_duration; /* Duration of bursts (us), 0 to disable. */ 64static int fqs_duration; /* Duration of bursts (us), 0 to disable. */
65static int fqs_holdoff; /* Hold time within burst (us). */ 65static int fqs_holdoff; /* Hold time within burst (us). */
66static int fqs_stutter = 3; /* Wait time between bursts (s). */ 66static int fqs_stutter = 3; /* Wait time between bursts (s). */
67static int n_barrier_cbs; /* Number of callbacks to test RCU barriers. */
67static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */ 68static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */
68static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */ 69static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */
69static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */ 70static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */
@@ -96,6 +97,8 @@ module_param(fqs_holdoff, int, 0444);
96MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)"); 97MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
97module_param(fqs_stutter, int, 0444); 98module_param(fqs_stutter, int, 0444);
98MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)"); 99MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
100module_param(n_barrier_cbs, int, 0444);
101MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing");
99module_param(onoff_interval, int, 0444); 102module_param(onoff_interval, int, 0444);
100MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable"); 103MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
101module_param(onoff_holdoff, int, 0444); 104module_param(onoff_holdoff, int, 0444);
@@ -139,6 +142,8 @@ static struct task_struct *shutdown_task;
139static struct task_struct *onoff_task; 142static struct task_struct *onoff_task;
140#endif /* #ifdef CONFIG_HOTPLUG_CPU */ 143#endif /* #ifdef CONFIG_HOTPLUG_CPU */
141static struct task_struct *stall_task; 144static struct task_struct *stall_task;
145static struct task_struct **barrier_cbs_tasks;
146static struct task_struct *barrier_task;
142 147
143#define RCU_TORTURE_PIPE_LEN 10 148#define RCU_TORTURE_PIPE_LEN 10
144 149
@@ -164,6 +169,7 @@ static atomic_t n_rcu_torture_alloc_fail;
164static atomic_t n_rcu_torture_free; 169static atomic_t n_rcu_torture_free;
165static atomic_t n_rcu_torture_mberror; 170static atomic_t n_rcu_torture_mberror;
166static atomic_t n_rcu_torture_error; 171static atomic_t n_rcu_torture_error;
172static long n_rcu_torture_barrier_error;
167static long n_rcu_torture_boost_ktrerror; 173static long n_rcu_torture_boost_ktrerror;
168static long n_rcu_torture_boost_rterror; 174static long n_rcu_torture_boost_rterror;
169static long n_rcu_torture_boost_failure; 175static long n_rcu_torture_boost_failure;
@@ -173,6 +179,8 @@ static long n_offline_attempts;
173static long n_offline_successes; 179static long n_offline_successes;
174static long n_online_attempts; 180static long n_online_attempts;
175static long n_online_successes; 181static long n_online_successes;
182static long n_barrier_attempts;
183static long n_barrier_successes;
176static struct list_head rcu_torture_removed; 184static struct list_head rcu_torture_removed;
177static cpumask_var_t shuffle_tmp_mask; 185static cpumask_var_t shuffle_tmp_mask;
178 186
@@ -197,6 +205,10 @@ static unsigned long shutdown_time; /* jiffies to system shutdown. */
197static unsigned long boost_starttime; /* jiffies of next boost test start. */ 205static unsigned long boost_starttime; /* jiffies of next boost test start. */
198DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */ 206DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
199 /* and boost task create/destroy. */ 207 /* and boost task create/destroy. */
208static atomic_t barrier_cbs_count; /* Barrier callbacks registered. */
209static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
210static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
211static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
200 212
201/* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */ 213/* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */
202 214
@@ -327,6 +339,7 @@ struct rcu_torture_ops {
327 int (*completed)(void); 339 int (*completed)(void);
328 void (*deferred_free)(struct rcu_torture *p); 340 void (*deferred_free)(struct rcu_torture *p);
329 void (*sync)(void); 341 void (*sync)(void);
342 void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
330 void (*cb_barrier)(void); 343 void (*cb_barrier)(void);
331 void (*fqs)(void); 344 void (*fqs)(void);
332 int (*stats)(char *page); 345 int (*stats)(char *page);
@@ -417,6 +430,7 @@ static struct rcu_torture_ops rcu_ops = {
417 .completed = rcu_torture_completed, 430 .completed = rcu_torture_completed,
418 .deferred_free = rcu_torture_deferred_free, 431 .deferred_free = rcu_torture_deferred_free,
419 .sync = synchronize_rcu, 432 .sync = synchronize_rcu,
433 .call = call_rcu,
420 .cb_barrier = rcu_barrier, 434 .cb_barrier = rcu_barrier,
421 .fqs = rcu_force_quiescent_state, 435 .fqs = rcu_force_quiescent_state,
422 .stats = NULL, 436 .stats = NULL,
@@ -460,6 +474,7 @@ static struct rcu_torture_ops rcu_sync_ops = {
460 .completed = rcu_torture_completed, 474 .completed = rcu_torture_completed,
461 .deferred_free = rcu_sync_torture_deferred_free, 475 .deferred_free = rcu_sync_torture_deferred_free,
462 .sync = synchronize_rcu, 476 .sync = synchronize_rcu,
477 .call = NULL,
463 .cb_barrier = NULL, 478 .cb_barrier = NULL,
464 .fqs = rcu_force_quiescent_state, 479 .fqs = rcu_force_quiescent_state,
465 .stats = NULL, 480 .stats = NULL,
@@ -477,6 +492,7 @@ static struct rcu_torture_ops rcu_expedited_ops = {
477 .completed = rcu_no_completed, 492 .completed = rcu_no_completed,
478 .deferred_free = rcu_sync_torture_deferred_free, 493 .deferred_free = rcu_sync_torture_deferred_free,
479 .sync = synchronize_rcu_expedited, 494 .sync = synchronize_rcu_expedited,
495 .call = NULL,
480 .cb_barrier = NULL, 496 .cb_barrier = NULL,
481 .fqs = rcu_force_quiescent_state, 497 .fqs = rcu_force_quiescent_state,
482 .stats = NULL, 498 .stats = NULL,
@@ -519,6 +535,7 @@ static struct rcu_torture_ops rcu_bh_ops = {
519 .completed = rcu_bh_torture_completed, 535 .completed = rcu_bh_torture_completed,
520 .deferred_free = rcu_bh_torture_deferred_free, 536 .deferred_free = rcu_bh_torture_deferred_free,
521 .sync = synchronize_rcu_bh, 537 .sync = synchronize_rcu_bh,
538 .call = call_rcu_bh,
522 .cb_barrier = rcu_barrier_bh, 539 .cb_barrier = rcu_barrier_bh,
523 .fqs = rcu_bh_force_quiescent_state, 540 .fqs = rcu_bh_force_quiescent_state,
524 .stats = NULL, 541 .stats = NULL,
@@ -535,6 +552,7 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {
535 .completed = rcu_bh_torture_completed, 552 .completed = rcu_bh_torture_completed,
536 .deferred_free = rcu_sync_torture_deferred_free, 553 .deferred_free = rcu_sync_torture_deferred_free,
537 .sync = synchronize_rcu_bh, 554 .sync = synchronize_rcu_bh,
555 .call = NULL,
538 .cb_barrier = NULL, 556 .cb_barrier = NULL,
539 .fqs = rcu_bh_force_quiescent_state, 557 .fqs = rcu_bh_force_quiescent_state,
540 .stats = NULL, 558 .stats = NULL,
@@ -551,6 +569,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
551 .completed = rcu_bh_torture_completed, 569 .completed = rcu_bh_torture_completed,
552 .deferred_free = rcu_sync_torture_deferred_free, 570 .deferred_free = rcu_sync_torture_deferred_free,
553 .sync = synchronize_rcu_bh_expedited, 571 .sync = synchronize_rcu_bh_expedited,
572 .call = NULL,
554 .cb_barrier = NULL, 573 .cb_barrier = NULL,
555 .fqs = rcu_bh_force_quiescent_state, 574 .fqs = rcu_bh_force_quiescent_state,
556 .stats = NULL, 575 .stats = NULL,
@@ -637,6 +656,7 @@ static struct rcu_torture_ops srcu_ops = {
637 .completed = srcu_torture_completed, 656 .completed = srcu_torture_completed,
638 .deferred_free = rcu_sync_torture_deferred_free, 657 .deferred_free = rcu_sync_torture_deferred_free,
639 .sync = srcu_torture_synchronize, 658 .sync = srcu_torture_synchronize,
659 .call = NULL,
640 .cb_barrier = NULL, 660 .cb_barrier = NULL,
641 .stats = srcu_torture_stats, 661 .stats = srcu_torture_stats,
642 .name = "srcu" 662 .name = "srcu"
@@ -661,6 +681,7 @@ static struct rcu_torture_ops srcu_raw_ops = {
661 .completed = srcu_torture_completed, 681 .completed = srcu_torture_completed,
662 .deferred_free = rcu_sync_torture_deferred_free, 682 .deferred_free = rcu_sync_torture_deferred_free,
663 .sync = srcu_torture_synchronize, 683 .sync = srcu_torture_synchronize,
684 .call = NULL,
664 .cb_barrier = NULL, 685 .cb_barrier = NULL,
665 .stats = srcu_torture_stats, 686 .stats = srcu_torture_stats,
666 .name = "srcu_raw" 687 .name = "srcu_raw"
@@ -680,6 +701,7 @@ static struct rcu_torture_ops srcu_expedited_ops = {
680 .completed = srcu_torture_completed, 701 .completed = srcu_torture_completed,
681 .deferred_free = rcu_sync_torture_deferred_free, 702 .deferred_free = rcu_sync_torture_deferred_free,
682 .sync = srcu_torture_synchronize_expedited, 703 .sync = srcu_torture_synchronize_expedited,
704 .call = NULL,
683 .cb_barrier = NULL, 705 .cb_barrier = NULL,
684 .stats = srcu_torture_stats, 706 .stats = srcu_torture_stats,
685 .name = "srcu_expedited" 707 .name = "srcu_expedited"
@@ -1129,7 +1151,8 @@ rcu_torture_printk(char *page)
1129 "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d " 1151 "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
1130 "rtmbe: %d rtbke: %ld rtbre: %ld " 1152 "rtmbe: %d rtbke: %ld rtbre: %ld "
1131 "rtbf: %ld rtb: %ld nt: %ld " 1153 "rtbf: %ld rtb: %ld nt: %ld "
1132 "onoff: %ld/%ld:%ld/%ld", 1154 "onoff: %ld/%ld:%ld/%ld "
1155 "barrier: %ld/%ld:%ld",
1133 rcu_torture_current, 1156 rcu_torture_current,
1134 rcu_torture_current_version, 1157 rcu_torture_current_version,
1135 list_empty(&rcu_torture_freelist), 1158 list_empty(&rcu_torture_freelist),
@@ -1145,14 +1168,17 @@ rcu_torture_printk(char *page)
1145 n_online_successes, 1168 n_online_successes,
1146 n_online_attempts, 1169 n_online_attempts,
1147 n_offline_successes, 1170 n_offline_successes,
1148 n_offline_attempts); 1171 n_offline_attempts,
1172 n_barrier_successes,
1173 n_barrier_attempts,
1174 n_rcu_torture_barrier_error);
1175 cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
1149 if (atomic_read(&n_rcu_torture_mberror) != 0 || 1176 if (atomic_read(&n_rcu_torture_mberror) != 0 ||
1177 n_rcu_torture_barrier_error != 0 ||
1150 n_rcu_torture_boost_ktrerror != 0 || 1178 n_rcu_torture_boost_ktrerror != 0 ||
1151 n_rcu_torture_boost_rterror != 0 || 1179 n_rcu_torture_boost_rterror != 0 ||
1152 n_rcu_torture_boost_failure != 0) 1180 n_rcu_torture_boost_failure != 0 ||
1153 cnt += sprintf(&page[cnt], " !!!"); 1181 i > 1) {
1154 cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
1155 if (i > 1) {
1156 cnt += sprintf(&page[cnt], "!!! "); 1182 cnt += sprintf(&page[cnt], "!!! ");
1157 atomic_inc(&n_rcu_torture_error); 1183 atomic_inc(&n_rcu_torture_error);
1158 WARN_ON_ONCE(1); 1184 WARN_ON_ONCE(1);
@@ -1560,6 +1586,151 @@ static void rcu_torture_stall_cleanup(void)
1560 stall_task = NULL; 1586 stall_task = NULL;
1561} 1587}
1562 1588
1589/* Callback function for RCU barrier testing. */
1590void rcu_torture_barrier_cbf(struct rcu_head *rcu)
1591{
1592 atomic_inc(&barrier_cbs_invoked);
1593}
1594
1595/* kthread function to register callbacks used to test RCU barriers. */
1596static int rcu_torture_barrier_cbs(void *arg)
1597{
1598 long myid = (long)arg;
1599 struct rcu_head rcu;
1600
1601 init_rcu_head_on_stack(&rcu);
1602 VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task started");
1603 set_user_nice(current, 19);
1604 do {
1605 wait_event(barrier_cbs_wq[myid],
1606 atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
1607 kthread_should_stop() ||
1608 fullstop != FULLSTOP_DONTSTOP);
1609 if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
1610 break;
1611 cur_ops->call(&rcu, rcu_torture_barrier_cbf);
1612 if (atomic_dec_and_test(&barrier_cbs_count))
1613 wake_up(&barrier_wq);
1614 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
1615 VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task stopping");
1616 rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
1617 while (!kthread_should_stop())
1618 schedule_timeout_interruptible(1);
1619 cur_ops->cb_barrier();
1620 destroy_rcu_head_on_stack(&rcu);
1621 return 0;
1622}
1623
1624/* kthread function to drive and coordinate RCU barrier testing. */
1625static int rcu_torture_barrier(void *arg)
1626{
1627 int i;
1628
1629 VERBOSE_PRINTK_STRING("rcu_torture_barrier task starting");
1630 do {
1631 atomic_set(&barrier_cbs_invoked, 0);
1632 atomic_set(&barrier_cbs_count, n_barrier_cbs);
1633 /* wake_up() path contains the required barriers. */
1634 for (i = 0; i < n_barrier_cbs; i++)
1635 wake_up(&barrier_cbs_wq[i]);
1636 wait_event(barrier_wq,
1637 atomic_read(&barrier_cbs_count) == 0 ||
1638 kthread_should_stop() ||
1639 fullstop != FULLSTOP_DONTSTOP);
1640 if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
1641 break;
1642 n_barrier_attempts++;
1643 cur_ops->cb_barrier();
1644 if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
1645 n_rcu_torture_barrier_error++;
1646 WARN_ON_ONCE(1);
1647 }
1648 n_barrier_successes++;
1649 schedule_timeout_interruptible(HZ / 10);
1650 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
1651 VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
1652 rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
1653 while (!kthread_should_stop())
1654 schedule_timeout_interruptible(1);
1655 return 0;
1656}
1657
1658/* Initialize RCU barrier testing. */
1659static int rcu_torture_barrier_init(void)
1660{
1661 int i;
1662 int ret;
1663
1664 if (n_barrier_cbs == 0)
1665 return 0;
1666 if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
1667 printk(KERN_ALERT "%s" TORTURE_FLAG
1668 " Call or barrier ops missing for %s,\n",
1669 torture_type, cur_ops->name);
1670 printk(KERN_ALERT "%s" TORTURE_FLAG
1671 " RCU barrier testing omitted from run.\n",
1672 torture_type);
1673 return 0;
1674 }
1675 atomic_set(&barrier_cbs_count, 0);
1676 atomic_set(&barrier_cbs_invoked, 0);
1677 barrier_cbs_tasks =
1678 kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]),
1679 GFP_KERNEL);
1680 barrier_cbs_wq =
1681 kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
1682 GFP_KERNEL);
1683 if (barrier_cbs_tasks == NULL || barrier_cbs_wq == 0)
1684 return -ENOMEM;
1685 for (i = 0; i < n_barrier_cbs; i++) {
1686 init_waitqueue_head(&barrier_cbs_wq[i]);
1687 barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs,
1688 (void *)i,
1689 "rcu_torture_barrier_cbs");
1690 if (IS_ERR(barrier_cbs_tasks[i])) {
1691 ret = PTR_ERR(barrier_cbs_tasks[i]);
1692 VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier_cbs");
1693 barrier_cbs_tasks[i] = NULL;
1694 return ret;
1695 }
1696 }
1697 barrier_task = kthread_run(rcu_torture_barrier, NULL,
1698 "rcu_torture_barrier");
1699 if (IS_ERR(barrier_task)) {
1700 ret = PTR_ERR(barrier_task);
1701 VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier");
1702 barrier_task = NULL;
1703 }
1704 return 0;
1705}
1706
1707/* Clean up after RCU barrier testing. */
1708static void rcu_torture_barrier_cleanup(void)
1709{
1710 int i;
1711
1712 if (barrier_task != NULL) {
1713 VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier task");
1714 kthread_stop(barrier_task);
1715 barrier_task = NULL;
1716 }
1717 if (barrier_cbs_tasks != NULL) {
1718 for (i = 0; i < n_barrier_cbs; i++) {
1719 if (barrier_cbs_tasks[i] != NULL) {
1720 VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier_cbs task");
1721 kthread_stop(barrier_cbs_tasks[i]);
1722 barrier_cbs_tasks[i] = NULL;
1723 }
1724 }
1725 kfree(barrier_cbs_tasks);
1726 barrier_cbs_tasks = NULL;
1727 }
1728 if (barrier_cbs_wq != NULL) {
1729 kfree(barrier_cbs_wq);
1730 barrier_cbs_wq = NULL;
1731 }
1732}
1733
1563static int rcutorture_cpu_notify(struct notifier_block *self, 1734static int rcutorture_cpu_notify(struct notifier_block *self,
1564 unsigned long action, void *hcpu) 1735 unsigned long action, void *hcpu)
1565{ 1736{
@@ -1602,6 +1773,7 @@ rcu_torture_cleanup(void)
1602 fullstop = FULLSTOP_RMMOD; 1773 fullstop = FULLSTOP_RMMOD;
1603 mutex_unlock(&fullstop_mutex); 1774 mutex_unlock(&fullstop_mutex);
1604 unregister_reboot_notifier(&rcutorture_shutdown_nb); 1775 unregister_reboot_notifier(&rcutorture_shutdown_nb);
1776 rcu_torture_barrier_cleanup();
1605 rcu_torture_stall_cleanup(); 1777 rcu_torture_stall_cleanup();
1606 if (stutter_task) { 1778 if (stutter_task) {
1607 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task"); 1779 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
@@ -1681,7 +1853,7 @@ rcu_torture_cleanup(void)
1681 1853
1682 if (cur_ops->cleanup) 1854 if (cur_ops->cleanup)
1683 cur_ops->cleanup(); 1855 cur_ops->cleanup();
1684 if (atomic_read(&n_rcu_torture_error)) 1856 if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
1685 rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE"); 1857 rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
1686 else if (n_online_successes != n_online_attempts || 1858 else if (n_online_successes != n_online_attempts ||
1687 n_offline_successes != n_offline_attempts) 1859 n_offline_successes != n_offline_attempts)
@@ -1697,6 +1869,7 @@ rcu_torture_init(void)
1697 int i; 1869 int i;
1698 int cpu; 1870 int cpu;
1699 int firsterr = 0; 1871 int firsterr = 0;
1872 int retval;
1700 static struct rcu_torture_ops *torture_ops[] = 1873 static struct rcu_torture_ops *torture_ops[] =
1701 { &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops, 1874 { &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
1702 &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops, 1875 &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
@@ -1754,6 +1927,7 @@ rcu_torture_init(void)
1754 atomic_set(&n_rcu_torture_free, 0); 1927 atomic_set(&n_rcu_torture_free, 0);
1755 atomic_set(&n_rcu_torture_mberror, 0); 1928 atomic_set(&n_rcu_torture_mberror, 0);
1756 atomic_set(&n_rcu_torture_error, 0); 1929 atomic_set(&n_rcu_torture_error, 0);
1930 n_rcu_torture_barrier_error = 0;
1757 n_rcu_torture_boost_ktrerror = 0; 1931 n_rcu_torture_boost_ktrerror = 0;
1758 n_rcu_torture_boost_rterror = 0; 1932 n_rcu_torture_boost_rterror = 0;
1759 n_rcu_torture_boost_failure = 0; 1933 n_rcu_torture_boost_failure = 0;
@@ -1877,7 +2051,6 @@ rcu_torture_init(void)
1877 test_boost_duration = 2; 2051 test_boost_duration = 2;
1878 if ((test_boost == 1 && cur_ops->can_boost) || 2052 if ((test_boost == 1 && cur_ops->can_boost) ||
1879 test_boost == 2) { 2053 test_boost == 2) {
1880 int retval;
1881 2054
1882 boost_starttime = jiffies + test_boost_interval * HZ; 2055 boost_starttime = jiffies + test_boost_interval * HZ;
1883 register_cpu_notifier(&rcutorture_cpu_nb); 2056 register_cpu_notifier(&rcutorture_cpu_nb);
@@ -1913,6 +2086,11 @@ rcu_torture_init(void)
1913 firsterr = i; 2086 firsterr = i;
1914 goto unwind; 2087 goto unwind;
1915 } 2088 }
2089 retval = rcu_torture_barrier_init();
2090 if (retval != 0) {
2091 firsterr = retval;
2092 goto unwind;
2093 }
1916 rcutorture_record_test_transition(); 2094 rcutorture_record_test_transition();
1917 mutex_unlock(&fullstop_mutex); 2095 mutex_unlock(&fullstop_mutex);
1918 return 0; 2096 return 0;