aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-02-02 14:46:33 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-03-03 14:16:47 -0500
commitb826565aaf8809df146666c03d1acbb7febbd13e (patch)
treecb5224792ca8c92abe2e695fcef61ecc49d83631
parenta3bd2c09adcc80946262fd15e63868de1f0f4963 (diff)
rcu: Reverse rcu_dereference_check() conditions
The rcu_dereference_check() family of primitives evaluates the RCU lockdep expression first, and only then evaluates the expression passed in. This works fine normally, but can potentially fail in environments (such as NMI handlers) where lockdep cannot be invoked. The problem is that even if the expression passed in is "1", the compiler would need to prove that the RCU lockdep expression (rcu_read_lock_held(), for example) is free of side effects in order to be able to elide it. Given that rcu_read_lock_held() is sometimes separately compiled, the compiler cannot always use this optimization. This commit therefore reverse the order of evaluation, so that the expression passed in is evaluated first, and the RCU lockdep expression is evaluated only if the passed-in expression evaluated to false, courtesy of the C-language short-circuit boolean evaluation rules. This compells the compiler to forego executing the RCU lockdep expression in cases where the passed-in expression evaluates to "1" at compile time, so that (for example) rcu_dereference_raw() can be guaranteed to execute safely within an NMI handler. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-rw-r--r--include/linux/rcupdate.h6
-rw-r--r--include/linux/srcu.h2
2 files changed, 4 insertions, 4 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 70b896e16f19..416ae2848c6c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -729,7 +729,7 @@ static inline void rcu_preempt_sleep_check(void)
729 * annotated as __rcu. 729 * annotated as __rcu.
730 */ 730 */
731#define rcu_dereference_check(p, c) \ 731#define rcu_dereference_check(p, c) \
732 __rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu) 732 __rcu_dereference_check((p), (c) || rcu_read_lock_held(), __rcu)
733 733
734/** 734/**
735 * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking 735 * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking
@@ -739,7 +739,7 @@ static inline void rcu_preempt_sleep_check(void)
739 * This is the RCU-bh counterpart to rcu_dereference_check(). 739 * This is the RCU-bh counterpart to rcu_dereference_check().
740 */ 740 */
741#define rcu_dereference_bh_check(p, c) \ 741#define rcu_dereference_bh_check(p, c) \
742 __rcu_dereference_check((p), rcu_read_lock_bh_held() || (c), __rcu) 742 __rcu_dereference_check((p), (c) || rcu_read_lock_bh_held(), __rcu)
743 743
744/** 744/**
745 * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking 745 * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking
@@ -749,7 +749,7 @@ static inline void rcu_preempt_sleep_check(void)
749 * This is the RCU-sched counterpart to rcu_dereference_check(). 749 * This is the RCU-sched counterpart to rcu_dereference_check().
750 */ 750 */
751#define rcu_dereference_sched_check(p, c) \ 751#define rcu_dereference_sched_check(p, c) \
752 __rcu_dereference_check((p), rcu_read_lock_sched_held() || (c), \ 752 __rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \
753 __rcu) 753 __rcu)
754 754
755#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/ 755#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 9cfd9623fb03..bdeb4567b71e 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -182,7 +182,7 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)
182 * lockdep_is_held() calls. 182 * lockdep_is_held() calls.
183 */ 183 */
184#define srcu_dereference_check(p, sp, c) \ 184#define srcu_dereference_check(p, sp, c) \
185 __rcu_dereference_check((p), srcu_read_lock_held(sp) || (c), __rcu) 185 __rcu_dereference_check((p), (c) || srcu_read_lock_held(sp), __rcu)
186 186
187/** 187/**
188 * srcu_dereference - fetch SRCU-protected pointer for later dereferencing 188 * srcu_dereference - fetch SRCU-protected pointer for later dereferencing