alarmtimers: Add alarm_forward functionality
authorJohn Stultz <john.stultz@linaro.org>
Wed, 10 Aug 2011 18:31:03 +0000 (11:31 -0700)
committerJohn Stultz <john.stultz@linaro.org>
Wed, 10 Aug 2011 21:55:23 +0000 (14:55 -0700)
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>
include/linux/alarmtimer.h
kernel/time/alarmtimer.c

index 0289eb29e7941aca2a8e3240e5207c01c62512c1..17535963b2744c14b9907308980b7761b345b9c6 100644 (file)
@@ -42,4 +42,6 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
 void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
 void alarm_cancel(struct alarm *alarm);
 
+u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
+
 #endif
index 55e634ea6054e2d8c8a9550c7a699b15a076d806..f03b04291b6fde23a7c529093eea08d5e3a2d44d 100644 (file)
@@ -347,6 +347,41 @@ void alarm_cancel(struct alarm *alarm)
 }
 
 
+
+u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
+{
+       u64 overrun = 1;
+       ktime_t delta;
+
+       delta = ktime_sub(now, alarm->node.expires);
+
+       if (delta.tv64 < 0)
+               return 0;
+
+       if (unlikely(delta.tv64 >= interval.tv64)) {
+               s64 incr = ktime_to_ns(interval);
+
+               overrun = ktime_divns(delta, incr);
+
+               alarm->node.expires = ktime_add_ns(alarm->node.expires,
+                                                       incr*overrun);
+
+               if (alarm->node.expires.tv64 > now.tv64)
+                       return overrun;
+               /*
+                * This (and the ktime_add() below) is the
+                * correction for exact:
+                */
+               overrun++;
+       }
+
+       alarm->node.expires = ktime_add(alarm->node.expires, interval);
+       return overrun;
+}
+
+
+
+
 /**
  * clock2alarm - helper that converts from clockid to alarmtypes
  * @clockid: clockid.
@@ -376,7 +411,7 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
 
        /* Re-add periodic timers */
        if (alarm->period.tv64) {
-               alarm->node.expires = ktime_add(now, alarm->period);
+               ptr->it_overrun += alarm_forward(alarm, now, alarm->period);
                return ALARMTIMER_RESTART;
        }
        return ALARMTIMER_NORESTART;