aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-06-26 15:23:46 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-07-25 16:04:47 -0400
commitb1a2d79fe7d210c114003362d93d529912d244df (patch)
treef739fab6c1a267b7da1d1e611cab4ad9b4a97ddc /kernel
parent95335c0355834c16cc11f041a981ee6782dba2e9 (diff)
rcu: Make NOCB CPUs migrate CBs directly from outgoing CPU
RCU's CPU-hotplug callback-migration code first moves the outgoing CPU's callbacks to ->orphan_done and ->orphan_pend, and only then moves them to the NOCB callback list. This commit avoids the extra step (and simplifies the code) by moving the callbacks directly from the outgoing CPU's callback list to the NOCB callback list. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/tree.c14
-rw-r--r--kernel/rcu/tree.h2
-rw-r--r--kernel/rcu/tree_plugin.h31
3 files changed, 19 insertions, 28 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index aeea697d6f9f..4ea28e820f4a 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3899,11 +3899,6 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
3899 3899
3900 lockdep_assert_held(&rsp->orphan_lock); 3900 lockdep_assert_held(&rsp->orphan_lock);
3901 3901
3902 /* No-CBs CPUs are handled specially. */
3903 if (!IS_ENABLED(CONFIG_HOTPLUG_CPU) ||
3904 rcu_nocb_adopt_orphan_cbs(rsp, rdp, flags))
3905 return;
3906
3907 /* Do the accounting first. */ 3902 /* Do the accounting first. */
3908 if (rsp->orphan_done.len_lazy != rsp->orphan_done.len) 3903 if (rsp->orphan_done.len_lazy != rsp->orphan_done.len)
3909 rcu_idle_count_callbacks_posted(); 3904 rcu_idle_count_callbacks_posted();
@@ -3928,13 +3923,20 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
3928static void rcu_migrate_callbacks(int cpu, struct rcu_state *rsp) 3923static void rcu_migrate_callbacks(int cpu, struct rcu_state *rsp)
3929{ 3924{
3930 unsigned long flags; 3925 unsigned long flags;
3926 struct rcu_data *my_rdp;
3931 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); 3927 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
3932 struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */ 3928 struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
3933 3929
3934 if (rcu_is_nocb_cpu(cpu) || rcu_segcblist_empty(&rdp->cblist)) 3930 if (rcu_is_nocb_cpu(cpu) || rcu_segcblist_empty(&rdp->cblist))
3935 return; /* No callbacks to migrate. */ 3931 return; /* No callbacks to migrate. */
3936 3932
3937 raw_spin_lock_irqsave(&rsp->orphan_lock, flags); 3933 local_irq_save(flags);
3934 my_rdp = this_cpu_ptr(rsp->rda);
3935 if (rcu_nocb_adopt_orphan_cbs(my_rdp, rdp, flags)) {
3936 local_irq_restore(flags);
3937 return;
3938 }
3939 raw_spin_lock(&rsp->orphan_lock); /* irqs already disabled. */
3938 rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp); 3940 rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
3939 rcu_adopt_orphan_cbs(rsp, flags); 3941 rcu_adopt_orphan_cbs(rsp, flags);
3940 raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags); 3942 raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index aec53c4d4aec..574513cf49b4 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -493,7 +493,7 @@ static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq);
493static void rcu_init_one_nocb(struct rcu_node *rnp); 493static void rcu_init_one_nocb(struct rcu_node *rnp);
494static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, 494static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
495 bool lazy, unsigned long flags); 495 bool lazy, unsigned long flags);
496static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, 496static bool rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
497 struct rcu_data *rdp, 497 struct rcu_data *rdp,
498 unsigned long flags); 498 unsigned long flags);
499static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp); 499static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 908b309d60d7..ff7d5ee49816 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1961,30 +1961,19 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
1961 * Adopt orphaned callbacks on a no-CBs CPU, or return 0 if this is 1961 * Adopt orphaned callbacks on a no-CBs CPU, or return 0 if this is
1962 * not a no-CBs CPU. 1962 * not a no-CBs CPU.
1963 */ 1963 */
1964static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, 1964static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
1965 struct rcu_data *rdp, 1965 struct rcu_data *rdp,
1966 unsigned long flags) 1966 unsigned long flags)
1967{ 1967{
1968 long ql = rsp->orphan_done.len; 1968 RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_nocb_adopt_orphan_cbs() invoked with irqs enabled!!!");
1969 long qll = rsp->orphan_done.len_lazy;
1970
1971 /* If this is not a no-CBs CPU, tell the caller to do it the old way. */
1972 if (!rcu_is_nocb_cpu(smp_processor_id())) 1969 if (!rcu_is_nocb_cpu(smp_processor_id()))
1973 return false; 1970 return false; /* Not NOCBs CPU, caller must migrate CBs. */
1974 1971 __call_rcu_nocb_enqueue(my_rdp, rcu_segcblist_head(&rdp->cblist),
1975 /* First, enqueue the donelist, if any. This preserves CB ordering. */ 1972 rcu_segcblist_tail(&rdp->cblist),
1976 if (rsp->orphan_done.head) { 1973 rcu_segcblist_n_cbs(&rdp->cblist),
1977 __call_rcu_nocb_enqueue(rdp, rcu_cblist_head(&rsp->orphan_done), 1974 rcu_segcblist_n_lazy_cbs(&rdp->cblist), flags);
1978 rcu_cblist_tail(&rsp->orphan_done), 1975 rcu_segcblist_init(&rdp->cblist);
1979 ql, qll, flags); 1976 rcu_segcblist_disable(&rdp->cblist);
1980 }
1981 if (rsp->orphan_pend.head) {
1982 __call_rcu_nocb_enqueue(rdp, rcu_cblist_head(&rsp->orphan_pend),
1983 rcu_cblist_tail(&rsp->orphan_pend),
1984 ql, qll, flags);
1985 }
1986 rcu_cblist_init(&rsp->orphan_done);
1987 rcu_cblist_init(&rsp->orphan_pend);
1988 return true; 1977 return true;
1989} 1978}
1990 1979
@@ -2459,7 +2448,7 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
2459 return false; 2448 return false;
2460} 2449}
2461 2450
2462static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, 2451static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
2463 struct rcu_data *rdp, 2452 struct rcu_data *rdp,
2464 unsigned long flags) 2453 unsigned long flags)
2465{ 2454{