diff options
author | John Stultz <john.stultz@linaro.org> | 2011-08-10 13:37:59 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-08-10 17:55:20 -0400 |
commit | 4b41308d2d0398409620613c7eaaaf52c738b042 (patch) | |
tree | 47a6becae6272eb9c06e57a0a9d1698b8f1811c8 | |
parent | 6af7e471e5a7746b8024d70b4363d3dfe41d36b8 (diff) |
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>
-rw-r--r-- | include/linux/alarmtimer.h | 9 | ||||
-rw-r--r-- | kernel/time/alarmtimer.c | 13 |
2 files changed, 16 insertions, 6 deletions
diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index c5d6095b46f8..0289eb29e794 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h | |||
@@ -13,6 +13,11 @@ enum alarmtimer_type { | |||
13 | ALARM_NUMTYPE, | 13 | ALARM_NUMTYPE, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | enum alarmtimer_restart { | ||
17 | ALARMTIMER_NORESTART, | ||
18 | ALARMTIMER_RESTART, | ||
19 | }; | ||
20 | |||
16 | /** | 21 | /** |
17 | * struct alarm - Alarm timer structure | 22 | * struct alarm - Alarm timer structure |
18 | * @node: timerqueue node for adding to the event list this value | 23 | * @node: timerqueue node for adding to the event list this value |
@@ -26,14 +31,14 @@ enum alarmtimer_type { | |||
26 | struct alarm { | 31 | struct alarm { |
27 | struct timerqueue_node node; | 32 | struct timerqueue_node node; |
28 | ktime_t period; | 33 | ktime_t period; |
29 | void (*function)(struct alarm *); | 34 | enum alarmtimer_restart (*function)(struct alarm *, ktime_t now); |
30 | enum alarmtimer_type type; | 35 | enum alarmtimer_type type; |
31 | bool enabled; | 36 | bool enabled; |
32 | void *data; | 37 | void *data; |
33 | }; | 38 | }; |
34 | 39 | ||
35 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | 40 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, |
36 | void (*function)(struct alarm *)); | 41 | enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); |
37 | void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period); | 42 | void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period); |
38 | void alarm_cancel(struct alarm *alarm); | 43 | void alarm_cancel(struct alarm *alarm); |
39 | 44 | ||
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index ea5e1a928d5b..9e786053ffa2 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -196,7 +196,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) | |||
196 | } | 196 | } |
197 | spin_unlock_irqrestore(&base->lock, flags); | 197 | spin_unlock_irqrestore(&base->lock, flags); |
198 | if (alarm->function) | 198 | if (alarm->function) |
199 | alarm->function(alarm); | 199 | alarm->function(alarm, now); |
200 | spin_lock_irqsave(&base->lock, flags); | 200 | spin_lock_irqsave(&base->lock, flags); |
201 | } | 201 | } |
202 | 202 | ||
@@ -299,7 +299,7 @@ static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | |||
299 | * @function: callback that is run when the alarm fires | 299 | * @function: callback that is run when the alarm fires |
300 | */ | 300 | */ |
301 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | 301 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, |
302 | void (*function)(struct alarm *)) | 302 | enum alarmtimer_restart (*function)(struct alarm *, ktime_t)) |
303 | { | 303 | { |
304 | timerqueue_init(&alarm->node); | 304 | timerqueue_init(&alarm->node); |
305 | alarm->period = ktime_set(0, 0); | 305 | alarm->period = ktime_set(0, 0); |
@@ -365,12 +365,15 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) | |||
365 | * | 365 | * |
366 | * Posix timer callback for expired alarm timers. | 366 | * Posix timer callback for expired alarm timers. |
367 | */ | 367 | */ |
368 | static void alarm_handle_timer(struct alarm *alarm) | 368 | static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, |
369 | ktime_t now) | ||
369 | { | 370 | { |
370 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, | 371 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, |
371 | it.alarmtimer); | 372 | it.alarmtimer); |
372 | if (posix_timer_event(ptr, 0) != 0) | 373 | if (posix_timer_event(ptr, 0) != 0) |
373 | ptr->it_overrun++; | 374 | ptr->it_overrun++; |
375 | |||
376 | return ALARMTIMER_NORESTART; | ||
374 | } | 377 | } |
375 | 378 | ||
376 | /** | 379 | /** |
@@ -509,13 +512,15 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, | |||
509 | * | 512 | * |
510 | * Wakes up the task that set the alarmtimer | 513 | * Wakes up the task that set the alarmtimer |
511 | */ | 514 | */ |
512 | static void alarmtimer_nsleep_wakeup(struct alarm *alarm) | 515 | static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm, |
516 | ktime_t now) | ||
513 | { | 517 | { |
514 | struct task_struct *task = (struct task_struct *)alarm->data; | 518 | struct task_struct *task = (struct task_struct *)alarm->data; |
515 | 519 | ||
516 | alarm->data = NULL; | 520 | alarm->data = NULL; |
517 | if (task) | 521 | if (task) |
518 | wake_up_process(task); | 522 | wake_up_process(task); |
523 | return ALARMTIMER_NORESTART; | ||
519 | } | 524 | } |
520 | 525 | ||
521 | /** | 526 | /** |