aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rcupdate.h
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2011-10-07 19:25:18 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-12-11 13:31:30 -0500
commite6b80a3b0994ea6c3d876d72464f2debbfcfeb05 (patch)
tree207337c207fecf2e05e52ffb3003831d240529fd /include/linux/rcupdate.h
parenta0f8eefb127f5be07628954f310a7fc8c82b2fc3 (diff)
rcu: Detect illegal rcu dereference in extended quiescent state
Report that none of the rcu read lock maps are held while in an RCU extended quiescent state (the section between rcu_idle_enter() and rcu_idle_exit()). This helps detect any use of rcu_dereference() and friends from within the section in idle where RCU is not allowed. This way we can guarantee an extended quiescent window where the CPU can be put in dyntick idle mode or can simply aoid to be part of any global grace period completion while in the idle loop. Uses of RCU from such mode are totally ignored by RCU, hence the importance of these checks. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'include/linux/rcupdate.h')
-rw-r--r--include/linux/rcupdate.h26
1 files changed, 26 insertions, 0 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 8d315b013e37..bf91fcfe181c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -228,6 +228,15 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
228 228
229#ifdef CONFIG_DEBUG_LOCK_ALLOC 229#ifdef CONFIG_DEBUG_LOCK_ALLOC
230 230
231#ifdef CONFIG_PROVE_RCU
232extern int rcu_is_cpu_idle(void);
233#else /* !CONFIG_PROVE_RCU */
234static inline int rcu_is_cpu_idle(void)
235{
236 return 0;
237}
238#endif /* else !CONFIG_PROVE_RCU */
239
231extern struct lockdep_map rcu_lock_map; 240extern struct lockdep_map rcu_lock_map;
232# define rcu_read_acquire() \ 241# define rcu_read_acquire() \
233 lock_acquire(&rcu_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_) 242 lock_acquire(&rcu_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_)
@@ -262,6 +271,8 @@ static inline int rcu_read_lock_held(void)
262{ 271{
263 if (!debug_lockdep_rcu_enabled()) 272 if (!debug_lockdep_rcu_enabled())
264 return 1; 273 return 1;
274 if (rcu_is_cpu_idle())
275 return 0;
265 return lock_is_held(&rcu_lock_map); 276 return lock_is_held(&rcu_lock_map);
266} 277}
267 278
@@ -285,6 +296,19 @@ extern int rcu_read_lock_bh_held(void);
285 * 296 *
286 * Check debug_lockdep_rcu_enabled() to prevent false positives during boot 297 * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
287 * and while lockdep is disabled. 298 * and while lockdep is disabled.
299 *
300 * Note that if the CPU is in the idle loop from an RCU point of
301 * view (ie: that we are in the section between rcu_idle_enter() and
302 * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU
303 * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs
304 * that are in such a section, considering these as in extended quiescent
305 * state, so such a CPU is effectively never in an RCU read-side critical
306 * section regardless of what RCU primitives it invokes. This state of
307 * affairs is required --- we need to keep an RCU-free window in idle
308 * where the CPU may possibly enter into low power mode. This way we can
309 * notice an extended quiescent state to other CPUs that started a grace
310 * period. Otherwise we would delay any grace period as long as we run in
311 * the idle task.
288 */ 312 */
289#ifdef CONFIG_PREEMPT_COUNT 313#ifdef CONFIG_PREEMPT_COUNT
290static inline int rcu_read_lock_sched_held(void) 314static inline int rcu_read_lock_sched_held(void)
@@ -293,6 +317,8 @@ static inline int rcu_read_lock_sched_held(void)
293 317
294 if (!debug_lockdep_rcu_enabled()) 318 if (!debug_lockdep_rcu_enabled())
295 return 1; 319 return 1;
320 if (rcu_is_cpu_idle())
321 return 0;
296 if (debug_locks) 322 if (debug_locks)
297 lockdep_opinion = lock_is_held(&rcu_sched_lock_map); 323 lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
298 return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); 324 return lockdep_opinion || preempt_count() != 0 || irqs_disabled();