ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
ts->tick_stopped = 1;
- ts->idle_jiffies = last_jiffies;
}
ts->idle_sleeps++;
static void __tick_nohz_idle_enter(struct tick_sched *ts)
{
ktime_t now;
+ int was_stopped = ts->tick_stopped;
now = tick_nohz_start_idle(smp_processor_id(), ts);
tick_nohz_stop_sched_tick(ts, now);
+
+ if (!was_stopped && ts->tick_stopped)
+ ts->idle_jiffies = ts->last_jiffies;
}
/**
static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
{
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
- unsigned long ticks;
-#endif
/* Update jiffies first */
select_nohz_load_balancer(0);
tick_do_update_jiffies64(now);
update_cpu_load_nohz();
+ touch_softlockup_watchdog();
+ /*
+ * Cancel the scheduled timer and restore the tick
+ */
+ ts->tick_stopped = 0;
+ ts->idle_exittime = now;
+
+ tick_nohz_restart(ts, now);
+}
+
+static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
+{
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+ unsigned long ticks;
/*
* We stopped the tick in idle. Update process times would miss the
* time we slept as update_process_times does only a 1 tick
if (ticks && ticks < LONG_MAX)
account_idle_ticks(ticks);
#endif
-
- touch_softlockup_watchdog();
- /*
- * Cancel the scheduled timer and restore the tick
- */
- ts->tick_stopped = 0;
- ts->idle_exittime = now;
-
- tick_nohz_restart(ts, now);
}
/**
if (ts->idle_active)
tick_nohz_stop_idle(cpu, now);
- if (ts->tick_stopped)
+ if (ts->tick_stopped) {
tick_nohz_restart_sched_tick(ts, now);
+ tick_nohz_account_idle_ticks(ts);
+ }
local_irq_enable();
}
*/
if (ts->tick_stopped) {
touch_softlockup_watchdog();
- ts->idle_jiffies++;
+ if (idle_cpu(cpu))
+ ts->idle_jiffies++;
}
update_process_times(user_mode(regs));
profile_tick(CPU_PROFILING);