summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-11-21 18:01:02 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-12-11 12:18:29 -0500
commit4ced3314fd3a73dabac4e8a41747883eff36c3e8 (patch)
treeaba2f62defd17a44cb3a0b6b7c8effa98ce5c7cd
parent2ce77d16db4240dd2e422fc0a5c26d3e2ec03446 (diff)
torture: Make stutter less vulnerable to compilers and races
The stutter_wait() function repeatedly fetched stutter_pause_test, and should really just fetch it once on each pass. The races should be harmless, but why have the races? Also, the whole point of the value "2" for stutter_pause_test is to get everyone to start at very nearly the same time, but the value "2" was the first jiffy of the stutter rather than the last jiffy of the stutter. This commit rearranges the code to be more sensible. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--kernel/torture.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/kernel/torture.c b/kernel/torture.c
index 52781e838541..3bcbd4fbfe18 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -573,18 +573,21 @@ static int stutter;
573 */ 573 */
574void stutter_wait(const char *title) 574void stutter_wait(const char *title)
575{ 575{
576 int spt;
577
576 cond_resched_rcu_qs(); 578 cond_resched_rcu_qs();
577 while (READ_ONCE(stutter_pause_test) || 579 spt = READ_ONCE(stutter_pause_test);
578 (torture_runnable && !READ_ONCE(*torture_runnable))) { 580 while (spt || (torture_runnable && !READ_ONCE(*torture_runnable))) {
579 if (stutter_pause_test) 581 if (spt == 1) {
580 if (READ_ONCE(stutter_pause_test) == 1) 582 schedule_timeout_interruptible(1);
581 schedule_timeout_interruptible(1); 583 } else if (spt == 2) {
582 else 584 while (READ_ONCE(stutter_pause_test))
583 while (READ_ONCE(stutter_pause_test)) 585 cond_resched();
584 cond_resched(); 586 } else {
585 else
586 schedule_timeout_interruptible(round_jiffies_relative(HZ)); 587 schedule_timeout_interruptible(round_jiffies_relative(HZ));
588 }
587 torture_shutdown_absorb(title); 589 torture_shutdown_absorb(title);
590 spt = READ_ONCE(stutter_pause_test);
588 } 591 }
589} 592}
590EXPORT_SYMBOL_GPL(stutter_wait); 593EXPORT_SYMBOL_GPL(stutter_wait);
@@ -597,17 +600,15 @@ static int torture_stutter(void *arg)
597{ 600{
598 VERBOSE_TOROUT_STRING("torture_stutter task started"); 601 VERBOSE_TOROUT_STRING("torture_stutter task started");
599 do { 602 do {
600 if (!torture_must_stop()) { 603 if (!torture_must_stop() && stutter > 1) {
601 if (stutter > 1) {
602 schedule_timeout_interruptible(stutter - 1);
603 WRITE_ONCE(stutter_pause_test, 2);
604 }
605 schedule_timeout_interruptible(1);
606 WRITE_ONCE(stutter_pause_test, 1); 604 WRITE_ONCE(stutter_pause_test, 1);
605 schedule_timeout_interruptible(stutter - 1);
606 WRITE_ONCE(stutter_pause_test, 2);
607 schedule_timeout_interruptible(1);
607 } 608 }
609 WRITE_ONCE(stutter_pause_test, 0);
608 if (!torture_must_stop()) 610 if (!torture_must_stop())
609 schedule_timeout_interruptible(stutter); 611 schedule_timeout_interruptible(stutter);
610 WRITE_ONCE(stutter_pause_test, 0);
611 torture_shutdown_absorb("torture_stutter"); 612 torture_shutdown_absorb("torture_stutter");
612 } while (!torture_must_stop()); 613 } while (!torture_must_stop());
613 torture_kthread_stopping("torture_stutter"); 614 torture_kthread_stopping("torture_stutter");