public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14
@ 2013-12-11 23:08 Paul E. McKenney
  2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
  2013-12-12  4:10 ` [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Josh Triplett
  0 siblings, 2 replies; 6+ messages in thread
From: Paul E. McKenney @ 2013-12-11 23:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
	peterz, rostedt, dhowells, edumazet, darren, fweisbec, oleg, sbw

Hello!

This series once again attempts to improve rcu_assign_pointer()'s
relationship with sparse.

1.	Add a comment indicating that despite appearances,
	rcu_assign_pointer() really only evaluates its arguments once,
	as a cpp macro should.

2.	Replace rcu_assign_pointer() of NULL with RCU_INIT_POINTER() to
	silence a sparse warning.

3.	Apply ACCESS_ONCE() to rcu_assign_pointer()'s target to prevent
	comiler mischief.  Also require that the source pointer be from
	the kernel address space.  Sometimes it can be from the RCU address
	space, which necessitates the remaining patches in this series.
	Which, it must be admitted, apply to a very small fraction of
	the rcu_assign_pointer() invocations in the kernel.  This commit
	courtesy of Josh Triplett.

4.	Add an RCU_INITIALIZER() for compile-time initialization of
	global RCU-protected pointers.

Changes from v1 (candidate for v3.14):

o	Remove the requirement that values passed to rcu_assign_pointer()
	needed to be in sparse's __kernel address space.  This found
	no bugs and produced a number of ugly false positives.	(Hey,
	it seemed like a good idea at the time...)

o	Remove lots of rcu_assign_pointer()-to-ACCESS_ONCE() changes
	that are no longer needed given the above change.

Changes from v3 (candidate for 3.13):

o	Remove the replacements of rcu_assign_pointer() with ACCESS_ONCE()
	where new data really was being exposed to readers.

Changes from v2:

o	Switch from rcu_assign_pointer() to ACCESS_ONCE() given that
	the pointers are all --rcu and already visible to readers,
	as suggested by Eric Dumazet and Josh Triplett.

o	Place the commit adding the rcu_assign_pointer()'s ACCESS_ONCE()
	at the end to allow better bisectability, as suggested by Josh
	Triplett.

o	Add a comment to rcu_assign_pointer() noting that it only evaluates
	its arguments once, as suggested by Josh Triplett.

Changes from v1:

o	Fix grammar nit in commit logs.

							Thanx, Paul

------------------------------------------------------------------------

 b/drivers/net/bonding/bond_main.c |    2 
 b/include/linux/rcupdate.h        |   90 +++++++++++++++++++++-----------------
 2 files changed, 52 insertions(+), 40 deletions(-)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer().
  2013-12-11 23:08 [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Paul E. McKenney
@ 2013-12-11 23:08 ` Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 2/4] bonding: Use RCU_INIT_POINTER() for better overhead and for sparse Paul E. McKenney
                     ` (2 more replies)
  2013-12-12  4:10 ` [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Josh Triplett
  1 sibling, 3 replies; 6+ messages in thread
From: Paul E. McKenney @ 2013-12-11 23:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
	peterz, rostedt, dhowells, edumazet, darren, fweisbec, oleg, sbw,
	Paul E. McKenney

From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>

The rcu_assign_pointer() macro, as with most cpp macros, must not evaluate
its argument more than once.  And it in fact does not.  But this might
not be obvious to the casual observer, because one of the arguments
appears no less than three times.  However, but one expansion is only
visible to sparse (__CHECKER__), and one lives inside a typeof (where
it will never be evaluated), so this is in fact safe.

This commit therefore adds a comment making this explicit.

Reported-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 include/linux/rcupdate.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 39cbb889e20d..00ad28168ef0 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -911,6 +911,14 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * rcu_assign_pointer() is a very bad thing that results in
  * impossible-to-diagnose memory corruption.  So please be careful.
  * See the RCU_INIT_POINTER() comment header for details.
+ *
+ * Note that rcu_assign_pointer() evaluates each of its arguments only
+ * once, appearances notwithstanding.  One of the "extra" evaluations
+ * is in typeof() and the other visible only to sparse (__CHECKER__),
+ * neither of which actually execute the argument.  As with most cpp
+ * macros, this execute-arguments-only-once property is important, so
+ * please be careful when making changes to rcu_assign_pointer() and the
+ * other macros that it invokes.
  */
 #define rcu_assign_pointer(p, v) \
 	__rcu_assign_pointer((p), (v), __rcu)
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 tip/core/rcu 2/4] bonding: Use RCU_INIT_POINTER() for better overhead and for sparse
  2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
@ 2013-12-11 23:08   ` Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 3/4] rcu: Make rcu_assign_pointer's assignment volatile and type-safe Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 4/4] rcu: Add an RCU_INITIALIZER for global RCU-protected pointers Paul E. McKenney
  2 siblings, 0 replies; 6+ messages in thread
From: Paul E. McKenney @ 2013-12-11 23:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
	peterz, rostedt, dhowells, edumazet, darren, fweisbec, oleg, sbw,
	Paul E. McKenney

From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>

Although rcu_assign_pointer() can be used to assign a constant
NULL pointer, doing so gets you an unnecessary memory barrier and
in some circumstances, sparse warnings.  This commit therefore
changes the rcu_assign_pointer() of NULL in __bond_release_one() to
RCU_INIT_POINTER().

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 drivers/net/bonding/bond_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 4dd5ee2a34cc..a0b97c4c655d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	}
 
 	if (all) {
-		rcu_assign_pointer(bond->curr_active_slave, NULL);
+		RCU_INIT_POINTER(bond->curr_active_slave, NULL);
 	} else if (oldcurrent == slave) {
 		/*
 		 * Note that we hold RTNL over this sequence, so there
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 tip/core/rcu 3/4] rcu: Make rcu_assign_pointer's assignment volatile and type-safe
  2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 2/4] bonding: Use RCU_INIT_POINTER() for better overhead and for sparse Paul E. McKenney
@ 2013-12-11 23:08   ` Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 4/4] rcu: Add an RCU_INITIALIZER for global RCU-protected pointers Paul E. McKenney
  2 siblings, 0 replies; 6+ messages in thread
From: Paul E. McKenney @ 2013-12-11 23:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
	peterz, rostedt, dhowells, edumazet, darren, fweisbec, oleg, sbw,
	Paul E. McKenney

From: Josh Triplett <josh@joshtriplett.org>

The rcu_assign_pointer() primitive needs to use ACCESS_ONCE to make
the assignment to the destination pointer volatile, to protect against
compilers too clever for their own good.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 include/linux/rcupdate.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 00ad28168ef0..97853cd2d7b4 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -551,7 +551,7 @@ static inline void rcu_preempt_sleep_check(void)
 #define __rcu_assign_pointer(p, v, space) \
 	do { \
 		smp_wmb(); \
-		(p) = (typeof(*v) __force space *)(v); \
+		ACCESS_ONCE(p) = (typeof(*(v)) __force space *)(v); \
 	} while (0)
 
 
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 tip/core/rcu 4/4] rcu: Add an RCU_INITIALIZER for global RCU-protected pointers
  2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 2/4] bonding: Use RCU_INIT_POINTER() for better overhead and for sparse Paul E. McKenney
  2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 3/4] rcu: Make rcu_assign_pointer's assignment volatile and type-safe Paul E. McKenney
