Skip to content

Commit d761de8

Browse files
committed
rcu: Make synchronize_rcu() fastpath update only boot-CPU counters
Large systems can have hundreds of rcu_node structures, and updating counters in each of them might slow down booting. This commit therefore updates only the counters in those rcu_node structures corresponding to the boot CPU, up to and including the root rcu_node structure. The counters for the remaining rcu_node structures are updated by the rcu_scheduler_starting() function, which executes just before the first non-boot kthread is spawned. Signed-off-by: Paul E. McKenney <[email protected]>
1 parent b3cdd0a commit d761de8

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

kernel/rcu/tree.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3504,11 +3504,14 @@ void synchronize_rcu(void)
35043504
rcu_poll_gp_seq_start_unlocked(&rcu_state.gp_seq_polled_snap);
35053505
rcu_poll_gp_seq_end_unlocked(&rcu_state.gp_seq_polled_snap);
35063506

3507-
// Update normal grace-period counters to record grace period.
3507+
// Update the normal grace-period counters to record
3508+
// this grace period, but only those used by the boot CPU.
3509+
// The rcu_scheduler_starting() will take care of the rest of
3510+
// these counters.
35083511
local_irq_save(flags);
35093512
WARN_ON_ONCE(num_online_cpus() > 1);
35103513
rcu_state.gp_seq += (1 << RCU_SEQ_CTR_SHIFT);
3511-
rcu_for_each_node_breadth_first(rnp)
3514+
for (rnp = this_cpu_ptr(&rcu_data)->mynode; rnp; rnp = rnp->parent)
35123515
rnp->gp_seq_needed = rnp->gp_seq = rcu_state.gp_seq;
35133516
local_irq_restore(flags);
35143517
}
@@ -4456,9 +4459,20 @@ early_initcall(rcu_spawn_gp_kthread);
44564459
*/
44574460
void rcu_scheduler_starting(void)
44584461
{
4462+
unsigned long flags;
4463+
struct rcu_node *rnp;
4464+
44594465
WARN_ON(num_online_cpus() != 1);
44604466
WARN_ON(nr_context_switches() > 0);
44614467
rcu_test_sync_prims();
4468+
4469+
// Fix up the ->gp_seq counters.
4470+
local_irq_save(flags);
4471+
rcu_for_each_node_breadth_first(rnp)
4472+
rnp->gp_seq_needed = rnp->gp_seq = rcu_state.gp_seq;
4473+
local_irq_restore(flags);
4474+
4475+
// Switch out of early boot mode.
44624476
rcu_scheduler_active = RCU_SCHEDULER_INIT;
44634477
rcu_test_sync_prims();
44644478
}

0 commit comments

Comments
 (0)