History

Merge branch 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: rtmutex: tester: Remove the remaining BKL leftovers lockdep/timers: Explain in detail the locking problems del_timer_sync() may cause rtmutex: Simplify PI algorithm and make highest prio task get lock rwsem: Remove redundant asmregparm annotation rwsem: Move duplicate function prototypes to linux/rwsem.h rwsem: Unify the duplicate rwsem_is_locked() inlines rwsem: Move duplicate init macros and functions to linux/rwsem.h rwsem: Move duplicate struct rwsem declaration to linux/rwsem.h x86: Cleanup rwsem_count_t typedef rwsem: Cleanup includes locking: Remove deprecated lock initializers cred: Replace deprecated spinlock initialization kthread: Replace deprecated spinlock initialization xtensa: Replace deprecated spinlock initialization um: Replace deprecated spinlock initialization sparc: Replace deprecated spinlock initialization mips: Replace deprecated spinlock initialization cris: Replace deprecated spinlock initialization alpha: Replace deprecated spinlock initialization rtmutex-tester: Remove BKL tests

Linus Torvalds committed 15 years ago

Commit 0586bed2 parents b80cd62 dbebbfb40 files · +228 −816Browse files

Showing the changes to kernel/timer.c (1 of 40 files). Show all

Unified · Split

kernel/timer.c+23−0
@@ -970,6 +970,25 @@ EXPORT_SYMBOL(try_to_del_timer_sync); · 969 unmodified lines
970970 * add_timer_on(). Upon exit the timer is not queued and the handler is
971971 * not running on any CPU.
972972 *
973+ * Note: You must not hold locks that are held in interrupt context
974+ * while calling this function. Even if the lock has nothing to do
975+ * with the timer in question. Here's why:
976+ *
977+ * CPU0 CPU1
978+ * ---- ----
979+ * <SOFTIRQ>
980+ * call_timer_fn();
981+ * base->running_timer = mytimer;
982+ * spin_lock_irq(somelock);
983+ * <IRQ>
984+ * spin_lock(somelock);
985+ * del_timer_sync(mytimer);
986+ * while (base->running_timer == mytimer);
987+ *
988+ * Now del_timer_sync() will never return and never release somelock.
989+ * The interrupt on the other CPU is waiting to grab somelock but
990+ * it has interrupted the softirq that CPU0 is waiting to finish.
991+ *
973992 * The function returns whether it has deactivated a pending timer or not.
974993 */
975994 int del_timer_sync(struct timer_list *timer)
@@ -977,6 +996,10 @@ int del_timer_sync(struct timer_list *timer) · 1 unmodified line
977996 #ifdef CONFIG_LOCKDEP
978997 unsigned long flags;
979998
999+ /*
1000+ * If lockdep gives a backtrace here, please reference
1001+ * the synchronization rules above.
1002+ */
9801003 local_irq_save(flags);
9811004 lock_map_acquire(&timer->lockdep_map);
9821005 lock_map_release(&timer->lockdep_map);