Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+47 -8
+33 -1
include/linux/alarmtimer.h
··· 18 18 ALARMTIMER_RESTART, 19 19 }; 20 20 21 + 22 + #define ALARMTIMER_STATE_INACTIVE 0x00 23 + #define ALARMTIMER_STATE_ENQUEUED 0x01 24 + #define ALARMTIMER_STATE_CALLBACK 0x02 25 + 21 26 /** 22 27 * struct alarm - Alarm timer structure 23 28 * @node: timerqueue node for adding to the event list this value ··· 37 32 struct timerqueue_node node; 38 33 enum alarmtimer_restart (*function)(struct alarm *, ktime_t now); 39 34 enum alarmtimer_type type; 40 - bool enabled; 35 + int state; 41 36 void *data; 42 37 }; 43 38 ··· 47 42 void alarm_cancel(struct alarm *alarm); 48 43 49 44 u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval); 45 + 46 + /* 47 + * A alarmtimer is active, when it is enqueued into timerqueue or the 48 + * callback function is running. 49 + */ 50 + static inline int alarmtimer_active(const struct alarm *timer) 51 + { 52 + return timer->state != ALARMTIMER_STATE_INACTIVE; 53 + } 54 + 55 + /* 56 + * Helper function to check, whether the timer is on one of the queues 57 + */ 58 + static inline int alarmtimer_is_queued(struct alarm *timer) 59 + { 60 + return timer->state & ALARMTIMER_STATE_ENQUEUED; 61 + } 62 + 63 + /* 64 + * Helper function to check, whether the timer is running the callback 65 + * function 66 + */ 67 + static inline int alarmtimer_callback_running(struct alarm *timer) 68 + { 69 + return timer->state & ALARMTIMER_STATE_CALLBACK; 70 + } 71 + 50 72 51 73 #endif
+14 -7
kernel/time/alarmtimer.c
··· 126 126 static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) 127 127 { 128 128 timerqueue_add(&base->timerqueue, &alarm->node); 129 + alarm->state |= ALARMTIMER_STATE_ENQUEUED; 130 + 129 131 if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { 130 132 hrtimer_try_to_cancel(&base->timer); 131 133 hrtimer_start(&base->timer, alarm->node.expires, ··· 149 147 { 150 148 struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); 151 149 150 + if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED)) 151 + return; 152 + 152 153 timerqueue_del(&base->timerqueue, &alarm->node); 154 + alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; 155 + 153 156 if (next == &alarm->node) { 154 157 hrtimer_try_to_cancel(&base->timer); 155 158 next = timerqueue_getnext(&base->timerqueue); ··· 195 188 alarm = container_of(next, struct alarm, node); 196 189 197 190 timerqueue_del(&base->timerqueue, &alarm->node); 198 - alarm->enabled = 0; 191 + alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; 199 192 193 + alarm->state |= ALARMTIMER_STATE_CALLBACK; 200 194 spin_unlock_irqrestore(&base->lock, flags); 201 195 if (alarm->function) 202 196 restart = alarm->function(alarm, now); 203 197 spin_lock_irqsave(&base->lock, flags); 198 + alarm->state &= ~ALARMTIMER_STATE_CALLBACK; 204 199 205 200 if (restart != ALARMTIMER_NORESTART) { 206 201 timerqueue_add(&base->timerqueue, &alarm->node); 207 - alarm->enabled = 1; 202 + alarm->state |= ALARMTIMER_STATE_ENQUEUED; 208 203 } 209 204 } 210 205 ··· 314 305 timerqueue_init(&alarm->node); 315 306 alarm->function = function; 316 307 alarm->type = type; 317 - alarm->enabled = 0; 308 + alarm->state = ALARMTIMER_STATE_INACTIVE; 318 309 } 319 310 320 311 /** ··· 328 319 unsigned long flags; 329 320 330 321 spin_lock_irqsave(&base->lock, flags); 331 - if (alarm->enabled) 322 + if (alarmtimer_active(alarm)) 332 323 alarmtimer_remove(base, alarm); 333 324 alarm->node.expires = start; 334 325 alarmtimer_enqueue(base, alarm); 335 - alarm->enabled = 1; 336 326 spin_unlock_irqrestore(&base->lock, flags); 337 327 } 338 328 ··· 345 337 unsigned long flags; 346 338 347 339 spin_lock_irqsave(&base->lock, flags); 348 - if (alarm->enabled) 340 + if (alarmtimer_is_queued(alarm)) 349 341 alarmtimer_remove(base, alarm); 350 - alarm->enabled = 0; 351 342 spin_unlock_irqrestore(&base->lock, flags); 352 343 } 353 344