aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/posix-timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r--kernel/posix-timers.c35
1 files changed, 33 insertions, 2 deletions
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)
353 * it should be restarted. 353 * it should be restarted.
354 */ 354 */
355 if (timr->it.real.interval.tv64 != 0) { 355 if (timr->it.real.interval.tv64 != 0) {
356 ktime_t now = hrtimer_cb_get_time(timer);
357
358 /*
359 * FIXME: What we really want, is to stop this
360 * timer completely and restart it in case the
361 * SIG_IGN is removed. This is a non trivial
362 * change which involves sighand locking
363 * (sigh !), which we don't want to do late in
364 * the release cycle.
365 *
366 * For now we just let timers with an interval
367 * less than a jiffie expire every jiffie to
368 * avoid softirq starvation in case of SIG_IGN
369 * and a very small interval, which would put
370 * the timer right back on the softirq pending
371 * list. By moving now ahead of time we trick
372 * hrtimer_forward() to expire the timer
373 * later, while we still maintain the overrun
374 * accuracy, but have some inconsistency in
375 * the timer_gettime() case. This is at least
376 * better than a starved softirq. A more
377 * complex fix which solves also another related
378 * inconsistency is already in the pipeline.
379 */
380#ifdef CONFIG_HIGH_RES_TIMERS
381 {
382 ktime_t kj = ktime_set(0, NSEC_PER_SEC / HZ);
383
384 if (timr->it.real.interval.tv64 < kj.tv64)
385 now = ktime_add(now, kj);
386 }
387#endif
356 timr->it_overrun += 388 timr->it_overrun +=
357 hrtimer_forward(timer, 389 hrtimer_forward(timer, now,
358 hrtimer_cb_get_time(timer),
359 timr->it.real.interval); 390 timr->it.real.interval);
360 ret = HRTIMER_RESTART; 391 ret = HRTIMER_RESTART;
361 ++timr->it_requeue_pending; 392 ++timr->it_requeue_pending;