X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=kernel%2Fposix-timers.c;h=329ce0172074a8270b662e3850118d08d42c0dc0;hb=849a4c375a8e06cd000399dceb25888d356d021f;hp=588c99da030792babb3c643b89e645c8abebdb2b;hpb=6ec129c3a2f8b38bc37e42348470ccfcb7460146;p=karo-tx-linux.git diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 588c99da0307..329ce0172074 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -353,9 +353,40 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer) * it should be restarted. */ if (timr->it.real.interval.tv64 != 0) { + ktime_t now = hrtimer_cb_get_time(timer); + + /* + * FIXME: What we really want, is to stop this + * timer completely and restart it in case the + * SIG_IGN is removed. This is a non trivial + * change which involves sighand locking + * (sigh !), which we don't want to do late in + * the release cycle. + * + * For now we just let timers with an interval + * less than a jiffie expire every jiffie to + * avoid softirq starvation in case of SIG_IGN + * and a very small interval, which would put + * the timer right back on the softirq pending + * list. By moving now ahead of time we trick + * hrtimer_forward() to expire the timer + * later, while we still maintain the overrun + * accuracy, but have some inconsistency in + * the timer_gettime() case. This is at least + * better than a starved softirq. A more + * complex fix which solves also another related + * inconsistency is already in the pipeline. + */ +#ifdef CONFIG_HIGH_RES_TIMERS + { + ktime_t kj = ktime_set(0, NSEC_PER_SEC / HZ); + + if (timr->it.real.interval.tv64 < kj.tv64) + now = ktime_add(now, kj); + } +#endif timr->it_overrun += - hrtimer_forward(timer, - hrtimer_cb_get_time(timer), + hrtimer_forward(timer, now, timr->it.real.interval); ret = HRTIMER_RESTART; ++timr->it_requeue_pending;