aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2011-08-10 13:37:59 -0400
committerJohn Stultz <john.stultz@linaro.org>2011-08-10 17:55:20 -0400
commit4b41308d2d0398409620613c7eaaaf52c738b042 (patch)
tree47a6becae6272eb9c06e57a0a9d1698b8f1811c8
parent6af7e471e5a7746b8024d70b4363d3dfe41d36b8 (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.h9
-rw-r--r--kernel/time/alarmtimer.c13
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
16enum 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 {
26struct alarm { 31struct 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
35void alarm_init(struct alarm *alarm, enum alarmtimer_type type, 40void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
36 void (*function)(struct alarm *)); 41 enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
37void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period); 42void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
38void alarm_cancel(struct alarm *alarm); 43void 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 */
301void alarm_init(struct alarm *alarm, enum alarmtimer_type type, 301void 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 */
368static void alarm_handle_timer(struct alarm *alarm) 368static 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 */
512static void alarmtimer_nsleep_wakeup(struct alarm *alarm) 515static 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/**