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

Reply via email to