|
@@ -226,6 +226,15 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
|
|
|
}
|
|
|
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
|
|
|
|
|
|
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
|
|
|
+bool rcu_lockdep_current_cpu_online(void);
|
|
|
+#else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
|
|
|
+static inline bool rcu_lockdep_current_cpu_online(void)
|
|
|
+{
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
|
|
|
+
|
|
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
|
|
|
#ifdef CONFIG_PROVE_RCU
|
|
@@ -270,6 +279,9 @@ extern int debug_lockdep_rcu_enabled(void);
|
|
|
* occur in the same context, for example, it is illegal to invoke
|
|
|
* rcu_read_unlock() in process context if the matching rcu_read_lock()
|
|
|
* was invoked from within an irq handler.
|
|
|
+ *
|
|
|
+ * Note that rcu_read_lock() is disallowed if the CPU is either idle or
|
|
|
+ * offline from an RCU perspective, so check for those as well.
|
|
|
*/
|
|
|
static inline int rcu_read_lock_held(void)
|
|
|
{
|
|
@@ -277,6 +289,8 @@ static inline int rcu_read_lock_held(void)
|
|
|
return 1;
|
|
|
if (rcu_is_cpu_idle())
|
|
|
return 0;
|
|
|
+ if (!rcu_lockdep_current_cpu_online())
|
|
|
+ return 0;
|
|
|
return lock_is_held(&rcu_lock_map);
|
|
|
}
|
|
|
|
|
@@ -313,6 +327,9 @@ extern int rcu_read_lock_bh_held(void);
|
|
|
* notice an extended quiescent state to other CPUs that started a grace
|
|
|
* period. Otherwise we would delay any grace period as long as we run in
|
|
|
* the idle task.
|
|
|
+ *
|
|
|
+ * Similarly, we avoid claiming an SRCU read lock held if the current
|
|
|
+ * CPU is offline.
|
|
|
*/
|
|
|
#ifdef CONFIG_PREEMPT_COUNT
|
|
|
static inline int rcu_read_lock_sched_held(void)
|
|
@@ -323,6 +340,8 @@ static inline int rcu_read_lock_sched_held(void)
|
|
|
return 1;
|
|
|
if (rcu_is_cpu_idle())
|
|
|
return 0;
|
|
|
+ if (!rcu_lockdep_current_cpu_online())
|
|
|
+ return 0;
|
|
|
if (debug_locks)
|
|
|
lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
|
|
|
return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
|