diff options
| author | Paul E. McKenney <paulmck@kernel.org> | 2023-08-02 13:42:00 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-11-08 16:28:22 +0100 |
| commit | 01a2b99ffcca885eb553c763a3603f1ad9678b52 (patch) | |
| tree | a7fc13f44a9e469e77866ad30a06184336312331 /include | |
| parent | 7d85884576a3be3616c260fc1fa862a59579d1ab (diff) | |
| download | linux-01a2b99ffcca885eb553c763a3603f1ad9678b52.tar.gz linux-01a2b99ffcca885eb553c763a3603f1ad9678b52.tar.bz2 linux-01a2b99ffcca885eb553c763a3603f1ad9678b52.zip | |
rcu-tasks: Pull sampling of ->percpu_dequeue_lim out of loop
[ Upstream commit e62d8ae4620865411d1b2347980aa28ccf891a3d ]
The rcu_tasks_need_gpcb() samples ->percpu_dequeue_lim as part of the
condition clause of a "for" loop, which is a bit confusing. This commit
therefore hoists this sampling out of the loop, using the result loaded
in the condition clause.
So why does this work in the face of a concurrent switch from single-CPU
queueing to per-CPU queueing?
o The call_rcu_tasks_generic() that makes the change has already
enqueued its callback, which means that all of the other CPU's
callback queues are empty.
o For the call_rcu_tasks_generic() that first notices
the switch to per-CPU queues, the smp_store_release()
used to update ->percpu_enqueue_lim pairs with the
raw_spin_trylock_rcu_node()'s full barrier that is
between the READ_ONCE(rtp->percpu_enqueue_shift) and the
rcu_segcblist_enqueue() that enqueues the callback.
o Because this CPU's queue is empty (unless it happens to
be the original single queue, in which case there is no
need for synchronization), this call_rcu_tasks_generic()
will do an irq_work_queue() to schedule a handler for the
needed rcuwait_wake_up() call. This call will be ordered
after the first call_rcu_tasks_generic() function's change to
->percpu_dequeue_lim.
o This rcuwait_wake_up() will either happen before or after the
set_current_state() in rcuwait_wait_event(). If it happens
before, the "condition" argument's call to rcu_tasks_need_gpcb()
will be ordered after the original change, and all callbacks on
all CPUs will be visible. Otherwise, if it happens after, then
the grace-period kthread's state will be set back to running,
which will result in a later call to rcuwait_wait_event() and
thus to rcu_tasks_need_gpcb(), which will again see the change.
So it all works out.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Stable-dep-of: fd70e9f1d85f ("rcu-tasks: Fix access non-existent percpu rtpcp variable in rcu_tasks_need_gpcb()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions
