Skip to content

Commit 02e3024

Browse files
Neeraj Upadhyaypaulmckrcu
authored andcommitted
rcu/nocb: Handle concurrent nocb kthreads creation
When multiple CPUs in the same nocb gp/cb group concurrently come online, they might try to concurrently create the same rcuog kthread. Fix this by using nocb gp CPU's spawn mutex to provide mutual exclusion for the rcuog kthread creation code. [ paulmck: Whitespace fixes per kernel test robot feedback. ] Acked-by: David Woodhouse <dwmw@amazon.co.uk> Signed-off-by: Neeraj Upadhyay <quic_neeraju@quicinc.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
1 parent a47f9f1 commit 02e3024

2 files changed

Lines changed: 8 additions & 1 deletion

File tree

kernel/rcu/tree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ struct rcu_data {
203203
int nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */
204204
struct timer_list nocb_timer; /* Enforce finite deferral. */
205205
unsigned long nocb_gp_adv_time; /* Last call_rcu() CB adv (jiffies). */
206+
struct mutex nocb_gp_kthread_mutex; /* Exclusion for nocb gp kthread */
207+
/* spawning */
206208

207209
/* The following fields are used by call_rcu, hence own cacheline. */
208210
raw_spinlock_t nocb_bypass_lock ____cacheline_internodealigned_in_smp;

kernel/rcu/tree_nocb.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
12261226
raw_spin_lock_init(&rdp->nocb_gp_lock);
12271227
timer_setup(&rdp->nocb_timer, do_nocb_deferred_wakeup_timer, 0);
12281228
rcu_cblist_init(&rdp->nocb_bypass);
1229+
mutex_init(&rdp->nocb_gp_kthread_mutex);
12291230
}
12301231

12311232
/*
@@ -1248,13 +1249,17 @@ static void rcu_spawn_cpu_nocb_kthread(int cpu)
12481249

12491250
/* If we didn't spawn the GP kthread first, reorganize! */
12501251
rdp_gp = rdp->nocb_gp_rdp;
1252+
mutex_lock(&rdp_gp->nocb_gp_kthread_mutex);
12511253
if (!rdp_gp->nocb_gp_kthread) {
12521254
t = kthread_run(rcu_nocb_gp_kthread, rdp_gp,
12531255
"rcuog/%d", rdp_gp->cpu);
1254-
if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo GP kthread, OOM is now expected behavior\n", __func__))
1256+
if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo GP kthread, OOM is now expected behavior\n", __func__)) {
1257+
mutex_unlock(&rdp_gp->nocb_gp_kthread_mutex);
12551258
return;
1259+
}
12561260
WRITE_ONCE(rdp_gp->nocb_gp_kthread, t);
12571261
}
1262+
mutex_unlock(&rdp_gp->nocb_gp_kthread_mutex);
12581263

12591264
/* Spawn the kthread for this CPU. */
12601265
t = kthread_run(rcu_nocb_cb_kthread, rdp,

0 commit comments

Comments
 (0)