Commit 0729fbf3bc70870370b4f43d652f05a468dc68b8

Authored by Paul E. McKenney
Committed by Ingo Molnar
1 parent 9a13150109

rcu: make rcutorture even more vicious: invoke RCU readers from irq handlers (timers)

This patch allows torturing RCU from irq handlers (timers, in this case).
A new module parameter irqreader enables such additional torturing,
and is enabled by default.  Variants of RCU that do not tolerate readers
being called from irq handlers (e.g., SRCU) ignore irqreader.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: josh@freedesktop.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: dino@in.ibm.com
Cc: akpm@linux-foundation.org
Cc: torvalds@linux-foundation.org
Cc: vegard.nossum@gmail.com
Cc: adobriyan@gmail.com
Cc: oleg@tv-sign.ru
Cc: bunk@kernel.org
Cc: rjw@sisk.pl
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 2 changed files with 84 additions and 13 deletions Side-by-side Diff

Documentation/RCU/torture.txt
... ... @@ -30,10 +30,10 @@
30 30  
31 31 This module has the following parameters:
32 32  
33   -nreaders This is the number of RCU reading threads supported.
34   - The default is twice the number of CPUs. Why twice?
35   - To properly exercise RCU implementations with preemptible
36   - read-side critical sections.
  33 +irqreaders Says to invoke RCU readers from irq level. This is currently
  34 + done via timers. Defaults to "1" for variants of RCU that
  35 + permit this. (Or, more accurately, variants of RCU that do
  36 + -not- permit this know to ignore this variable.)
37 37  
38 38 nfakewriters This is the number of RCU fake writer threads to run. Fake
39 39 writer threads repeatedly use the synchronous "wait for
40 40  
... ... @@ -44,17 +44,22 @@
44 44 to trigger special cases caused by multiple writers, such as
45 45 the synchronize_srcu() early return optimization.
46 46  
  47 +nreaders This is the number of RCU reading threads supported.
  48 + The default is twice the number of CPUs. Why twice?
  49 + To properly exercise RCU implementations with preemptible
  50 + read-side critical sections.
  51 +
  52 +shuffle_interval
  53 + The number of seconds to keep the test threads affinitied
  54 + to a particular subset of the CPUs, defaults to 3 seconds.
  55 + Used in conjunction with test_no_idle_hz.
  56 +
47 57 stat_interval The number of seconds between output of torture
48 58 statistics (via printk()). Regardless of the interval,
49 59 statistics are printed when the module is unloaded.
50 60 Setting the interval to zero causes the statistics to
51 61 be printed -only- when the module is unloaded, and this
52 62 is the default.
53   -
54   -shuffle_interval
55   - The number of seconds to keep the test threads affinitied
56   - to a particular subset of the CPUs, defaults to 3 seconds.
57   - Used in conjunction with test_no_idle_hz.
58 63  
59 64 stutter The length of time to run the test before pausing for this
60 65 same period of time. Defaults to "stutter=5", so as
... ... @@ -59,6 +59,7 @@
59 59 static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
60 60 static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
61 61 static int stutter = 5; /* Start/stop testing interval (in sec) */
  62 +static int irqreader = 1; /* RCU readers from irq (timers). */
62 63 static char *torture_type = "rcu"; /* What RCU implementation to torture. */
63 64  
64 65 module_param(nreaders, int, 0444);
... ... @@ -75,6 +76,8 @@
75 76 MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
76 77 module_param(stutter, int, 0444);
77 78 MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
  79 +module_param(irqreader, int, 0444);
  80 +MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
78 81 module_param(torture_type, charp, 0444);
79 82 MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
80 83  
... ... @@ -121,6 +124,7 @@
121 124 static atomic_t n_rcu_torture_free;
122 125 static atomic_t n_rcu_torture_mberror;
123 126 static atomic_t n_rcu_torture_error;
  127 +static long n_rcu_torture_timers = 0;
124 128 static struct list_head rcu_torture_removed;
125 129  
126 130 static int stutter_pause_test = 0;
... ... @@ -217,6 +221,7 @@
217 221 void (*sync)(void);
218 222 void (*cb_barrier)(void);
219 223 int (*stats)(char *page);
  224 + int irqcapable;
220 225 char *name;
221 226 };
222 227 static struct rcu_torture_ops *cur_ops = NULL;
... ... @@ -291,6 +296,7 @@
291 296 .sync = synchronize_rcu,
292 297 .cb_barrier = rcu_barrier,
293 298 .stats = NULL,
  299 + .irqcapable = 1,
294 300 .name = "rcu"
295 301 };
296 302  
... ... @@ -331,6 +337,7 @@
331 337 .sync = synchronize_rcu,
332 338 .cb_barrier = NULL,
333 339 .stats = NULL,
  340 + .irqcapable = 1,
334 341 .name = "rcu_sync"
335 342 };
336 343  
... ... @@ -392,6 +399,7 @@
392 399 .sync = rcu_bh_torture_synchronize,
393 400 .cb_barrier = rcu_barrier_bh,
394 401 .stats = NULL,
  402 + .irqcapable = 1,
395 403 .name = "rcu_bh"
396 404 };
397 405  
... ... @@ -406,6 +414,7 @@
406 414 .sync = rcu_bh_torture_synchronize,
407 415 .cb_barrier = NULL,
408 416 .stats = NULL,
  417 + .irqcapable = 1,
