|
@@ -953,6 +953,41 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index)
|
|
return index;
|
|
return index;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
|
|
|
|
+ unsigned long data)
|
|
|
|
+{
|
|
|
|
+ int preempt_count = preempt_count();
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_LOCKDEP
|
|
|
|
+ /*
|
|
|
|
+ * It is permissible to free the timer from inside the
|
|
|
|
+ * function that is called from it, this we need to take into
|
|
|
|
+ * account for lockdep too. To avoid bogus "held lock freed"
|
|
|
|
+ * warnings as well as problems when looking into
|
|
|
|
+ * timer->lockdep_map, make a copy and use that here.
|
|
|
|
+ */
|
|
|
|
+ struct lockdep_map lockdep_map = timer->lockdep_map;
|
|
|
|
+#endif
|
|
|
|
+ /*
|
|
|
|
+ * Couple the lock chain with the lock chain at
|
|
|
|
+ * del_timer_sync() by acquiring the lock_map around the fn()
|
|
|
|
+ * call here and in del_timer_sync().
|
|
|
|
+ */
|
|
|
|
+ lock_map_acquire(&lockdep_map);
|
|
|
|
+
|
|
|
|
+ trace_timer_expire_entry(timer);
|
|
|
|
+ fn(data);
|
|
|
|
+ trace_timer_expire_exit(timer);
|
|
|
|
+
|
|
|
|
+ lock_map_release(&lockdep_map);
|
|
|
|
+
|
|
|
|
+ if (preempt_count != preempt_count()) {
|
|
|
|
+ printk(KERN_ERR "timer: %pF preempt leak: %08x -> %08x\n",
|
|
|
|
+ fn, preempt_count, preempt_count());
|
|
|
|
+ BUG();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
|
|
#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -996,42 +1031,7 @@ static inline void __run_timers(struct tvec_base *base)
|
|
detach_timer(timer, 1);
|
|
detach_timer(timer, 1);
|
|
|
|
|
|
spin_unlock_irq(&base->lock);
|
|
spin_unlock_irq(&base->lock);
|
|
- {
|
|
|
|
- int preempt_count = preempt_count();
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_LOCKDEP
|
|
|
|
- /*
|
|
|
|
- * It is permissible to free the timer from
|
|
|
|
- * inside the function that is called from
|
|
|
|
- * it, this we need to take into account for
|
|
|
|
- * lockdep too. To avoid bogus "held lock
|
|
|
|
- * freed" warnings as well as problems when
|
|
|
|
- * looking into timer->lockdep_map, make a
|
|
|
|
- * copy and use that here.
|
|
|
|
- */
|
|
|
|
- struct lockdep_map lockdep_map =
|
|
|
|
- timer->lockdep_map;
|
|
|
|
-#endif
|
|
|
|
- /*
|
|
|
|
- * Couple the lock chain with the lock chain at
|
|
|
|
- * del_timer_sync() by acquiring the lock_map
|
|
|
|
- * around the fn() call here and in
|
|
|
|
- * del_timer_sync().
|
|
|
|
- */
|
|
|
|
- lock_map_acquire(&lockdep_map);
|
|
|
|
-
|
|
|
|
- trace_timer_expire_entry(timer);
|
|
|
|
- fn(data);
|
|
|
|
- trace_timer_expire_exit(timer);
|
|
|
|
-
|
|
|
|
- lock_map_release(&lockdep_map);
|
|
|
|
-
|
|
|
|
- if (preempt_count != preempt_count()) {
|
|
|
|
- printk(KERN_ERR "timer: %pF preempt leak: %08x -> %08x\n",
|
|
|
|
- fn, preempt_count, preempt_count());
|
|
|
|
- BUG();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ call_timer_fn(timer, fn, data);
|
|
spin_lock_irq(&base->lock);
|
|
spin_lock_irq(&base->lock);
|
|
}
|
|
}
|
|
}
|
|
}
|