[RFC,tip/core/rcu,24/41] rcu: Check for idle-loop entry while in RCU read-side critical section

Message ID 1328125319-5205-24-git-send-email-paulmck@linux.vnet.ibm.com
State New
Headers show

Commit Message

Paul E. McKenney Feb. 1, 2012, 7:41 p.m.
From: "Paul E. McKenney" <paul.mckenney@linaro.org>

The inner idle loop is an extended quiescent state for all flavors
of RCU, but there have been recent bug involving use of RCU read-side
primitives from within the idle loop.  Therefore, this commit enlists
lockdep-RCU to detect attempts to enter the inner idle loop while in
an RCU read-side critical section, emitting a lockdep-RCU splat if so.

Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcutree.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

Comments

Josh Triplett Feb. 2, 2012, 5:13 a.m. | #1
On Wed, Feb 01, 2012 at 11:41:42AM -0800, Paul E. McKenney wrote:
> --- a/kernel/rcutree.c
> +++ b/kernel/rcutree.c
> @@ -366,6 +366,20 @@ static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
>  	atomic_inc(&rdtp->dynticks);
>  	smp_mb__after_atomic_inc();  /* Force ordering with next sojourn. */
>  	WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
> +
> +	/*
> +	 * The idle task is not permitted to enter the idle loop while
> +	 * in an RCU read-side critical section.
> +	 */
> +	rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
> +			   "Illegal idle entry in RCU read-side "
> +			   "critical section.");
> +	rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map),
> +			   "Illegal idle entry in RCU-bh read-side "
> +			   "critical section.");
> +	rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map),
> +			   "Illegal idle entry in RCU-sched read-side "
> +			   "critical section.");

Quoting a paragraph I added to Documentation/CodingStyle:

> Statements longer than 80 columns will be broken into sensible chunks, unless
> exceeding 80 columns significantly increases readability and does not hide
> information. Descendants are always substantially shorter than the parent and
> are placed substantially to the right. The same applies to function headers
> with a long argument list. However, never break user-visible strings such as
> printk messages, because that breaks the ability to grep for them.

So, please don't break those strings across multiple lines.  The same
goes for the similar rcu_lockdep_assert strings added in a previous
patch in this series.

- Josh Triplett
Paul E. McKenney Feb. 2, 2012, 5:50 p.m. | #2
On Wed, Feb 01, 2012 at 09:13:37PM -0800, Josh Triplett wrote:
> On Wed, Feb 01, 2012 at 11:41:42AM -0800, Paul E. McKenney wrote:
> > --- a/kernel/rcutree.c
> > +++ b/kernel/rcutree.c
> > @@ -366,6 +366,20 @@ static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
> >  	atomic_inc(&rdtp->dynticks);
> >  	smp_mb__after_atomic_inc();  /* Force ordering with next sojourn. */
> >  	WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
> > +
> > +	/*
> > +	 * The idle task is not permitted to enter the idle loop while
> > +	 * in an RCU read-side critical section.
> > +	 */
> > +	rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
> > +			   "Illegal idle entry in RCU read-side "
> > +			   "critical section.");
> > +	rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map),
> > +			   "Illegal idle entry in RCU-bh read-side "
> > +			   "critical section.");
> > +	rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map),
> > +			   "Illegal idle entry in RCU-sched read-side "
> > +			   "critical section.");
> 
> Quoting a paragraph I added to Documentation/CodingStyle:
> 
> > Statements longer than 80 columns will be broken into sensible chunks, unless
> > exceeding 80 columns significantly increases readability and does not hide
> > information. Descendants are always substantially shorter than the parent and
> > are placed substantially to the right. The same applies to function headers
> > with a long argument list. However, never break user-visible strings such as
> > printk messages, because that breaks the ability to grep for them.
> 
> So, please don't break those strings across multiple lines.  The same
> goes for the similar rcu_lockdep_assert strings added in a previous
> patch in this series.

Fixed!

Again, I leave it to you to get checkpatch.pl to complain about this.  ;-)

							Thanx, Paul

Patch

diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 6168153..e11bee9 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -366,6 +366,20 @@  static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
 	atomic_inc(&rdtp->dynticks);
 	smp_mb__after_atomic_inc();  /* Force ordering with next sojourn. */
 	WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
+
+	/*
+	 * The idle task is not permitted to enter the idle loop while
+	 * in an RCU read-side critical section.
+	 */
+	rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
+			   "Illegal idle entry in RCU read-side "
+			   "critical section.");
+	rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map),
+			   "Illegal idle entry in RCU-bh read-side "
+			   "critical section.");
+	rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map),
+			   "Illegal idle entry in RCU-sched read-side "
+			   "critical section.");
 }
 
 /**