From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: linux-rt-users@vger.kernel.org, mingo@elte.hu,
akpm@linux-foundation.org, dipankar@in.ibm.com,
josht@linux.vnet.ibm.com, tytso@us.ibm.com, dvhltc@us.ibm.com,
tglx@linutronix.de, a.p.zijlstra@chello.nl, bunk@kernel.org,
ego@in.ibm.com, oleg@tv-sign.ru, srostedt@redhat.com
Subject: [PATCH RFC 5/9] RCU: CPU hotplug support for preemptible RCU
Date: Mon, 10 Sep 2007 11:36:22 -0700 [thread overview]
Message-ID: <20070910183622.GE3819@linux.vnet.ibm.com> (raw)
In-Reply-To: <20070910183004.GA3299@linux.vnet.ibm.com>
Work in progress, not for inclusion.
This patch allows preemptible RCU to tolerate CPU-hotplug operations.
It accomplishes this by maintaining a local copy of a map of online
CPUs, which it accesses under its own lock.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
include/linux/rcuclassic.h | 2
include/linux/rcupreempt.h | 2
kernel/rcuclassic.c | 8 +++
kernel/rcupreempt.c | 93 +++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 100 insertions(+), 5 deletions(-)
diff -urpNa -X dontdiff linux-2.6.22-d-schedclassic/include/linux/rcuclassic.h linux-2.6.22-e-hotplugcpu/include/linux/rcuclassic.h
--- linux-2.6.22-d-schedclassic/include/linux/rcuclassic.h 2007-08-22 15:38:22.000000000 -0700
+++ linux-2.6.22-e-hotplugcpu/include/linux/rcuclassic.h 2007-08-22 15:55:39.000000000 -0700
@@ -143,6 +143,8 @@ extern int rcu_needs_cpu(int cpu);
#define rcu_check_callbacks_rt(cpu, user)
#define rcu_init_rt()
#define rcu_needs_cpu_rt(cpu) 0
+#define rcu_offline_cpu_rt(cpu)
+#define rcu_online_cpu_rt(cpu)
#define rcu_pending_rt(cpu) 0
#define rcu_process_callbacks_rt(unused)
diff -urpNa -X dontdiff linux-2.6.22-d-schedclassic/include/linux/rcupreempt.h linux-2.6.22-e-hotplugcpu/include/linux/rcupreempt.h
--- linux-2.6.22-d-schedclassic/include/linux/rcupreempt.h 2007-08-22 15:38:22.000000000 -0700
+++ linux-2.6.22-e-hotplugcpu/include/linux/rcupreempt.h 2007-08-22 15:55:39.000000000 -0700
@@ -59,6 +59,8 @@ extern void rcu_advance_callbacks_rt(int
extern void rcu_check_callbacks_rt(int cpu, int user);
extern void rcu_init_rt(void);
extern int rcu_needs_cpu_rt(int cpu);
+extern void rcu_offline_cpu_rt(int cpu);
+extern void rcu_online_cpu_rt(int cpu);
extern int rcu_pending_rt(int cpu);
struct softirq_action;
extern void rcu_process_callbacks_rt(struct softirq_action *unused);
diff -urpNa -X dontdiff linux-2.6.22-d-schedclassic/kernel/rcuclassic.c linux-2.6.22-e-hotplugcpu/kernel/rcuclassic.c
--- linux-2.6.22-d-schedclassic/kernel/rcuclassic.c 2007-08-22 15:51:22.000000000 -0700
+++ linux-2.6.22-e-hotplugcpu/kernel/rcuclassic.c 2007-08-22 15:55:39.000000000 -0700
@@ -414,14 +414,19 @@ static void __rcu_offline_cpu(struct rcu
static void rcu_offline_cpu(int cpu)
{
struct rcu_data *this_rdp = &get_cpu_var(rcu_data);
+#ifdef CONFIG_CLASSIC_RCU
struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data);
+#endif /* #ifdef CONFIG_CLASSIC_RCU */
__rcu_offline_cpu(this_rdp, &rcu_ctrlblk,
&per_cpu(rcu_data, cpu));
+#ifdef CONFIG_CLASSIC_RCU
__rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk,
&per_cpu(rcu_bh_data, cpu));
- put_cpu_var(rcu_data);
put_cpu_var(rcu_bh_data);
+#endif /* #ifdef CONFIG_CLASSIC_RCU */
+ put_cpu_var(rcu_data);
+ rcu_offline_cpu_rt(cpu);
}
#else
@@ -571,6 +576,7 @@ static void __devinit rcu_online_cpu(int
rdp->passed_quiesc = &per_cpu(rcu_data_passed_quiesc, cpu);
rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp);
bh_rdp->passed_quiesc = &per_cpu(rcu_data_bh_passed_quiesc, cpu);
+ rcu_online_cpu_rt(cpu);
}
static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
diff -urpNa -X dontdiff linux-2.6.22-d-schedclassic/kernel/rcupreempt.c linux-2.6.22-e-hotplugcpu/kernel/rcupreempt.c
--- linux-2.6.22-d-schedclassic/kernel/rcupreempt.c 2007-08-22 15:45:28.000000000 -0700
+++ linux-2.6.22-e-hotplugcpu/kernel/rcupreempt.c 2007-08-22 15:56:22.000000000 -0700
@@ -125,6 +125,8 @@ enum rcu_mb_flag_values {
};
static DEFINE_PER_CPU(enum rcu_mb_flag_values, rcu_mb_flag) = rcu_mb_done;
+static cpumask_t rcu_cpu_online_map = CPU_MASK_NONE;
+
/*
* Macro that prevents the compiler from reordering accesses, but does
* absolutely -nothing- to prevent CPUs from reordering. This is used
@@ -404,7 +406,7 @@ rcu_try_flip_idle(void)
/* Now ask each CPU for acknowledgement of the flip. */
- for_each_possible_cpu(cpu)
+ for_each_cpu_mask(cpu, rcu_cpu_online_map)
per_cpu(rcu_flip_flag, cpu) = rcu_flipped;
return 1;
@@ -420,7 +422,7 @@ rcu_try_flip_waitack(void)
int cpu;
RCU_TRACE_ME(rcupreempt_trace_try_flip_a1);
- for_each_possible_cpu(cpu)
+ for_each_cpu_mask(cpu, rcu_cpu_online_map)
if (per_cpu(rcu_flip_flag, cpu) != rcu_flip_seen) {
RCU_TRACE_ME(rcupreempt_trace_try_flip_ae1);
return 0;
@@ -462,7 +464,7 @@ rcu_try_flip_waitzero(void)
/* Call for a memory barrier from each CPU. */
- for_each_possible_cpu(cpu)
+ for_each_cpu_mask(cpu, rcu_cpu_online_map)
per_cpu(rcu_mb_flag, cpu) = rcu_mb_needed;
RCU_TRACE_ME(rcupreempt_trace_try_flip_z2);
@@ -480,7 +482,7 @@ rcu_try_flip_waitmb(void)
int cpu;
RCU_TRACE_ME(rcupreempt_trace_try_flip_m1);
- for_each_possible_cpu(cpu)
+ for_each_cpu_mask(cpu, rcu_cpu_online_map)
if (per_cpu(rcu_mb_flag, cpu) != rcu_mb_done) {
RCU_TRACE_ME(rcupreempt_trace_try_flip_me1);
return 0;
@@ -583,6 +585,89 @@ void rcu_advance_callbacks_rt(int cpu, i
spin_unlock_irqrestore(&rdp->lock, oldirq);
}
+#ifdef CONFIG_HOTPLUG_CPU
+
+#define rcu_offline_cpu_rt_enqueue(srclist, srctail, dstlist, dsttail) do { \
+ *dsttail = srclist; \
+ if (srclist != NULL) { \
+ dsttail = srctail; \
+ srclist = NULL; \
+ srctail = &srclist;\
+ } \
+ } while (0)
+
+
+void rcu_offline_cpu_rt(int cpu)
+{
+ int i;
+ struct rcu_head *list = NULL;
+ unsigned long oldirq;
+ struct rcu_data *rdp = RCU_DATA_CPU(cpu);
+ struct rcu_head **tail = &list;
+
+ /* Remove all callbacks from the newly dead CPU, retaining order. */
+
+ spin_lock_irqsave(&rdp->lock, oldirq);
+ rcu_offline_cpu_rt_enqueue(rdp->donelist, rdp->donetail, list, tail);
+ for (i = GP_STAGES - 1; i >= 0; i--)
+ rcu_offline_cpu_rt_enqueue(rdp->waitlist[i], rdp->waittail[i],
+ list, tail);
+ rcu_offline_cpu_rt_enqueue(rdp->nextlist, rdp->nexttail, list, tail);
+ spin_unlock_irqrestore(&rdp->lock, oldirq);
+ rdp->waitlistcount = 0;
+
+ /* Disengage the newly dead CPU from grace-period computation. */
+
+ spin_lock_irqsave(&rcu_ctrlblk.fliplock, oldirq);
+ rcu_check_mb(cpu);
+ if (per_cpu(rcu_flip_flag, cpu) == rcu_flipped) {
+ smp_mb(); /* Subsequent counter accesses must see new value */
+ per_cpu(rcu_flip_flag, cpu) = rcu_flip_seen;
+ smp_mb(); /* Subsequent RCU read-side critical sections */
+ /* seen -after- acknowledgement. */
+ }
+ cpu_clear(cpu, rcu_cpu_online_map);
+ spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, oldirq);
+
+ /*
+ * Place the removed callbacks on the current CPU's queue.
+ * Make them all start a new grace period: simple approach,
+ * in theory could starve a given set of callbacks, but
+ * you would need to be doing some serious CPU hotplugging
+ * to make this happen. If this becomes a problem, adding
+ * a synchronize_rcu() to the hotplug path would be a simple
+ * fix.
+ */
+
+ rdp = RCU_DATA_ME();
+ spin_lock_irqsave(&rdp->lock, oldirq);
+ *rdp->nexttail = list;
+ if (list)
+ rdp->nexttail = tail;
+ spin_unlock_irqrestore(&rdp->lock, oldirq);
+}
+
+void __devinit rcu_online_cpu_rt(int cpu)
+{
+ unsigned long oldirq;
+
+ spin_lock_irqsave(&rcu_ctrlblk.fliplock, oldirq);
+ cpu_set(cpu, rcu_cpu_online_map);
+ spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, oldirq);
+}
+
+#else /* #ifdef CONFIG_HOTPLUG_CPU */
+
+void rcu_offline_cpu(int cpu)
+{
+}
+
+void __devinit rcu_online_cpu_rt(int cpu)
+{
+}
+
+#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
+
void rcu_process_callbacks_rt(struct softirq_action *unused)
{
unsigned long flags;
next prev parent reply other threads:[~2007-09-10 18:36 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-10 18:30 [PATCH RFC 0/9] RCU: Preemptible RCU Paul E. McKenney
2007-09-10 18:32 ` [PATCH RFC 1/9] RCU: Split API to permit multiple RCU implementations Paul E. McKenney
2007-09-21 4:14 ` Steven Rostedt
2007-09-10 18:33 ` [PATCH RFC 2/9] RCU: Fix barriers Paul E. McKenney
2007-09-10 18:34 ` [PATCH RFC 3/9] RCU: Preemptible RCU Paul E. McKenney
2007-09-21 4:17 ` Steven Rostedt
2007-09-21 5:50 ` Paul E. McKenney
2007-09-21 5:56 ` Dipankar Sarma
2007-09-21 14:40 ` Steven Rostedt
2007-09-21 15:46 ` Peter Zijlstra
2007-09-21 22:06 ` Paul E. McKenney
2007-09-21 22:31 ` Steven Rostedt
2007-09-21 22:44 ` Paul E. McKenney
2007-09-21 23:23 ` Steven Rostedt
2007-09-21 23:44 ` Paul E. McKenney
2007-09-22 0:26 ` Paul E. McKenney
2007-09-22 1:15 ` Steven Rostedt
2007-09-22 1:53 ` Paul E. McKenney
2007-09-22 3:15 ` Steven Rostedt
2007-09-22 4:07 ` Paul E. McKenney
2007-09-21 15:20 ` Steven Rostedt
2007-09-21 23:03 ` Paul E. McKenney
2007-09-22 0:32 ` Paul E. McKenney
2007-09-22 1:19 ` Steven Rostedt
2007-09-22 1:43 ` Paul E. McKenney
2007-09-22 2:56 ` Steven Rostedt
2007-09-22 4:10 ` Paul E. McKenney
2007-09-23 17:38 ` Oleg Nesterov
2007-09-24 0:15 ` Paul E. McKenney
2007-09-26 15:13 ` Oleg Nesterov
2007-09-27 15:46 ` Paul E. McKenney
2007-09-28 14:47 ` Oleg Nesterov
2007-09-28 18:57 ` Paul E. McKenney
2007-09-30 16:31 ` Oleg Nesterov
2007-09-30 23:02 ` Davide Libenzi
2007-10-01 1:37 ` Paul E. McKenney
2007-10-01 18:44 ` Davide Libenzi
2007-10-01 19:21 ` Paul E. McKenney
2007-10-01 22:09 ` Davide Libenzi
2007-10-01 22:24 ` Paul E. McKenney
2007-10-02 18:02 ` Oleg Nesterov
2007-10-01 1:20 ` Paul E. McKenney
2007-09-10 18:35 ` [PATCH RFC 4/9] RCU: synchronize_sched() workaround for CPU hotplug Paul E. McKenney
2007-09-10 18:36 ` Paul E. McKenney [this message]
2007-09-30 16:38 ` [PATCH RFC 5/9] RCU: CPU hotplug support for preemptible RCU Oleg Nesterov
2007-10-01 1:41 ` Paul E. McKenney
2007-09-10 18:39 ` [PATCH RFC 6/9] RCU priority boosting " Paul E. McKenney
2007-09-28 22:56 ` Gautham R Shenoy
2007-09-28 23:05 ` Steven Rostedt
2007-09-30 3:11 ` Paul E. McKenney
2007-10-05 11:46 ` Gautham R Shenoy
2007-10-05 12:24 ` Steven Rostedt
2007-10-05 13:21 ` Gautham R Shenoy
2007-10-05 14:07 ` Paul E. McKenney
2007-09-10 18:39 ` [PATCH RFC 7/9] RCU: rcutorture testing for RCU priority boosting Paul E. McKenney
2007-09-10 18:41 ` [PATCH RFC 8/9] RCU: Make RCU priority boosting consume less power Paul E. McKenney
2007-09-10 18:42 ` [PATCH RFC 9/9] RCU: preemptible documentation and comment cleanups Paul E. McKenney
2007-09-10 18:44 ` [PATCH RFC 0/9] RCU: Preemptible RCU Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070910183622.GE3819@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=bunk@kernel.org \
--cc=dipankar@in.ibm.com \
--cc=dvhltc@us.ibm.com \
--cc=ego@in.ibm.com \
--cc=josht@linux.vnet.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-users@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=oleg@tv-sign.ru \
--cc=srostedt@redhat.com \
--cc=tglx@linutronix.de \
--cc=tytso@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox