diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-27 13:39:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-27 13:39:04 -0400 |
commit | 6f5071020d5ec89b5d095aa488db604adb921aec (patch) | |
tree | 8d70c104b436d1ab6bdadf4cd618386802c37316 /kernel | |
parent | 73964f6bc8e378715887592abe8a512f403db6a8 (diff) | |
parent | 7403f41f19574d6805197e9b97dfa7592003be10 (diff) |
Merge branch 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
hrtimer: Eliminate needless reprogramming of clock events device
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/hrtimer.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index e5d98ce50f89..6d7020490f94 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -509,13 +509,14 @@ static inline int hrtimer_hres_active(void) | |||
509 | * next event | 509 | * next event |
510 | * Called with interrupts disabled and base->lock held | 510 | * Called with interrupts disabled and base->lock held |
511 | */ | 511 | */ |
512 | static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | 512 | static void |
513 | hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) | ||
513 | { | 514 | { |
514 | int i; | 515 | int i; |
515 | struct hrtimer_clock_base *base = cpu_base->clock_base; | 516 | struct hrtimer_clock_base *base = cpu_base->clock_base; |
516 | ktime_t expires; | 517 | ktime_t expires, expires_next; |
517 | 518 | ||
518 | cpu_base->expires_next.tv64 = KTIME_MAX; | 519 | expires_next.tv64 = KTIME_MAX; |
519 | 520 | ||
520 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { | 521 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { |
521 | struct hrtimer *timer; | 522 | struct hrtimer *timer; |
@@ -531,10 +532,15 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) | |||
531 | */ | 532 | */ |
532 | if (expires.tv64 < 0) | 533 | if (expires.tv64 < 0) |
533 | expires.tv64 = 0; | 534 | expires.tv64 = 0; |
534 | if (expires.tv64 < cpu_base->expires_next.tv64) | 535 | if (expires.tv64 < expires_next.tv64) |
535 | cpu_base->expires_next = expires; | 536 | expires_next = expires; |
536 | } | 537 | } |
537 | 538 | ||
539 | if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64) | ||
540 | return; | ||
541 | |||
542 | cpu_base->expires_next.tv64 = expires_next.tv64; | ||
543 | |||
538 | if (cpu_base->expires_next.tv64 != KTIME_MAX) | 544 | if (cpu_base->expires_next.tv64 != KTIME_MAX) |
539 | tick_program_event(cpu_base->expires_next, 1); | 545 | tick_program_event(cpu_base->expires_next, 1); |
540 | } | 546 | } |
@@ -617,7 +623,7 @@ static void retrigger_next_event(void *arg) | |||
617 | base->clock_base[CLOCK_REALTIME].offset = | 623 | base->clock_base[CLOCK_REALTIME].offset = |
618 | timespec_to_ktime(realtime_offset); | 624 | timespec_to_ktime(realtime_offset); |
619 | 625 | ||
620 | hrtimer_force_reprogram(base); | 626 | hrtimer_force_reprogram(base, 0); |
621 | spin_unlock(&base->lock); | 627 | spin_unlock(&base->lock); |
622 | } | 628 | } |
623 | 629 | ||
@@ -730,7 +736,8 @@ static int hrtimer_switch_to_hres(void) | |||
730 | static inline int hrtimer_hres_active(void) { return 0; } | 736 | static inline int hrtimer_hres_active(void) { return 0; } |
731 | static inline int hrtimer_is_hres_enabled(void) { return 0; } | 737 | static inline int hrtimer_is_hres_enabled(void) { return 0; } |
732 | static inline int hrtimer_switch_to_hres(void) { return 0; } | 738 | static inline int hrtimer_switch_to_hres(void) { return 0; } |
733 | static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { } | 739 | static inline void |
740 | hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } | ||
734 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | 741 | static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, |
735 | struct hrtimer_clock_base *base, | 742 | struct hrtimer_clock_base *base, |
736 | int wakeup) | 743 | int wakeup) |
@@ -873,19 +880,29 @@ static void __remove_hrtimer(struct hrtimer *timer, | |||
873 | struct hrtimer_clock_base *base, | 880 | struct hrtimer_clock_base *base, |
874 | unsigned long newstate, int reprogram) | 881 | unsigned long newstate, int reprogram) |
875 | { | 882 | { |
876 | if (timer->state & HRTIMER_STATE_ENQUEUED) { | 883 | if (!(timer->state & HRTIMER_STATE_ENQUEUED)) |
877 | /* | 884 | goto out; |
878 | * Remove the timer from the rbtree and replace the | 885 | |
879 | * first entry pointer if necessary. | 886 | /* |
880 | */ | 887 | * Remove the timer from the rbtree and replace the first |
881 | if (base->first == &timer->node) { | 888 | * entry pointer if necessary. |
882 | base->first = rb_next(&timer->node); | 889 | */ |
883 | /* Reprogram the clock event device. if enabled */ | 890 | if (base->first == &timer->node) { |
884 | if (reprogram && hrtimer_hres_active()) | 891 | base->first = rb_next(&timer->node); |
885 | hrtimer_force_reprogram(base->cpu_base); | 892 | #ifdef CONFIG_HIGH_RES_TIMERS |
893 | /* Reprogram the clock event device. if enabled */ | ||
894 | if (reprogram && hrtimer_hres_active()) { | ||
895 | ktime_t expires; | ||
896 | |||
897 | expires = ktime_sub(hrtimer_get_expires(timer), | ||
898 | base->offset); | ||
899 | if (base->cpu_base->expires_next.tv64 == expires.tv64) | ||
900 | hrtimer_force_reprogram(base->cpu_base, 1); | ||
886 | } | 901 | } |
887 | rb_erase(&timer->node, &base->active); | 902 | #endif |
888 | } | 903 | } |
904 | rb_erase(&timer->node, &base->active); | ||
905 | out: | ||
889 | timer->state = newstate; | 906 | timer->state = newstate; |
890 | } | 907 | } |
891 | 908 | ||