X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=kernel%2Ftimer.c;h=dd6c2c1c561bf1ecc1e3bf162b33e8028de0c194;hb=1d00e832f0d65039abdebf83054b323a9aa05687;hp=cb1b86a9c52f5749f767625ffe6f6895f4b476aa;hpb=8800c0ebf5e8363dab66647512dcef5b83203dec;p=firefly-linux-kernel-4.4.55.git diff --git a/kernel/timer.c b/kernel/timer.c index cb1b86a9c52f..dd6c2c1c561b 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -695,15 +695,28 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, { ktime_t hr_delta = hrtimer_get_next_event(); struct timespec tsdelta; + unsigned long delta; if (hr_delta.tv64 == KTIME_MAX) return expires; - if (hr_delta.tv64 <= TICK_NSEC) - return now; + /* + * Expired timer available, let it expire in the next tick + */ + if (hr_delta.tv64 <= 0) + return now + 1; tsdelta = ktime_to_timespec(hr_delta); - now += timespec_to_jiffies(&tsdelta); + delta = timespec_to_jiffies(&tsdelta); + /* + * Take rounding errors in to account and make sure, that it + * expires in the next tick. Otherwise we go into an endless + * ping pong due to tick_nohz_stop_sched_tick() retriggering + * the timer softirq + */ + if (delta < 1) + delta = 1; + now += delta; if (time_before(now, expires)) return now; return expires; @@ -711,6 +724,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, /** * next_timer_interrupt - return the jiffy of the next pending timer + * @now: current time (in jiffies) */ unsigned long get_next_timer_interrupt(unsigned long now) { @@ -861,6 +875,8 @@ int do_settimeofday(struct timespec *tv) clock->error = 0; ntp_clear(); + update_vsyscall(&xtime, clock); + write_sequnlock_irqrestore(&xtime_lock, flags); /* signal hrtimers about time change */ @@ -908,7 +924,7 @@ static inline void change_clocksource(void) { } #endif /** - * timeofday_is_continuous - check to see if timekeeping is free running + * timekeeping_is_continuous - check to see if timekeeping is free running */ int timekeeping_is_continuous(void) { @@ -996,8 +1012,11 @@ static int timekeeping_resume(struct sys_device *dev) write_sequnlock_irqrestore(&xtime_lock, flags); touch_softlockup_watchdog(); + + clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL); + /* Resume hrtimers */ - clock_was_set(); + hres_timers_resume(); return 0; } @@ -1010,6 +1029,9 @@ static int timekeeping_suspend(struct sys_device *dev, pm_message_t state) timekeeping_suspended = 1; timekeeping_suspend_time = read_persistent_clock(); write_sequnlock_irqrestore(&xtime_lock, flags); + + clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); + return 0; } @@ -1650,8 +1672,8 @@ static void __devinit migrate_timers(int cpu) new_base = get_cpu_var(tvec_bases); local_irq_disable(); - spin_lock(&new_base->lock); - spin_lock(&old_base->lock); + double_spin_lock(&new_base->lock, &old_base->lock, + smp_processor_id() < cpu); BUG_ON(old_base->running_timer); @@ -1664,8 +1686,8 @@ static void __devinit migrate_timers(int cpu) migrate_timer_list(new_base, old_base->tv5.vec + i); } - spin_unlock(&old_base->lock); - spin_unlock(&new_base->lock); + double_spin_unlock(&new_base->lock, &old_base->lock, + smp_processor_id() < cpu); local_irq_enable(); put_cpu_var(tvec_bases); }