aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutorture.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2008-06-18 08:21:44 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-18 09:06:56 -0400
commitd120f65f3aaf306c957bc4c82e510f5b0f1e9b27 (patch)
tree4b10376660bbfdb4ed8c79b17d0c1abc93b44089 /kernel/rcutorture.c
parent5af970a48f3ba0dd96a036b196c79dc923f28231 (diff)
rcu: make rcutorture more vicious: add stutter feature
This patch takes a step towards making rcutorture more brutal by allowing the test to be automatically periodically paused, with the default being to run the test for five seconds then pause for five seconds and repeat. This behavior can be controlled using a new "stutter" module parameter, so that "stutter=0" gives the old default behavior of running continuously. Starting and stopping rcutorture more heavily stresses RCU's interaction with the scheduler, as well as exercising more paths through the grace-period detection code. Note that the default to "shuffle_interval" has also been adjusted from 5 seconds to 3 seconds to provide varying overlap with the "stutter" interval. I am still unable to provoke the failures that Alexey has been seeing, even with this patch, but will be doing a few additional things to beef up rcutorture. Suggested-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r--kernel/rcutorture.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 0ca7e9b290b0..98ae7d168225 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -57,7 +57,8 @@ static int stat_interval; /* Interval between stats, in seconds. */
57 /* Defaults to "only at end of test". */ 57 /* Defaults to "only at end of test". */
58static int verbose; /* Print more debug info. */ 58static int verbose; /* Print more debug info. */
59static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ 59static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
60static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/ 60static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
61static int stutter = 5; /* Start/stop testing interval (in sec) */
61static char *torture_type = "rcu"; /* What RCU implementation to torture. */ 62static char *torture_type = "rcu"; /* What RCU implementation to torture. */
62 63
63module_param(nreaders, int, 0444); 64module_param(nreaders, int, 0444);
@@ -72,6 +73,8 @@ module_param(test_no_idle_hz, bool, 0444);
72MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); 73MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
73module_param(shuffle_interval, int, 0444); 74module_param(shuffle_interval, int, 0444);
74MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); 75MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
76module_param(stutter, int, 0444);
77MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
75module_param(torture_type, charp, 0444); 78module_param(torture_type, charp, 0444);
76MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)"); 79MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
77 80
@@ -91,6 +94,7 @@ static struct task_struct **fakewriter_tasks;
91static struct task_struct **reader_tasks; 94static struct task_struct **reader_tasks;
92static struct task_struct *stats_task; 95static struct task_struct *stats_task;
93static struct task_struct *shuffler_task; 96static struct task_struct *shuffler_task;
97static struct task_struct *stutter_task;
94 98
95#define RCU_TORTURE_PIPE_LEN 10 99#define RCU_TORTURE_PIPE_LEN 10
96 100
@@ -119,6 +123,8 @@ static atomic_t n_rcu_torture_mberror;
119static atomic_t n_rcu_torture_error; 123static atomic_t n_rcu_torture_error;
120static struct list_head rcu_torture_removed; 124static struct list_head rcu_torture_removed;
121 125
126static int stutter_pause_test = 0;
127
122/* 128/*
123 * Allocate an element from the rcu_tortures pool. 129 * Allocate an element from the rcu_tortures pool.
124 */ 130 */
@@ -179,6 +185,13 @@ rcu_random(struct rcu_random_state *rrsp)
179 return swahw32(rrsp->rrs_state); 185 return swahw32(rrsp->rrs_state);
180} 186}
181 187
188static void
189rcu_stutter_wait(void)
190{
191 while (stutter_pause_test)
192 schedule_timeout_interruptible(1);
193}
194
182/* 195/*
183 * Operations vector for selecting different types of tests. 196 * Operations vector for selecting different types of tests.
184 */ 197 */
@@ -563,6 +576,7 @@ rcu_torture_writer(void *arg)
563 } 576 }
564 rcu_torture_current_version++; 577 rcu_torture_current_version++;
565 oldbatch = cur_ops->completed(); 578 oldbatch = cur_ops->completed();
579 rcu_stutter_wait();
566 } while (!kthread_should_stop() && !fullstop); 580 } while (!kthread_should_stop() && !fullstop);
567 VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); 581 VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
568 while (!kthread_should_stop()) 582 while (!kthread_should_stop())
@@ -586,6 +600,7 @@ rcu_torture_fakewriter(void *arg)
586 schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10); 600 schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
587 udelay(rcu_random(&rand) & 0x3ff); 601 udelay(rcu_random(&rand) & 0x3ff);
588 cur_ops->sync(); 602 cur_ops->sync();
603 rcu_stutter_wait();
589 } while (!kthread_should_stop() && !fullstop); 604 } while (!kthread_should_stop() && !fullstop);
590 605
591 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); 606 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
@@ -641,6 +656,7 @@ rcu_torture_reader(void *arg)
641 preempt_enable(); 656 preempt_enable();
642 cur_ops->readunlock(idx); 657 cur_ops->readunlock(idx);
643 schedule(); 658 schedule();
659 rcu_stutter_wait();
644 } while (!kthread_should_stop() && !fullstop); 660 } while (!kthread_should_stop() && !fullstop);
645 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping"); 661 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
646 while (!kthread_should_stop()) 662 while (!kthread_should_stop())
@@ -812,15 +828,34 @@ rcu_torture_shuffle(void *arg)
812 return 0; 828 return 0;
813} 829}
814 830
831/* Cause the rcutorture test to "stutter", starting and stopping all
832 * threads periodically.
833 */
834static int
835rcu_torture_stutter(void *arg)
836{
837 VERBOSE_PRINTK_STRING("rcu_torture_stutter task started");
838 do {
839 schedule_timeout_interruptible(stutter * HZ);
840 stutter_pause_test = 1;
841 if (!kthread_should_stop())
842 schedule_timeout_interruptible(stutter * HZ);
843 stutter_pause_test = 0;
844 } while (!kthread_should_stop());
845 VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
846 return 0;
847}
848
815static inline void 849static inline void
816rcu_torture_print_module_parms(char *tag) 850rcu_torture_print_module_parms(char *tag)
817{ 851{
818 printk(KERN_ALERT "%s" TORTURE_FLAG 852 printk(KERN_ALERT "%s" TORTURE_FLAG
819 "--- %s: nreaders=%d nfakewriters=%d " 853 "--- %s: nreaders=%d nfakewriters=%d "
820 "stat_interval=%d verbose=%d test_no_idle_hz=%d " 854 "stat_interval=%d verbose=%d test_no_idle_hz=%d "
821 "shuffle_interval = %d\n", 855 "shuffle_interval=%d stutter=%d\n",
822 torture_type, tag, nrealreaders, nfakewriters, 856 torture_type, tag, nrealreaders, nfakewriters,
823 stat_interval, verbose, test_no_idle_hz, shuffle_interval); 857 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
858 stutter);
824} 859}
825 860
826static void 861static void
@@ -829,6 +864,11 @@ rcu_torture_cleanup(void)
829 int i; 864 int i;
830 865
831 fullstop = 1; 866 fullstop = 1;
867 if (stutter_task) {
868 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
869 kthread_stop(stutter_task);
870 }
871 stutter_task = NULL;
832 if (shuffler_task) { 872 if (shuffler_task) {
833 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task"); 873 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
834 kthread_stop(shuffler_task); 874 kthread_stop(shuffler_task);
@@ -1017,6 +1057,19 @@ rcu_torture_init(void)
1017 goto unwind; 1057 goto unwind;
1018 } 1058 }
1019 } 1059 }
1060 if (stutter < 0)
1061 stutter = 0;
1062 if (stutter) {
1063 /* Create the stutter thread */
1064 stutter_task = kthread_run(rcu_torture_stutter, NULL,
1065 "rcu_torture_stutter");
1066 if (IS_ERR(stutter_task)) {
1067 firsterr = PTR_ERR(stutter_task);
1068 VERBOSE_PRINTK_ERRSTRING("Failed to create stutter");
1069 stutter_task = NULL;
1070 goto unwind;
1071 }
1072 }
1020 return 0; 1073 return 0;
1021 1074
1022unwind: 1075unwind: