aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/RCU/torture.txt8
-rw-r--r--kernel/rcutorture.c59
2 files changed, 63 insertions, 4 deletions
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index 2967a65269d8..02b3d14c0209 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -46,9 +46,15 @@ stat_interval The number of seconds between output of torture
46 46
47shuffle_interval 47shuffle_interval
48 The number of seconds to keep the test threads affinitied 48 The number of seconds to keep the test threads affinitied
49 to a particular subset of the CPUs, defaults to 5 seconds. 49 to a particular subset of the CPUs, defaults to 3 seconds.
50 Used in conjunction with test_no_idle_hz. 50 Used in conjunction with test_no_idle_hz.
51 51
52stutter The length of time to run the test before pausing for this
53 same period of time. Defaults to "stutter=5", so as
54 to run and pause for (roughly) five-second intervals.
55 Specifying "stutter=0" causes the test to run continuously
56 without pausing, which is the old default behavior.
57
52test_no_idle_hz Whether or not to test the ability of RCU to operate in 58test_no_idle_hz Whether or not to test the ability of RCU to operate in
53 a kernel that disables the scheduling-clock interrupt to 59 a kernel that disables the scheduling-clock interrupt to
54 idle CPUs. Boolean parameter, "1" to test, "0" otherwise. 60 idle CPUs. Boolean parameter, "1" to test, "0" otherwise.
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: