Commit 4b41308d authored by John Stultz's avatar John Stultz

alarmtimers: Change alarmtimer functions to return alarmtimer_restart values

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: default avatarJohn Stultz <john.stultz@linaro.org>
parent 6af7e471
...@@ -13,6 +13,11 @@ enum alarmtimer_type { ...@@ -13,6 +13,11 @@ enum alarmtimer_type {
ALARM_NUMTYPE, ALARM_NUMTYPE,
}; };
enum alarmtimer_restart {
ALARMTIMER_NORESTART,
ALARMTIMER_RESTART,
};
/** /**
* struct alarm - Alarm timer structure * struct alarm - Alarm timer structure
* @node: timerqueue node for adding to the event list this value * @node: timerqueue node for adding to the event list this value
...@@ -26,14 +31,14 @@ enum alarmtimer_type { ...@@ -26,14 +31,14 @@ enum alarmtimer_type {
struct alarm { struct alarm {
struct timerqueue_node node; struct timerqueue_node node;
ktime_t period; ktime_t period;
void (*function)(struct alarm *); enum alarmtimer_restart (*function)(struct alarm *, ktime_t now);
enum alarmtimer_type type; enum alarmtimer_type type;
bool enabled; bool enabled;
void *data; void *data;
}; };
void alarm_init(struct alarm *alarm, enum alarmtimer_type type, 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_start(struct alarm *alarm, ktime_t start, ktime_t period);
void alarm_cancel(struct alarm *alarm); void alarm_cancel(struct alarm *alarm);
......
...@@ -196,7 +196,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) ...@@ -196,7 +196,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
} }
spin_unlock_irqrestore(&base->lock, flags); spin_unlock_irqrestore(&base->lock, flags);
if (alarm->function) if (alarm->function)
alarm->function(alarm); alarm->function(alarm, now);
spin_lock_irqsave(&base->lock, flags); spin_lock_irqsave(&base->lock, flags);
} }
...@@ -299,7 +299,7 @@ static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) ...@@ -299,7 +299,7 @@ static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
* @function: callback that is run when the alarm fires * @function: callback that is run when the alarm fires
*/ */
void alarm_init(struct alarm *alarm, enum alarmtimer_type type, 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); timerqueue_init(&alarm->node);
alarm->period = ktime_set(0, 0); alarm->period = ktime_set(0, 0);
...@@ -365,12 +365,15 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) ...@@ -365,12 +365,15 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)
* *
* Posix timer callback for expired alarm timers. * 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, struct k_itimer *ptr = container_of(alarm, struct k_itimer,
it.alarmtimer); it.alarmtimer);
if (posix_timer_event(ptr, 0) != 0) if (posix_timer_event(ptr, 0) != 0)
ptr->it_overrun++; ptr->it_overrun++;
return ALARMTIMER_NORESTART;
} }
/** /**
...@@ -509,13 +512,15 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, ...@@ -509,13 +512,15 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
* *
* Wakes up the task that set the alarmtimer * 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; struct task_struct *task = (struct task_struct *)alarm->data;
alarm->data = NULL; alarm->data = NULL;
if (task) if (task)
wake_up_process(task); wake_up_process(task);
return ALARMTIMER_NORESTART;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment