Skip to content

Commit dce75a8

Browse files
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>
1 parent 54da23b commit dce75a8

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

include/linux/alarmtimer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
4242
void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
4343
void alarm_cancel(struct alarm *alarm);
4444

45+
u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
46+
4547
#endif

kernel/time/alarmtimer.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,41 @@ void alarm_cancel(struct alarm *alarm)
347347
}
348348

349349

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+
350385
/**
351386
* clock2alarm - helper that converts from clockid to alarmtypes
352387
* @clockid: clockid.
@@ -376,7 +411,7 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
376411

377412
/* Re-add periodic timers */
378413
if (alarm->period.tv64) {
379-
alarm->node.expires = ktime_add(now, alarm->period);
414+
ptr->it_overrun += alarm_forward(alarm, now, alarm->period);
380415
return ALARMTIMER_RESTART;
381416
}
382417
return ALARMTIMER_NORESTART;

0 commit comments

Comments
 (0)