* [PATCH tip/core/rcu 0/10] Reduce latency impact of PREEMPT_RCU CPU offline
@ 2014-11-05 17:41 Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
0 siblings, 1 reply; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani
Hello!
This series reduces worst-case CPU-hotplug latency for PREEMPT_RCU
by avoiding an O(N) list move, where N is the number of threads that
were preempted recently while in an RCU read-side critical section.
This situation is rare, occurring only when the last CPU corresponding
to a given rcu_node structure goes offline, for example, when CPUs 1-14
are all offline and CPU 15 goes offline. In this case, all the tasks
that were recently preempted while running on one of CPUs 0-15 will be
moved to the root rcu_node structure. Because this could be a very large
number of tasks, and because this moving is carried out with interrupts
disabled, a very large latency spike can result. This series therefore
reworks RCU's CPU-hotplug code and grace-period computation to remove
the need for moving tasks.
Because there was an obscure bug in the task-move process, this change
also fixes that bug by annihilating the function containing it. This bug
manifests only when RCU priority boosting is enabled, and even then occurs
only roughly once per hundred hours or so of focused rcutorture testing.
It was made somewhat more probable by a recent change to rcutorture
that registers 60,000 RCU callbacks in three batches of 20,000 each,
with one jiffy between each batch.
The individual commits in this series are as follows:
1. Fix a comment: softirqs are disabled, not interrupts.
2. Apply ACCESS_ONCE to rcu_boost().
3. Change rcu_read_unlock_special()'s "empty" variable's name to
"empty_norm" to make room for a new "empty" that will track
the emptiness of the full list rather than just that part that
is blocking the current normal (non-expedited) grace period.
4. Abstract rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu().
The new rcu_cleanup_dead_rnp() function clears ->qsmaskinit bits
up the rcu_node tree to allow for the last CPU in a given leaf
rcu_node structure going offline. This function will be called
from rcu_read_unlock_special() when the last blocked task exits
its outermost RCU read-side critical section.
5. Make rcu_read_unlock_special() to propagate ->qsmaskinit bit
clearing up the rcu_node tree once the last task has exited
its RCU read-side critical section.
6. Stop migrating the list of blocked tasks to the root rcu_node
structure.
7. Stop holding the irq-disabled ->orphan_lock across the
->qsmaskinit bit-clearing process, thus reducing the length
of time that interrupts are disabled.
8. Make use of the new rcu_preempt_has_tasks() function.
9. Stop creating an rcub kthread for the root rcu_node structure,
which no longer has tasks in its ->blkd_tasks list (unless it
is also the sole leaf rcu_node structure).
10. Drop the code from force_qs_rnp() that attempts to awaken the
now-nonexistent root rcu_node structure's rcub kthread.
Thanx, Paul
------------------------------------------------------------------------
b/kernel/rcu/tree.c | 103 ++++++++++++++++-------------
b/kernel/rcu/tree.h | 13 ---
b/kernel/rcu/tree_plugin.h | 159 +++++++++++----------------------------------
3 files changed, 98 insertions(+), 177 deletions(-)
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment
2014-11-05 17:41 [PATCH tip/core/rcu 0/10] Reduce latency impact of PREEMPT_RCU CPU offline Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 02/10] rcu: Protect rcu_boost() lockless accesses with ACCESS_ONCE() Paul E. McKenney
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Despite what the comment says, it is only softirqs that are disabled,
not interrupts. This commit therefore fixes the comment.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 7680fc275036..1b8dc3f8d80c 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2569,7 +2569,7 @@ static void rcu_process_callbacks(struct softirq_action *unused)
* Schedule RCU callback invocation. If the specified type of RCU
* does not support RCU priority boosting, just do a direct call,
* otherwise wake up the per-CPU kernel kthread. Note that because we
- * are running on the current CPU with interrupts disabled, the
+ * are running on the current CPU with softirqs disabled, the
* rcu_cpu_kthread_task cannot disappear out from under us.
*/
static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 02/10] rcu: Protect rcu_boost() lockless accesses with ACCESS_ONCE()
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 03/10] rcu: Rename "empty" to "empty_norm" in preparation for boost rework Paul E. McKenney
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
This commit prevents random compiler optimizations by applying
ACCESS_ONCE() to lockless accesses.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree_plugin.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 3ec85cb5d544..d59913ef8360 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1127,7 +1127,8 @@ static int rcu_boost(struct rcu_node *rnp)
struct task_struct *t;
struct list_head *tb;
- if (rnp->exp_tasks == NULL && rnp->boost_tasks == NULL)
+ if (ACCESS_ONCE(rnp->exp_tasks) == NULL &&
+ ACCESS_ONCE(rnp->boost_tasks) == NULL)
return 0; /* Nothing left to boost. */
raw_spin_lock_irqsave(&rnp->lock, flags);
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 03/10] rcu: Rename "empty" to "empty_norm" in preparation for boost rework
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 02/10] rcu: Protect rcu_boost() lockless accesses with ACCESS_ONCE() Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 04/10] rcu: Abstract rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu() Paul E. McKenney
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
This commit undertakes a simple variable renaming to make way for
some rework of RCU priority boosting.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree_plugin.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index d59913ef8360..3d22f0b2dea9 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -313,8 +313,8 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,
*/
void rcu_read_unlock_special(struct task_struct *t)
{
- int empty;
int empty_exp;
+ int empty_norm;
int empty_exp_now;
unsigned long flags;
struct list_head *np;
@@ -367,7 +367,7 @@ void rcu_read_unlock_special(struct task_struct *t)
break;
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
}
- empty = !rcu_preempt_blocked_readers_cgp(rnp);
+ empty_norm = !rcu_preempt_blocked_readers_cgp(rnp);
empty_exp = !rcu_preempted_readers_exp(rnp);
smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */
np = rcu_next_node_entry(t, rnp);
@@ -393,7 +393,7 @@ void rcu_read_unlock_special(struct task_struct *t)
* so we must take a snapshot of the expedited state.
*/
empty_exp_now = !rcu_preempted_readers_exp(rnp);
- if (!empty && !rcu_preempt_blocked_readers_cgp(rnp)) {
+ if (!empty_norm && !rcu_preempt_blocked_readers_cgp(rnp)) {
trace_rcu_quiescent_state_report(TPS("preempt_rcu"),
rnp->gpnum,
0, rnp->qsmask,
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 04/10] rcu: Abstract rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu()
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 02/10] rcu: Protect rcu_boost() lockless accesses with ACCESS_ONCE() Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 03/10] rcu: Rename "empty" to "empty_norm" in preparation for boost rework Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 05/10] rcu: Make rcu_read_unlock_special() propagate ->qsmaskinit bit clearing Paul E. McKenney
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
This commit abstracts rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu()
in preparation for the rework of RCU priority boosting. This new function
will be invoked from rcu_read_unlock_special() in the reworked scheme,
which is why rcu_cleanup_dead_rnp() assumes that the leaf rcu_node
structure's ->qsmaskinit field has already been updated.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 67 ++++++++++++++++++++++++++++++++++--------------
kernel/rcu/tree.h | 1 +
kernel/rcu/tree_plugin.h | 17 ++++++++++++
3 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 1b8dc3f8d80c..ccaf5ec78a56 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2195,6 +2195,46 @@ static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
}
/*
+ * All CPUs for the specified rcu_node structure have gone offline,
+ * and all tasks that were preempted within an RCU read-side critical
+ * section while running on one of those CPUs have since exited their RCU
+ * read-side critical section. Some other CPU is reporting this fact with
+ * the specified rcu_node structure's ->lock held and interrupts disabled.
+ * This function therefore goes up the tree of rcu_node structures,
+ * clearing the corresponding bits in the ->qsmaskinit fields. Note that
+ * the leaf rcu_node structure's ->qsmaskinit field has already been
+ * updated
+ *
+ * This function does check that the specified rcu_node structure has
+ * all CPUs offline and no blocked tasks, so it is OK to invoke it
+ * prematurely. That said, invoking it after the fact will cost you
+ * a needless lock acquisition. So once it has done its work, don't
+ * invoke it again.
+ */
+static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
+{
+ long mask;
+ struct rcu_node *rnp = rnp_leaf;
+
+ if (rnp->qsmaskinit || rcu_preempt_has_tasks(rnp))
+ return;
+ for (;;) {
+ mask = rnp->grpmask;
+ rnp = rnp->parent;
+ if (!rnp)
+ break;
+ raw_spin_lock(&rnp->lock); /* irqs already disabled. */
+ smp_mb__after_unlock_lock(); /* GP memory ordering. */
+ rnp->qsmaskinit &= ~mask;
+ if (rnp->qsmaskinit) {
+ raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
+ return;
+ }
+ raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
+ }
+}
+
+/*
* The CPU has been completely removed, and some other CPU is reporting
* this fact from process context. Do the remainder of the cleanup,
* including orphaning the outgoing CPU's RCU callbacks, and also
@@ -2204,7 +2244,6 @@ static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
{
unsigned long flags;
- unsigned long mask;
int need_report = 0;
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
@@ -2220,24 +2259,14 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
rcu_adopt_orphan_cbs(rsp, flags);
- /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */
- mask = rdp->grpmask; /* rnp->grplo is constant. */
- do {
- raw_spin_lock(&rnp->lock); /* irqs already disabled. */
- smp_mb__after_unlock_lock();
- rnp->qsmaskinit &= ~mask;
- if (rnp->qsmaskinit != 0) {
- if (rnp != rdp->mynode)
- raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
- break;
- }
- if (rnp == rdp->mynode)
- need_report = rcu_preempt_offline_tasks(rsp, rnp, rdp);
- else
- raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
- mask = rnp->grpmask;
- rnp = rnp->parent;
- } while (rnp != NULL);
+ /* Remove outgoing CPU from mask in the leaf rcu_node structure. */
+ raw_spin_lock(&rnp->lock); /* irqs already disabled. */
+ smp_mb__after_unlock_lock(); /* Enforce GP memory-order guarantee. */
+ rnp->qsmaskinit &= ~rdp->grpmask;
+ if (rnp->qsmaskinit == 0) {
+ need_report = rcu_preempt_offline_tasks(rsp, rnp, rdp);
+ rcu_cleanup_dead_rnp(rnp);
+ }
/*
* We still hold the leaf rcu_node structure lock here, and
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 8e7b1843896e..bdf53aabaf42 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -553,6 +553,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
unsigned long flags);
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
static void rcu_print_detail_task_stall(struct rcu_state *rsp);
static int rcu_print_task_stall(struct rcu_node *rnp);
static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 3d22f0b2dea9..10d934cab9b3 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -307,6 +307,15 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,
}
/*
+ * Return true if the specified rcu_node structure has tasks that were
+ * preempted within an RCU read-side critical section.
+ */
+static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
+{
+ return !list_empty(&rnp->blkd_tasks);
+}
+
+/*
* Handle special cases during rcu_read_unlock(), such as needing to
* notify RCU core processing or task having blocked during the RCU
* read-side critical section.
@@ -970,6 +979,14 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
/*
+ * Because there is no preemptible RCU, there can be no readers blocked.
+ */
+static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
+{
+ return false;
+}
+
+/*
* Because preemptible RCU does not exist, we never have to check for
* tasks blocked within RCU read-side critical sections.
*/
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 05/10] rcu: Make rcu_read_unlock_special() propagate ->qsmaskinit bit clearing
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (2 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 04/10] rcu: Abstract rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu() Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 06/10] rcu: Don't migrate blocked tasks even if all corresponding CPUs offline Paul E. McKenney
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
This commit causes rcu_read_unlock_special() to propagate ->qsmaskinit
bit clearing up the rcu_node tree once a given rcu_node structure's
blkd_tasks list becomes empty. This is the final commit in preparation
for the rework of RCU priority boosting: It enables preempted tasks to
remain queued on their rcu_node structure even after all of that rcu_node
structure's CPUs have gone offline.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 4 ++++
kernel/rcu/tree_plugin.h | 16 +++++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index ccaf5ec78a56..fc3e8e574e01 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2297,6 +2297,10 @@ static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
{
}
+static void __maybe_unused rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
+{
+}
+
static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
{
}
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 10d934cab9b3..7bd0088b51c2 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -322,9 +322,10 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
*/
void rcu_read_unlock_special(struct task_struct *t)
{
- int empty_exp;
- int empty_norm;
- int empty_exp_now;
+ bool empty;
+ bool empty_exp;
+ bool empty_norm;
+ bool empty_exp_now;
unsigned long flags;
struct list_head *np;
#ifdef CONFIG_RCU_BOOST
@@ -376,6 +377,7 @@ void rcu_read_unlock_special(struct task_struct *t)
break;
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
}
+ empty = !rcu_preempt_has_tasks(rnp);
empty_norm = !rcu_preempt_blocked_readers_cgp(rnp);
empty_exp = !rcu_preempted_readers_exp(rnp);
smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */
@@ -396,6 +398,14 @@ void rcu_read_unlock_special(struct task_struct *t)
#endif /* #ifdef CONFIG_RCU_BOOST */
/*
+ * If this was the last task on the list, go see if we
+ * need to propagate ->qsmaskinit bit clearing up the
+ * rcu_node tree.
+ */
+ if (!empty && !rcu_preempt_has_tasks(rnp))
+ rcu_cleanup_dead_rnp(rnp);
+
+ /*
* If this was the last task on the current list, and if
* we aren't waiting on any CPUs, report the quiescent state.
* Note that rcu_report_unblock_qs_rnp() releases rnp->lock,
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 06/10] rcu: Don't migrate blocked tasks even if all corresponding CPUs offline
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (3 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 05/10] rcu: Make rcu_read_unlock_special() propagate ->qsmaskinit bit clearing Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 07/10] rcu: Shorten irq-disable region in rcu_cleanup_dead_cpu() Paul E. McKenney
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
When the last CPU associated with a given leaf rcu_node structure
goes offline, something must be done about the tasks queued on that
rcu_node structure. Each of these tasks has been preempted on one of
the leaf rcu_node structure's CPUs while in an RCU read-side critical
section that it have not yet exited. Handling these tasks is the job of
rcu_preempt_offline_tasks(), which migrates them from the leaf rcu_node
structure to the root rcu_node structure.
Unfortunately, this migration has to be done one task at a time because
each tasks allegiance must be shifted from the original leaf rcu_node to
the root, so that future attempts to deal with these tasks will acquire
the root rcu_node structure's ->lock rather than that of the leaf.
Worse yet, this migration must be done with interrupts disabled, which
is not so good for realtime response, especially given that there is
no bound on the number of tasks on a given rcu_node structure's list.
(OK, OK, there is a bound, it is just that it is unreasonably large,
especially on 64-bit systems.) This was not considered a problem back
when rcu_preempt_offline_tasks() was first written because realtime
systems were assumed not to do CPU-hotplug operations while real-time
applications were running. This assumption has proved of dubious validity
given that people are starting to run multiple realtime applications
on a single SMP system and that it is common practice to offline then
online a CPU before starting its real-time application in order to clear
extraneous processing off of that CPU. So we now need CPU hotplug
operations to avoid undue latencies.
This commit therefore avoids migrating these tasks, instead letting
them be dequeued one by one from the original leaf rcu_node structure
by rcu_read_unlock_special(). This means that the clearing of bits
from the upper-level rcu_node structures must be deferred until the
last such task has been dequeued, because otherwise subsequent grace
periods won't wait on them. This commit has the beneficial side effect
of simplifying the CPU-hotplug code for TREE_PREEMPT_RCU, especially in
CONFIG_RCU_BOOST builds.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 20 +--------
kernel/rcu/tree.h | 12 ------
kernel/rcu/tree_plugin.h | 103 -----------------------------------------------
3 files changed, 2 insertions(+), 133 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index fc3e8e574e01..e870b0f5e1b9 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2244,7 +2244,6 @@ static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
{
unsigned long flags;
- int need_report = 0;
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
@@ -2263,25 +2262,10 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
raw_spin_lock(&rnp->lock); /* irqs already disabled. */
smp_mb__after_unlock_lock(); /* Enforce GP memory-order guarantee. */
rnp->qsmaskinit &= ~rdp->grpmask;
- if (rnp->qsmaskinit == 0) {
- need_report = rcu_preempt_offline_tasks(rsp, rnp, rdp);
+ if (rnp->qsmaskinit == 0 && !rcu_preempt_has_tasks(rnp))
rcu_cleanup_dead_rnp(rnp);
- }
-
- /*
- * We still hold the leaf rcu_node structure lock here, and
- * irqs are still disabled. The reason for this subterfuge is
- * because invoking rcu_report_unblock_qs_rnp() with ->orphan_lock
- * held leads to deadlock.
- */
raw_spin_unlock(&rsp->orphan_lock); /* irqs remain disabled. */
- rnp = rdp->mynode;
- if (need_report & RCU_OFL_TASKS_NORM_GP)
- rcu_report_unblock_qs_rnp(rnp, flags);
- else
- raw_spin_unlock_irqrestore(&rnp->lock, flags);
- if (need_report & RCU_OFL_TASKS_EXP_GP)
- rcu_report_exp_rnp(rsp, rnp, true);
+ raw_spin_unlock_irqrestore(&rnp->lock, flags);
WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
"rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
cpu, rdp->qlen, rdp->nxtlist);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index bdf53aabaf42..49b3da7e0c12 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -514,13 +514,6 @@ extern struct list_head rcu_struct_flavors;
#define for_each_rcu_flavor(rsp) \
list_for_each_entry((rsp), &rcu_struct_flavors, flavors)
-/* Return values for rcu_preempt_offline_tasks(). */
-
-#define RCU_OFL_TASKS_NORM_GP 0x1 /* Tasks blocking normal */
- /* GP were moved to root. */
-#define RCU_OFL_TASKS_EXP_GP 0x2 /* Tasks blocking expedited */
- /* GP were moved to root. */
-
/*
* RCU implementation internal declarations:
*/
@@ -557,11 +550,6 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
static void rcu_print_detail_task_stall(struct rcu_state *rsp);
static int rcu_print_task_stall(struct rcu_node *rnp);
static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
-#ifdef CONFIG_HOTPLUG_CPU
-static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
- struct rcu_node *rnp,
- struct rcu_data *rdp);
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
static void rcu_preempt_check_callbacks(void);
void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PREEMPT_RCU)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 7bd0088b51c2..eb05cd805536 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -545,92 +545,6 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
#ifdef CONFIG_HOTPLUG_CPU
-/*
- * Handle tasklist migration for case in which all CPUs covered by the
- * specified rcu_node have gone offline. Move them up to the root
- * rcu_node. The reason for not just moving them to the immediate
- * parent is to remove the need for rcu_read_unlock_special() to
- * make more than two attempts to acquire the target rcu_node's lock.
- * Returns true if there were tasks blocking the current RCU grace
- * period.
- *
- * Returns 1 if there was previously a task blocking the current grace
- * period on the specified rcu_node structure.
- *
- * The caller must hold rnp->lock with irqs disabled.
- */
-static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
- struct rcu_node *rnp,
- struct rcu_data *rdp)
-{
- struct list_head *lp;
- struct list_head *lp_root;
- int retval = 0;
- struct rcu_node *rnp_root = rcu_get_root(rsp);
- struct task_struct *t;
-
- if (rnp == rnp_root) {
- WARN_ONCE(1, "Last CPU thought to be offlined?");
- return 0; /* Shouldn't happen: at least one CPU online. */
- }
-
- /* If we are on an internal node, complain bitterly. */
- WARN_ON_ONCE(rnp != rdp->mynode);
-
- /*
- * Move tasks up to root rcu_node. Don't try to get fancy for
- * this corner-case operation -- just put this node's tasks
- * at the head of the root node's list, and update the root node's
- * ->gp_tasks and ->exp_tasks pointers to those of this node's,
- * if non-NULL. This might result in waiting for more tasks than
- * absolutely necessary, but this is a good performance/complexity
- * tradeoff.
- */
- if (rcu_preempt_blocked_readers_cgp(rnp) && rnp->qsmask == 0)
- retval |= RCU_OFL_TASKS_NORM_GP;
- if (rcu_preempted_readers_exp(rnp))
- retval |= RCU_OFL_TASKS_EXP_GP;
- lp = &rnp->blkd_tasks;
- lp_root = &rnp_root->blkd_tasks;
- while (!list_empty(lp)) {
- t = list_entry(lp->next, typeof(*t), rcu_node_entry);
- raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
- smp_mb__after_unlock_lock();
- list_del(&t->rcu_node_entry);
- t->rcu_blocked_node = rnp_root;
- list_add(&t->rcu_node_entry, lp_root);
- if (&t->rcu_node_entry == rnp->gp_tasks)
- rnp_root->gp_tasks = rnp->gp_tasks;
- if (&t->rcu_node_entry == rnp->exp_tasks)
- rnp_root->exp_tasks = rnp->exp_tasks;
-#ifdef CONFIG_RCU_BOOST
- if (&t->rcu_node_entry == rnp->boost_tasks)
- rnp_root->boost_tasks = rnp->boost_tasks;
-#endif /* #ifdef CONFIG_RCU_BOOST */
- raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
- }
-
- rnp->gp_tasks = NULL;
- rnp->exp_tasks = NULL;
-#ifdef CONFIG_RCU_BOOST
- rnp->boost_tasks = NULL;
- /*
- * In case root is being boosted and leaf was not. Make sure
- * that we boost the tasks blocking the current grace period
- * in this case.
- */
- raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
- smp_mb__after_unlock_lock();
- if (rnp_root->boost_tasks != NULL &&
- rnp_root->boost_tasks != rnp_root->gp_tasks &&
- rnp_root->boost_tasks != rnp_root->exp_tasks)
- rnp_root->boost_tasks = rnp_root->gp_tasks;
- raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
-#endif /* #ifdef CONFIG_RCU_BOOST */
-
- return retval;
-}
-
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
/*
@@ -1023,23 +937,6 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
WARN_ON_ONCE(rnp->qsmask);
}
-#ifdef CONFIG_HOTPLUG_CPU
-
-/*
- * Because preemptible RCU does not exist, it never needs to migrate
- * tasks that were blocked within RCU read-side critical sections, and
- * such non-existent tasks cannot possibly have been blocking the current
- * grace period.
- */
-static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
- struct rcu_node *rnp,
- struct rcu_data *rdp)
-{
- return 0;
-}
-
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-
/*
* Because preemptible RCU does not exist, it never has any callbacks
* to check.
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 07/10] rcu: Shorten irq-disable region in rcu_cleanup_dead_cpu()
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (4 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 06/10] rcu: Don't migrate blocked tasks even if all corresponding CPUs offline Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 08/10] rcu: Make use of rcu_preempt_has_tasks() Paul E. McKenney
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Now that we are not migrating callbacks, there is no need to hold the
->orphan_lock across the the ->qsmaskinit bit-clearing process.
This commit therefore releases ->orphan_lock immediately after adopting
the orphaned RCU callbacks.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index e870b0f5e1b9..3c23e921b438 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2257,14 +2257,14 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
/* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
rcu_adopt_orphan_cbs(rsp, flags);
+ raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags);
/* Remove outgoing CPU from mask in the leaf rcu_node structure. */
- raw_spin_lock(&rnp->lock); /* irqs already disabled. */
+ raw_spin_lock_irqsave(&rnp->lock, flags);
smp_mb__after_unlock_lock(); /* Enforce GP memory-order guarantee. */
rnp->qsmaskinit &= ~rdp->grpmask;
if (rnp->qsmaskinit == 0 && !rcu_preempt_has_tasks(rnp))
rcu_cleanup_dead_rnp(rnp);
- raw_spin_unlock(&rsp->orphan_lock); /* irqs remain disabled. */
raw_spin_unlock_irqrestore(&rnp->lock, flags);
WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
"rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 08/10] rcu: Make use of rcu_preempt_has_tasks()
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (5 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 07/10] rcu: Shorten irq-disable region in rcu_cleanup_dead_cpu() Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 09/10] rcu: Don't spawn rcub kthreads on root rcu_node structure Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 10/10] rcu: Don't initiate RCU priority boosting on root rcu_node Paul E. McKenney
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Given that there is now arcu_preempt_has_tasks() function that checks
to see if the ->blkd_tasks list is non-empty, this commit makes use of it.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree_plugin.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index eb05cd805536..65786864dcfb 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -538,7 +538,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
{
WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp));
- if (!list_empty(&rnp->blkd_tasks))
+ if (rcu_preempt_has_tasks(rnp))
rnp->gp_tasks = rnp->blkd_tasks.next;
WARN_ON_ONCE(rnp->qsmask);
}
@@ -704,7 +704,7 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
raw_spin_lock_irqsave(&rnp->lock, flags);
smp_mb__after_unlock_lock();
- if (list_empty(&rnp->blkd_tasks)) {
+ if (!rcu_preempt_has_tasks(rnp)) {
raw_spin_unlock_irqrestore(&rnp->lock, flags);
} else {
rnp->exp_tasks = rnp->blkd_tasks.next;
@@ -1004,7 +1004,7 @@ void exit_rcu(void)
static void rcu_initiate_boost_trace(struct rcu_node *rnp)
{
- if (list_empty(&rnp->blkd_tasks))
+ if (!rcu_preempt_has_tasks(rnp))
rnp->n_balk_blkd_tasks++;
else if (rnp->exp_tasks == NULL && rnp->gp_tasks == NULL)
rnp->n_balk_exp_gp_tasks++;
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 09/10] rcu: Don't spawn rcub kthreads on root rcu_node structure
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (6 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 08/10] rcu: Make use of rcu_preempt_has_tasks() Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 10/10] rcu: Don't initiate RCU priority boosting on root rcu_node Paul E. McKenney
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Now that offlining CPUs no longer moves leaf rcu_node structures'
->blkd_tasks lists to the root, there is no way for the root rcu_node
structure's ->blkd_task list to be nonempty, unless the root node is also
the sole leaf node. This commit therefore refrains from creating an rcub
kthread for the root rcu_node structure unless it is also the sole leaf.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree_plugin.h | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 65786864dcfb..fb05d963eaaa 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1371,12 +1371,8 @@ static void __init rcu_spawn_boost_kthreads(void)
for_each_possible_cpu(cpu)
per_cpu(rcu_cpu_has_work, cpu) = 0;
BUG_ON(smpboot_register_percpu_thread(&rcu_cpu_thread_spec));
- rnp = rcu_get_root(rcu_state_p);
- (void)rcu_spawn_one_boost_kthread(rcu_state_p, rnp);
- if (NUM_RCU_NODES > 1) {
- rcu_for_each_leaf_node(rcu_state_p, rnp)
- (void)rcu_spawn_one_boost_kthread(rcu_state_p, rnp);
- }
+ rcu_for_each_leaf_node(rcu_state_p, rnp)
+ (void)rcu_spawn_one_boost_kthread(rcu_state_p, rnp);
}
static void rcu_prepare_kthreads(int cpu)
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH tip/core/rcu 10/10] rcu: Don't initiate RCU priority boosting on root rcu_node
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
` (7 preceding siblings ...)
2014-11-05 17:41 ` [PATCH tip/core/rcu 09/10] rcu: Don't spawn rcub kthreads on root rcu_node structure Paul E. McKenney
@ 2014-11-05 17:41 ` Paul E. McKenney
8 siblings, 0 replies; 11+ messages in thread
From: Paul E. McKenney @ 2014-11-05 17:41 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, tglx,
peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Because there is no longer any preempted tasks on the root rcu_node, and
because there is no longer ever an rcub kthread for the root rcu_node,
this commit drops the code in force_qs_rnp() that attempts to awaken
the non-existent root rcub kthread. This is strictly a performance
enhancement, removing a root rcu_node ->lock acquisition and release
along with some tests in rcu_initiate_boost(), ending with the test that
notes that there is no rcub kthread.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
kernel/rcu/tree.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 3c23e921b438..d574f65ac023 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2481,12 +2481,6 @@ static void force_qs_rnp(struct rcu_state *rsp,
}
raw_spin_unlock_irqrestore(&rnp->lock, flags);
}
- rnp = rcu_get_root(rsp);
- if (rnp->qsmask == 0) {
- raw_spin_lock_irqsave(&rnp->lock, flags);
- smp_mb__after_unlock_lock();
- rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
- }
}
/*
--
1.8.1.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-11-05 17:43 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-05 17:41 [PATCH tip/core/rcu 0/10] Reduce latency impact of PREEMPT_RCU CPU offline Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 01/10] rcu: Fix invoke_rcu_callbacks() comment Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 02/10] rcu: Protect rcu_boost() lockless accesses with ACCESS_ONCE() Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 03/10] rcu: Rename "empty" to "empty_norm" in preparation for boost rework Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 04/10] rcu: Abstract rcu_cleanup_dead_rnp() from rcu_cleanup_dead_cpu() Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 05/10] rcu: Make rcu_read_unlock_special() propagate ->qsmaskinit bit clearing Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 06/10] rcu: Don't migrate blocked tasks even if all corresponding CPUs offline Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 07/10] rcu: Shorten irq-disable region in rcu_cleanup_dead_cpu() Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 08/10] rcu: Make use of rcu_preempt_has_tasks() Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 09/10] rcu: Don't spawn rcub kthreads on root rcu_node structure Paul E. McKenney
2014-11-05 17:41 ` [PATCH tip/core/rcu 10/10] rcu: Don't initiate RCU priority boosting on root rcu_node Paul E. McKenney
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.