@ 2013-12-11 23:08   ` Paul E. McKenney
  2 siblings, 0 replies; 6+ messages in thread
From: Paul E. McKenney @ 2013-12-11 23:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, laijs, dipankar, akpm, mathieu.desnoyers, josh, niv, tglx,
	peterz, rostedt, dhowells, edumazet, darren, fweisbec, oleg, sbw,
	Paul E. McKenney

From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>

There is currently no way to initialize a global RCU-protected pointer
without either putting up with sparse complaints or open-coding an
obscure cast.  This commit therefore creates RCU_INITIALIZER(), which
is intended to be used as follows:

	struct foo __rcu *p = RCU_INITIALIZER(&my_rcu_structure);

This commit also applies RCU_INITIALIZER() to eliminate repeated
open-coded obscure casts in __rcu_assign_pointer(), RCU_INIT_POINTER(),
and RCU_POINTER_INITIALIZER().  This commit also inlines
__rcu_assign_pointer() into its only caller, rcu_assign_pointer().

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

Conflicts:
	include/linux/rcupdate.h
---
 include/linux/rcupdate.h | 80 +++++++++++++++++++++++++-----------------------
 1 file changed, 42 insertions(+), 38 deletions(-)

diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 97853cd2d7b4..ea3816cf1a13 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -548,10 +548,48 @@ static inline void rcu_preempt_sleep_check(void)
 		smp_read_barrier_depends(); \
 		(_________p1); \
 	})
-#define __rcu_assign_pointer(p, v, space) \
+
+/**
+ * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
+ * @v: The value to statically initialize with.
+ */
+#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
+
+/**
+ * rcu_assign_pointer() - assign to RCU-protected pointer
+ * @p: pointer to assign to
+ * @v: value to assign (publish)
+ *
+ * Assigns the specified value to the specified RCU-protected
+ * pointer, ensuring that any concurrent RCU readers will see
+ * any prior initialization.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (which is most of them), and also prevents the compiler from
+ * reordering the code that initializes the structure after the pointer
+ * assignment.  More importantly, this call documents which pointers
+ * will be dereferenced by RCU read-side code.
+ *
+ * In some special cases, you may use RCU_INIT_POINTER() instead
+ * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
+ * to the fact that it does not constrain either the CPU or the compiler.
+ * That said, using RCU_INIT_POINTER() when you should have used
+ * rcu_assign_pointer() is a very bad thing that results in
+ * impossible-to-diagnose memory corruption.  So please be careful.
+ * See the RCU_INIT_POINTER() comment header for details.
+ *
+ * Note that rcu_assign_pointer() evaluates each of its arguments only
+ * once, appearances notwithstanding.  One of the "extra" evaluations
+ * is in typeof() and the other visible only to sparse (__CHECKER__),
+ * neither of which actually execute the argument.  As with most cpp
+ * macros, this execute-arguments-only-once property is important, so
+ * please be careful when making changes to rcu_assign_pointer() and the
+ * other macros that it invokes.
+ */
+#define rcu_assign_pointer(p, v) \
 	do { \
 		smp_wmb(); \
-		ACCESS_ONCE(p) = (typeof(*(v)) __force space *)(v); \
+		ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
 	} while (0)
 
 
@@ -890,40 +928,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
 }
 
 /**
- * rcu_assign_pointer() - assign to RCU-protected pointer
- * @p: pointer to assign to
- * @v: value to assign (publish)
- *
- * Assigns the specified value to the specified RCU-protected
- * pointer, ensuring that any concurrent RCU readers will see
- * any prior initialization.
- *
- * Inserts memory barriers on architectures that require them
- * (which is most of them), and also prevents the compiler from
- * reordering the code that initializes the structure after the pointer
- * assignment.  More importantly, this call documents which pointers
- * will be dereferenced by RCU read-side code.
- *
- * In some special cases, you may use RCU_INIT_POINTER() instead
- * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
- * to the fact that it does not constrain either the CPU or the compiler.
- * That said, using RCU_INIT_POINTER() when you should have used
- * rcu_assign_pointer() is a very bad thing that results in
- * impossible-to-diagnose memory corruption.  So please be careful.
- * See the RCU_INIT_POINTER() comment header for details.
- *
- * Note that rcu_assign_pointer() evaluates each of its arguments only
- * once, appearances notwithstanding.  One of the "extra" evaluations
- * is in typeof() and the other visible only to sparse (__CHECKER__),
- * neither of which actually execute the argument.  As with most cpp
- * macros, this execute-arguments-only-once property is important, so
- * please be careful when making changes to rcu_assign_pointer() and the
- * other macros that it invokes.
- */
-#define rcu_assign_pointer(p, v) \
-	__rcu_assign_pointer((p), (v), __rcu)
-
-/**
  * RCU_INIT_POINTER() - initialize an RCU protected pointer
  *
  * Initialize an RCU-protected pointer in special cases where readers
@@ -957,7 +961,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  */
 #define RCU_INIT_POINTER(p, v) \
 	do { \
-		p = (typeof(*v) __force __rcu *)(v); \
+		p = RCU_INITIALIZER(v); \
 	} while (0)
 
 /**
@@ -966,7 +970,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * GCC-style initialization for an RCU-protected pointer in a structure field.
  */
 #define RCU_POINTER_INITIALIZER(p, v) \
-		.p = (typeof(*v) __force __rcu *)(v)
+		.p = RCU_INITIALIZER(v)
 
 /*
  * Does the specified offset indicate that the corresponding rcu_head
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14
  2013-12-11 23:08 [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Paul E. McKenney
  2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
@ 2013-12-12  4:10 ` Josh Triplett
  1 sibling, 0 replies; 6+ messages in thread
