[PATCH 01/10] rcu: define __rcu address space modifier for sparse

From: Arnd Bergmann
Date: Wed Feb 24 2010 - 15:06:42 EST


This is a first attempt to define an __rcu annotation
that lets sparse check for correct use of rcu_assign_pointer()
and rcu_dereference(). Pointers that are annotated __rcu
must be dereferenced using rcu_dereference or the new
__rcu_dereference and must be assigned using rcu_assign_pointer
or the new __rcu_assign_pointer.

The new macros are used in cases where not using the
regular accessors is proven to be correct.

Signed-off-by: Arnd Bergmann <arnd@xxxxxxxx>
---
include/linux/compiler.h | 2 ++
include/linux/rcupdate.h | 46 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 188fcae..6cc0857 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -10,6 +10,7 @@
# define __force __attribute__((force))
# define __nocast __attribute__((nocast))
# define __iomem __attribute__((noderef, address_space(2)))
+# define __rcu __attribute__((noderef, address_space(3)))
# define __acquires(x) __attribute__((context(x,0,1)))
# define __releases(x) __attribute__((context(x,1,0)))
# define __acquire(x) __context__(x,1)
@@ -25,6 +26,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
# define __force
# define __nocast
# define __iomem
+# define __rcu
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
# define __builtin_warning(x, y...) (1)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 24440f4..644e28c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -40,6 +40,7 @@
#include <linux/seqlock.h>
#include <linux/lockdep.h>
#include <linux/completion.h>
+#include <linux/compiler.h>

/**
* struct rcu_head - callback structure for use with RCU
@@ -225,13 +226,31 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
*
* Inserts memory barriers on architectures that require them
* (currently only the Alpha), and, more importantly, documents
- * exactly which pointers are protected by RCU.
+ * exactly which pointers are protected by RCU and checks that
+ * the pointer is annotated as __rcu.
*/
-
#define rcu_dereference(p) ({ \
- typeof(p) _________p1 = ACCESS_ONCE(p); \
+ typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+ (void) (((typeof (*p) __rcu *)p) == p); \
smp_read_barrier_depends(); \
- (_________p1); \
+ ((typeof(*p) __force __kernel *)(_________p1)); \
+ })
+
+/**
+ * __rcu_dereference - fetch an __rcu pointer outside of a
+ * read-side critical section.
+ *
+ * __rcu_dereference does not contain any barrier but only
+ * converts a __rcu pointer to one that can be dereferenced.
+ * Use this for annotating code that operates on __rcu variables
+ * for checking with sparse in places where you can be sure
+ * that no writers exist, e.g. in a write-side critical section
+ * or in an RCU call.
+ */
+
+#define __rcu_dereference(p) ({ \
+ (void) (((typeof (*p) __rcu *)p) == p); \
+ ((typeof(*p) __force __kernel *)(p)); \
})

/**
@@ -252,9 +271,26 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
if (!__builtin_constant_p(v) || \
((v) != NULL)) \
smp_wmb(); \
- (p) = (v); \
+ (p) = (typeof(*v) __force __rcu *)(v); \
})

+/**
+ * __rcu_assign_pointer - assign a variable to an __rcu pointer
+ * without barriers.
+ * Using this is almost always a bug.
+ */
+#define __rcu_assign_pointer(p, v) \
+ ({ \
+ (p) = (typeof(*v) __force __rcu *)(v); \
+ })
+
+/**
+ * RCU_INIT_POINTER - initialize an RCU protected member
+ * in a statically allocated data structure.
+ */
+#define RCU_INIT_POINTER(p, v) \
+ p = (typeof(*v) __force __rcu *)(v)
+
/* Infrastructure to implement the synchronize_() primitives. */

struct rcu_synchronize {
--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/