mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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>
This commit is contained in:
parent
9e26476243
commit
a28cde81ab
2 changed files with 47 additions and 8 deletions
|
@ -126,6 +126,8 @@ static struct rtc_device *alarmtimer_get_rtcdev(void)
|
|||
static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
|
||||
{
|
||||
timerqueue_add(&base->timerqueue, &alarm->node);
|
||||
alarm->state |= ALARMTIMER_STATE_ENQUEUED;
|
||||
|
||||
if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
|
||||
hrtimer_try_to_cancel(&base->timer);
|
||||
hrtimer_start(&base->timer, alarm->node.expires,
|
||||
|
@ -147,7 +149,12 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
|
|||
{
|
||||
struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
|
||||
|
||||
if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
|
||||
return;
|
||||
|
||||
timerqueue_del(&base->timerqueue, &alarm->node);
|
||||
alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
|
||||
|
||||
if (next == &alarm->node) {
|
||||
hrtimer_try_to_cancel(&base->timer);
|
||||
next = timerqueue_getnext(&base->timerqueue);
|
||||
|
@ -188,16 +195,18 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
|
|||
alarm = container_of(next, struct alarm, node);
|
||||
|
||||
timerqueue_del(&base->timerqueue, &alarm->node);
|
||||
alarm->enabled = 0;
|
||||
alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
|
||||
|
||||
alarm->state |= ALARMTIMER_STATE_CALLBACK;
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
if (alarm->function)
|
||||
restart = alarm->function(alarm, now);
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
alarm->state &= ~ALARMTIMER_STATE_CALLBACK;
|
||||
|
||||
if (restart != ALARMTIMER_NORESTART) {
|
||||
timerqueue_add(&base->timerqueue, &alarm->node);
|
||||
alarm->enabled = 1;
|
||||
alarm->state |= ALARMTIMER_STATE_ENQUEUED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,7 +314,7 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
|
|||
timerqueue_init(&alarm->node);
|
||||
alarm->function = function;
|
||||
alarm->type = type;
|
||||
alarm->enabled = 0;
|
||||
alarm->state = ALARMTIMER_STATE_INACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,11 +328,10 @@ void alarm_start(struct alarm *alarm, ktime_t start)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
if (alarm->enabled)
|
||||
if (alarmtimer_active(alarm))
|
||||
alarmtimer_remove(base, alarm);
|
||||
alarm->node.expires = start;
|
||||
alarmtimer_enqueue(base, alarm);
|
||||
alarm->enabled = 1;
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -337,9 +345,8 @@ void alarm_cancel(struct alarm *alarm)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
if (alarm->enabled)
|
||||
if (alarmtimer_is_queued(alarm))
|
||||
alarmtimer_remove(base, alarm);
|
||||
alarm->enabled = 0;
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue