On 2017-11-29 16:30:53 [+0100], Anna-Maria Gleixner wrote: > diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c > index 65211fd7288d..40b14f025829 100644 > --- a/kernel/time/hrtimer.c > +++ b/kernel/time/hrtimer.c > @@ -711,6 +768,28 @@ static void hrtimer_reprogram(struct hrtimer *timer) > WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0); > > /* > + * CLOCK_REALTIME timer might be requested with an absolute > + * expiry time which is less than base->offset. Set it to 0. > + */ > + if (expires < 0) > + expires = 0; > + > + if (timer->is_soft) { > + if (cpu_base->softirq_activated) > + return; > + > + if (!ktime_before(expires, cpu_base->softirq_expires_next)) > + return; > + > + cpu_base->softirq_next_timer = timer; > + cpu_base->softirq_expires_next = expires; > + > + if (!ktime_before(expires, cpu_base->expires_next) || > + !reprogram) > + return; > + } > + > + /* > * If the timer is not on the current cpu, we cannot reprogram > * the other cpus clock event device. > */
if the timer is enqueud on CPUX and we run on CPUY then we have to update the cpu_base bits of the correct CPU. Not sure if this accounts for all the pieces but it might be okay with the check we have in hrtimer_check_target() (that we have nothing to do but just wait). Without this, all "sleep 1" which are invoked on CPU1 but migrated to/ programmed on CPU0 (due to timer migration wth NOHZ_FULL) won't expire as expected. Reported-by: bert schulze <spambemygu...@googlemail.com> Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de> --- kernel/time/hrtimer.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index af16a5af2269..c2c344fda487 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -801,16 +801,18 @@ static void hrtimer_reprogram(struct hrtimer *timer, bool reprogram) expires = 0; if (timer->is_soft) { - if (cpu_base->softirq_activated) + struct hrtimer_cpu_base *timer_cpu_base = base->cpu_base; + + if (timer_cpu_base->softirq_activated) return; - if (!ktime_before(expires, cpu_base->softirq_expires_next)) + if (!ktime_before(expires, timer_cpu_base->softirq_expires_next)) return; - cpu_base->softirq_next_timer = timer; - cpu_base->softirq_expires_next = expires; + timer_cpu_base->softirq_next_timer = timer; + timer_cpu_base->softirq_expires_next = expires; - if (!ktime_before(expires, cpu_base->expires_next) || + if (!ktime_before(expires, timer_cpu_base->expires_next) || !reprogram) return; } -- 2.15.1