diff options
| author | John Stultz <john.stultz@linaro.org> | 2011-08-10 12:30:21 -0700 | 
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2011-08-10 14:55:27 -0700 | 
| commit | a28cde81ab13cc251748a4c4ef06883dd09a10ea (patch) | |
| tree | b38ce180912957731cfe736d1d3f978342d099e1 /kernel/time/alarmtimer.c | |
| parent | 9e26476243e438f4534a562660c1296a15a9e202 (diff) | |
| download | olio-linux-3.10-a28cde81ab13cc251748a4c4ef06883dd09a10ea.tar.xz olio-linux-3.10-a28cde81ab13cc251748a4c4ef06883dd09a10ea.zip  | |
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 90935591dd4..5b14cc29b6a 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -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);  }  |