Skip to content

Commit

Permalink
rcutorture: Check preemption for failing reader
Browse files Browse the repository at this point in the history
This commit checks to see if the RCU reader has been preempted within
its read-side critical section for RCU flavors supporting this notion
(currently only preemptible RCU).  If such a preemption occurred, then
this is printed at the end of the "Failure/close-call rcutorture reader
segments" list at the end of the rcutorture run.

[ paulmck: Apply kernel test robot feedback. ]

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Frederic Weisbecker <frederic@kernel.org>
Tested-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
  • Loading branch information
paulmckrcu authored and urezki committed Dec 14, 2024
1 parent 4569cf6 commit 0f38c06
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
11 changes: 11 additions & 0 deletions include/linux/rcupdate_wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,15 @@ static inline void cond_resched_rcu(void)
#endif
}

// Has the current task blocked within its current RCU read-side
// critical section?
static inline bool has_rcu_reader_blocked(void)
{
#ifdef CONFIG_PREEMPT_RCU
return !list_empty(&current->rcu_node_entry);
#else
return false;
#endif
}

#endif /* _LINUX_SCHED_RCUPDATE_WAIT_H */
11 changes: 11 additions & 0 deletions kernel/rcu/rcutorture.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ struct rt_read_seg {
static int err_segs_recorded;
static struct rt_read_seg err_segs[RCUTORTURE_RDR_MAX_SEGS];
static int rt_read_nsegs;
static int rt_read_preempted;

static const char *rcu_torture_writer_state_getname(void)
{
Expand Down Expand Up @@ -394,6 +395,7 @@ struct rcu_torture_ops {
void (*get_gp_data)(int *flags, unsigned long *gp_seq);
void (*gp_slow_register)(atomic_t *rgssp);
void (*gp_slow_unregister)(atomic_t *rgssp);
bool (*reader_blocked)(void);
long cbflood_max;
int irq_capable;
int can_boost;
Expand Down Expand Up @@ -587,6 +589,9 @@ static struct rcu_torture_ops rcu_ops = {
.get_gp_data = rcutorture_get_gp_data,
.gp_slow_register = rcu_gp_slow_register,
.gp_slow_unregister = rcu_gp_slow_unregister,
.reader_blocked = IS_ENABLED(CONFIG_RCU_TORTURE_TEST_LOG_CPU)
? has_rcu_reader_blocked
: NULL,
.irq_capable = 1,
.can_boost = IS_ENABLED(CONFIG_RCU_BOOST),
.extendables = RCUTORTURE_MAX_EXTEND,
Expand Down Expand Up @@ -2035,6 +2040,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
int newstate;
struct rcu_torture *p;
int pipe_count;
bool preempted = false;
int readstate = 0;
struct rt_read_seg rtseg[RCUTORTURE_RDR_MAX_SEGS] = { { 0 } };
struct rt_read_seg *rtrsp = &rtseg[0];
Expand Down Expand Up @@ -2100,6 +2106,8 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
rcu_torture_writer_state,
cpumask_pr_args(cpu_online_mask));
}
if (cur_ops->reader_blocked)
preempted = cur_ops->reader_blocked();
rcutorture_one_extend(&readstate, 0, trsp, rtrsp);
WARN_ON_ONCE(readstate);
// This next splat is expected behavior if leakpointer, especially
Expand All @@ -2112,6 +2120,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
for (rtrsp1 = &rtseg[0]; rtrsp1 < rtrsp; rtrsp1++)
err_segs[i++] = *rtrsp1;
rt_read_nsegs = i;
rt_read_preempted = preempted;
}

return true;
Expand Down Expand Up @@ -3569,6 +3578,8 @@ rcu_torture_cleanup(void)
pr_cont("\n");

}
if (rt_read_preempted)
pr_alert("\tReader was preempted.\n");
}
if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
Expand Down

0 comments on commit 0f38c06

Please sign in to comment.