diff options
| author | John Stultz <john.stultz@linaro.org> | 2011-08-10 15:30:21 -0400 |
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2011-08-10 17:55:27 -0400 |
| commit | a28cde81ab13cc251748a4c4ef06883dd09a10ea (patch) | |
| tree | b38ce180912957731cfe736d1d3f978342d099e1 /kernel | |
| parent | 9e26476243e438f4534a562660c1296a15a9e202 (diff) | |
alarmtimers: Add more refined alarm state tracking
In order to allow for functionality like try_to_cancel, add
more refined state tracking (similar to hrtimers).
CC: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/time/alarmtimer.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 90935591dd44..5b14cc29b6a6 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
| @@ -126,6 +126,8 @@ static struct rtc_device *alarmtimer_get_rtcdev(void) | |||
| 126 | static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) | 126 | static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) |
| 127 | { | 127 | { |
| 128 | timerqueue_add(&base->timerqueue, &alarm->node); | 128 | timerqueue_add(&base->timerqueue, &alarm->node); |
| 129 | alarm->state |= ALARMTIMER_STATE_ENQUEUED; | ||
| 130 | |||
| 129 | if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { | 131 | if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { |
| 130 | hrtimer_try_to_cancel(&base->timer); | 132 | hrtimer_try_to_cancel(&base->timer); |
| 131 | hrtimer_start(&base->timer, alarm->node.expires, | 133 | hrtimer_start(&base->timer, alarm->node.expires, |
| @@ -147,7 +149,12 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) | |||
| 147 | { | 149 | { |
| 148 | struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); | 150 | struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); |
| 149 | 151 | ||
| 152 | if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED)) | ||
| 153 | return; | ||
| 154 | |||
| 150 | timerqueue_del(&base->timerqueue, &alarm->node); | 155 | timerqueue_del(&base->timerqueue, &alarm->node); |
| 156 | alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; | ||
| 157 | |||
| 151 | if (next == &alarm->node) { | 158 | if (next == &alarm->node) { |
| 152 | hrtimer_try_to_cancel(&base->timer); | 159 | hrtimer_try_to_cancel(&base->timer); |
| 153 | next = timerqueue_getnext(&base->timerqueue); | 160 | next = timerqueue_getnext(&base->timerqueue); |
| @@ -188,16 +195,18 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) | |||
| 188 | alarm = container_of(next, struct alarm, node); | 195 | alarm = container_of(next, struct alarm, node); |
| 189 | 196 | ||
| 190 | timerqueue_del(&base->timerqueue, &alarm->node); | 197 | timerqueue_del(&base->timerqueue, &alarm->node); |
| 191 | alarm->enabled = 0; | 198 | alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; |
| 192 | 199 | ||
| 200 | alarm->state |= ALARMTIMER_STATE_CALLBACK; | ||
| 193 | spin_unlock_irqrestore(&base->lock, flags); | 201 | spin_unlock_irqrestore(&base->lock, flags); |
| 194 | if (alarm->function) | 202 | if (alarm->function) |
| 195 | restart = alarm->function(alarm, now); | 203 | restart = alarm->function(alarm, now); |
| 196 | spin_lock_irqsave(&base->lock, flags); | 204 | spin_lock_irqsave(&base->lock, flags); |
| 205 | alarm->state &= ~ALARMTIMER_STATE_CALLBACK; | ||
| 197 | 206 | ||
| 198 | if (restart != ALARMTIMER_NORESTART) { | 207 | if (restart != ALARMTIMER_NORESTART) { |
| 199 | timerqueue_add(&base->timerqueue, &alarm->node); | 208 | timerqueue_add(&base->timerqueue, &alarm->node); |
| 200 | alarm->enabled = 1; | 209 | alarm->state |= ALARMTIMER_STATE_ENQUEUED; |
| 201 | } | 210 | } |
| 202 | } | 211 | } |
| 203 | 212 | ||
| @@ -305,7 +314,7 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | |||
| 305 | timerqueue_init(&alarm->node); | 314 | timerqueue_init(&alarm->node); |
| 306 | alarm->function = function; | 315 | alarm->function = function; |
| 307 | alarm->type = type; | 316 | alarm->type = type; |
| 308 | alarm->enabled = 0; | 317 | alarm->state = ALARMTIMER_STATE_INACTIVE; |
| 309 | } | 318 | } |
| 310 | 319 | ||
| 311 | /** | 320 | /** |
| @@ -319,11 +328,10 @@ void alarm_start(struct alarm *alarm, ktime_t start) | |||
| 319 | unsigned long flags; | 328 | unsigned long flags; |
| 320 | 329 | ||
| 321 | spin_lock_irqsave(&base->lock, flags); | 330 | spin_lock_irqsave(&base->lock, flags); |
| 322 | if (alarm->enabled) | 331 | if (alarmtimer_active(alarm)) |
| 323 | alarmtimer_remove(base, alarm); | 332 | alarmtimer_remove(base, alarm); |
| 324 | alarm->node.expires = start; | 333 | alarm->node.expires = start; |
| 325 | alarmtimer_enqueue(base, alarm); | 334 | alarmtimer_enqueue(base, alarm); |
| 326 | alarm->enabled = 1; | ||
| 327 | spin_unlock_irqrestore(&base->lock, flags); | 335 | spin_unlock_irqrestore(&base->lock, flags); |
| 328 | } | 336 | } |
| 329 | 337 | ||
| @@ -337,9 +345,8 @@ void alarm_cancel(struct alarm *alarm) | |||
| 337 | unsigned long flags; | 345 | unsigned long flags; |
| 338 | 346 | ||
| 339 | spin_lock_irqsave(&base->lock, flags); | 347 | spin_lock_irqsave(&base->lock, flags); |
| 340 | if (alarm->enabled) | 348 | if (alarmtimer_is_queued(alarm)) |
| 341 | alarmtimer_remove(base, alarm); | 349 | alarmtimer_remove(base, alarm); |
| 342 | alarm->enabled = 0; | ||
| 343 | spin_unlock_irqrestore(&base->lock, flags); | 350 | spin_unlock_irqrestore(&base->lock, flags); |
| 344 | } | 351 | } |
| 345 | 352 | ||
