aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r--kernel/time/tick-sched.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 34f9a9c417d9..a935cbdc55a4 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -568,6 +568,11 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
568 tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); 568 tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
569} 569}
570 570
571static inline bool local_timer_softirq_pending(void)
572{
573 return local_softirq_pending() & TIMER_SOFTIRQ;
574}
575
571static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, 576static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
572 ktime_t now, int cpu) 577 ktime_t now, int cpu)
573{ 578{
@@ -584,8 +589,18 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
584 } while (read_seqretry(&jiffies_lock, seq)); 589 } while (read_seqretry(&jiffies_lock, seq));
585 ts->last_jiffies = basejiff; 590 ts->last_jiffies = basejiff;
586 591
587 if (rcu_needs_cpu(basemono, &next_rcu) || 592 /*
588 arch_needs_cpu() || irq_work_needs_cpu()) { 593 * Keep the periodic tick, when RCU, architecture or irq_work
594 * requests it.
595 * Aside of that check whether the local timer softirq is
596 * pending. If so its a bad idea to call get_next_timer_interrupt()
597 * because there is an already expired timer, so it will request
598 * immeditate expiry, which rearms the hardware timer with a
599 * minimal delta which brings us back to this place
600 * immediately. Lather, rinse and repeat...
601 */
602 if (rcu_needs_cpu(basemono, &next_rcu) || arch_needs_cpu() ||
603 irq_work_needs_cpu() || local_timer_softirq_pending()) {
589 next_tick = basemono + TICK_NSEC; 604 next_tick = basemono + TICK_NSEC;
590 } else { 605 } else {
591 /* 606 /*