|
@@ -208,6 +208,7 @@ void tick_nohz_stop_sched_tick(int inidle)
|
|
|
struct tick_sched *ts;
|
|
|
ktime_t last_update, expires, now;
|
|
|
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
|
|
|
+ u64 time_delta;
|
|
|
int cpu;
|
|
|
|
|
|
local_irq_save(flags);
|
|
@@ -262,6 +263,17 @@ void tick_nohz_stop_sched_tick(int inidle)
|
|
|
seq = read_seqbegin(&xtime_lock);
|
|
|
last_update = last_jiffies_update;
|
|
|
last_jiffies = jiffies;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * On SMP we really should only care for the CPU which
|
|
|
+ * has the do_timer duty assigned. All other CPUs can
|
|
|
+ * sleep as long as they want.
|
|
|
+ */
|
|
|
+ if (cpu == tick_do_timer_cpu ||
|
|
|
+ tick_do_timer_cpu == TICK_DO_TIMER_NONE)
|
|
|
+ time_delta = timekeeping_max_deferment();
|
|
|
+ else
|
|
|
+ time_delta = KTIME_MAX;
|
|
|
} while (read_seqretry(&xtime_lock, seq));
|
|
|
|
|
|
if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
|
|
@@ -284,11 +296,26 @@ void tick_nohz_stop_sched_tick(int inidle)
|
|
|
if ((long)delta_jiffies >= 1) {
|
|
|
|
|
|
/*
|
|
|
- * calculate the expiry time for the next timer wheel
|
|
|
- * timer
|
|
|
- */
|
|
|
- expires = ktime_add_ns(last_update, tick_period.tv64 *
|
|
|
- delta_jiffies);
|
|
|
+ * calculate the expiry time for the next timer wheel
|
|
|
+ * timer. delta_jiffies >= NEXT_TIMER_MAX_DELTA signals
|
|
|
+ * that there is no timer pending or at least extremely
|
|
|
+ * far into the future (12 days for HZ=1000). In this
|
|
|
+ * case we set the expiry to the end of time.
|
|
|
+ */
|
|
|
+ if (likely(delta_jiffies < NEXT_TIMER_MAX_DELTA)) {
|
|
|
+ /*
|
|
|
+ * Calculate the time delta for the next timer event.
|
|
|
+ * If the time delta exceeds the maximum time delta
|
|
|
+ * permitted by the current clocksource then adjust
|
|
|
+ * the time delta accordingly to ensure the
|
|
|
+ * clocksource does not wrap.
|
|
|
+ */
|
|
|
+ time_delta = min_t(u64, time_delta,
|
|
|
+ tick_period.tv64 * delta_jiffies);
|
|
|
+ expires = ktime_add_ns(last_update, time_delta);
|
|
|
+ } else {
|
|
|
+ expires.tv64 = KTIME_MAX;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* If this cpu is the one which updates jiffies, then
|
|
@@ -332,22 +359,19 @@ void tick_nohz_stop_sched_tick(int inidle)
|
|
|
|
|
|
ts->idle_sleeps++;
|
|
|
|
|
|
+ /* Mark expires */
|
|
|
+ ts->idle_expires = expires;
|
|
|
+
|
|
|
/*
|
|
|
- * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that
|
|
|
- * there is no timer pending or at least extremly far
|
|
|
- * into the future (12 days for HZ=1000). In this case
|
|
|
- * we simply stop the tick timer:
|
|
|
+ * If the expiration time == KTIME_MAX, then
|
|
|
+ * in this case we simply stop the tick timer.
|
|
|
*/
|
|
|
- if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) {
|
|
|
- ts->idle_expires.tv64 = KTIME_MAX;
|
|
|
+ if (unlikely(expires.tv64 == KTIME_MAX)) {
|
|
|
if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
|
|
|
hrtimer_cancel(&ts->sched_timer);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* Mark expiries */
|
|
|
- ts->idle_expires = expires;
|
|
|
-
|
|
|
if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
|
|
|
hrtimer_start(&ts->sched_timer, expires,
|
|
|
HRTIMER_MODE_ABS_PINNED);
|