Commit 218b957a authored by David Woodhouse's avatar David Woodhouse Committed by Paul E. McKenney
Browse files

rcu: Add mutex for rcu boost kthread spawning and affinity setting



As we handle parallel CPU bringup, we will need to take care to avoid
spawning multiple boost threads, or race conditions when setting their
affinity. Spotted by Paul McKenney.

Signed-off-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 150154aa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4570,6 +4570,7 @@ static void __init rcu_init_one(void)
			init_waitqueue_head(&rnp->exp_wq[2]);
			init_waitqueue_head(&rnp->exp_wq[3]);
			spin_lock_init(&rnp->exp_lock);
			mutex_init(&rnp->boost_kthread_mutex);
		}
	}

+3 −0
Original line number Diff line number Diff line
@@ -110,6 +110,9 @@ struct rcu_node {
				/*  side effect, not as a lock. */
	unsigned long boost_time;
				/* When to start boosting (jiffies). */
	struct mutex boost_kthread_mutex;
				/* Exclusion for thread spawning and affinity */
				/*  manipulation. */
	struct task_struct *boost_kthread_task;
				/* kthread that takes care of priority */
				/*  boosting for this rcu_node structure. */
+8 −2
Original line number Diff line number Diff line
@@ -1172,15 +1172,16 @@ static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp)
	struct sched_param sp;
	struct task_struct *t;

	mutex_lock(&rnp->boost_kthread_mutex);
	if (rnp->boost_kthread_task || !rcu_scheduler_fully_active)
		return;
		goto out;

	rcu_state.boost = 1;

	t = kthread_create(rcu_boost_kthread, (void *)rnp,
			   "rcub/%d", rnp_index);
	if (WARN_ON_ONCE(IS_ERR(t)))
		return;
		goto out;

	raw_spin_lock_irqsave_rcu_node(rnp, flags);
	rnp->boost_kthread_task = t;
@@ -1188,6 +1189,9 @@ static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp)
	sp.sched_priority = kthread_prio;
	sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
	wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */

 out:
	mutex_unlock(&rnp->boost_kthread_mutex);
}

/*
@@ -1210,6 +1214,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
		return;
	if (!zalloc_cpumask_var(&cm, GFP_KERNEL))
		return;
	mutex_lock(&rnp->boost_kthread_mutex);
	for_each_leaf_node_possible_cpu(rnp, cpu)
		if ((mask & leaf_node_cpu_bit(rnp, cpu)) &&
		    cpu != outgoingcpu)
@@ -1218,6 +1223,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
	if (cpumask_weight(cm) == 0)
		cpumask_copy(cm, housekeeping_cpumask(HK_FLAG_RCU));
	set_cpus_allowed_ptr(t, cm);
	mutex_unlock(&rnp->boost_kthread_mutex);
	free_cpumask_var(cm);
}