]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/hrtimer.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt
[linux-2.6-omap-h63xx.git] / kernel / hrtimer.c
index c642ef75069f28f4b230bea197dcbf86e3ea4b95..e379ef0e9c20c5e77b0003398e46eb859c6399e3 100644 (file)
@@ -1080,8 +1080,19 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base)
                         * If the timer was rearmed on another CPU, reprogram
                         * the event device.
                         */
-                       if (timer->base->first == &timer->node)
-                               hrtimer_reprogram(timer, timer->base);
+                       struct hrtimer_clock_base *base = timer->base;
+
+                       if (base->first == &timer->node &&
+                           hrtimer_reprogram(timer, base)) {
+                               /*
+                                * Timer is expired. Thus move it from tree to
+                                * pending list again.
+                                */
+                               __remove_hrtimer(timer, base,
+                                                HRTIMER_STATE_PENDING, 0);
+                               list_add_tail(&timer->cb_entry,
+                                             &base->cpu_base->cb_pending);
+                       }
                }
        }
        spin_unlock_irq(&cpu_base->lock);
@@ -1238,51 +1249,50 @@ void hrtimer_run_pending(void)
 /*
  * Called from hardirq context every jiffy
  */
-static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
-                                    int index)
+void hrtimer_run_queues(void)
 {
        struct rb_node *node;
-       struct hrtimer_clock_base *base = &cpu_base->clock_base[index];
+       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+       struct hrtimer_clock_base *base;
+       int index, gettime = 1;
 
-       if (!base->first)
+       if (hrtimer_hres_active())
                return;
 
-       if (base->get_softirq_time)
-               base->softirq_time = base->get_softirq_time();
+       for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
+               base = &cpu_base->clock_base[index];
 
-       spin_lock(&cpu_base->lock);
-
-       while ((node = base->first)) {
-               struct hrtimer *timer;
-
-               timer = rb_entry(node, struct hrtimer, node);
-               if (base->softirq_time.tv64 <= timer->expires.tv64)
-                       break;
-
-               if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
-                       __remove_hrtimer(timer, base, HRTIMER_STATE_PENDING, 0);
-                       list_add_tail(&timer->cb_entry,
-                                       &base->cpu_base->cb_pending);
+               if (!base->first)
                        continue;
+
+               if (base->get_softirq_time)
+                       base->softirq_time = base->get_softirq_time();
+               else if (gettime) {
+                       hrtimer_get_softirq_time(cpu_base);
+                       gettime = 0;
                }
 
-               __run_hrtimer(timer);
-       }
-       spin_unlock(&cpu_base->lock);
-}
+               spin_lock(&cpu_base->lock);
 
-void hrtimer_run_queues(void)
-{
-       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
-       int i;
+               while ((node = base->first)) {
+                       struct hrtimer *timer;
 
-       if (hrtimer_hres_active())
-               return;
+                       timer = rb_entry(node, struct hrtimer, node);
+                       if (base->softirq_time.tv64 <= timer->expires.tv64)
+                               break;
 
-       hrtimer_get_softirq_time(cpu_base);
+                       if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
+                               __remove_hrtimer(timer, base,
+                                       HRTIMER_STATE_PENDING, 0);
+                               list_add_tail(&timer->cb_entry,
+                                       &base->cpu_base->cb_pending);
+                               continue;
+                       }
 
-       for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
-               run_hrtimer_queue(cpu_base, i);
+                       __run_hrtimer(timer);
+               }
+               spin_unlock(&cpu_base->lock);
+       }
 }
 
 /*