alarmtimers: Change alarmtimer functions to return alarmtimer_restart values
authorJohn Stultz <john.stultz@linaro.org>
Wed, 10 Aug 2011 17:37:59 +0000 (10:37 -0700)
committerJohn Stultz <john.stultz@linaro.org>
Wed, 10 Aug 2011 21:55:20 +0000 (14:55 -0700)
In order to properly fix the denial of service issue with high freq
periodic alarm timers, we need to push the re-arming logic into the
alarm timer handler, much as the hrtimer code does.

This patch introduces alarmtimer_restart enum and changes the
alarmtimer handler declarations to use it as a return value. Further,
to ease following changes, it extends the alarmtimer handler functions
to also take the time at expiration. No logic is yet modified.

CC: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
include/linux/alarmtimer.h
kernel/time/alarmtimer.c

index c5d6095..0289eb2 100644 (file)
@@ -13,6 +13,11 @@ enum alarmtimer_type {
        ALARM_NUMTYPE,
 };
 
+enum alarmtimer_restart {
+       ALARMTIMER_NORESTART,
+       ALARMTIMER_RESTART,
+};
+
 /**
  * struct alarm - Alarm timer structure
  * @node:      timerqueue node for adding to the event list this value
@@ -26,14 +31,14 @@ enum alarmtimer_type {
 struct alarm {
        struct timerqueue_node  node;
        ktime_t                 period;
-       void                    (*function)(struct alarm *);
+       enum alarmtimer_restart (*function)(struct alarm *, ktime_t now);
        enum alarmtimer_type    type;
        bool                    enabled;
        void                    *data;
 };
 
 void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
-               void (*function)(struct alarm *));
+               enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
 void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
 void alarm_cancel(struct alarm *alarm);
 
index ea5e1a9..9e78605 100644 (file)
@@ -196,7 +196,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
                }
                spin_unlock_irqrestore(&base->lock, flags);
                if (alarm->function)
-                       alarm->function(alarm);
+                       alarm->function(alarm, now);
                spin_lock_irqsave(&base->lock, flags);
        }
 
@@ -299,7 +299,7 @@ static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
  * @function: callback that is run when the alarm fires
  */
 void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
-               void (*function)(struct alarm *))
+               enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
 {
        timerqueue_init(&alarm->node);
        alarm->period = ktime_set(0, 0);
@@ -365,12 +365,15 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)
  *
  * Posix timer callback for expired alarm timers.
  */
-static void alarm_handle_timer(struct alarm *alarm)
+static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
+                                                       ktime_t now)
 {
        struct k_itimer *ptr = container_of(alarm, struct k_itimer,
                                                it.alarmtimer);
        if (posix_timer_event(ptr, 0) != 0)
                ptr->it_overrun++;
+
+       return ALARMTIMER_NORESTART;
 }
 
 /**
@@ -509,13 +512,15 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
  *
  * Wakes up the task that set the alarmtimer
  */
-static void alarmtimer_nsleep_wakeup(struct alarm *alarm)
+static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
+                                                               ktime_t now)
 {
        struct task_struct *task = (struct task_struct *)alarm->data;
 
        alarm->data = NULL;
        if (task)
                wake_up_process(task);
+       return ALARMTIMER_NORESTART;
 }
 
 /**