|
@@ -221,6 +221,18 @@ void tick_nohz_stop_sched_tick(void)
|
|
|
ts->tick_stopped = 1;
|
|
|
ts->idle_jiffies = last_jiffies;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If this cpu is the one which updates jiffies, then
|
|
|
+ * give up the assignment and let it be taken by the
|
|
|
+ * cpu which runs the tick timer next, which might be
|
|
|
+ * this cpu as well. If we don't drop this here the
|
|
|
+ * jiffies might be stale and do_timer() never
|
|
|
+ * invoked.
|
|
|
+ */
|
|
|
+ if (cpu == tick_do_timer_cpu)
|
|
|
+ tick_do_timer_cpu = -1;
|
|
|
+
|
|
|
/*
|
|
|
* calculate the expiry time for the next timer wheel
|
|
|
* timer
|
|
@@ -338,12 +350,24 @@ static void tick_nohz_handler(struct clock_event_device *dev)
|
|
|
{
|
|
|
struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
|
|
|
struct pt_regs *regs = get_irq_regs();
|
|
|
+ int cpu = smp_processor_id();
|
|
|
ktime_t now = ktime_get();
|
|
|
|
|
|
dev->next_event.tv64 = KTIME_MAX;
|
|
|
|
|
|
+ /*
|
|
|
+ * Check if the do_timer duty was dropped. We don't care about
|
|
|
+ * concurrency: This happens only when the cpu in charge went
|
|
|
+ * into a long sleep. If two cpus happen to assign themself to
|
|
|
+ * this duty, then the jiffies update is still serialized by
|
|
|
+ * xtime_lock.
|
|
|
+ */
|
|
|
+ if (unlikely(tick_do_timer_cpu == -1))
|
|
|
+ tick_do_timer_cpu = cpu;
|
|
|
+
|
|
|
/* Check, if the jiffies need an update */
|
|
|
- tick_do_update_jiffies64(now);
|
|
|
+ if (tick_do_timer_cpu == cpu)
|
|
|
+ tick_do_update_jiffies64(now);
|
|
|
|
|
|
/*
|
|
|
* When we are idle and the tick is stopped, we have to touch
|
|
@@ -431,9 +455,23 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
|
|
|
struct hrtimer_cpu_base *base = timer->base->cpu_base;
|
|
|
struct pt_regs *regs = get_irq_regs();
|
|
|
ktime_t now = ktime_get();
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+
|
|
|
+#ifdef CONFIG_NO_HZ
|
|
|
+ /*
|
|
|
+ * Check if the do_timer duty was dropped. We don't care about
|
|
|
+ * concurrency: This happens only when the cpu in charge went
|
|
|
+ * into a long sleep. If two cpus happen to assign themself to
|
|
|
+ * this duty, then the jiffies update is still serialized by
|
|
|
+ * xtime_lock.
|
|
|
+ */
|
|
|
+ if (unlikely(tick_do_timer_cpu == -1))
|
|
|
+ tick_do_timer_cpu = cpu;
|
|
|
+#endif
|
|
|
|
|
|
/* Check, if the jiffies need an update */
|
|
|
- tick_do_update_jiffies64(now);
|
|
|
+ if (tick_do_timer_cpu == cpu)
|
|
|
+ tick_do_update_jiffies64(now);
|
|
|
|
|
|
/*
|
|
|
* Do not call, when we are not in irq context and have
|