Skip to content

Commit 15c7c97

Browse files
committed
rcu: Use *_ONCE() to protect lockless ->expmask accesses
The rcu_node structure's ->expmask field is accessed locklessly when starting a new expedited grace period and when reporting an expedited RCU CPU stall warning. This commit therefore handles the former by taking a snapshot of ->expmask while the lock is held and the latter by applying READ_ONCE() to lockless reads and WRITE_ONCE() to the corresponding updates. Link: https://lore.kernel.org/lkml/CANpmjNNmSOagbTpffHr4=Yedckx9Rm2NuGqC9UqE+AOz5f1-ZQ@mail.gmail.com Reported-by: [email protected] Signed-off-by: Paul E. McKenney <[email protected]> Acked-by: Marco Elver <[email protected]>
1 parent e42617b commit 15c7c97

File tree

1 file changed

+9
-10
lines changed

1 file changed

+9
-10
lines changed

kernel/rcu/tree_exp.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static void __maybe_unused sync_exp_reset_tree(void)
134134
rcu_for_each_node_breadth_first(rnp) {
135135
raw_spin_lock_irqsave_rcu_node(rnp, flags);
136136
WARN_ON_ONCE(rnp->expmask);
137-
rnp->expmask = rnp->expmaskinit;
137+
WRITE_ONCE(rnp->expmask, rnp->expmaskinit);
138138
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
139139
}
140140
}
@@ -211,7 +211,7 @@ static void __rcu_report_exp_rnp(struct rcu_node *rnp,
211211
rnp = rnp->parent;
212212
raw_spin_lock_rcu_node(rnp); /* irqs already disabled */
213213
WARN_ON_ONCE(!(rnp->expmask & mask));
214-
rnp->expmask &= ~mask;
214+
WRITE_ONCE(rnp->expmask, rnp->expmask & ~mask);
215215
}
216216
}
217217

@@ -241,7 +241,7 @@ static void rcu_report_exp_cpu_mult(struct rcu_node *rnp,
241241
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
242242
return;
243243
}
244-
rnp->expmask &= ~mask;
244+
WRITE_ONCE(rnp->expmask, rnp->expmask & ~mask);
245245
__rcu_report_exp_rnp(rnp, wake, flags); /* Releases rnp->lock. */
246246
}
247247

@@ -372,12 +372,10 @@ static void sync_rcu_exp_select_node_cpus(struct work_struct *wp)
372372
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
373373

374374
/* IPI the remaining CPUs for expedited quiescent state. */
375-
for_each_leaf_node_cpu_mask(rnp, cpu, rnp->expmask) {
375+
for_each_leaf_node_cpu_mask(rnp, cpu, mask_ofl_ipi) {
376376
unsigned long mask = leaf_node_cpu_bit(rnp, cpu);
377377
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
378378

379-
if (!(mask_ofl_ipi & mask))
380-
continue;
381379
retry_ipi:
382380
if (rcu_dynticks_in_eqs_since(rdp, rdp->exp_dynticks_snap)) {
383381
mask_ofl_test |= mask;
@@ -491,7 +489,7 @@ static void synchronize_sched_expedited_wait(void)
491489
struct rcu_data *rdp;
492490

493491
mask = leaf_node_cpu_bit(rnp, cpu);
494-
if (!(rnp->expmask & mask))
492+
if (!(READ_ONCE(rnp->expmask) & mask))
495493
continue;
496494
ndetected++;
497495
rdp = per_cpu_ptr(&rcu_data, cpu);
@@ -503,7 +501,8 @@ static void synchronize_sched_expedited_wait(void)
503501
}
504502
pr_cont(" } %lu jiffies s: %lu root: %#lx/%c\n",
505503
jiffies - jiffies_start, rcu_state.expedited_sequence,
506-
rnp_root->expmask, ".T"[!!rnp_root->exp_tasks]);
504+
READ_ONCE(rnp_root->expmask),
505+
".T"[!!rnp_root->exp_tasks]);
507506
if (ndetected) {
508507
pr_err("blocking rcu_node structures:");
509508
rcu_for_each_node_breadth_first(rnp) {
@@ -513,15 +512,15 @@ static void synchronize_sched_expedited_wait(void)
513512
continue;
514513
pr_cont(" l=%u:%d-%d:%#lx/%c",
515514
rnp->level, rnp->grplo, rnp->grphi,
516-
rnp->expmask,
515+
READ_ONCE(rnp->expmask),
517516
".T"[!!rnp->exp_tasks]);
518517
}
519518
pr_cont("\n");
520519
}
521520
rcu_for_each_leaf_node(rnp) {
522521
for_each_leaf_node_possible_cpu(rnp, cpu) {
523522
mask = leaf_node_cpu_bit(rnp, cpu);
524-
if (!(rnp->expmask & mask))
523+
if (!(READ_ONCE(rnp->expmask) & mask))
525524
continue;
526525
dump_cpu_task(cpu);
527526
}

0 commit comments

Comments
 (0)