Commit 18f08e75 authored by Paul E. McKenney's avatar Paul E. McKenney

rcu-tasks: Add trc_inspect_reader() checks for exiting critical section

Currently, trc_inspect_reader() treats a task exiting its RCU Tasks
Trace read-side critical section the same as being within that critical
section.  However, this can fail because that task might have already
checked its .need_qs field, which means that it might never decrement
the all-important trc_n_readers_need_end counter.  Of course, for that
to happen, the task would need to never again execute an RCU Tasks Trace
read-side critical section, but this really could happen if the system's
last trampoline was removed.  Note that exit from such a critical section
cannot be treated as a quiescent state due to the possibility of nested
critical sections.  This means that if trc_inspect_reader() sees a
negative nesting value, it must set up to try again later.

This commit therefore ignores tasks that are exiting their RCU Tasks
Trace read-side critical sections so that they will be rechecked later.

[ paulmck: Apply feedback from Neeraj Upadhyay and Boqun Feng. ]
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 96017bf9
...@@ -923,7 +923,7 @@ static void trc_read_check_handler(void *t_in) ...@@ -923,7 +923,7 @@ static void trc_read_check_handler(void *t_in)
static bool trc_inspect_reader(struct task_struct *t, void *arg) static bool trc_inspect_reader(struct task_struct *t, void *arg)
{ {
int cpu = task_cpu(t); int cpu = task_cpu(t);
bool in_qs = false; int nesting;
bool ofl = cpu_is_offline(cpu); bool ofl = cpu_is_offline(cpu);
if (task_curr(t)) { if (task_curr(t)) {
...@@ -943,18 +943,18 @@ static bool trc_inspect_reader(struct task_struct *t, void *arg) ...@@ -943,18 +943,18 @@ static bool trc_inspect_reader(struct task_struct *t, void *arg)
n_heavy_reader_updates++; n_heavy_reader_updates++;
if (ofl) if (ofl)
n_heavy_reader_ofl_updates++; n_heavy_reader_ofl_updates++;
in_qs = true; nesting = 0;
} else { } else {
// The task is not running, so C-language access is safe. // The task is not running, so C-language access is safe.
in_qs = likely(!t->trc_reader_nesting); nesting = t->trc_reader_nesting;
} }
// Mark as checked so that the grace-period kthread will // If not exiting a read-side critical section, mark as checked
// remove it from the holdout list. // so that the grace-period kthread will remove it from the
t->trc_reader_checked = true; // holdout list.
t->trc_reader_checked = nesting >= 0;
if (in_qs) if (nesting <= 0)
return true; // Already in quiescent state, done!!! return !nesting; // If in QS, done, otherwise try again later.
// The task is in a read-side critical section, so set up its // The task is in a read-side critical section, so set up its
// state so that it will awaken the grace-period kthread upon exit // state so that it will awaken the grace-period kthread upon exit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment