|
@@ -536,6 +536,11 @@ static inline int rcu_read_lock_sched_held(void)
|
|
|
|
|
|
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
|
|
|
|
|
+/* Deprecate rcu_lockdep_assert(): Use RCU_LOCKDEP_WARN() instead. */
|
|
|
+static inline void __attribute((deprecated)) deprecate_rcu_lockdep_assert(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_PROVE_RCU
|
|
|
|
|
|
/**
|
|
@@ -546,17 +551,32 @@ static inline int rcu_read_lock_sched_held(void)
|
|
|
#define rcu_lockdep_assert(c, s) \
|
|
|
do { \
|
|
|
static bool __section(.data.unlikely) __warned; \
|
|
|
+ deprecate_rcu_lockdep_assert(); \
|
|
|
if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
|
|
|
__warned = true; \
|
|
|
lockdep_rcu_suspicious(__FILE__, __LINE__, s); \
|
|
|
} \
|
|
|
} while (0)
|
|
|
|
|
|
+/**
|
|
|
+ * RCU_LOCKDEP_WARN - emit lockdep splat if specified condition is met
|
|
|
+ * @c: condition to check
|
|
|
+ * @s: informative message
|
|
|
+ */
|
|
|
+#define RCU_LOCKDEP_WARN(c, s) \
|
|
|
+ do { \
|
|
|
+ static bool __section(.data.unlikely) __warned; \
|
|
|
+ if (debug_lockdep_rcu_enabled() && !__warned && (c)) { \
|
|
|
+ __warned = true; \
|
|
|
+ lockdep_rcu_suspicious(__FILE__, __LINE__, s); \
|
|
|
+ } \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
#if defined(CONFIG_PROVE_RCU) && !defined(CONFIG_PREEMPT_RCU)
|
|
|
static inline void rcu_preempt_sleep_check(void)
|
|
|
{
|
|
|
- rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
|
|
|
- "Illegal context switch in RCU read-side critical section");
|
|
|
+ RCU_LOCKDEP_WARN(lock_is_held(&rcu_lock_map),
|
|
|
+ "Illegal context switch in RCU read-side critical section");
|
|
|
}
|
|
|
#else /* #ifdef CONFIG_PROVE_RCU */
|
|
|
static inline void rcu_preempt_sleep_check(void)
|
|
@@ -567,15 +587,16 @@ static inline void rcu_preempt_sleep_check(void)
|
|
|
#define rcu_sleep_check() \
|
|
|
do { \
|
|
|
rcu_preempt_sleep_check(); \
|
|
|
- rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \
|
|
|
- "Illegal context switch in RCU-bh read-side critical section"); \
|
|
|
- rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \
|
|
|
- "Illegal context switch in RCU-sched read-side critical section"); \
|
|
|
+ RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map), \
|
|
|
+ "Illegal context switch in RCU-bh read-side critical section"); \
|
|
|
+ RCU_LOCKDEP_WARN(lock_is_held(&rcu_sched_lock_map), \
|
|
|
+ "Illegal context switch in RCU-sched read-side critical section"); \
|
|
|
} while (0)
|
|
|
|
|
|
#else /* #ifdef CONFIG_PROVE_RCU */
|
|
|
|
|
|
-#define rcu_lockdep_assert(c, s) do { } while (0)
|
|
|
+#define rcu_lockdep_assert(c, s) deprecate_rcu_lockdep_assert()
|
|
|
+#define RCU_LOCKDEP_WARN(c, s) do { } while (0)
|
|
|
#define rcu_sleep_check() do { } while (0)
|
|
|
|
|
|
#endif /* #else #ifdef CONFIG_PROVE_RCU */
|
|
@@ -606,13 +627,13 @@ static inline void rcu_preempt_sleep_check(void)
|
|
|
({ \
|
|
|
/* Dependency order vs. p above. */ \
|
|
|
typeof(*p) *________p1 = (typeof(*p) *__force)lockless_dereference(p); \
|
|
|
- rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \
|
|
|
+ RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \
|
|
|
rcu_dereference_sparse(p, space); \
|
|
|
((typeof(*p) __force __kernel *)(________p1)); \
|
|
|
})
|
|
|
#define __rcu_dereference_protected(p, c, space) \
|
|
|
({ \
|
|
|
- rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \
|
|
|
+ RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \
|
|
|
rcu_dereference_sparse(p, space); \
|
|
|
((typeof(*p) __force __kernel *)(p)); \
|
|
|
})
|
|
@@ -836,8 +857,8 @@ static inline void rcu_read_lock(void)
|
|
|
__rcu_read_lock();
|
|
|
__acquire(RCU);
|
|
|
rcu_lock_acquire(&rcu_lock_map);
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_lock() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_lock() used illegally while idle");
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -887,8 +908,8 @@ static inline void rcu_read_lock(void)
|
|
|
*/
|
|
|
static inline void rcu_read_unlock(void)
|
|
|
{
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_unlock() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_unlock() used illegally while idle");
|
|
|
__release(RCU);
|
|
|
__rcu_read_unlock();
|
|
|
rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */
|
|
@@ -916,8 +937,8 @@ static inline void rcu_read_lock_bh(void)
|
|
|
local_bh_disable();
|
|
|
__acquire(RCU_BH);
|
|
|
rcu_lock_acquire(&rcu_bh_lock_map);
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_lock_bh() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_lock_bh() used illegally while idle");
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -927,8 +948,8 @@ static inline void rcu_read_lock_bh(void)
|
|
|
*/
|
|
|
static inline void rcu_read_unlock_bh(void)
|
|
|
{
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_unlock_bh() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_unlock_bh() used illegally while idle");
|
|
|
rcu_lock_release(&rcu_bh_lock_map);
|
|
|
__release(RCU_BH);
|
|
|
local_bh_enable();
|
|
@@ -952,8 +973,8 @@ static inline void rcu_read_lock_sched(void)
|
|
|
preempt_disable();
|
|
|
__acquire(RCU_SCHED);
|
|
|
rcu_lock_acquire(&rcu_sched_lock_map);
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_lock_sched() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_lock_sched() used illegally while idle");
|
|
|
}
|
|
|
|
|
|
/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */
|
|
@@ -970,8 +991,8 @@ static inline notrace void rcu_read_lock_sched_notrace(void)
|
|
|
*/
|
|
|
static inline void rcu_read_unlock_sched(void)
|
|
|
{
|
|
|
- rcu_lockdep_assert(rcu_is_watching(),
|
|
|
- "rcu_read_unlock_sched() used illegally while idle");
|
|
|
+ RCU_LOCKDEP_WARN(!rcu_is_watching(),
|
|
|
+ "rcu_read_unlock_sched() used illegally while idle");
|
|
|
rcu_lock_release(&rcu_sched_lock_map);
|
|
|
__release(RCU_SCHED);
|
|
|
preempt_enable();
|