Skip to content

Commit cca42bd

Browse files
joelagnelFrederic Weisbecker
authored andcommitted
rcutorture: Fix stuttering races and other issues
The stuttering code isn't functioning as expected. Ideally, it should pause the torture threads for a designated period before resuming. Yet, it fails to halt the test for the correct duration. Additionally, a race condition exists, potentially causing the stuttering code to pause for an extended period if the 'spt' variable is non-zero due to the stutter orchestration thread's inadequate CPU time. Moreover, over-stuttering can hinder RCU's progress on TREE07 kernels. This happens as the stuttering code may run within a softirq due to RCU callbacks. Consequently, ksoftirqd keeps a CPU busy for several seconds, thus obstructing RCU's progress. This situation triggers a warning message in the logs: [ 2169.481783] rcu_torture_writer: rtort_pipe_count: 9 This warning suggests that an RCU torture object, although invisible to RCU readers, couldn't make it past the pipe array and be freed -- a strong indication that there weren't enough grace periods during the stutter interval. To address these issues, this patch sets the "stutter end" time to an absolute point in the future set by the main stutter thread. This is then used for waiting in stutter_wait(). While the stutter thread still defines this absolute time, the waiters' waiting logic doesn't rely on the stutter thread receiving sufficient CPU time to halt the stuttering as the halting is now self-controlled. Cc: [email protected] Signed-off-by: Joel Fernandes (Google) <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]>
1 parent 65b73f1 commit cca42bd

File tree

1 file changed

+12
-33
lines changed

1 file changed

+12
-33
lines changed

kernel/torture.c

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ static void torture_shutdown_cleanup(void)
720720
* suddenly applied to or removed from the system.
721721
*/
722722
static struct task_struct *stutter_task;
723-
static int stutter_pause_test;
723+
static ktime_t stutter_till_abs_time;
724724
static int stutter;
725725
static int stutter_gap;
726726

@@ -730,30 +730,16 @@ static int stutter_gap;
730730
*/
731731
bool stutter_wait(const char *title)
732732
{
733-
unsigned int i = 0;
734733
bool ret = false;
735-
int spt;
734+
ktime_t till_ns;
736735

737736
cond_resched_tasks_rcu_qs();
738-
spt = READ_ONCE(stutter_pause_test);
739-
for (; spt; spt = READ_ONCE(stutter_pause_test)) {
740-
if (!ret && !rt_task(current)) {
741-
sched_set_normal(current, MAX_NICE);
742-
ret = true;
743-
}
744-
if (spt == 1) {
745-
torture_hrtimeout_jiffies(1, NULL);
746-
} else if (spt == 2) {
747-
while (READ_ONCE(stutter_pause_test)) {
748-
if (!(i++ & 0xffff))
749-
torture_hrtimeout_us(10, 0, NULL);
750-
cond_resched();
751-
}
752-
} else {
753-
torture_hrtimeout_jiffies(round_jiffies_relative(HZ), NULL);
754-
}
755-
torture_shutdown_absorb(title);
737+
till_ns = READ_ONCE(stutter_till_abs_time);
738+
if (till_ns && ktime_before(ktime_get(), till_ns)) {
739+
torture_hrtimeout_ns(till_ns, 0, HRTIMER_MODE_ABS, NULL);
740+
ret = true;
756741
}
742+
torture_shutdown_absorb(title);
757743
return ret;
758744
}
759745
EXPORT_SYMBOL_GPL(stutter_wait);
@@ -764,23 +750,16 @@ EXPORT_SYMBOL_GPL(stutter_wait);
764750
*/
765751
static int torture_stutter(void *arg)
766752
{
767-
DEFINE_TORTURE_RANDOM(rand);
768-
int wtime;
753+
ktime_t till_ns;
769754

770755
VERBOSE_TOROUT_STRING("torture_stutter task started");
771756
do {
772757
if (!torture_must_stop() && stutter > 1) {
773-
wtime = stutter;
774-
if (stutter > 2) {
775-
WRITE_ONCE(stutter_pause_test, 1);
776-
wtime = stutter - 3;
777-
torture_hrtimeout_jiffies(wtime, &rand);
778-
wtime = 2;
779-
}
780-
WRITE_ONCE(stutter_pause_test, 2);
781-
torture_hrtimeout_jiffies(wtime, NULL);
758+
till_ns = ktime_add_ns(ktime_get(),
759+
jiffies_to_nsecs(stutter));
760+
WRITE_ONCE(stutter_till_abs_time, till_ns);
761+
torture_hrtimeout_jiffies(stutter - 1, NULL);
782762
}
783-
WRITE_ONCE(stutter_pause_test, 0);
784763
if (!torture_must_stop())
785764
torture_hrtimeout_jiffies(stutter_gap, NULL);
786765
torture_shutdown_absorb("torture_stutter");

0 commit comments

Comments
 (0)