From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: mingo@elte.hu, laijs@cn.fujitsu.com, dipankar@in.ibm.com,
akpm@linux-foundation.org, mathieu.desnoyers@polymtl.ca,
josh@joshtriplett.org, dvhltc@us.ibm.com, niv@us.ibm.com,
tglx@linutronix.de, peterz@infradead.org, rostedt@goodmis.org,
Valdis.Kletnieks@vt.edu, dhowells@redhat.com,
eric.dumazet@gmail.com,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Subject: [PATCH tip/core/rcu 09/23] rcu: refactor RCU's context-switch handling
Date: Tue, 20 Apr 2010 14:44:41 -0700 [thread overview]
Message-ID: <1271799895-21028-9-git-send-email-paulmck@linux.vnet.ibm.com> (raw)
In-Reply-To: <20100420214431.GA20777@linux.vnet.ibm.com>
The addition of preemptible RCU to treercu resulted in a bit of
confusion and inefficiency surrounding the handling of context switches
for RCU-sched and for RCU-preempt. For RCU-sched, a context switch
is a quiescent state, pure and simple, just like it always has been.
For RCU-preempt, a context switch is in no way a quiescent state, but
special handling is required when a task blocks in an RCU read-side
critical section.
However, the callout from the scheduler and the outer loop in ksoftirqd
still calls something named rcu_sched_qs(), whose name is no longer
accurate. Furthermore, when rcu_check_callbacks() notes an RCU-sched
quiescent state, it ends up unnecessarily (though harmlessly, aside
from the performance hit) enqueuing the current task if it happens to
be running in an RCU-preempt read-side critical section. This not only
increases the maximum latency of scheduler_tick(), it also needlessly
increases the overhead of the next outermost rcu_read_unlock() invocation.
This patch addresses this situation by separating the notion of RCU's
context-switch handling from that of RCU-sched's quiescent states.
The context-switch handling is covered by rcu_note_context_switch() in
general and by rcu_preempt_note_context_switch() for preemptible RCU.
This permits rcu_sched_qs() to handle quiescent states and only quiescent
states. It also reduces the maximum latency of scheduler_tick(), though
probably by much less than a microsecond. Finally, it means that tasks
within preemptible-RCU read-side critical sections avoid incurring the
overhead of queuing unless there really is a context switch.
Suggested-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Acked-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
include/linux/rcutiny.h | 4 ++++
include/linux/rcutree.h | 1 +
kernel/rcutree.c | 17 ++++++++++++-----
kernel/rcutree_plugin.h | 11 +++++++----
kernel/sched.c | 2 +-
kernel/softirq.c | 2 +-
6 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index bbeb55b..ff22b97 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -29,6 +29,10 @@
void rcu_sched_qs(int cpu);
void rcu_bh_qs(int cpu);
+static inline void rcu_note_context_switch(int cpu)
+{
+ rcu_sched_qs(cpu);
+}
#define __rcu_read_lock() preempt_disable()
#define __rcu_read_unlock() preempt_enable()
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 7484fe6..b9f7460 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -34,6 +34,7 @@ struct notifier_block;
extern void rcu_sched_qs(int cpu);
extern void rcu_bh_qs(int cpu);
+extern void rcu_note_context_switch(int cpu);
extern int rcu_needs_cpu(int cpu);
extern int rcu_expedited_torture_stats(char *page);
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 86bb949..e336313 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -97,25 +97,32 @@ static int rcu_gp_in_progress(struct rcu_state *rsp)
*/
void rcu_sched_qs(int cpu)
{
- struct rcu_data *rdp;
+ struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu);
- rdp = &per_cpu(rcu_sched_data, cpu);
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
- rcu_preempt_note_context_switch(cpu);
}
void rcu_bh_qs(int cpu)
{
- struct rcu_data *rdp;
+ struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu);
- rdp = &per_cpu(rcu_bh_data, cpu);
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
}
+/*
+ * Note a context switch. This is a quiescent state for RCU-sched,
+ * and requires special handling for preemptible RCU.
+ */
+void rcu_note_context_switch(int cpu)
+{
+ rcu_sched_qs(cpu);
+ rcu_preempt_note_context_switch(cpu);
+}
+
#ifdef CONFIG_NO_HZ
DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
.dynticks_nesting = 1,
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 687c4e9..f9bc83a 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -75,13 +75,19 @@ EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
* that this just means that the task currently running on the CPU is
* not in a quiescent state. There might be any number of tasks blocked
* while in an RCU read-side critical section.
+ *
+ * Unlike the other rcu_*_qs() functions, callers to this function
+ * must disable irqs in order to protect the assignment to
+ * ->rcu_read_unlock_special.
*/
static void rcu_preempt_qs(int cpu)
{
struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu);
+
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
+ current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
}
/*
@@ -144,9 +150,8 @@ static void rcu_preempt_note_context_switch(int cpu)
* grace period, then the fact that the task has been enqueued
* means that we continue to block the current grace period.
*/
- rcu_preempt_qs(cpu);
local_irq_save(flags);
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
+ rcu_preempt_qs(cpu);
local_irq_restore(flags);
}
@@ -236,7 +241,6 @@ static void rcu_read_unlock_special(struct task_struct *t)
*/
special = t->rcu_read_unlock_special;
if (special & RCU_READ_UNLOCK_NEED_QS) {
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
rcu_preempt_qs(smp_processor_id());
}
@@ -473,7 +477,6 @@ static void rcu_preempt_check_callbacks(int cpu)
struct task_struct *t = current;
if (t->rcu_read_lock_nesting == 0) {
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
rcu_preempt_qs(cpu);
return;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 6af210a..f8ca2c0 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3696,7 +3696,7 @@ need_resched:
preempt_disable();
cpu = smp_processor_id();
rq = cpu_rq(cpu);
- rcu_sched_qs(cpu);
+ rcu_note_context_switch(cpu);
prev = rq->curr;
switch_count = &prev->nivcsw;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 7c1a67e..0db913a 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -716,7 +716,7 @@ static int run_ksoftirqd(void * __bind_cpu)
preempt_enable_no_resched();
cond_resched();
preempt_disable();
- rcu_sched_qs((long)__bind_cpu);
+ rcu_note_context_switch((long)__bind_cpu);
}
preempt_enable();
set_current_state(TASK_INTERRUPTIBLE);
--
1.7.0
next prev parent reply other threads:[~2010-04-20 21:48 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-20 21:44 [PATCH tip/core/rcu 0/23] v3 patches queued for 2.6.35 Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 01/23] rcu: substitute set_need_resched for sending resched IPIs Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 02/23] rcu: make dead code really dead Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 03/23] rcu: move some code from macro to function Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 04/23] rcu: ignore offline CPUs in last non-dyntick-idle CPU check Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 05/23] rcu: Fix bogus CONFIG_PROVE_LOCKING in comments to reflect reality Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 06/23] rcu: fix now-bogus rcu_scheduler_active comments Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 07/23] rcu: shrink rcutiny by making synchronize_rcu_bh() be inline Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 08/23] rcu: rename rcutiny rcu_ctrlblk to rcu_sched_ctrlblk Paul E. McKenney
2010-04-20 21:44 ` Paul E. McKenney [this message]
2010-04-20 21:44 ` [PATCH tip/core/rcu 10/23] rcu: slim down rcutiny by removing rcu_scheduler_active and friends Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 11/23] rcu: enable CPU_STALL_VERBOSE by default Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 12/23] rcu: disable CPU stall warnings upon panic Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 13/23] rcu: print boot-time console messages if RCU configs out of ordinary Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 14/23] rcu: improve RCU CPU stall-warning messages Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 15/23] rcu: permit discontiguous cpu_possible_mask CPU numbering Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 16/23] rcu: v2: reduce the number of spurious RCU_SOFTIRQ invocations Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 17/23] rcu: improve the RCU CPU-stall warning documentation Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 18/23] Debugobjects transition check Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 19/23] rcu head introduce rcu head init on stack Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 20/23] remove all rcu head initializations, except on_stack initializations Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 21/23] rcu head remove init Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 22/23] tree/tiny rcu: Add debug RCU head objects (v5) Paul E. McKenney
2010-04-20 21:44 ` [PATCH tip/core/rcu 23/23] rcu: make SRCU usable in modules Paul E. McKenney
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=1271799895-21028-9-git-send-email-paulmck@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=Valdis.Kletnieks@vt.edu \
--cc=akpm@linux-foundation.org \
--cc=dhowells@redhat.com \
--cc=dipankar@in.ibm.com \
--cc=dvhltc@us.ibm.com \
--cc=eric.dumazet@gmail.com \
--cc=josh@joshtriplett.org \
--cc=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=mingo@elte.hu \
--cc=niv@us.ibm.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/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
all inboxes | Powered by JetHome®