409 418 .name = "rcu_bh_sync"
410 419 };
411 420  
... ... @@ -532,6 +541,7 @@
532 541 .sync = sched_torture_synchronize,
533 542 .cb_barrier = rcu_barrier_sched,
534 543 .stats = NULL,
  544 + .irqcapable = 1,
535 545 .name = "sched"
536 546 };
537 547  
... ... @@ -620,6 +630,52 @@
620 630 }
621 631  
622 632 /*
  633 + * RCU torture reader from timer handler. Dereferences rcu_torture_current,
  634 + * incrementing the corresponding element of the pipeline array. The
  635 + * counter in the element should never be greater than 1, otherwise, the
  636 + * RCU implementation is broken.
  637 + */
  638 +static void rcu_torture_timer(unsigned long unused)
  639 +{
  640 + int idx;
  641 + int completed;
  642 + static DEFINE_RCU_RANDOM(rand);
  643 + static DEFINE_SPINLOCK(rand_lock);
  644 + struct rcu_torture *p;
  645 + int pipe_count;
  646 +
  647 + idx = cur_ops->readlock();
  648 + completed = cur_ops->completed();
  649 + p = rcu_dereference(rcu_torture_current);
  650 + if (p == NULL) {
  651 + /* Leave because rcu_torture_writer is not yet underway */
  652 + cur_ops->readunlock(idx);
  653 + return;
  654 + }
  655 + if (p->rtort_mbtest == 0)
  656 + atomic_inc(&n_rcu_torture_mberror);
  657 + spin_lock(&rand_lock);
  658 + cur_ops->readdelay(&rand);
  659 + n_rcu_torture_timers++;
  660 + spin_unlock(&rand_lock);
  661 + preempt_disable();
  662 + pipe_count = p->rtort_pipe_count;
  663 + if (pipe_count > RCU_TORTURE_PIPE_LEN) {
  664 + /* Should not happen, but... */
  665 + pipe_count = RCU_TORTURE_PIPE_LEN;
  666 + }
  667 + ++__get_cpu_var(rcu_torture_count)[pipe_count];
  668 + completed = cur_ops->completed() - completed;
  669 + if (completed > RCU_TORTURE_PIPE_LEN) {
  670 + /* Should not happen, but... */
  671 + completed = RCU_TORTURE_PIPE_LEN;
  672 + }
  673 + ++__get_cpu_var(rcu_torture_batch)[completed];
  674 + preempt_enable();
  675 + cur_ops->readunlock(idx);
  676 +}
  677 +
  678 +/*
623 679 * RCU torture reader kthread. Repeatedly dereferences rcu_torture_current,
624 680 * incrementing the corresponding element of the pipeline array. The
625 681 * counter in the element should never be greater than 1, otherwise, the
626 682  
627 683  
... ... @@ -633,11 +689,18 @@
633 689 DEFINE_RCU_RANDOM(rand);
634 690 struct rcu_torture *p;
635 691 int pipe_count;
  692 + struct timer_list t;
636 693  
637 694 VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
638 695 set_user_nice(current, 19);
  696 + if (irqreader && cur_ops->irqcapable)
  697 + setup_timer_on_stack(&t, rcu_torture_timer, 0);
639 698  
640 699 do {
  700 + if (irqreader && cur_ops->irqcapable) {
  701 + if (!timer_pending(&t))
  702 + mod_timer(&t, 1);
  703 + }
641 704 idx = cur_ops->readlock();
642 705 completed = cur_ops->completed();
643 706 p = rcu_dereference(rcu_torture_current);
... ... @@ -669,6 +732,8 @@
669 732 rcu_stutter_wait();
670 733 } while (!kthread_should_stop() && !fullstop);
671 734 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
  735 + if (irqreader && cur_ops->irqcapable)
  736 + del_timer_sync(&t);
672 737 while (!kthread_should_stop())
673 738 schedule_timeout_uninterruptible(1);
674 739 return 0;
675 740  
... ... @@ -699,14 +764,15 @@
699 764 cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
700 765 cnt += sprintf(&page[cnt],
701 766 "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d "
702   - "rtmbe: %d",
  767 + "rtmbe: %d nt: %ld",
703 768 rcu_torture_current,
704 769 rcu_torture_current_version,
705 770 list_empty(&rcu_torture_freelist),
706 771 atomic_read(&n_rcu_torture_alloc),
707 772 atomic_read(&n_rcu_torture_alloc_fail),
708 773 atomic_read(&n_rcu_torture_free),
709   - atomic_read(&n_rcu_torture_mberror));
  774 + atomic_read(&n_rcu_torture_mberror),
  775 + n_rcu_torture_timers);
710 776 if (atomic_read(&n_rcu_torture_mberror) != 0)
711 777 cnt += sprintf(&page[cnt], " !!!");
712 778 cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
713 779  
... ... @@ -862,10 +928,10 @@
862 928 printk(KERN_ALERT "%s" TORTURE_FLAG
863 929 "--- %s: nreaders=%d nfakewriters=%d "
864 930 "stat_interval=%d verbose=%d test_no_idle_hz=%d "
865   - "shuffle_interval=%d stutter=%d\n",
  931 + "shuffle_interval=%d stutter=%d irqreader=%d\n",
866 932 torture_type, tag, nrealreaders, nfakewriters,
867 933 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
868   - stutter);
  934 + stutter, irqreader);
869 935 }
870 936  
871 937 static void