Skip to content

Commit 885a6f4

Browse files
paulmckrcuurezki
authored andcommitted
rcutorture: Read CPU ID for decoration protected by both reader types
Currently, rcutorture_one_extend() reads the CPU ID before making any change to the type of RCU reader. This can be confusing because the properties of the code from which the CPU ID is read are not that of the reader segment that this same CPU ID is listed with. This commit therefore causes rcutorture_one_extend() to read the CPU ID just after the new protections have been added, but before the old protections have been removed. With this change in place, all of the protections of a given reader segment apply from the reading of one CPU ID to the reading of the next. This change therefore also allows a single read of the CPU ID to work for both the old and the new reader segment. And this dual use of a single read of the CPU ID avoids inflicting any additional to heisenbugs. Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
1 parent c31569e commit 885a6f4

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

kernel/rcu/rcutorture.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,12 @@ struct rt_read_seg {
271271
unsigned long rt_delay_us;
272272
bool rt_preempted;
273273
int rt_cpu;
274+
int rt_end_cpu;
274275
};
275276
static int err_segs_recorded;
276277
static struct rt_read_seg err_segs[RCUTORTURE_RDR_MAX_SEGS];
277278
static int rt_read_nsegs;
278279
static int rt_read_preempted;
279-
static int rt_last_cpu;
280280

281281
static const char *rcu_torture_writer_state_getname(void)
282282
{
@@ -1922,6 +1922,7 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
19221922
struct torture_random_state *trsp,
19231923
struct rt_read_seg *rtrsp)
19241924
{
1925+
bool first;
19251926
unsigned long flags;
19261927
int idxnew1 = -1;
19271928
int idxnew2 = -1;
@@ -1930,12 +1931,11 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
19301931
int statesnew = ~*readstate & newstate;
19311932
int statesold = *readstate & ~newstate;
19321933

1934+
first = idxold1 == 0;
19331935
WARN_ON_ONCE(idxold2 < 0);
19341936
WARN_ON_ONCE(idxold2 & ~RCUTORTURE_RDR_ALLBITS);
19351937
rcutorture_one_extend_check("before change", idxold1, statesnew, statesold, insoftirq);
19361938
rtrsp->rt_readstate = newstate;
1937-
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU))
1938-
rtrsp->rt_cpu = raw_smp_processor_id();
19391939

19401940
/* First, put new protection in place to avoid critical-section gap. */
19411941
if (statesnew & RCUTORTURE_RDR_BH)
@@ -1957,6 +1957,14 @@ static void rcutorture_one_extend(int *readstate, int newstate, bool insoftirq,
19571957
rcutorture_one_extend_check("during change",
19581958
idxold1 | statesnew, statesnew, statesold, insoftirq);
19591959

1960+
// Sample CPU under both sets of protections to reduce confusion.
1961+
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU)) {
1962+
int cpu = raw_smp_processor_id();
1963+
rtrsp->rt_cpu = cpu;
1964+
if (!first)
1965+
rtrsp[-1].rt_end_cpu = cpu;
1966+
}
1967+
19601968
/*
19611969
* Next, remove old protection, in decreasing order of strength
19621970
* to avoid unlock paths that aren't safe in the stronger
@@ -2178,8 +2186,6 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
21782186
}
21792187
if (cur_ops->reader_blocked)
21802188
preempted = cur_ops->reader_blocked();
2181-
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU))
2182-
rt_last_cpu = raw_smp_processor_id();
21832189
rcutorture_one_extend(&readstate, 0, myid < 0, trsp, rtrsp);
21842190
WARN_ON_ONCE(readstate);
21852191
// This next splat is expected behavior if leakpointer, especially
@@ -3634,8 +3640,13 @@ rcu_torture_cleanup(void)
36343640
err_segs[i].rt_delay_jiffies);
36353641
firsttime = 0;
36363642
}
3637-
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU))
3638-
pr_cont(" CPU %-2d", err_segs[i].rt_cpu);
3643+
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU)) {
3644+
pr_cont(" CPU %2d", err_segs[i].rt_cpu);
3645+
if (err_segs[i].rt_cpu != err_segs[i].rt_end_cpu)
3646+
pr_cont("->%-2d", err_segs[i].rt_end_cpu);
3647+
else
3648+
pr_cont(" ...");
3649+
}
36393650
if (err_segs[i].rt_delay_ms != 0) {
36403651
pr_cont(" %s%ldms", firsttime ? "" : "+",
36413652
err_segs[i].rt_delay_ms);
@@ -3666,8 +3677,6 @@ rcu_torture_cleanup(void)
36663677
}
36673678
if (rt_read_preempted)
36683679
pr_alert("\tReader was preempted.\n");
3669-
if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU))
3670-
pr_alert("\tReader last ran on CPU %d.\n", rt_last_cpu);
36713680
}
36723681
if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
36733682
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");

0 commit comments

Comments
 (0)