diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/timer.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 797cccb86431..440048acaea1 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -695,15 +695,28 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, | |||
695 | { | 695 | { |
696 | ktime_t hr_delta = hrtimer_get_next_event(); | 696 | ktime_t hr_delta = hrtimer_get_next_event(); |
697 | struct timespec tsdelta; | 697 | struct timespec tsdelta; |
698 | unsigned long delta; | ||
698 | 699 | ||
699 | if (hr_delta.tv64 == KTIME_MAX) | 700 | if (hr_delta.tv64 == KTIME_MAX) |
700 | return expires; | 701 | return expires; |
701 | 702 | ||
702 | if (hr_delta.tv64 <= TICK_NSEC) | 703 | /* |
703 | return now; | 704 | * Expired timer available, let it expire in the next tick |
705 | */ | ||
706 | if (hr_delta.tv64 <= 0) | ||
707 | return now + 1; | ||
704 | 708 | ||
705 | tsdelta = ktime_to_timespec(hr_delta); | 709 | tsdelta = ktime_to_timespec(hr_delta); |
706 | now += timespec_to_jiffies(&tsdelta); | 710 | delta = timespec_to_jiffies(&tsdelta); |
711 | /* | ||
712 | * Take rounding errors in to account and make sure, that it | ||
713 | * expires in the next tick. Otherwise we go into an endless | ||
714 | * ping pong due to tick_nohz_stop_sched_tick() retriggering | ||
715 | * the timer softirq | ||
716 | */ | ||
717 | if (delta < 1) | ||
718 | delta = 1; | ||
719 | now += delta; | ||
707 | if (time_before(now, expires)) | 720 | if (time_before(now, expires)) |
708 | return now; | 721 | return now; |
709 | return expires; | 722 | return expires; |