diff options
| -rw-r--r-- | Documentation/RCU/torture.txt | 8 | ||||
| -rw-r--r-- | kernel/rcutorture.c | 59 |
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 | ||
| 47 | shuffle_interval | 47 | shuffle_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 | ||
| 52 | stutter 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 | |||
| 52 | test_no_idle_hz Whether or not to test the ability of RCU to operate in | 58 | test_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". */ |
| 58 | static int verbose; /* Print more debug info. */ | 58 | static int verbose; /* Print more debug info. */ |
| 59 | static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ | 59 | static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ |
| 60 | static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/ | 60 | static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/ |
| 61 | static int stutter = 5; /* Start/stop testing interval (in sec) */ | ||
| 61 | static char *torture_type = "rcu"; /* What RCU implementation to torture. */ | 62 | static char *torture_type = "rcu"; /* What RCU implementation to torture. */ |
| 62 | 63 | ||
| 63 | module_param(nreaders, int, 0444); | 64 | module_param(nreaders, int, 0444); |
| @@ -72,6 +73,8 @@ module_param(test_no_idle_hz, bool, 0444); | |||
| 72 | MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); | 73 | MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); |
| 73 | module_param(shuffle_interval, int, 0444); | 74 | module_param(shuffle_interval, int, 0444); |
| 74 | MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); | 75 | MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); |
| 76 | module_param(stutter, int, 0444); | ||
| 77 | MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test"); | ||
| 75 | module_param(torture_type, charp, 0444); | 78 | module_param(torture_type, charp, 0444); |
| 76 | MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)"); | 79 | MODULE_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; | |||
| 91 | static struct task_struct **reader_tasks; | 94 | static struct task_struct **reader_tasks; |
| 92 | static struct task_struct *stats_task; | 95 | static struct task_struct *stats_task; |
| 93 | static struct task_struct *shuffler_task; | 96 | static struct task_struct *shuffler_task; |
| 97 | static 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; | |||
| 119 | static atomic_t n_rcu_torture_error; | 123 | static atomic_t n_rcu_torture_error; |
| 120 | static struct list_head rcu_torture_removed; | 124 | static struct list_head rcu_torture_removed; |
| 121 | 125 | ||
| 126 | static 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 | ||
| 188 | static void | ||
| 189 | rcu_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 | */ | ||
| 834 | static int | ||
| 835 | rcu_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 | |||
| 815 | static inline void | 849 | static inline void |
| 816 | rcu_torture_print_module_parms(char *tag) | 850 | rcu_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 | ||
| 826 | static void | 861 | static 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 | ||
| 1022 | unwind: | 1075 | unwind: |
