summaryrefslogtreecommitdiff
path: root/kernel/rcu/tree.c
diff options
context:
space:
mode:
authorPuranjay Mohan <puranjay@kernel.org>2026-07-24 11:31:23 -0700
committerPaul E. McKenney <paulmck@kernel.org>2026-07-24 16:52:56 -0700
commitaaca360ebb04ccd15a733bcbd863c2aebba8c1d5 (patch)
tree64910bbe7f12617006fdfdf554835408827f49d3 /kernel/rcu/tree.c
parent60b54875bd0ba87a7d39204e0cd494a29d22e72f (diff)
downloadlwn-aaca360ebb04ccd15a733bcbd863c2aebba8c1d5.tar.gz
lwn-aaca360ebb04ccd15a733bcbd863c2aebba8c1d5.zip
rcu: Enable RCU callbacks to benefit from expedited grace periods
Currently, RCU callbacks only track normal grace-period sequence numbers. This means callbacks must wait for normal grace periods to complete even when expedited grace periods have already elapsed. Use the full struct rcu_gp_seq (which tracks both the normal and expedited grace-period sequences) throughout the callback infrastructure. rcu_segcblist_advance() now checks both normal and expedited GP completion via poll_state_synchronize_rcu_full(), and becomes parameterless since it reads the grace-period state internally. rcu_segcblist_accelerate() stores the full state (both sequences) instead of just the normal one. rcu_accelerate_cbs() and rcu_accelerate_cbs_unlocked() use get_state_synchronize_rcu_full() to capture both sequences, and the NOCB advance checks use poll_state_synchronize_rcu_full() instead of comparing only the normal sequence. srcu_segcblist_advance() becomes a standalone implementation because it compares SRCU sequences directly and cannot use poll_state_synchronize_rcu_full(), which reads RCU-specific globals. srcu_segcblist_accelerate() sets the ->exp field to RCU_GET_STATE_NOT_TRACKED so that poll_state_synchronize_rcu_full() compares only ->norm and ignores ->exp. Signed-off-by: Puranjay Mohan <puranjay@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r--kernel/rcu/tree.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 640ebe055a24..f63ce75c5b4f 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1159,7 +1159,7 @@ static bool rcu_accelerate_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
* accelerating callback invocation to an earlier grace-period
* number.
*/
- gs.norm = rcu_seq_snap(&rcu_state.gp_seq);
+ get_state_synchronize_rcu_full(&gs);
if (rcu_segcblist_accelerate(&rdp->cblist, &gs))
ret = rcu_start_this_gp(rnp, rdp, gs.norm);
@@ -1188,7 +1188,7 @@ static void rcu_accelerate_cbs_unlocked(struct rcu_node *rnp,
bool needwake;
rcu_lockdep_assert_cblist_protected(rdp);
- gs.norm = rcu_seq_snap(&rcu_state.gp_seq);
+ get_state_synchronize_rcu_full(&gs);
if (!READ_ONCE(rdp->gpwrap) && ULONG_CMP_GE(rdp->gp_seq_needed, gs.norm)) {
/* Old request still live, so mark recent callbacks. */
(void)rcu_segcblist_accelerate(&rdp->cblist, &gs);
@@ -1213,8 +1213,6 @@ static void rcu_accelerate_cbs_unlocked(struct rcu_node *rnp,
*/
static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
{
- struct rcu_gp_seq gs;
-
rcu_lockdep_assert_cblist_protected(rdp);
raw_lockdep_assert_held_rcu_node(rnp);
@@ -1226,8 +1224,7 @@ static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
* Find all callbacks whose ->gp_seq numbers indicate that they
* are ready to invoke, and put them into the RCU_DONE_TAIL sublist.
*/
- gs.norm = rnp->gp_seq;
- rcu_segcblist_advance(&rdp->cblist, &gs);
+ rcu_segcblist_advance(&rdp->cblist);
/* Classify any remaining callbacks. */
return rcu_accelerate_cbs(rnp, rdp);