diff options
Diffstat (limited to 'include/linux/rcupdate.h')
-rw-r--r-- | include/linux/rcupdate.h | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index f409529ff35a..146d37d31778 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -226,6 +226,15 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head) | |||
226 | } | 226 | } |
227 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | 227 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
228 | 228 | ||
229 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) | ||
230 | bool rcu_lockdep_current_cpu_online(void); | ||
231 | #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */ | ||
232 | static inline bool rcu_lockdep_current_cpu_online(void) | ||
233 | { | ||
234 | return 1; | ||
235 | } | ||
236 | #endif /* #else #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */ | ||
237 | |||
229 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 238 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
230 | 239 | ||
231 | #ifdef CONFIG_PROVE_RCU | 240 | #ifdef CONFIG_PROVE_RCU |
@@ -270,6 +279,9 @@ extern int debug_lockdep_rcu_enabled(void); | |||
270 | * occur in the same context, for example, it is illegal to invoke | 279 | * occur in the same context, for example, it is illegal to invoke |
271 | * rcu_read_unlock() in process context if the matching rcu_read_lock() | 280 | * rcu_read_unlock() in process context if the matching rcu_read_lock() |
272 | * was invoked from within an irq handler. | 281 | * was invoked from within an irq handler. |
282 | * | ||
283 | * Note that rcu_read_lock() is disallowed if the CPU is either idle or | ||
284 | * offline from an RCU perspective, so check for those as well. | ||
273 | */ | 285 | */ |
274 | static inline int rcu_read_lock_held(void) | 286 | static inline int rcu_read_lock_held(void) |
275 | { | 287 | { |
@@ -277,6 +289,8 @@ static inline int rcu_read_lock_held(void) | |||
277 | return 1; | 289 | return 1; |
278 | if (rcu_is_cpu_idle()) | 290 | if (rcu_is_cpu_idle()) |
279 | return 0; | 291 | return 0; |
292 | if (!rcu_lockdep_current_cpu_online()) | ||
293 | return 0; | ||
280 | return lock_is_held(&rcu_lock_map); | 294 | return lock_is_held(&rcu_lock_map); |
281 | } | 295 | } |
282 | 296 | ||
@@ -313,6 +327,9 @@ extern int rcu_read_lock_bh_held(void); | |||
313 | * notice an extended quiescent state to other CPUs that started a grace | 327 | * notice an extended quiescent state to other CPUs that started a grace |
314 | * period. Otherwise we would delay any grace period as long as we run in | 328 | * period. Otherwise we would delay any grace period as long as we run in |
315 | * the idle task. | 329 | * the idle task. |
330 | * | ||
331 | * Similarly, we avoid claiming an SRCU read lock held if the current | ||
332 | * CPU is offline. | ||
316 | */ | 333 | */ |
317 | #ifdef CONFIG_PREEMPT_COUNT | 334 | #ifdef CONFIG_PREEMPT_COUNT |
318 | static inline int rcu_read_lock_sched_held(void) | 335 | static inline int rcu_read_lock_sched_held(void) |
@@ -323,6 +340,8 @@ static inline int rcu_read_lock_sched_held(void) | |||
323 | return 1; | 340 | return 1; |
324 | if (rcu_is_cpu_idle()) | 341 | if (rcu_is_cpu_idle()) |
325 | return 0; | 342 | return 0; |
343 | if (!rcu_lockdep_current_cpu_online()) | ||
344 | return 0; | ||
326 | if (debug_locks) | 345 | if (debug_locks) |
327 | lockdep_opinion = lock_is_held(&rcu_sched_lock_map); | 346 | lockdep_opinion = lock_is_held(&rcu_sched_lock_map); |
328 | return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); | 347 | return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); |