|
@@ -231,6 +231,18 @@ extern struct lockdep_map rcu_lock_map;
|
|
local_bh_enable(); \
|
|
local_bh_enable(); \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Prevent the compiler from merging or refetching accesses. The compiler
|
|
|
|
+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
|
|
|
|
+ * but only when the compiler is aware of some particular ordering. One way
|
|
|
|
+ * to make the compiler aware of ordering is to put the two invocations of
|
|
|
|
+ * ACCESS_ONCE() in different C statements.
|
|
|
|
+ *
|
|
|
|
+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
|
|
|
|
+ * merging, or refetching absolutely anything at any time.
|
|
|
|
+ */
|
|
|
|
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* rcu_dereference - fetch an RCU-protected pointer in an
|
|
* rcu_dereference - fetch an RCU-protected pointer in an
|
|
* RCU read-side critical section. This pointer may later
|
|
* RCU read-side critical section. This pointer may later
|
|
@@ -242,7 +254,7 @@ extern struct lockdep_map rcu_lock_map;
|
|
*/
|
|
*/
|
|
|
|
|
|
#define rcu_dereference(p) ({ \
|
|
#define rcu_dereference(p) ({ \
|
|
- typeof(p) _________p1 = p; \
|
|
|
|
|
|
+ typeof(p) _________p1 = ACCESS_ONCE(p); \
|
|
smp_read_barrier_depends(); \
|
|
smp_read_barrier_depends(); \
|
|
(_________p1); \
|
|
(_________p1); \
|
|
})
|
|
})
|