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/time/alarmtimer.c | |
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/time/alarmtimer.c')
-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 | ||