aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/tick-sched.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 81409bba242..911834b33b8 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -402,7 +402,6 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts, ktime_t now)
402 402
403 ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); 403 ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
404 ts->tick_stopped = 1; 404 ts->tick_stopped = 1;
405 ts->idle_jiffies = last_jiffies;
406 } 405 }
407 406
408 ts->idle_sleeps++; 407 ts->idle_sleeps++;
@@ -445,9 +444,13 @@ out:
445static void __tick_nohz_idle_enter(struct tick_sched *ts) 444static void __tick_nohz_idle_enter(struct tick_sched *ts)
446{ 445{
447 ktime_t now; 446 ktime_t now;
447 int was_stopped = ts->tick_stopped;
448 448
449 now = tick_nohz_start_idle(smp_processor_id(), ts); 449 now = tick_nohz_start_idle(smp_processor_id(), ts);
450 tick_nohz_stop_sched_tick(ts, now); 450 tick_nohz_stop_sched_tick(ts, now);
451
452 if (!was_stopped && ts->tick_stopped)
453 ts->idle_jiffies = ts->last_jiffies;
451} 454}
452 455
453/** 456/**
@@ -548,15 +551,25 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
548 551
549static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) 552static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
550{ 553{
551#ifndef CONFIG_VIRT_CPU_ACCOUNTING
552 unsigned long ticks;
553#endif
554 /* Update jiffies first */ 554 /* Update jiffies first */
555 select_nohz_load_balancer(0); 555 select_nohz_load_balancer(0);
556 tick_do_update_jiffies64(now); 556 tick_do_update_jiffies64(now);
557 update_cpu_load_nohz(); 557 update_cpu_load_nohz();
558 558
559 touch_softlockup_watchdog();
560 /*
561 * Cancel the scheduled timer and restore the tick
562 */
563 ts->tick_stopped = 0;
564 ts->idle_exittime = now;
565
566 tick_nohz_restart(ts, now);
567}
568
569static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
570{
559#ifndef CONFIG_VIRT_CPU_ACCOUNTING 571#ifndef CONFIG_VIRT_CPU_ACCOUNTING
572 unsigned long ticks;
560 /* 573 /*
561 * We stopped the tick in idle. Update process times would miss the 574 * We stopped the tick in idle. Update process times would miss the
562 * time we slept as update_process_times does only a 1 tick 575 * time we slept as update_process_times does only a 1 tick
@@ -569,15 +582,6 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
569 if (ticks && ticks < LONG_MAX) 582 if (ticks && ticks < LONG_MAX)
570 account_idle_ticks(ticks); 583 account_idle_ticks(ticks);
571#endif 584#endif
572
573 touch_softlockup_watchdog();
574 /*
575 * Cancel the scheduled timer and restore the tick
576 */
577 ts->tick_stopped = 0;
578 ts->idle_exittime = now;
579
580 tick_nohz_restart(ts, now);
581} 585}
582 586
583/** 587/**
@@ -605,8 +609,10 @@ void tick_nohz_idle_exit(void)
605 if (ts->idle_active) 609 if (ts->idle_active)
606 tick_nohz_stop_idle(cpu, now); 610 tick_nohz_stop_idle(cpu, now);
607 611
608 if (ts->tick_stopped) 612 if (ts->tick_stopped) {
609 tick_nohz_restart_sched_tick(ts, now); 613 tick_nohz_restart_sched_tick(ts, now);
614 tick_nohz_account_idle_ticks(ts);
615 }
610 616
611 local_irq_enable(); 617 local_irq_enable();
612} 618}
@@ -811,7 +817,8 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
811 */ 817 */
812 if (ts->tick_stopped) { 818 if (ts->tick_stopped) {
813 touch_softlockup_watchdog(); 819 touch_softlockup_watchdog();
814 ts->idle_jiffies++; 820 if (idle_cpu(cpu))
821 ts->idle_jiffies++;
815 } 822 }
816 update_process_times(user_mode(regs)); 823 update_process_times(user_mode(regs));
817 profile_tick(CPU_PROFILING); 824 profile_tick(CPU_PROFILING);