aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree_plugin.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-07-31 17:09:49 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-09-23 10:42:50 -0400
commit5cc900cf55fe58aaad93767c5a526e2a69cbcbc6 (patch)
treed6eb08a2df0797927d5288e2fa0ba9f2b8b1d4b6 /kernel/rcutree_plugin.h
parentb4270ee356e5ecef5394ab80c0a0301c1676b7f0 (diff)
rcu: Improve boost selection when moving tasks to root rcu_node
The rcu_preempt_offline_tasks() moves all tasks queued on a given leaf rcu_node structure to the root rcu_node, which is done when the last CPU corresponding the the leaf rcu_node structure goes offline. Now that RCU-preempt's synchronize_rcu_expedited() implementation blocks CPU-hotplug operations during the initialization of each rcu_node structure's ->boost_tasks pointer, rcu_preempt_offline_tasks() can do a better job of setting the root rcu_node's ->boost_tasks pointer. The key point is that rcu_preempt_offline_tasks() runs as part of the CPU-hotplug process, so that a concurrent synchronize_rcu_expedited() is guaranteed to either have not started on the one hand (in which case there is no boosting on behalf of the expedited grace period) or to be completely initialized on the other (in which case, in the absence of other priority boosting, all ->boost_tasks pointers will be initialized). Therefore, if rcu_preempt_offline_tasks() finds that the ->boost_tasks pointer is equal to the ->exp_tasks pointer, it can be sure that it is correctly placed. In the case where there was boosting ongoing at the time that the synchronize_rcu_expedited() function started, different nodes might start boosting the tasks blocking the expedited grace period at different times. In this mixed case, the root node will either be boosting tasks for the expedited grace period already, or it will start as soon as it gets done boosting for the normal grace period -- but in this latter case, the root node's tasks needed to be boosted in any case. This commit therefore adds a check of the ->boost_tasks pointer against the ->exp_tasks pointer to the list that prevents updating ->boost_tasks. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r--kernel/rcutree_plugin.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index b1b485111321..15d28febbbd4 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -588,10 +588,15 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
588 rnp->exp_tasks = NULL; 588 rnp->exp_tasks = NULL;
589#ifdef CONFIG_RCU_BOOST 589#ifdef CONFIG_RCU_BOOST
590 rnp->boost_tasks = NULL; 590 rnp->boost_tasks = NULL;
591 /* In case root is being boosted and leaf was not. */ 591 /*
592 * In case root is being boosted and leaf was not. Make sure
593 * that we boost the tasks blocking the current grace period
594 * in this case.
595 */
592 raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ 596 raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
593 if (rnp_root->boost_tasks != NULL && 597 if (rnp_root->boost_tasks != NULL &&
594 rnp_root->boost_tasks != rnp_root->gp_tasks) 598 rnp_root->boost_tasks != rnp_root->gp_tasks &&
599 rnp_root->boost_tasks != rnp_root->exp_tasks)
595 rnp_root->boost_tasks = rnp_root->gp_tasks; 600 rnp_root->boost_tasks = rnp_root->gp_tasks;
596 raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */ 601 raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
597#endif /* #ifdef CONFIG_RCU_BOOST */ 602#endif /* #ifdef CONFIG_RCU_BOOST */