From: Lai Jiangshan <laijs@cn.fujitsu.com>
To: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
Ingo Molnar <mingo@elte.hu>, LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH] rcu: only raise softirq when need
Date: Tue, 30 Mar 2010 18:11:55 +0800 [thread overview]
Message-ID: <4BB1CE6B.6030207@cn.fujitsu.com> (raw)
I found something RCU_SOFTIRQ are called without do any thing.
(use function_graph to find it:
1) | rcu_process_callbacks() {
1) | __rcu_process_callbacks() {
1) 0.634 us | rcu_process_gp_end();
1) 0.487 us | check_for_new_grace_period();
1) 2.672 us | }
1) | __rcu_process_callbacks() {
1) 0.633 us | rcu_process_gp_end();
1) 0.491 us | check_for_new_grace_period();
1) 2.672 us | }
)
This patch make RCU_SOFTIRQ raised when need.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 1947c4e..06a1780 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -133,6 +133,7 @@ module_param(qlowmark, int, 0);
static void force_quiescent_state(struct rcu_state *rsp, int relaxed);
static int rcu_pending(int cpu);
+static int rcu_qs_pending(int cpu);
/*
* Return the number of RCU-sched batches processed thus far for debug & stats.
@@ -1125,8 +1126,9 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
*/
void rcu_check_callbacks(int cpu, int user)
{
- if (!rcu_pending(cpu))
- return; /* if nothing for RCU to do. */
+ if (!rcu_qs_pending(cpu))
+ goto check_rcu_softirq_work;
+
if (user ||
(idle_cpu(cpu) && rcu_scheduler_active &&
!in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
@@ -1158,7 +1160,10 @@ void rcu_check_callbacks(int cpu, int user)
rcu_bh_qs(cpu);
}
rcu_preempt_check_callbacks(cpu);
- raise_softirq(RCU_SOFTIRQ);
+
+check_rcu_softirq_work:
+ if (rcu_pending(cpu))
+ raise_softirq(RCU_SOFTIRQ);
}
#ifdef CONFIG_SMP
@@ -1497,9 +1502,9 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
/* Check for CPU stalls, if enabled. */
check_cpu_stall(rsp, rdp);
- /* Is the RCU core waiting for a quiescent state from this CPU? */
- if (rdp->qs_pending) {
- rdp->n_rp_qs_pending++;
+ /* Does this RCU need to report quiescent state? */
+ if (rdp->qs_pending && rdp->passed_quiesc) {
+ rdp->n_rp_report_qs++;
return 1;
}
@@ -1551,6 +1556,24 @@ static int rcu_pending(int cpu)
rcu_preempt_pending(cpu);
}
+/* Is the RCU core waiting for a quiescent state from this CPU? */
+static int __rcu_qs_pending(struct rcu_data *rdp)
+{
+ if (rdp->qs_pending) {
+ rdp->n_rp_qs_pending++;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int rcu_qs_pending(int cpu)
+{
+ return __rcu_qs_pending(&per_cpu(rcu_sched_data, cpu)) ||
+ __rcu_qs_pending(&per_cpu(rcu_bh_data, cpu)) ||
+ rcu_preempt_qs_pending(cpu);
+}
+
/*
* Check to see if any future RCU-related work will need to be done
* by the current CPU, even if none need be done immediately, returning
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 4a525a3..c0f312e 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -223,6 +223,7 @@ struct rcu_data {
/* 5) __rcu_pending() statistics. */
unsigned long n_rcu_pending; /* rcu_pending() calls since boot. */
unsigned long n_rp_qs_pending;
+ unsigned long n_rp_report_qs;
unsigned long n_rp_cb_ready;
unsigned long n_rp_cpu_needs_gp;
unsigned long n_rp_gp_completed;
@@ -378,6 +379,7 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp);
#endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */
static int rcu_preempt_pending(int cpu);
+static int rcu_preempt_qs_pending(int cpu);
static int rcu_preempt_needs_cpu(int cpu);
static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
static void rcu_preempt_send_cbs_to_orphanage(void);
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 79b53bd..4befb64 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -689,6 +689,11 @@ static int rcu_preempt_pending(int cpu)
&per_cpu(rcu_preempt_data, cpu));
}
+static int rcu_preempt_qs_pending(int cpu)
+{
+ return __rcu_qs_pending(&per_cpu(rcu_preempt_data, cpu));
+}
+
/*
* Does preemptable RCU need the CPU to stay out of dynticks mode?
*/
@@ -914,6 +919,11 @@ static int rcu_preempt_pending(int cpu)
return 0;
}
+static int rcu_preempt_qs_pending(int cpu)
+{
+ return 0;
+}
+
/*
* Because preemptable RCU does not exist, it never needs any CPU.
*/
next reply other threads:[~2010-03-30 10:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-30 10:11 Lai Jiangshan [this message]
2010-03-30 16:30 ` [PATCH] rcu: only raise softirq when need Paul E. McKenney
2010-03-31 2:10 ` Lai Jiangshan
2010-03-31 15:30 ` Paul E. McKenney
2010-04-01 7:40 ` Lai Jiangshan
2010-04-02 1:07 ` 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=4BB1CE6B.6030207@cn.fujitsu.com \
--to=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=paulmck@linux.vnet.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.