aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/alarmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/alarmtimer.c')
-rw-r--r--kernel/time/alarmtimer.c94
1 files changed, 27 insertions, 67 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 54e7145c5414..b1560ebe759f 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -37,7 +37,6 @@
37static struct alarm_base { 37static struct alarm_base {
38 spinlock_t lock; 38 spinlock_t lock;
39 struct timerqueue_head timerqueue; 39 struct timerqueue_head timerqueue;
40 struct hrtimer timer;
41 ktime_t (*gettime)(void); 40 ktime_t (*gettime)(void);
42 clockid_t base_clockid; 41 clockid_t base_clockid;
43} alarm_bases[ALARM_NUMTYPE]; 42} alarm_bases[ALARM_NUMTYPE];
@@ -132,21 +131,17 @@ static inline void alarmtimer_rtc_timer_init(void) { }
132 * @base: pointer to the base where the timer is being run 131 * @base: pointer to the base where the timer is being run
133 * @alarm: pointer to alarm being enqueued. 132 * @alarm: pointer to alarm being enqueued.
134 * 133 *
135 * Adds alarm to a alarm_base timerqueue and if necessary sets 134 * Adds alarm to a alarm_base timerqueue
136 * an hrtimer to run.
137 * 135 *
138 * Must hold base->lock when calling. 136 * Must hold base->lock when calling.
139 */ 137 */
140static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) 138static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
141{ 139{
140 if (alarm->state & ALARMTIMER_STATE_ENQUEUED)
141 timerqueue_del(&base->timerqueue, &alarm->node);
142
142 timerqueue_add(&base->timerqueue, &alarm->node); 143 timerqueue_add(&base->timerqueue, &alarm->node);
143 alarm->state |= ALARMTIMER_STATE_ENQUEUED; 144 alarm->state |= ALARMTIMER_STATE_ENQUEUED;
144
145 if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
146 hrtimer_try_to_cancel(&base->timer);
147 hrtimer_start(&base->timer, alarm->node.expires,
148 HRTIMER_MODE_ABS);
149 }
150} 145}
151 146
152/** 147/**
@@ -154,28 +149,17 @@ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
154 * @base: pointer to the base where the timer is running 149 * @base: pointer to the base where the timer is running
155 * @alarm: pointer to alarm being removed 150 * @alarm: pointer to alarm being removed
156 * 151 *
157 * Removes alarm to a alarm_base timerqueue and if necessary sets 152 * Removes alarm to a alarm_base timerqueue
158 * a new timer to run.
159 * 153 *
160 * Must hold base->lock when calling. 154 * Must hold base->lock when calling.
161 */ 155 */
162static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) 156static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
163{ 157{
164 struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
165
166 if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED)) 158 if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
167 return; 159 return;
168 160
169 timerqueue_del(&base->timerqueue, &alarm->node); 161 timerqueue_del(&base->timerqueue, &alarm->node);
170 alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; 162 alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
171
172 if (next == &alarm->node) {
173 hrtimer_try_to_cancel(&base->timer);
174 next = timerqueue_getnext(&base->timerqueue);
175 if (!next)
176 return;
177 hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS);
178 }
179} 163}
180 164
181 165
@@ -190,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
190 */ 174 */
191static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) 175static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
192{ 176{
193 struct alarm_base *base = container_of(timer, struct alarm_base, timer); 177 struct alarm *alarm = container_of(timer, struct alarm, timer);
194 struct timerqueue_node *next; 178 struct alarm_base *base = &alarm_bases[alarm->type];
195 unsigned long flags; 179 unsigned long flags;
196 ktime_t now;
197 int ret = HRTIMER_NORESTART; 180 int ret = HRTIMER_NORESTART;
198 int restart = ALARMTIMER_NORESTART; 181 int restart = ALARMTIMER_NORESTART;
199 182
200 spin_lock_irqsave(&base->lock, flags); 183 spin_lock_irqsave(&base->lock, flags);
201 now = base->gettime(); 184 alarmtimer_remove(base, alarm);
202 while ((next = timerqueue_getnext(&base->timerqueue))) { 185 spin_unlock_irqrestore(&base->lock, flags);
203 struct alarm *alarm;
204 ktime_t expired = next->expires;
205
206 if (expired.tv64 > now.tv64)
207 break;
208
209 alarm = container_of(next, struct alarm, node);
210
211 timerqueue_del(&base->timerqueue, &alarm->node);
212 alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
213
214 alarm->state |= ALARMTIMER_STATE_CALLBACK;
215 spin_unlock_irqrestore(&base->lock, flags);
216 if (alarm->function)
217 restart = alarm->function(alarm, now);
218 spin_lock_irqsave(&base->lock, flags);
219 alarm->state &= ~ALARMTIMER_STATE_CALLBACK;
220 186
221 if (restart != ALARMTIMER_NORESTART) { 187 if (alarm->function)
222 timerqueue_add(&base->timerqueue, &alarm->node); 188 restart = alarm->function(alarm, base->gettime());
223 alarm->state |= ALARMTIMER_STATE_ENQUEUED;
224 }
225 }
226 189
227 if (next) { 190 spin_lock_irqsave(&base->lock, flags);
228 hrtimer_set_expires(&base->timer, next->expires); 191 if (restart != ALARMTIMER_NORESTART) {
192 hrtimer_set_expires(&alarm->timer, alarm->node.expires);
193 alarmtimer_enqueue(base, alarm);
229 ret = HRTIMER_RESTART; 194 ret = HRTIMER_RESTART;
230 } 195 }
231 spin_unlock_irqrestore(&base->lock, flags); 196 spin_unlock_irqrestore(&base->lock, flags);
@@ -331,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
331 enum alarmtimer_restart (*function)(struct alarm *, ktime_t)) 296 enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
332{ 297{
333 timerqueue_init(&alarm->node); 298 timerqueue_init(&alarm->node);
299 hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
300 HRTIMER_MODE_ABS);
301 alarm->timer.function = alarmtimer_fired;
334 alarm->function = function; 302 alarm->function = function;
335 alarm->type = type; 303 alarm->type = type;
336 alarm->state = ALARMTIMER_STATE_INACTIVE; 304 alarm->state = ALARMTIMER_STATE_INACTIVE;
@@ -341,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
341 * @alarm: ptr to alarm to set 309 * @alarm: ptr to alarm to set
342 * @start: time to run the alarm 310 * @start: time to run the alarm
343 */ 311 */
344void alarm_start(struct alarm *alarm, ktime_t start) 312int alarm_start(struct alarm *alarm, ktime_t start)
345{ 313{
346 struct alarm_base *base = &alarm_bases[alarm->type]; 314 struct alarm_base *base = &alarm_bases[alarm->type];
347 unsigned long flags; 315 unsigned long flags;
316 int ret;
348 317
349 spin_lock_irqsave(&base->lock, flags); 318 spin_lock_irqsave(&base->lock, flags);
350 if (alarmtimer_active(alarm))
351 alarmtimer_remove(base, alarm);
352 alarm->node.expires = start; 319 alarm->node.expires = start;
353 alarmtimer_enqueue(base, alarm); 320 alarmtimer_enqueue(base, alarm);
321 ret = hrtimer_start(&alarm->timer, alarm->node.expires,
322 HRTIMER_MODE_ABS);
354 spin_unlock_irqrestore(&base->lock, flags); 323 spin_unlock_irqrestore(&base->lock, flags);
324 return ret;
355} 325}
356 326
357/** 327/**
@@ -365,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm)
365{ 335{
366 struct alarm_base *base = &alarm_bases[alarm->type]; 336 struct alarm_base *base = &alarm_bases[alarm->type];
367 unsigned long flags; 337 unsigned long flags;
368 int ret = -1; 338 int ret;
369 spin_lock_irqsave(&base->lock, flags);
370
371 if (alarmtimer_callback_running(alarm))
372 goto out;
373 339
374 if (alarmtimer_is_queued(alarm)) { 340 spin_lock_irqsave(&base->lock, flags);
341 ret = hrtimer_try_to_cancel(&alarm->timer);
342 if (ret >= 0)
375 alarmtimer_remove(base, alarm); 343 alarmtimer_remove(base, alarm);
376 ret = 1;
377 } else
378 ret = 0;
379out:
380 spin_unlock_irqrestore(&base->lock, flags); 344 spin_unlock_irqrestore(&base->lock, flags);
381 return ret; 345 return ret;
382} 346}
@@ -809,10 +773,6 @@ static int __init alarmtimer_init(void)
809 for (i = 0; i < ALARM_NUMTYPE; i++) { 773 for (i = 0; i < ALARM_NUMTYPE; i++) {
810 timerqueue_init_head(&alarm_bases[i].timerqueue); 774 timerqueue_init_head(&alarm_bases[i].timerqueue);
811 spin_lock_init(&alarm_bases[i].lock); 775 spin_lock_init(&alarm_bases[i].lock);
812 hrtimer_init(&alarm_bases[i].timer,
813 alarm_bases[i].base_clockid,
814 HRTIMER_MODE_ABS);
815 alarm_bases[i].timer.function = alarmtimer_fired;
816 } 776 }
817 777
818 error = alarmtimer_rtc_interface_setup(); 778 error = alarmtimer_rtc_interface_setup();