base->running_timer != timer);
}
-# define wakeup_timer_waiters(b) wake_up(&(b)->wait_for_running_timer)
+# define wakeup_timer_waiters(b) wake_up_all(&(b)->wait_for_running_timer)
#else
static inline void wait_for_running_timer(struct timer_list *timer)
{
}
}
}
- wakeup_timer_waiters(base);
spin_unlock_irq(&base->lock);
+ wakeup_timer_waiters(base);
}
#ifdef CONFIG_NO_HZ_COMMON
* the base lock to check when the next timer is pending and so
* we assume the next jiffy.
*/
- return basem + TICK_NSEC;
-#endif
+ if (!spin_do_trylock(&base->lock))
+ return basem + TICK_NSEC;
+#else
spin_lock(&base->lock);
+#endif
if (base->active_timers) {
if (time_before_eq(base->next_timer, base->timer_jiffies))
base->next_timer = __next_timer_interrupt(base);
else
expires = basem + (nextevt - basej) * TICK_NSEC;
}
+#ifdef CONFIG_PREEMPT_RT_FULL
+ rt_spin_unlock(&base->lock);
+#else
spin_unlock(&base->lock);
+#endif
return cmp_next_hrtimer_event(basem, expires);
}
*/
void run_local_timers(void)
{
+ struct tvec_base *base = this_cpu_ptr(&tvec_bases);
+
hrtimer_run_queues();
- raise_softirq(TIMER_SOFTIRQ);
+ /*
+ * We can access this lockless as we are in the timer
+ * interrupt. If there are no timers queued, nothing to do in
+ * the timer softirq.
+ */
+#ifdef CONFIG_PREEMPT_RT_FULL
+ if (irq_work_needs_cpu()) {
+ raise_softirq(TIMER_SOFTIRQ);
+ return;
+ }
+ if (!spin_do_trylock(&base->lock)) {
+ raise_softirq(TIMER_SOFTIRQ);
+ return;
+ }
+#endif
+ if (!base->active_timers)
+ goto out;
+
+ /* Check whether the next pending timer has expired */
+ if (time_before_eq(base->next_timer, jiffies))
+ raise_softirq(TIMER_SOFTIRQ);
+out:
+#ifdef CONFIG_PREEMPT_RT_FULL
+ rt_spin_unlock(&base->lock);
+#endif
+ /* The ; ensures that gcc won't complain in the !RT case */
+ ;
}
#ifdef __ARCH_WANT_SYS_ALARM