diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-01-29 10:40:27 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-23 12:01:04 -0500 |
commit | f67a33561e6e5463b548219df98130da95f2e4a7 (patch) | |
tree | 6cdbf7152900045acb4f0f9d5426f995adf0ba66 /kernel/rcu/rcutorture.c | |
parent | c2884de38e01134ae040d55aa5644049d1bb850f (diff) |
rcutorture: Abstract torture_shutdown_absorb()
Because handling races between rmmod and normal shutdown is not specific
to rcutorture, this commit renames rcutorture_shutdown_absorb() to
torture_shutdown_absorb() and pulls it out into then kernel/torture.c
module. This implies pulling the fullstop mechanism into kernel/torture.c
as well.
The exporting of fullstop and fullstop_mutex is ugly and must die.
And it does in fact die in later commits that introduce higher-level
APIs that encapsulate both of these variables.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>`
Diffstat (limited to 'kernel/rcu/rcutorture.c')
-rw-r--r-- | kernel/rcu/rcutorture.c | 57 |
1 files changed, 18 insertions, 39 deletions
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 86fd8c11257b..a868758a6f9c 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c | |||
@@ -91,11 +91,15 @@ torture_param(int, test_boost_interval, 7, | |||
91 | "Interval between boost tests, seconds."); | 91 | "Interval between boost tests, seconds."); |
92 | torture_param(bool, test_no_idle_hz, true, | 92 | torture_param(bool, test_no_idle_hz, true, |
93 | "Test support for tickless idle CPUs"); | 93 | "Test support for tickless idle CPUs"); |
94 | torture_param(bool, verbose, false, "Enable verbose debugging printk()s"); | ||
95 | 94 | ||
96 | static char *torture_type = "rcu"; | 95 | char *torture_type = "rcu"; |
96 | EXPORT_SYMBOL_GPL(torture_type); | ||
97 | module_param(torture_type, charp, 0444); | 97 | module_param(torture_type, charp, 0444); |
98 | MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)"); | 98 | MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)"); |
99 | bool verbose; | ||
100 | EXPORT_SYMBOL_GPL(verbose); | ||
101 | module_param(verbose, bool, 0444); | ||
102 | MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); | ||
99 | 103 | ||
100 | static int nrealreaders; | 104 | static int nrealreaders; |
101 | static struct task_struct *writer_task; | 105 | static struct task_struct *writer_task; |
@@ -200,17 +204,6 @@ static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */ | |||
200 | static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */ | 204 | static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */ |
201 | static DECLARE_WAIT_QUEUE_HEAD(barrier_wq); | 205 | static DECLARE_WAIT_QUEUE_HEAD(barrier_wq); |
202 | 206 | ||
203 | /* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */ | ||
204 | |||
205 | #define FULLSTOP_DONTSTOP 0 /* Normal operation. */ | ||
206 | #define FULLSTOP_SHUTDOWN 1 /* System shutdown with rcutorture running. */ | ||
207 | #define FULLSTOP_RMMOD 2 /* Normal rmmod of rcutorture. */ | ||
208 | static int fullstop = FULLSTOP_RMMOD; | ||
209 | /* | ||
210 | * Protect fullstop transitions and spawning of kthreads. | ||
211 | */ | ||
212 | static DEFINE_MUTEX(fullstop_mutex); | ||
213 | |||
214 | /* Forward reference. */ | 207 | /* Forward reference. */ |
215 | static void rcu_torture_cleanup(void); | 208 | static void rcu_torture_cleanup(void); |
216 | 209 | ||
@@ -232,20 +225,6 @@ rcutorture_shutdown_notify(struct notifier_block *unused1, | |||
232 | } | 225 | } |
233 | 226 | ||
234 | /* | 227 | /* |
235 | * Absorb kthreads into a kernel function that won't return, so that | ||
236 | * they won't ever access module text or data again. | ||
237 | */ | ||
238 | static void rcutorture_shutdown_absorb(const char *title) | ||
239 | { | ||
240 | if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) { | ||
241 | pr_notice( | ||
242 | "rcutorture thread %s parking due to system shutdown\n", | ||
243 | title); | ||
244 | schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * Allocate an element from the rcu_tortures pool. | 228 | * Allocate an element from the rcu_tortures pool. |
250 | */ | 229 | */ |
251 | static struct rcu_torture * | 230 | static struct rcu_torture * |
@@ -286,7 +265,7 @@ rcu_stutter_wait(const char *title) | |||
286 | schedule_timeout_interruptible(1); | 265 | schedule_timeout_interruptible(1); |
287 | else | 266 | else |
288 | schedule_timeout_interruptible(round_jiffies_relative(HZ)); | 267 | schedule_timeout_interruptible(round_jiffies_relative(HZ)); |
289 | rcutorture_shutdown_absorb(title); | 268 | torture_shutdown_absorb(title); |
290 | } | 269 | } |
291 | } | 270 | } |
292 | 271 | ||
@@ -681,7 +660,7 @@ checkwait: rcu_stutter_wait("rcu_torture_boost"); | |||
681 | 660 | ||
682 | /* Clean up and exit. */ | 661 | /* Clean up and exit. */ |
683 | VERBOSE_TOROUT_STRING("rcu_torture_boost task stopping"); | 662 | VERBOSE_TOROUT_STRING("rcu_torture_boost task stopping"); |
684 | rcutorture_shutdown_absorb("rcu_torture_boost"); | 663 | torture_shutdown_absorb("rcu_torture_boost"); |
685 | while (!kthread_should_stop() || rbi.inflight) | 664 | while (!kthread_should_stop() || rbi.inflight) |
686 | schedule_timeout_uninterruptible(1); | 665 | schedule_timeout_uninterruptible(1); |
687 | smp_mb(); /* order accesses to ->inflight before stack-frame death. */ | 666 | smp_mb(); /* order accesses to ->inflight before stack-frame death. */ |
@@ -717,7 +696,7 @@ rcu_torture_fqs(void *arg) | |||
717 | rcu_stutter_wait("rcu_torture_fqs"); | 696 | rcu_stutter_wait("rcu_torture_fqs"); |
718 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 697 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
719 | VERBOSE_TOROUT_STRING("rcu_torture_fqs task stopping"); | 698 | VERBOSE_TOROUT_STRING("rcu_torture_fqs task stopping"); |
720 | rcutorture_shutdown_absorb("rcu_torture_fqs"); | 699 | torture_shutdown_absorb("rcu_torture_fqs"); |
721 | while (!kthread_should_stop()) | 700 | while (!kthread_should_stop()) |
722 | schedule_timeout_uninterruptible(1); | 701 | schedule_timeout_uninterruptible(1); |
723 | return 0; | 702 | return 0; |
@@ -789,7 +768,7 @@ rcu_torture_writer(void *arg) | |||
789 | rcu_stutter_wait("rcu_torture_writer"); | 768 | rcu_stutter_wait("rcu_torture_writer"); |
790 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 769 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
791 | VERBOSE_TOROUT_STRING("rcu_torture_writer task stopping"); | 770 | VERBOSE_TOROUT_STRING("rcu_torture_writer task stopping"); |
792 | rcutorture_shutdown_absorb("rcu_torture_writer"); | 771 | torture_shutdown_absorb("rcu_torture_writer"); |
793 | while (!kthread_should_stop()) | 772 | while (!kthread_should_stop()) |
794 | schedule_timeout_uninterruptible(1); | 773 | schedule_timeout_uninterruptible(1); |
795 | return 0; | 774 | return 0; |
@@ -827,7 +806,7 @@ rcu_torture_fakewriter(void *arg) | |||
827 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 806 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
828 | 807 | ||
829 | VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task stopping"); | 808 | VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task stopping"); |
830 | rcutorture_shutdown_absorb("rcu_torture_fakewriter"); | 809 | torture_shutdown_absorb("rcu_torture_fakewriter"); |
831 | while (!kthread_should_stop()) | 810 | while (!kthread_should_stop()) |
832 | schedule_timeout_uninterruptible(1); | 811 | schedule_timeout_uninterruptible(1); |
833 | return 0; | 812 | return 0; |
@@ -971,7 +950,7 @@ rcu_torture_reader(void *arg) | |||
971 | rcu_stutter_wait("rcu_torture_reader"); | 950 | rcu_stutter_wait("rcu_torture_reader"); |
972 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 951 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
973 | VERBOSE_TOROUT_STRING("rcu_torture_reader task stopping"); | 952 | VERBOSE_TOROUT_STRING("rcu_torture_reader task stopping"); |
974 | rcutorture_shutdown_absorb("rcu_torture_reader"); | 953 | torture_shutdown_absorb("rcu_torture_reader"); |
975 | if (irqreader && cur_ops->irq_capable) | 954 | if (irqreader && cur_ops->irq_capable) |
976 | del_timer_sync(&t); | 955 | del_timer_sync(&t); |
977 | while (!kthread_should_stop()) | 956 | while (!kthread_should_stop()) |
@@ -1095,7 +1074,7 @@ rcu_torture_stats(void *arg) | |||
1095 | do { | 1074 | do { |
1096 | schedule_timeout_interruptible(stat_interval * HZ); | 1075 | schedule_timeout_interruptible(stat_interval * HZ); |
1097 | rcu_torture_stats_print(); | 1076 | rcu_torture_stats_print(); |
1098 | rcutorture_shutdown_absorb("rcu_torture_stats"); | 1077 | torture_shutdown_absorb("rcu_torture_stats"); |
1099 | } while (!kthread_should_stop()); | 1078 | } while (!kthread_should_stop()); |
1100 | VERBOSE_TOROUT_STRING("rcu_torture_stats task stopping"); | 1079 | VERBOSE_TOROUT_STRING("rcu_torture_stats task stopping"); |
1101 | return 0; | 1080 | return 0; |
@@ -1179,7 +1158,7 @@ rcu_torture_shuffle(void *arg) | |||
1179 | do { | 1158 | do { |
1180 | schedule_timeout_interruptible(shuffle_interval * HZ); | 1159 | schedule_timeout_interruptible(shuffle_interval * HZ); |
1181 | rcu_torture_shuffle_tasks(); | 1160 | rcu_torture_shuffle_tasks(); |
1182 | rcutorture_shutdown_absorb("rcu_torture_shuffle"); | 1161 | torture_shutdown_absorb("rcu_torture_shuffle"); |
1183 | } while (!kthread_should_stop()); | 1162 | } while (!kthread_should_stop()); |
1184 | VERBOSE_TOROUT_STRING("rcu_torture_shuffle task stopping"); | 1163 | VERBOSE_TOROUT_STRING("rcu_torture_shuffle task stopping"); |
1185 | return 0; | 1164 | return 0; |
@@ -1198,7 +1177,7 @@ rcu_torture_stutter(void *arg) | |||
1198 | if (!kthread_should_stop()) | 1177 | if (!kthread_should_stop()) |
1199 | schedule_timeout_interruptible(stutter * HZ); | 1178 | schedule_timeout_interruptible(stutter * HZ); |
1200 | stutter_pause_test = 0; | 1179 | stutter_pause_test = 0; |
1201 | rcutorture_shutdown_absorb("rcu_torture_stutter"); | 1180 | torture_shutdown_absorb("rcu_torture_stutter"); |
1202 | } while (!kthread_should_stop()); | 1181 | } while (!kthread_should_stop()); |
1203 | VERBOSE_TOROUT_STRING("rcu_torture_stutter task stopping"); | 1182 | VERBOSE_TOROUT_STRING("rcu_torture_stutter task stopping"); |
1204 | return 0; | 1183 | return 0; |
@@ -1470,7 +1449,7 @@ static int rcu_torture_stall(void *args) | |||
1470 | rcu_read_unlock(); | 1449 | rcu_read_unlock(); |
1471 | pr_alert("rcu_torture_stall end.\n"); | 1450 | pr_alert("rcu_torture_stall end.\n"); |
1472 | } | 1451 | } |
1473 | rcutorture_shutdown_absorb("rcu_torture_stall"); | 1452 | torture_shutdown_absorb("rcu_torture_stall"); |
1474 | while (!kthread_should_stop()) | 1453 | while (!kthread_should_stop()) |
1475 | schedule_timeout_interruptible(10 * HZ); | 1454 | schedule_timeout_interruptible(10 * HZ); |
1476 | return 0; | 1455 | return 0; |
@@ -1534,7 +1513,7 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1534 | wake_up(&barrier_wq); | 1513 | wake_up(&barrier_wq); |
1535 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 1514 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
1536 | VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task stopping"); | 1515 | VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task stopping"); |
1537 | rcutorture_shutdown_absorb("rcu_torture_barrier_cbs"); | 1516 | torture_shutdown_absorb("rcu_torture_barrier_cbs"); |
1538 | while (!kthread_should_stop()) | 1517 | while (!kthread_should_stop()) |
1539 | schedule_timeout_interruptible(1); | 1518 | schedule_timeout_interruptible(1); |
1540 | cur_ops->cb_barrier(); | 1519 | cur_ops->cb_barrier(); |
@@ -1571,7 +1550,7 @@ static int rcu_torture_barrier(void *arg) | |||
1571 | schedule_timeout_interruptible(HZ / 10); | 1550 | schedule_timeout_interruptible(HZ / 10); |
1572 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); | 1551 | } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); |
1573 | VERBOSE_TOROUT_STRING("rcu_torture_barrier task stopping"); | 1552 | VERBOSE_TOROUT_STRING("rcu_torture_barrier task stopping"); |
1574 | rcutorture_shutdown_absorb("rcu_torture_barrier"); | 1553 | torture_shutdown_absorb("rcu_torture_barrier"); |
1575 | while (!kthread_should_stop()) | 1554 | while (!kthread_should_stop()) |
1576 | schedule_timeout_interruptible(1); | 1555 | schedule_timeout_interruptible(1); |
1577 | return 0; | 1556 | return 0; |