Merge branch 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Sep 2009 17:39:04 +0000 (10:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Sep 2009 17:39:04 +0000 (10:39 -0700)
* '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

1  2 
kernel/hrtimer.c

diff --combined kernel/hrtimer.c
@@@ -48,8 -48,6 +48,8 @@@
  
  #include <asm/uaccess.h>
  
 +#include <trace/events/timer.h>
 +
  /*
   * The timer bases:
   *
@@@ -431,7 -429,6 +431,7 @@@ void hrtimer_init_on_stack(struct hrtim
        debug_object_init_on_stack(timer, &hrtimer_debug_descr);
        __hrtimer_init(timer, clock_id, mode);
  }
 +EXPORT_SYMBOL_GPL(hrtimer_init_on_stack);
  
  void destroy_hrtimer_on_stack(struct hrtimer *timer)
  {
@@@ -444,26 -441,6 +444,26 @@@ static inline void debug_hrtimer_activa
  static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
  #endif
  
 +static inline void
 +debug_init(struct hrtimer *timer, clockid_t clockid,
 +         enum hrtimer_mode mode)
 +{
 +      debug_hrtimer_init(timer);
 +      trace_hrtimer_init(timer, clockid, mode);
 +}
 +
 +static inline void debug_activate(struct hrtimer *timer)
 +{
 +      debug_hrtimer_activate(timer);
 +      trace_hrtimer_start(timer);
 +}
 +
 +static inline void debug_deactivate(struct hrtimer *timer)
 +{
 +      debug_hrtimer_deactivate(timer);
 +      trace_hrtimer_cancel(timer);
 +}
 +
  /* High resolution timer related functions */
  #ifdef CONFIG_HIGH_RES_TIMERS
  
@@@ -509,13 -486,14 +509,14 @@@ static inline int hrtimer_hres_active(v
   * next event
   * Called with interrupts disabled and base->lock held
   */
- static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
+ static void
+ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
  {
        int i;
        struct hrtimer_clock_base *base = cpu_base->clock_base;
-       ktime_t expires;
+       ktime_t expires, expires_next;
  
-       cpu_base->expires_next.tv64 = KTIME_MAX;
+       expires_next.tv64 = KTIME_MAX;
  
        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
                struct hrtimer *timer;
                 */
                if (expires.tv64 < 0)
                        expires.tv64 = 0;
-               if (expires.tv64 < cpu_base->expires_next.tv64)
-                       cpu_base->expires_next = expires;
+               if (expires.tv64 < expires_next.tv64)
+                       expires_next = expires;
        }
  
+       if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64)
+               return;
+       cpu_base->expires_next.tv64 = expires_next.tv64;
        if (cpu_base->expires_next.tv64 != KTIME_MAX)
                tick_program_event(cpu_base->expires_next, 1);
  }
@@@ -617,7 -600,7 +623,7 @@@ static void retrigger_next_event(void *
        base->clock_base[CLOCK_REALTIME].offset =
                timespec_to_ktime(realtime_offset);
  
-       hrtimer_force_reprogram(base);
+       hrtimer_force_reprogram(base, 0);
        spin_unlock(&base->lock);
  }
  
@@@ -730,7 -713,8 +736,8 @@@ static int hrtimer_switch_to_hres(void
  static inline int hrtimer_hres_active(void) { return 0; }
  static inline int hrtimer_is_hres_enabled(void) { return 0; }
  static inline int hrtimer_switch_to_hres(void) { return 0; }
- static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
+ static inline void
+ hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
  static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                                            struct hrtimer_clock_base *base,
                                            int wakeup)
@@@ -820,7 -804,7 +827,7 @@@ static int enqueue_hrtimer(struct hrtim
        struct hrtimer *entry;
        int leftmost = 1;
  
 -      debug_hrtimer_activate(timer);
 +      debug_activate(timer);
  
        /*
         * Find the right place in the rbtree:
@@@ -873,19 -857,29 +880,29 @@@ static void __remove_hrtimer(struct hrt
                             struct hrtimer_clock_base *base,
                             unsigned long newstate, int reprogram)
  {
-       if (timer->state & HRTIMER_STATE_ENQUEUED) {
-               /*
-                * Remove the timer from the rbtree and replace the
-                * first entry pointer if necessary.
-                */
-               if (base->first == &timer->node) {
-                       base->first = rb_next(&timer->node);
-                       /* Reprogram the clock event device. if enabled */
-                       if (reprogram && hrtimer_hres_active())
-                               hrtimer_force_reprogram(base->cpu_base);
+       if (!(timer->state & HRTIMER_STATE_ENQUEUED))
+               goto out;
+       /*
+        * Remove the timer from the rbtree and replace the first
+        * entry pointer if necessary.
+        */
+       if (base->first == &timer->node) {
+               base->first = rb_next(&timer->node);
+ #ifdef CONFIG_HIGH_RES_TIMERS
+               /* Reprogram the clock event device. if enabled */
+               if (reprogram && hrtimer_hres_active()) {
+                       ktime_t expires;
+                       expires = ktime_sub(hrtimer_get_expires(timer),
+                                           base->offset);
+                       if (base->cpu_base->expires_next.tv64 == expires.tv64)
+                               hrtimer_force_reprogram(base->cpu_base, 1);
                }
-               rb_erase(&timer->node, &base->active);
+ #endif
        }
+       rb_erase(&timer->node, &base->active);
+ out:
        timer->state = newstate;
  }
  
@@@ -906,7 -900,7 +923,7 @@@ remove_hrtimer(struct hrtimer *timer, s
                 * reprogramming happens in the interrupt handler. This is a
                 * rare case and less expensive than a smp call.
                 */
 -              debug_hrtimer_deactivate(timer);
 +              debug_deactivate(timer);
                timer_stats_hrtimer_clear_start_info(timer);
                reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
                __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
@@@ -1139,7 -1133,7 +1156,7 @@@ static void __hrtimer_init(struct hrtim
  void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
                  enum hrtimer_mode mode)
  {
 -      debug_hrtimer_init(timer);
 +      debug_init(timer, clock_id, mode);
        __hrtimer_init(timer, clock_id, mode);
  }
  EXPORT_SYMBOL_GPL(hrtimer_init);
@@@ -1163,7 -1157,7 +1180,7 @@@ int hrtimer_get_res(const clockid_t whi
  }
  EXPORT_SYMBOL_GPL(hrtimer_get_res);
  
 -static void __run_hrtimer(struct hrtimer *timer)
 +static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
  {
        struct hrtimer_clock_base *base = timer->base;
        struct hrtimer_cpu_base *cpu_base = base->cpu_base;
  
        WARN_ON(!irqs_disabled());
  
 -      debug_hrtimer_deactivate(timer);
 +      debug_deactivate(timer);
        __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
        timer_stats_account_hrtimer(timer);
        fn = timer->function;
         * the timer base.
         */
        spin_unlock(&cpu_base->lock);
 +      trace_hrtimer_expire_entry(timer, now);
        restart = fn(timer);
 +      trace_hrtimer_expire_exit(timer);
        spin_lock(&cpu_base->lock);
  
        /*
@@@ -1296,7 -1288,7 +1313,7 @@@ void hrtimer_interrupt(struct clock_eve
                                break;
                        }
  
 -                      __run_hrtimer(timer);
 +                      __run_hrtimer(timer, &basenow);
                }
                base++;
        }
@@@ -1418,7 -1410,7 +1435,7 @@@ void hrtimer_run_queues(void
                                        hrtimer_get_expires_tv64(timer))
                                break;
  
 -                      __run_hrtimer(timer);
 +                      __run_hrtimer(timer, &base->softirq_time);
                }
                spin_unlock(&cpu_base->lock);
        }
@@@ -1445,7 -1437,6 +1462,7 @@@ void hrtimer_init_sleeper(struct hrtime
        sl->timer.function = hrtimer_wakeup;
        sl->task = task;
  }
 +EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
  
  static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
  {
@@@ -1595,7 -1586,7 +1612,7 @@@ static void migrate_hrtimer_list(struc
        while ((node = rb_first(&old_base->active))) {
                timer = rb_entry(node, struct hrtimer, node);
                BUG_ON(hrtimer_callback_running(timer));
 -              debug_hrtimer_deactivate(timer);
 +              debug_deactivate(timer);
  
                /*
                 * Mark it as STATE_MIGRATE not INACTIVE otherwise the