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: John Stultz <john.stultz@linaro.org>
This commit is contained in:
parent
6af7e471e5
commit
4b41308d2d
|
@ -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 {
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
* @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)
|
||||||
*
|
*
|
||||||
* 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,
|
||||||
*
|
*
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue