aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f073a2461faa..04ccab099e84 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -275,7 +275,7 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
275 * The number of overruns is added to the overrun field. 275 * The number of overruns is added to the overrun field.
276 */ 276 */
277unsigned long 277unsigned long
278hrtimer_forward(struct hrtimer *timer, const ktime_t interval) 278hrtimer_forward(struct hrtimer *timer, ktime_t interval)
279{ 279{
280 unsigned long orun = 1; 280 unsigned long orun = 1;
281 ktime_t delta, now; 281 ktime_t delta, now;
@@ -287,6 +287,9 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
287 if (delta.tv64 < 0) 287 if (delta.tv64 < 0)
288 return 0; 288 return 0;
289 289
290 if (interval.tv64 < timer->base->resolution.tv64)
291 interval.tv64 = timer->base->resolution.tv64;
292
290 if (unlikely(delta.tv64 >= interval.tv64)) { 293 if (unlikely(delta.tv64 >= interval.tv64)) {
291 nsec_t incr = ktime_to_ns(interval); 294 nsec_t incr = ktime_to_ns(interval);
292 295
@@ -314,7 +317,6 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
314static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) 317static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
315{ 318{
316 struct rb_node **link = &base->active.rb_node; 319 struct rb_node **link = &base->active.rb_node;
317 struct list_head *prev = &base->pending;
318 struct rb_node *parent = NULL; 320 struct rb_node *parent = NULL;
319 struct hrtimer *entry; 321 struct hrtimer *entry;
320 322
@@ -330,22 +332,23 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
330 */ 332 */
331 if (timer->expires.tv64 < entry->expires.tv64) 333 if (timer->expires.tv64 < entry->expires.tv64)
332 link = &(*link)->rb_left; 334 link = &(*link)->rb_left;
333 else { 335 else
334 link = &(*link)->rb_right; 336 link = &(*link)->rb_right;
335 prev = &entry->list;
336 }
337 } 337 }
338 338
339 /* 339 /*
340 * Insert the timer to the rbtree and to the sorted list: 340 * Insert the timer to the rbtree and check whether it
341 * replaces the first pending timer
341 */ 342 */
342 rb_link_node(&timer->node, parent, link); 343 rb_link_node(&timer->node, parent, link);
343 rb_insert_color(&timer->node, &base->active); 344 rb_insert_color(&timer->node, &base->active);
344 list_add(&timer->list, prev);
345 345
346 timer->state = HRTIMER_PENDING; 346 timer->state = HRTIMER_PENDING;
347}
348 347
348 if (!base->first || timer->expires.tv64 <
349 rb_entry(base->first, struct hrtimer, node)->expires.tv64)
350 base->first = &timer->node;
351}
349 352
350/* 353/*
351 * __remove_hrtimer - internal function to remove a timer 354 * __remove_hrtimer - internal function to remove a timer
@@ -355,9 +358,11 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
355static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) 358static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
356{ 359{
357 /* 360 /*
358 * Remove the timer from the sorted list and from the rbtree: 361 * Remove the timer from the rbtree and replace the
362 * first entry pointer if necessary.
359 */ 363 */
360 list_del(&timer->list); 364 if (base->first == &timer->node)
365 base->first = rb_next(&timer->node);
361 rb_erase(&timer->node, &base->active); 366 rb_erase(&timer->node, &base->active);
362} 367}
363 368
@@ -516,9 +521,8 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
516{ 521{
517 struct hrtimer_base *bases; 522 struct hrtimer_base *bases;
518 523
519 tp->tv_sec = 0;
520 bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); 524 bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
521 tp->tv_nsec = bases[which_clock].resolution; 525 *tp = ktime_to_timespec(bases[which_clock].resolution);
522 526
523 return 0; 527 return 0;
524} 528}
@@ -529,16 +533,17 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
529static inline void run_hrtimer_queue(struct hrtimer_base *base) 533static inline void run_hrtimer_queue(struct hrtimer_base *base)
530{ 534{
531 ktime_t now = base->get_time(); 535 ktime_t now = base->get_time();
536 struct rb_node *node;
532 537
533 spin_lock_irq(&base->lock); 538 spin_lock_irq(&base->lock);
534 539
535 while (!list_empty(&base->pending)) { 540 while ((node = base->first)) {
536 struct hrtimer *timer; 541 struct hrtimer *timer;
537 int (*fn)(void *); 542 int (*fn)(void *);
538 int restart; 543 int restart;
539 void *data; 544 void *data;
540 545
541 timer = list_entry(base->pending.next, struct hrtimer, list); 546 timer = rb_entry(node, struct hrtimer, node);
542 if (now.tv64 <= timer->expires.tv64) 547 if (now.tv64 <= timer->expires.tv64)
543 break; 548 break;
544 549
@@ -732,7 +737,6 @@ static void __devinit init_hrtimers_cpu(int cpu)
732 737
733 for (i = 0; i < MAX_HRTIMER_BASES; i++) { 738 for (i = 0; i < MAX_HRTIMER_BASES; i++) {
734 spin_lock_init(&base->lock); 739 spin_lock_init(&base->lock);
735 INIT_LIST_HEAD(&base->pending);
736 base++; 740 base++;
737 } 741 }
738} 742}