summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-11-22 00:01:02 +0100
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-12-11 18:18:29 +0100
commit4ced3314fd3a73dabac4e8a41747883eff36c3e8 (patch)
treeaba2f62defd17a44cb3a0b6b7c8effa98ce5c7cd
parentlocking/locktorture: Fix num reader/writer corner cases (diff)
downloadlinux-4ced3314fd3a73dabac4e8a41747883eff36c3e8.tar.xz
linux-4ced3314fd3a73dabac4e8a41747883eff36c3e8.zip
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;
*/
void stutter_wait(const char *title)
{
+ int spt;
+
cond_resched_rcu_qs();
- while (READ_ONCE(stutter_pause_test) ||
- (torture_runnable && !READ_ONCE(*torture_runnable))) {
- if (stutter_pause_test)
- if (READ_ONCE(stutter_pause_test) == 1)
- schedule_timeout_interruptible(1);
- else
- while (READ_ONCE(stutter_pause_test))
- cond_resched();
- else
+ spt = READ_ONCE(stutter_pause_test);
+ while (spt || (torture_runnable && !READ_ONCE(*torture_runnable))) {
+ if (spt == 1) {
+ schedule_timeout_interruptible(1);
+ } else if (spt == 2) {
+ while (READ_ONCE(stutter_pause_test))
+ cond_resched();
+ } else {
schedule_timeout_interruptible(round_jiffies_relative(HZ));
+ }
torture_shutdown_absorb(title);
+ spt = READ_ONCE(stutter_pause_test);
}
}
EXPORT_SYMBOL_GPL(stutter_wait);
@@ -597,17 +600,15 @@ static int torture_stutter(void *arg)
{
VERBOSE_TOROUT_STRING("torture_stutter task started");
do {
- if (!torture_must_stop()) {
- if (stutter > 1) {
- schedule_timeout_interruptible(stutter - 1);
- WRITE_ONCE(stutter_pause_test, 2);
- }
- schedule_timeout_interruptible(1);
+ if (!torture_must_stop() && stutter > 1) {
WRITE_ONCE(stutter_pause_test, 1);
+ schedule_timeout_interruptible(stutter - 1);
+ WRITE_ONCE(stutter_pause_test, 2);
+ schedule_timeout_interruptible(1);
}
+ WRITE_ONCE(stutter_pause_test, 0);
if (!torture_must_stop())
schedule_timeout_interruptible(stutter);
- WRITE_ONCE(stutter_pause_test, 0);
torture_shutdown_absorb("torture_stutter");
} while (!torture_must_stop());
torture_kthread_stopping("torture_stutter");