diff options
Diffstat (limited to 'kernel/time/alarmtimer.c')
| -rw-r--r-- | kernel/time/alarmtimer.c | 94 | 
1 files changed, 27 insertions, 67 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 54e7145c541..b1560ebe759 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -37,7 +37,6 @@  static struct alarm_base {  	spinlock_t		lock;  	struct timerqueue_head	timerqueue; -	struct hrtimer		timer;  	ktime_t			(*gettime)(void);  	clockid_t		base_clockid;  } alarm_bases[ALARM_NUMTYPE]; @@ -132,21 +131,17 @@ static inline void alarmtimer_rtc_timer_init(void) { }   * @base: pointer to the base where the timer is being run   * @alarm: pointer to alarm being enqueued.   * - * Adds alarm to a alarm_base timerqueue and if necessary sets - * an hrtimer to run. + * Adds alarm to a alarm_base timerqueue   *   * Must hold base->lock when calling.   */  static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)  { +	if (alarm->state & ALARMTIMER_STATE_ENQUEUED) +		timerqueue_del(&base->timerqueue, &alarm->node); +  	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, -				HRTIMER_MODE_ABS); -	}  }  /** @@ -154,28 +149,17 @@ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)   * @base: pointer to the base where the timer is running   * @alarm: pointer to alarm being removed   * - * Removes alarm to a alarm_base timerqueue and if necessary sets - * a new timer to run. + * Removes alarm to a alarm_base timerqueue   *   * Must hold base->lock when calling.   */  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); -		if (!next) -			return; -		hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); -	}  } @@ -190,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)   */  static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)  { -	struct alarm_base *base = container_of(timer, struct alarm_base, timer); -	struct timerqueue_node *next; +	struct alarm *alarm = container_of(timer, struct alarm, timer); +	struct alarm_base *base = &alarm_bases[alarm->type];  	unsigned long flags; -	ktime_t now;  	int ret = HRTIMER_NORESTART;  	int restart = ALARMTIMER_NORESTART;  	spin_lock_irqsave(&base->lock, flags); -	now = base->gettime(); -	while ((next = timerqueue_getnext(&base->timerqueue))) { -		struct alarm *alarm; -		ktime_t expired = next->expires; - -		if (expired.tv64 > now.tv64) -			break; - -		alarm = container_of(next, struct alarm, node); - -		timerqueue_del(&base->timerqueue, &alarm->node); -		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; +	alarmtimer_remove(base, alarm); +	spin_unlock_irqrestore(&base->lock, flags); -		if (restart != ALARMTIMER_NORESTART) { -			timerqueue_add(&base->timerqueue, &alarm->node); -			alarm->state |= ALARMTIMER_STATE_ENQUEUED; -		} -	} +	if (alarm->function) +		restart = alarm->function(alarm, base->gettime()); -	if (next) { -		hrtimer_set_expires(&base->timer, next->expires); +	spin_lock_irqsave(&base->lock, flags); +	if (restart != ALARMTIMER_NORESTART) { +		hrtimer_set_expires(&alarm->timer, alarm->node.expires); +		alarmtimer_enqueue(base, alarm);  		ret = HRTIMER_RESTART;  	}  	spin_unlock_irqrestore(&base->lock, flags); @@ -331,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,  		enum alarmtimer_restart (*function)(struct alarm *, ktime_t))  {  	timerqueue_init(&alarm->node); +	hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid, +			HRTIMER_MODE_ABS); +	alarm->timer.function = alarmtimer_fired;  	alarm->function = function;  	alarm->type = type;  	alarm->state = ALARMTIMER_STATE_INACTIVE; @@ -341,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,   * @alarm: ptr to alarm to set   * @start: time to run the alarm   */ -void alarm_start(struct alarm *alarm, ktime_t start) +int alarm_start(struct alarm *alarm, ktime_t start)  {  	struct alarm_base *base = &alarm_bases[alarm->type];  	unsigned long flags; +	int ret;  	spin_lock_irqsave(&base->lock, flags); -	if (alarmtimer_active(alarm)) -		alarmtimer_remove(base, alarm);  	alarm->node.expires = start;  	alarmtimer_enqueue(base, alarm); +	ret = hrtimer_start(&alarm->timer, alarm->node.expires, +				HRTIMER_MODE_ABS);  	spin_unlock_irqrestore(&base->lock, flags); +	return ret;  }  /** @@ -365,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm)  {  	struct alarm_base *base = &alarm_bases[alarm->type];  	unsigned long flags; -	int ret = -1; -	spin_lock_irqsave(&base->lock, flags); - -	if (alarmtimer_callback_running(alarm)) -		goto out; +	int ret; -	if (alarmtimer_is_queued(alarm)) { +	spin_lock_irqsave(&base->lock, flags); +	ret = hrtimer_try_to_cancel(&alarm->timer); +	if (ret >= 0)  		alarmtimer_remove(base, alarm); -		ret = 1; -	} else -		ret = 0; -out:  	spin_unlock_irqrestore(&base->lock, flags);  	return ret;  } @@ -809,10 +773,6 @@ static int __init alarmtimer_init(void)  	for (i = 0; i < ALARM_NUMTYPE; i++) {  		timerqueue_init_head(&alarm_bases[i].timerqueue);  		spin_lock_init(&alarm_bases[i].lock); -		hrtimer_init(&alarm_bases[i].timer, -				alarm_bases[i].base_clockid, -				HRTIMER_MODE_ABS); -		alarm_bases[i].timer.function = alarmtimer_fired;  	}  	error = alarmtimer_rtc_interface_setup();  |