aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutorture.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r--kernel/rcutorture.c93
1 files changed, 71 insertions, 22 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 85cb90588a55..3245b40952c6 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -39,6 +39,7 @@
39#include <linux/moduleparam.h> 39#include <linux/moduleparam.h>
40#include <linux/percpu.h> 40#include <linux/percpu.h>
41#include <linux/notifier.h> 41#include <linux/notifier.h>
42#include <linux/reboot.h>
42#include <linux/freezer.h> 43#include <linux/freezer.h>
43#include <linux/cpu.h> 44#include <linux/cpu.h>
44#include <linux/delay.h> 45#include <linux/delay.h>
@@ -108,7 +109,6 @@ struct rcu_torture {
108 int rtort_mbtest; 109 int rtort_mbtest;
109}; 110};
110 111
111static int fullstop = 0; /* stop generating callbacks at test end. */
112static LIST_HEAD(rcu_torture_freelist); 112static LIST_HEAD(rcu_torture_freelist);
113static struct rcu_torture *rcu_torture_current = NULL; 113static struct rcu_torture *rcu_torture_current = NULL;
114static long rcu_torture_current_version = 0; 114static long rcu_torture_current_version = 0;
@@ -136,6 +136,30 @@ static int stutter_pause_test = 0;
136#endif 136#endif
137int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT; 137int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
138 138
139#define FULLSTOP_SIGNALED 1 /* Bail due to signal. */
140#define FULLSTOP_CLEANUP 2 /* Orderly shutdown. */
141static int fullstop; /* stop generating callbacks at test end. */
142DEFINE_MUTEX(fullstop_mutex); /* protect fullstop transitions and */
143 /* spawning of kthreads. */
144
145/*
146 * Detect and respond to a signal-based shutdown.
147 */
148static int
149rcutorture_shutdown_notify(struct notifier_block *unused1,
150 unsigned long unused2, void *unused3)
151{
152 if (fullstop)
153 return NOTIFY_DONE;
154 if (signal_pending(current)) {
155 mutex_lock(&fullstop_mutex);
156 if (!ACCESS_ONCE(fullstop))
157 fullstop = FULLSTOP_SIGNALED;
158 mutex_unlock(&fullstop_mutex);
159 }
160 return NOTIFY_DONE;
161}
162
139/* 163/*
140 * Allocate an element from the rcu_tortures pool. 164 * Allocate an element from the rcu_tortures pool.
141 */ 165 */
@@ -199,11 +223,12 @@ rcu_random(struct rcu_random_state *rrsp)
199static void 223static void
200rcu_stutter_wait(void) 224rcu_stutter_wait(void)
201{ 225{
202 while (stutter_pause_test || !rcutorture_runnable) 226 while ((stutter_pause_test || !rcutorture_runnable) && !fullstop) {
203 if (rcutorture_runnable) 227 if (rcutorture_runnable)
204 schedule_timeout_interruptible(1); 228 schedule_timeout_interruptible(1);
205 else 229 else
206 schedule_timeout_interruptible(round_jiffies_relative(HZ)); 230 schedule_timeout_interruptible(round_jiffies_relative(HZ));
231 }
207} 232}
208 233
209/* 234/*
@@ -599,7 +624,7 @@ rcu_torture_writer(void *arg)
599 rcu_stutter_wait(); 624 rcu_stutter_wait();
600 } while (!kthread_should_stop() && !fullstop); 625 } while (!kthread_should_stop() && !fullstop);
601 VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); 626 VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
602 while (!kthread_should_stop()) 627 while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)
603 schedule_timeout_uninterruptible(1); 628 schedule_timeout_uninterruptible(1);
604 return 0; 629 return 0;
605} 630}
@@ -624,7 +649,7 @@ rcu_torture_fakewriter(void *arg)
624 } while (!kthread_should_stop() && !fullstop); 649 } while (!kthread_should_stop() && !fullstop);
625 650
626 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); 651 VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
627 while (!kthread_should_stop()) 652 while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)
628 schedule_timeout_uninterruptible(1); 653 schedule_timeout_uninterruptible(1);
629 return 0; 654 return 0;
630} 655}
@@ -734,7 +759,7 @@ rcu_torture_reader(void *arg)
734 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping"); 759 VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
735 if (irqreader && cur_ops->irqcapable) 760 if (irqreader && cur_ops->irqcapable)
736 del_timer_sync(&t); 761 del_timer_sync(&t);
737 while (!kthread_should_stop()) 762 while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)
738 schedule_timeout_uninterruptible(1); 763 schedule_timeout_uninterruptible(1);
739 return 0; 764 return 0;
740} 765}
@@ -831,7 +856,7 @@ rcu_torture_stats(void *arg)
831 do { 856 do {
832 schedule_timeout_interruptible(stat_interval * HZ); 857 schedule_timeout_interruptible(stat_interval * HZ);
833 rcu_torture_stats_print(); 858 rcu_torture_stats_print();
834 } while (!kthread_should_stop()); 859 } while (!kthread_should_stop() && !fullstop);
835 VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping"); 860 VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");
836 return 0; 861 return 0;
837} 862}
@@ -843,49 +868,52 @@ static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
843 */ 868 */
844static void rcu_torture_shuffle_tasks(void) 869static void rcu_torture_shuffle_tasks(void)
845{ 870{
846 cpumask_t tmp_mask; 871 cpumask_var_t tmp_mask;
847 int i; 872 int i;
848 873
849 cpus_setall(tmp_mask); 874 if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
875 BUG();
876
877 cpumask_setall(tmp_mask);
850 get_online_cpus(); 878 get_online_cpus();
851 879
852 /* No point in shuffling if there is only one online CPU (ex: UP) */ 880 /* No point in shuffling if there is only one online CPU (ex: UP) */
853 if (num_online_cpus() == 1) { 881 if (num_online_cpus() == 1)
854 put_online_cpus(); 882 goto out;
855 return;
856 }
857 883
858 if (rcu_idle_cpu != -1) 884 if (rcu_idle_cpu != -1)
859 cpu_clear(rcu_idle_cpu, tmp_mask); 885 cpumask_clear_cpu(rcu_idle_cpu, tmp_mask);
860 886
861 set_cpus_allowed_ptr(current, &tmp_mask); 887 set_cpus_allowed_ptr(current, tmp_mask);
862 888
863 if (reader_tasks) { 889 if (reader_tasks) {
864 for (i = 0; i < nrealreaders; i++) 890 for (i = 0; i < nrealreaders; i++)
865 if (reader_tasks[i]) 891 if (reader_tasks[i])
866 set_cpus_allowed_ptr(reader_tasks[i], 892 set_cpus_allowed_ptr(reader_tasks[i],
867 &tmp_mask); 893 tmp_mask);
868 } 894 }
869 895
870 if (fakewriter_tasks) { 896 if (fakewriter_tasks) {
871 for (i = 0; i < nfakewriters; i++) 897 for (i = 0; i < nfakewriters; i++)
872 if (fakewriter_tasks[i]) 898 if (fakewriter_tasks[i])
873 set_cpus_allowed_ptr(fakewriter_tasks[i], 899 set_cpus_allowed_ptr(fakewriter_tasks[i],
874 &tmp_mask); 900 tmp_mask);
875 } 901 }
876 902
877 if (writer_task) 903 if (writer_task)
878 set_cpus_allowed_ptr(writer_task, &tmp_mask); 904 set_cpus_allowed_ptr(writer_task, tmp_mask);
879 905
880 if (stats_task) 906 if (stats_task)
881 set_cpus_allowed_ptr(stats_task, &tmp_mask); 907 set_cpus_allowed_ptr(stats_task, tmp_mask);
882 908
883 if (rcu_idle_cpu == -1) 909 if (rcu_idle_cpu == -1)
884 rcu_idle_cpu = num_online_cpus() - 1; 910 rcu_idle_cpu = num_online_cpus() - 1;
885 else 911 else
886 rcu_idle_cpu--; 912 rcu_idle_cpu--;
887 913
914out:
888 put_online_cpus(); 915 put_online_cpus();
916 free_cpumask_var(tmp_mask);
889} 917}
890 918
891/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the 919/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
@@ -899,7 +927,7 @@ rcu_torture_shuffle(void *arg)
899 do { 927 do {
900 schedule_timeout_interruptible(shuffle_interval * HZ); 928 schedule_timeout_interruptible(shuffle_interval * HZ);
901 rcu_torture_shuffle_tasks(); 929 rcu_torture_shuffle_tasks();
902 } while (!kthread_should_stop()); 930 } while (!kthread_should_stop() && !fullstop);
903 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping"); 931 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
904 return 0; 932 return 0;
905} 933}
@@ -914,10 +942,10 @@ rcu_torture_stutter(void *arg)
914 do { 942 do {
915 schedule_timeout_interruptible(stutter * HZ); 943 schedule_timeout_interruptible(stutter * HZ);
916 stutter_pause_test = 1; 944 stutter_pause_test = 1;
917 if (!kthread_should_stop()) 945 if (!kthread_should_stop() && !fullstop)
918 schedule_timeout_interruptible(stutter * HZ); 946 schedule_timeout_interruptible(stutter * HZ);
919 stutter_pause_test = 0; 947 stutter_pause_test = 0;
920 } while (!kthread_should_stop()); 948 } while (!kthread_should_stop() && !fullstop);
921 VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping"); 949 VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
922 return 0; 950 return 0;
923} 951}
@@ -934,12 +962,27 @@ rcu_torture_print_module_parms(char *tag)
934 stutter, irqreader); 962 stutter, irqreader);
935} 963}
936 964
965static struct notifier_block rcutorture_nb = {
966 .notifier_call = rcutorture_shutdown_notify,
967};
968
937static void 969static void
938rcu_torture_cleanup(void) 970rcu_torture_cleanup(void)
939{ 971{
940 int i; 972 int i;
941 973
942 fullstop = 1; 974 mutex_lock(&fullstop_mutex);
975 if (!fullstop) {
976 /* If being signaled, let it happen, then exit. */
977 mutex_unlock(&fullstop_mutex);
978 schedule_timeout_interruptible(10 * HZ);
979 if (cur_ops->cb_barrier != NULL)
980 cur_ops->cb_barrier();
981 return;
982 }
983 fullstop = FULLSTOP_CLEANUP;
984 mutex_unlock(&fullstop_mutex);
985 unregister_reboot_notifier(&rcutorture_nb);
943 if (stutter_task) { 986 if (stutter_task) {
944 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task"); 987 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
945 kthread_stop(stutter_task); 988 kthread_stop(stutter_task);
@@ -1015,6 +1058,8 @@ rcu_torture_init(void)
1015 { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, 1058 { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops,
1016 &srcu_ops, &sched_ops, &sched_ops_sync, }; 1059 &srcu_ops, &sched_ops, &sched_ops_sync, };
1017 1060
1061 mutex_lock(&fullstop_mutex);
1062
1018 /* Process args and tell the world that the torturer is on the job. */ 1063 /* Process args and tell the world that the torturer is on the job. */
1019 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { 1064 for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
1020 cur_ops = torture_ops[i]; 1065 cur_ops = torture_ops[i];
@@ -1024,6 +1069,7 @@ rcu_torture_init(void)
1024 if (i == ARRAY_SIZE(torture_ops)) { 1069 if (i == ARRAY_SIZE(torture_ops)) {
1025 printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n", 1070 printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n",
1026 torture_type); 1071 torture_type);
1072 mutex_unlock(&fullstop_mutex);
1027 return (-EINVAL); 1073 return (-EINVAL);
1028 } 1074 }
1029 if (cur_ops->init) 1075 if (cur_ops->init)
@@ -1146,9 +1192,12 @@ rcu_torture_init(void)
1146 goto unwind; 1192 goto unwind;
1147 } 1193 }
1148 } 1194 }
1195 register_reboot_notifier(&rcutorture_nb);
1196 mutex_unlock(&fullstop_mutex);
1149 return 0; 1197 return 0;
1150 1198
1151unwind: 1199unwind:
1200 mutex_unlock(&fullstop_mutex);
1152 rcu_torture_cleanup(); 1201 rcu_torture_cleanup();
1153 return firsterr; 1202 return firsterr;
1154} 1203}