From: Josh Triplett @ 2013-12-12  4:10 UTC (permalink / raw)
  To: Paul E. McKenney
  Cc: linux-kernel, mingo, laijs, dipankar, akpm, mathieu.desnoyers,
	niv, tglx, peterz, rostedt, dhowells, edumazet, darren, fweisbec,
	oleg, sbw

On Wed, Dec 11, 2013 at 03:08:23PM -0800, Paul E. McKenney wrote:
> Hello!
> 
> This series once again attempts to improve rcu_assign_pointer()'s
> relationship with sparse.
> 
> 1.	Add a comment indicating that despite appearances,
> 	rcu_assign_pointer() really only evaluates its arguments once,
> 	as a cpp macro should.
> 
> 2.	Replace rcu_assign_pointer() of NULL with RCU_INIT_POINTER() to
> 	silence a sparse warning.
> 
> 3.	Apply ACCESS_ONCE() to rcu_assign_pointer()'s target to prevent
> 	comiler mischief.  Also require that the source pointer be from
> 	the kernel address space.  Sometimes it can be from the RCU address
> 	space, which necessitates the remaining patches in this series.
> 	Which, it must be admitted, apply to a very small fraction of
> 	the rcu_assign_pointer() invocations in the kernel.  This commit
> 	courtesy of Josh Triplett.
> 
> 4.	Add an RCU_INITIALIZER() for compile-time initialization of
> 	global RCU-protected pointers.

For all the patches (other than the one I wrote, for obvious reasons):
Reviewed-by: Josh Triplett <josh@joshtriplett.org>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-12-12  4:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-11 23:08 [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Paul E. McKenney
2013-12-11 23:08 ` [PATCH v2 tip/core/rcu 1/4] rcu: Add comment on evaluate-once properties of rcu_assign_pointer() Paul E. McKenney
2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 2/4] bonding: Use RCU_INIT_POINTER() for better overhead and for sparse Paul E. McKenney
2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 3/4] rcu: Make rcu_assign_pointer's assignment volatile and type-safe Paul E. McKenney
2013-12-11 23:08   ` [PATCH v2 tip/core/rcu 4/4] rcu: Add an RCU_INITIALIZER for global RCU-protected pointers Paul E. McKenney
2013-12-12  4:10 ` [PATCH v2 tip/core/rcu 0/4] Documentation changes for 3.14 Josh Triplett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox