aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2007-10-17 02:26:04 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:46 -0400
commit97b430320ce7c95f0d5587c5ecc8f6a9d0c698e9 (patch)
tree3f805b4351c2c4ce68b8de869320f2afc9a805d5
parentf6b450d489f2fb4e909447beacad64edb8aa0cda (diff)
Immunize rcu_dereference() against crazy compiler writers
Turns out that compiler writers are a bit more aggressive about optimizing than one might expect. This patch prevents a number of such optimizations from messing up rcu_deference(). This is not merely a theoretical problem, as evidenced by the rmb() in mce_log(). Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: Josh Triplett <josh@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/rcupdate.h14
1 files changed, 13 insertions, 1 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 76c1a530edc5..cc24a01df940 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -231,6 +231,18 @@ extern struct lockdep_map rcu_lock_map;
231 local_bh_enable(); \ 231 local_bh_enable(); \
232 } while(0) 232 } while(0)
233 233
234/*
235 * Prevent the compiler from merging or refetching accesses. The compiler
236 * is also forbidden from reordering successive instances of ACCESS_ONCE(),
237 * but only when the compiler is aware of some particular ordering. One way
238 * to make the compiler aware of ordering is to put the two invocations of
239 * ACCESS_ONCE() in different C statements.
240 *
241 * This macro does absolutely -nothing- to prevent the CPU from reordering,
242 * merging, or refetching absolutely anything at any time.
243 */
244#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
245
234/** 246/**
235 * rcu_dereference - fetch an RCU-protected pointer in an 247 * rcu_dereference - fetch an RCU-protected pointer in an
236 * RCU read-side critical section. This pointer may later 248 * RCU read-side critical section. This pointer may later
@@ -242,7 +254,7 @@ extern struct lockdep_map rcu_lock_map;
242 */ 254 */
243 255
244#define rcu_dereference(p) ({ \ 256#define rcu_dereference(p) ({ \
245 typeof(p) _________p1 = p; \ 257 typeof(p) _________p1 = ACCESS_ONCE(p); \
246 smp_read_barrier_depends(); \ 258 smp_read_barrier_depends(); \
247 (_________p1); \ 259 (_________p1); \
248 }) 260 })