diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 34 |
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 | */ |
277 | unsigned long | 277 | unsigned long |
278 | hrtimer_forward(struct hrtimer *timer, const ktime_t interval) | 278 | hrtimer_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) | |||
314 | static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) | 317 | static 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) | |||
355 | static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) | 358 | static 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) | |||
529 | static inline void run_hrtimer_queue(struct hrtimer_base *base) | 533 | static 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 | } |