diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 20:10:53 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 20:10:53 -0500 |
| commit | 3610639d1fceb09cb418c65fcbe9136c31eee03a (patch) | |
| tree | 78aa6de9e9495c39f8671aed927fece5adff8d24 | |
| parent | cfa97f993c275d193fe82c22511dfb5f1e51b661 (diff) | |
| parent | 82c5b7b527ccc4b5d3cf832437e842f9d2920a79 (diff) | |
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
hrtimer: splitout peek ahead functionality, fix
hrtimer: fixup comments
hrtimer: fix recursion deadlock by re-introducing the softirq
hrtimer: simplify hotplug migration
hrtimer: fix HOTPLUG_CPU=n compile warning
hrtimer: splitout peek ahead functionality
| -rw-r--r-- | include/linux/interrupt.h | 3 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 142 |
2 files changed, 72 insertions, 73 deletions
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index af886b26c9d1..9127f6b51a39 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
| @@ -252,7 +252,8 @@ enum | |||
| 252 | BLOCK_SOFTIRQ, | 252 | BLOCK_SOFTIRQ, |
| 253 | TASKLET_SOFTIRQ, | 253 | TASKLET_SOFTIRQ, |
| 254 | SCHED_SOFTIRQ, | 254 | SCHED_SOFTIRQ, |
| 255 | RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ | 255 | HRTIMER_SOFTIRQ, |
| 256 | RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ | ||
| 256 | 257 | ||
| 257 | NR_SOFTIRQS | 258 | NR_SOFTIRQS |
| 258 | }; | 259 | }; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index eb2bfefa6dcc..1455b7651b6b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -634,7 +634,6 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer) | |||
| 634 | { | 634 | { |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | static void __run_hrtimer(struct hrtimer *timer); | ||
| 638 | 637 | ||
| 639 | /* | 638 | /* |
| 640 | * When High resolution timers are active, try to reprogram. Note, that in case | 639 | * When High resolution timers are active, try to reprogram. Note, that in case |
| @@ -646,13 +645,9 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 646 | struct hrtimer_clock_base *base) | 645 | struct hrtimer_clock_base *base) |
| 647 | { | 646 | { |
| 648 | if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { | 647 | if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { |
| 649 | /* | 648 | spin_unlock(&base->cpu_base->lock); |
| 650 | * XXX: recursion check? | 649 | raise_softirq_irqoff(HRTIMER_SOFTIRQ); |
| 651 | * hrtimer_forward() should round up with timer granularity | 650 | spin_lock(&base->cpu_base->lock); |
| 652 | * so that we never get into inf recursion here, | ||
| 653 | * it doesn't do that though | ||
| 654 | */ | ||
| 655 | __run_hrtimer(timer); | ||
| 656 | return 1; | 651 | return 1; |
| 657 | } | 652 | } |
| 658 | return 0; | 653 | return 0; |
| @@ -705,11 +700,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 705 | } | 700 | } |
| 706 | static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { } | 701 | static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { } |
| 707 | static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { } | 702 | static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { } |
| 708 | static inline int hrtimer_reprogram(struct hrtimer *timer, | ||
| 709 | struct hrtimer_clock_base *base) | ||
| 710 | { | ||
| 711 | return 0; | ||
| 712 | } | ||
| 713 | 703 | ||
| 714 | #endif /* CONFIG_HIGH_RES_TIMERS */ | 704 | #endif /* CONFIG_HIGH_RES_TIMERS */ |
| 715 | 705 | ||
| @@ -780,9 +770,11 @@ EXPORT_SYMBOL_GPL(hrtimer_forward); | |||
| 780 | * | 770 | * |
| 781 | * The timer is inserted in expiry order. Insertion into the | 771 | * The timer is inserted in expiry order. Insertion into the |
| 782 | * red black tree is O(log(n)). Must hold the base lock. | 772 | * red black tree is O(log(n)). Must hold the base lock. |
| 773 | * | ||
| 774 | * Returns 1 when the new timer is the leftmost timer in the tree. | ||
| 783 | */ | 775 | */ |
| 784 | static void enqueue_hrtimer(struct hrtimer *timer, | 776 | static int enqueue_hrtimer(struct hrtimer *timer, |
| 785 | struct hrtimer_clock_base *base, int reprogram) | 777 | struct hrtimer_clock_base *base) |
| 786 | { | 778 | { |
| 787 | struct rb_node **link = &base->active.rb_node; | 779 | struct rb_node **link = &base->active.rb_node; |
| 788 | struct rb_node *parent = NULL; | 780 | struct rb_node *parent = NULL; |
| @@ -814,20 +806,8 @@ static void enqueue_hrtimer(struct hrtimer *timer, | |||
| 814 | * Insert the timer to the rbtree and check whether it | 806 | * Insert the timer to the rbtree and check whether it |
| 815 | * replaces the first pending timer | 807 | * replaces the first pending timer |
| 816 | */ | 808 | */ |
| 817 | if (leftmost) { | 809 | if (leftmost) |
| 818 | /* | ||
| 819 | * Reprogram the clock event device. When the timer is already | ||
| 820 | * expired hrtimer_enqueue_reprogram has either called the | ||
| 821 | * callback or added it to the pending list and raised the | ||
| 822 | * softirq. | ||
| 823 | * | ||
| 824 | * This is a NOP for !HIGHRES | ||
| 825 | */ | ||
| 826 | if (reprogram && hrtimer_enqueue_reprogram(timer, base)) | ||
| 827 | return; | ||
| 828 | |||
| 829 | base->first = &timer->node; | 810 | base->first = &timer->node; |
| 830 | } | ||
| 831 | 811 | ||
| 832 | rb_link_node(&timer->node, parent, link); | 812 | rb_link_node(&timer->node, parent, link); |
| 833 | rb_insert_color(&timer->node, &base->active); | 813 | rb_insert_color(&timer->node, &base->active); |
| @@ -836,6 +816,8 @@ static void enqueue_hrtimer(struct hrtimer *timer, | |||
| 836 | * state of a possibly running callback. | 816 | * state of a possibly running callback. |
| 837 | */ | 817 | */ |
| 838 | timer->state |= HRTIMER_STATE_ENQUEUED; | 818 | timer->state |= HRTIMER_STATE_ENQUEUED; |
| 819 | |||
| 820 | return leftmost; | ||
| 839 | } | 821 | } |
| 840 | 822 | ||
| 841 | /* | 823 | /* |
| @@ -912,7 +894,7 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n | |||
| 912 | { | 894 | { |
| 913 | struct hrtimer_clock_base *base, *new_base; | 895 | struct hrtimer_clock_base *base, *new_base; |
| 914 | unsigned long flags; | 896 | unsigned long flags; |
| 915 | int ret; | 897 | int ret, leftmost; |
| 916 | 898 | ||
| 917 | base = lock_hrtimer_base(timer, &flags); | 899 | base = lock_hrtimer_base(timer, &flags); |
| 918 | 900 | ||
| @@ -940,12 +922,16 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n | |||
| 940 | 922 | ||
| 941 | timer_stats_hrtimer_set_start_info(timer); | 923 | timer_stats_hrtimer_set_start_info(timer); |
| 942 | 924 | ||
| 925 | leftmost = enqueue_hrtimer(timer, new_base); | ||
| 926 | |||
| 943 | /* | 927 | /* |
| 944 | * Only allow reprogramming if the new base is on this CPU. | 928 | * Only allow reprogramming if the new base is on this CPU. |
| 945 | * (it might still be on another CPU if the timer was pending) | 929 | * (it might still be on another CPU if the timer was pending) |
| 930 | * | ||
| 931 | * XXX send_remote_softirq() ? | ||
| 946 | */ | 932 | */ |
| 947 | enqueue_hrtimer(timer, new_base, | 933 | if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)) |
| 948 | new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); | 934 | hrtimer_enqueue_reprogram(timer, new_base); |
| 949 | 935 | ||
| 950 | unlock_hrtimer_base(timer, &flags); | 936 | unlock_hrtimer_base(timer, &flags); |
| 951 | 937 | ||
| @@ -1157,13 +1143,13 @@ static void __run_hrtimer(struct hrtimer *timer) | |||
| 1157 | spin_lock(&cpu_base->lock); | 1143 | spin_lock(&cpu_base->lock); |
| 1158 | 1144 | ||
| 1159 | /* | 1145 | /* |
| 1160 | * Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid | 1146 | * Note: We clear the CALLBACK bit after enqueue_hrtimer and |
| 1161 | * reprogramming of the event hardware. This happens at the end of this | 1147 | * we do not reprogramm the event hardware. Happens either in |
| 1162 | * function anyway. | 1148 | * hrtimer_start_range_ns() or in hrtimer_interrupt() |
| 1163 | */ | 1149 | */ |
| 1164 | if (restart != HRTIMER_NORESTART) { | 1150 | if (restart != HRTIMER_NORESTART) { |
| 1165 | BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); | 1151 | BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); |
| 1166 | enqueue_hrtimer(timer, base, 0); | 1152 | enqueue_hrtimer(timer, base); |
| 1167 | } | 1153 | } |
| 1168 | timer->state &= ~HRTIMER_STATE_CALLBACK; | 1154 | timer->state &= ~HRTIMER_STATE_CALLBACK; |
| 1169 | } | 1155 | } |
| @@ -1243,6 +1229,22 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1243 | } | 1229 | } |
| 1244 | } | 1230 | } |
| 1245 | 1231 | ||
| 1232 | /* | ||
| 1233 | * local version of hrtimer_peek_ahead_timers() called with interrupts | ||
| 1234 | * disabled. | ||
| 1235 | */ | ||
| 1236 | static void __hrtimer_peek_ahead_timers(void) | ||
| 1237 | { | ||
| 1238 | struct tick_device *td; | ||
| 1239 | |||
| 1240 | if (!hrtimer_hres_active()) | ||
| 1241 | return; | ||
| 1242 | |||
| 1243 | td = &__get_cpu_var(tick_cpu_device); | ||
| 1244 | if (td && td->evtdev) | ||
| 1245 | hrtimer_interrupt(td->evtdev); | ||
| 1246 | } | ||
| 1247 | |||
| 1246 | /** | 1248 | /** |
| 1247 | * hrtimer_peek_ahead_timers -- run soft-expired timers now | 1249 | * hrtimer_peek_ahead_timers -- run soft-expired timers now |
| 1248 | * | 1250 | * |
| @@ -1254,20 +1256,23 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1254 | */ | 1256 | */ |
| 1255 | void hrtimer_peek_ahead_timers(void) | ||
