aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-09-13 19:12:16 -0400
committerJohn Stultz <john.stultz@linaro.org>2012-09-24 12:38:02 -0400
commitdae373be9fec6f850159a05af3a1c36236a70d43 (patch)
tree4a58f2fd66b2cbee680dfd3b83d78e1cfea34128 /kernel
parent59a93c27c4892f04dfd8f91f8b64d0d6eae43e6e (diff)
alarmtimer: Use hrtimer per-alarm instead of per-base
Arve Hjønnevåg reported numerous crashes from the "BUG_ON(timer->state != HRTIMER_STATE_CALLBACK)" check in __run_hrtimer after it called alarmtimer_fired. It ends up the alarmtimer code was not properly handling possible failures of hrtimer_try_to_cancel, and because these faulres occur when the underlying base hrtimer is being run, this limits the ability to properly handle modifications to any alarmtimers on that base. Because much of the logic duplicates the hrtimer logic, it seems that we might as well have a per-alarmtimer hrtimer, and avoid the extra complextity of trying to multiplex many alarmtimers off of one hrtimer. Thus this patch moves the hrtimer to the alarm structure and simplifies the management logic. Changelog: v2: * Includes a fix for double alarm_start calls found by Arve Cc: Arve Hjønnevåg <arve@android.com> Cc: Colin Cross <ccross@android.com> Cc: Thomas Gleixner <tglx@linutronix.de> Reported-by: Arve Hjønnevåg <arve@android.com> Tested-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
-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();