diff options
author | John Stultz <john.stultz@linaro.org> | 2011-08-10 14:31:03 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-08-10 17:55:23 -0400 |
commit | dce75a8c71819ed4c7efdcd53c9b6f6356dc8cb5 (patch) | |
tree | 76d25888bb83814fc1f9d5f8838483730ca59882 /kernel/time/alarmtimer.c | |
parent | 54da23b720d5d612f8f1669f9ed3744008fb7382 (diff) |
alarmtimers: Add alarm_forward functionality
In order to avoid wasting time expiring and re-adding very high freq
periodic alarmtimers, introduce alarm_forward() which is similar to
hrtimer_forward and moves the timer to the next future expiration time
and returns the number of overruns.
CC: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel/time/alarmtimer.c')
-rw-r--r-- | kernel/time/alarmtimer.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 55e634ea6054..f03b04291b6f 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -347,6 +347,41 @@ void alarm_cancel(struct alarm *alarm) | |||
347 | } | 347 | } |
348 | 348 | ||
349 | 349 | ||
350 | |||
351 | u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) | ||
352 | { | ||
353 | u64 overrun = 1; | ||
354 | ktime_t delta; | ||
355 | |||
356 | delta = ktime_sub(now, alarm->node.expires); | ||
357 | |||
358 | if (delta.tv64 < 0) | ||
359 | return 0; | ||
360 | |||
361 | if (unlikely(delta.tv64 >= interval.tv64)) { | ||
362 | s64 incr = ktime_to_ns(interval); | ||
363 | |||
364 | overrun = ktime_divns(delta, incr); | ||
365 | |||
366 | alarm->node.expires = ktime_add_ns(alarm->node.expires, | ||
367 | incr*overrun); | ||
368 | |||
369 | if (alarm->node.expires.tv64 > now.tv64) | ||
370 | return overrun; | ||
371 | /* | ||
372 | * This (and the ktime_add() below) is the | ||
373 | * correction for exact: | ||
374 | */ | ||
375 | overrun++; | ||
376 | } | ||
377 | |||
378 | alarm->node.expires = ktime_add(alarm->node.expires, interval); | ||
379 | return overrun; | ||
380 | } | ||
381 | |||
382 | |||
383 | |||
384 | |||
350 | /** | 385 | /** |
351 | * clock2alarm - helper that converts from clockid to alarmtypes | 386 | * clock2alarm - helper that converts from clockid to alarmtypes |
352 | * @clockid: clockid. | 387 | * @clockid: clockid. |
@@ -376,7 +411,7 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, | |||
376 | 411 | ||
377 | /* Re-add periodic timers */ | 412 | /* Re-add periodic timers */ |
378 | if (alarm->period.tv64) { | 413 | if (alarm->period.tv64) { |
379 | alarm->node.expires = ktime_add(now, alarm->period); | 414 | ptr->it_overrun += alarm_forward(alarm, now, alarm->period); |
380 | return ALARMTIMER_RESTART; | 415 | return ALARMTIMER_RESTART; |
381 | } | 416 | } |
382 | return ALARMTIMER_NORESTART; | 417 | return ALARMTIMER_NORESTART; |