aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rcupdate.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-01-23 15:41:26 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-02-21 12:06:03 -0500
commitc0d6d01bffdce19fa19baad6cb8cc3eed7bfd6f5 (patch)
treeea4c20ddc87b94d7bef2402fe6dbe3186be263c2 /include/linux/rcupdate.h
parent24cd7fd0eaa0d9f5e197ff77a83b006a86696068 (diff)
rcu: Check for illegal use of RCU from offlined CPUs
Although it is legal to use RCU during early boot, it is anything but legal to use RCU at runtime from an offlined CPU. After all, RCU explicitly ignores offlined CPUs. This commit therefore adds checks for runtime use of RCU from offlined CPUs. These checks are not perfect, in particular, they can be subverted through use of things like rcu_dereference_raw(). Note that it is not possible to put checks in rcu_read_lock() and friends due to the fact that these primitives are used in code that might be used under either RCU or lock-based protection, which means that checking rcu_read_lock() gets you fat piles of false positives. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'include/linux/rcupdate.h')
-rw-r--r--include/linux/rcupdate.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index f409529ff35..146d37d3177 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)
230bool rcu_lockdep_current_cpu_online(void);
231#else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
232static 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 */
274static inline int rcu_read_lock_held(void) 286static 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
318static inline int rcu_read_lock_sched_held(void) 335static 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();