diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2011-02-08 12:39:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-02-16 07:35:08 -0500 |
commit | 48228f7b470a74b6469a250d2977a13128d8fe96 (patch) | |
tree | 1ed8f82ffef779ccf665f68c1fcf302d34d09826 /kernel/timer.c | |
parent | a3ec4a603faf4244e275bf11b467aad092dfbd8a (diff) |
lockdep/timers: Explain in detail the locking problems del_timer_sync() may cause
Twice I had to explain the output about why lockdep gives an error with
locks in IRQ context and with del_timer_sync(). Might as well write it
up and place it in the comments above the code in del_timer_sync().
Perhaps the next time this lockdep dump triggers people will understand
the issues.
It is a ticky issue and very subtle, explaining it in detail in the code
may help others understand the issue when they stumble upon the bug
again.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <1297186794.23343.19.camel@gandalf.stny.rr.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index d6459923d24..5f40c2e0a94 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -964,6 +964,25 @@ EXPORT_SYMBOL(try_to_del_timer_sync); | |||
964 | * add_timer_on(). Upon exit the timer is not queued and the handler is | 964 | * add_timer_on(). Upon exit the timer is not queued and the handler is |
965 | * not running on any CPU. | 965 | * not running on any CPU. |
966 | * | 966 | * |
967 | * Note: You must not hold locks that are held in interrupt context | ||
968 | * while calling this function. Even if the lock has nothing to do | ||
969 | * with the timer in question. Here's why: | ||
970 | * | ||
971 | * CPU0 CPU1 | ||
972 | * ---- ---- | ||
973 | * <SOFTIRQ> | ||
974 | * call_timer_fn(); | ||
975 | * base->running_timer = mytimer; | ||
976 | * spin_lock_irq(somelock); | ||
977 | * <IRQ> | ||
978 | * spin_lock(somelock); | ||
979 | * del_timer_sync(mytimer); | ||
980 | * while (base->running_timer == mytimer); | ||
981 | * | ||
982 | * Now del_timer_sync() will never return and never release somelock. | ||
983 | * The interrupt on the other CPU is waiting to grab somelock but | ||
984 | * it has interrupted the softirq that CPU0 is waiting to finish. | ||
985 | * | ||
967 | * The function returns whether it has deactivated a pending timer or not. | 986 | * The function returns whether it has deactivated a pending timer or not. |
968 | */ | 987 | */ |
969 | int del_timer_sync(struct timer_list *timer) | 988 | int del_timer_sync(struct timer_list *timer) |
@@ -971,6 +990,10 @@ int del_timer_sync(struct timer_list *timer) | |||
971 | #ifdef CONFIG_LOCKDEP | 990 | #ifdef CONFIG_LOCKDEP |
972 | unsigned long flags; | 991 | unsigned long flags; |
973 | 992 | ||
993 | /* | ||
994 | * If lockdep gives a backtrace here, please reference | ||
995 | * the synchronization rules above. | ||
996 | */ | ||
974 | local_irq_save(flags); | 997 | local_irq_save(flags); |
975 | lock_map_acquire(&timer->lockdep_map); | 998 | lock_map_acquire(&timer->lockdep_map); |
976 | lock_map_release(&timer->lockdep_map); | 999 | lock_map_release(&timer->lockdep_map); |