aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f073a2461faa..e6e8278bcb18 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -314,7 +314,6 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
314static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) 314static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
315{ 315{
316 struct rb_node **link = &base->active.rb_node; 316 struct rb_node **link = &base->active.rb_node;
317 struct list_head *prev = &base->pending;
318 struct rb_node *parent = NULL; 317 struct rb_node *parent = NULL;
319 struct hrtimer *entry; 318 struct hrtimer *entry;
320 319
@@ -330,22 +329,23 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
330 */ 329 */
331 if (timer->expires.tv64 < entry->expires.tv64) 330 if (timer->expires.tv64 < entry->expires.tv64)
332 link = &(*link)->rb_left; 331 link = &(*link)->rb_left;
333 else { 332 else
334 link = &(*link)->rb_right; 333 link = &(*link)->rb_right;
335 prev = &entry->list;
336 }
337 } 334 }
338 335
339 /* 336 /*
340 * Insert the timer to the rbtree and to the sorted list: 337 * Insert the timer to the rbtree and check whether it
338 * replaces the first pending timer
341 */ 339 */
342 rb_link_node(&timer->node, parent, link); 340 rb_link_node(&timer->node, parent, link);
343 rb_insert_color(&timer->node, &base->active); 341 rb_insert_color(&timer->node, &base->active);
344 list_add(&timer->list, prev);
345 342
346 timer->state = HRTIMER_PENDING; 343 timer->state = HRTIMER_PENDING;
347}
348 344
345 if (!base->first || timer->expires.tv64 <
346 rb_entry(base->first, struct hrtimer, node)->expires.tv64)
347 base->first = &timer->node;
348}
349 349
350/* 350/*
351 * __remove_hrtimer - internal function to remove a timer 351 * __remove_hrtimer - internal function to remove a timer
@@ -355,9 +355,11 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
355static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) 355static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
356{ 356{
357 /* 357 /*
358 * Remove the timer from the sorted list and from the rbtree: 358 * Remove the timer from the rbtree and replace the
359 * first entry pointer if necessary.
359 */ 360 */
360 list_del(&timer->list); 361 if (base->first == &timer->node)
362 base->first = rb_next(&timer->node);
361 rb_erase(&timer->node, &base->active); 363 rb_erase(&timer->node, &base->active);
362} 364}
363 365
@@ -529,16 +531,17 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
529static inline void run_hrtimer_queue(struct hrtimer_base *base) 531static inline void run_hrtimer_queue(struct hrtimer_base *base)
530{ 532{
531 ktime_t now = base->get_time(); 533 ktime_t now = base->get_time();
534 struct rb_node *node;
532 535
533 spin_lock_irq(&base->lock); 536 spin_lock_irq(&base->lock);
534 537
535 while (!list_empty(&base->pending)) { 538 while ((node = base->first)) {
536 struct hrtimer *timer; 539 struct hrtimer *timer;
537 int (*fn)(void *); 540 int (*fn)(void *);
538 int restart; 541 int restart;
539 void *data; 542 void *data;
540 543
541 timer = list_entry(base->pending.next, struct hrtimer, list); 544 timer = rb_entry(node, struct hrtimer, node);
542 if (now.tv64 <= timer->expires.tv64) 545 if (now.tv64 <= timer->expires.tv64)
543 break; 546 break;
544 547
@@ -732,7 +735,6 @@ static void __devinit init_hrtimers_cpu(int cpu)
732 735
733 for (i = 0; i < MAX_HRTIMER_BASES; i++) { 736 for (i = 0; i < MAX_HRTIMER_BASES; i++) {
734 spin_lock_init(&base->lock); 737 spin_lock_init(&base->lock);
735 INIT_LIST_HEAD(&base->pending);
736 base++; 738 base++;
737 } 739 }
738} 740}