All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ashwin Chaugule <ashwinc@codeaurora.org>
To: linux-kernel@vger.kernel.org, mingo@redhat.com, tglx@linutronix.de
Subject: Re: [RFC] [PATCH 1/1] hrtimers: Cache next hrtimer
Date: Thu, 27 Aug 2009 17:56:19 -0400	[thread overview]
Message-ID: <4A970103.7010804@codeaurora.org> (raw)
In-Reply-To: <4A96FFE9.6060105@codeaurora.org>

Resending. This time with patch inlined.

 From 6558900969ef1f4492aad4d9a2a87cd8900dee92 Mon Sep 17 00:00:00 2001
From: Ashwin Chaugule <ashwinc@quicinc.com>
Date: Thu, 27 Aug 2009 10:42:48 -0400
Subject: [PATCH][hrtimers]  Cache next hrtimer

    Cached the hrtimer which causes the expire_next
    value to change. This is to avoid unnecessary re-programming
    of the clock events device.

    modified:   include/linux/hrtimer.h
    modified:   kernel/hrtimer.c

    Signed-off-by: Ashwin Chaugule <ashwinc@quicinc.com>
---
 include/linux/hrtimer.h |    5 ++-
 kernel/hrtimer.c        |   81 
+++++++++++++++++++++++++++++++---------------
 2 files changed, 58 insertions(+), 28 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index bd37078..dd8fa9b 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -4,7 +4,8 @@
  *  hrtimers - High-resolution kernel timers
  *
  *   Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
- *   Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *   Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *   Copyright(C) 2009, Code Aurora Forum. All rights reserved.
  *
  *  data type definitions, declarations, prototypes
  *
@@ -157,6 +158,7 @@ struct hrtimer_clock_base {
  *            and timers
  * @clock_base:        array of clock bases for this cpu
  * @curr_timer:        the timer which is executing a callback right now
+ * @next_hrtimer:    the hrtimer that caused expires_next to change
  * @expires_next:    absolute time of the next event which was scheduled
  *            via clock_set_next_event()
  * @hres_active:    State of high resolution mode
@@ -169,6 +171,7 @@ struct hrtimer_cpu_base {
     spinlock_t            lock;
     struct hrtimer_clock_base    clock_base[HRTIMER_MAX_CLOCK_BASES];
 #ifdef CONFIG_HIGH_RES_TIMERS
+    struct hrtimer             *next_hrtimer;
     ktime_t                expires_next;
     int                hres_active;
     unsigned long            nr_events;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f394d2a..d823987 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -4,6 +4,8 @@
  *  Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
  *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
  *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner
+ *  Copyright(C) 2009, Code Aurora Forum. All rights reserved.
+ *
  *
  *  High-resolution kernel timers
  *
@@ -508,8 +510,10 @@ static void hrtimer_force_reprogram(struct 
hrtimer_cpu_base *cpu_base)
          */
         if (expires.tv64 < 0)
             expires.tv64 = 0;
-        if (expires.tv64 < cpu_base->expires_next.tv64)
+        if (expires.tv64 < cpu_base->expires_next.tv64) {
             cpu_base->expires_next = expires;
+            cpu_base->next_hrtimer = timer;
+        }
     }
 
     if (cpu_base->expires_next.tv64 != KTIME_MAX)
@@ -529,6 +533,7 @@ static int hrtimer_reprogram(struct hrtimer *timer,
                  struct hrtimer_clock_base *base)
 {
     ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next;
+    struct hrtimer *next_hrtimer = 
__get_cpu_var(hrtimer_bases).next_hrtimer;
     ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
     int res;
 
@@ -560,8 +565,10 @@ static int hrtimer_reprogram(struct hrtimer *timer,
      * Clockevents returns -ETIME, when the event was in the past.
      */
     res = tick_program_event(expires, 0);
-    if (!IS_ERR_VALUE(res))
+    if (!IS_ERR_VALUE(res)) {
         *expires_next = expires;
+        next_hrtimer = timer;
+    }
     return res;
 }
 
@@ -634,6 +641,7 @@ static inline void hrtimer_init_hres(struct 
hrtimer_cpu_base *base)
 {
     base->expires_next.tv64 = KTIME_MAX;
     base->hres_active = 0;
+    base->next_hrtimer = NULL;
 }
 
 /*
@@ -843,16 +851,20 @@ static void __remove_hrtimer(struct hrtimer *timer,
                  struct hrtimer_clock_base *base,
                  unsigned long newstate, int reprogram)
 {
-    if (timer->state & HRTIMER_STATE_ENQUEUED) {
+    struct hrtimer *next_hrtimer = 
__get_cpu_var(hrtimer_bases).next_hrtimer;
+
+    if (hrtimer_is_queued(timer)) {
         /*
          * 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 (next_hrtimer == timer) {
+                /* Reprogram the clock event device. if enabled */
+                if (reprogram && hrtimer_hres_active())
+                    hrtimer_force_reprogram(base->cpu_base);
+            }
         }
         rb_erase(&timer->node, &base->active);
     }
@@ -865,25 +877,22 @@ static void __remove_hrtimer(struct hrtimer *timer,
 static inline int
 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
-    if (hrtimer_is_queued(timer)) {
-        int reprogram;
+    int reprogram;
 
-        /*
-         * Remove the timer and force reprogramming when high
-         * resolution mode is active and the timer is on the current
-         * CPU. If we remove a timer on another CPU, reprogramming is
-         * skipped. The interrupt event on this CPU is fired and
-         * reprogramming happens in the interrupt handler. This is a
-         * rare case and less expensive than a smp call.
-         */
-        debug_hrtimer_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,
-                 reprogram);
-        return 1;
-    }
-    return 0;
+    /*
+     * Remove the timer and force reprogramming when high
+     * resolution mode is active and the timer is on the current
+     * CPU. If we remove a timer on another CPU, reprogramming is
+     * skipped. The interrupt event on this CPU is fired and
+     * reprogramming happens in the interrupt handler. This is a
+     * rare case and less expensive than a smp call.
+     */
+    debug_hrtimer_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,
+            reprogram);
+    return 1;
 }
 
 /**
@@ -903,12 +912,26 @@ hrtimer_start_range_ns(struct hrtimer *timer, 
ktime_t tim, unsigned long delta_n
 {
     struct hrtimer_clock_base *base, *new_base;
     unsigned long flags;
-    int ret, leftmost;
+    int ret = 0;
+        int leftmost;
 
     base = lock_hrtimer_base(timer, &flags);
 
     /* Remove an active timer from the queue: */
-    ret = remove_hrtimer(timer, base);
+    if (hrtimer_is_queued(timer)) {
+        if (timer == __get_cpu_var(hrtimer_bases).next_hrtimer)
+            ret = remove_hrtimer(timer, base);
+        else {
+            debug_hrtimer_deactivate(timer);
+            timer_stats_hrtimer_clear_start_info(timer);
+            if (base->first == &timer->node) {
+                base->first = rb_next(&timer->node);
+            }
+            rb_erase(&timer->node, &base->active);
+            timer->state = HRTIMER_STATE_INACTIVE;
+            ret = 1;
+        }
+    }
 
     /* Switch the timer base, if necessary: */
     new_base = switch_hrtimer_base(timer, base);
@@ -1196,6 +1219,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 {
     struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
     struct hrtimer_clock_base *base;
+    struct hrtimer *next_hrtimer = NULL;
     ktime_t expires_next, now;
     int nr_retries = 0;
     int i;
@@ -1246,8 +1270,10 @@ void hrtimer_interrupt(struct clock_event_device 
*dev)
 
                 expires = ktime_sub(hrtimer_get_expires(timer),
                             base->offset);
-                if (expires.tv64 < expires_next.tv64)
+                if (expires.tv64 < expires_next.tv64) {
                     expires_next = expires;
+                    next_hrtimer = timer;
+                }
                 break;
             }
 
@@ -1258,6 +1284,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
     }
 
     cpu_base->expires_next = expires_next;
+    cpu_base->next_hrtimer = next_hrtimer;
 
     /* Reprogramming necessary ? */
     if (expires_next.tv64 != KTIME_MAX) {
-- 
1.5.6.3


  reply	other threads:[~2009-08-27 21:56 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-27 21:51 [RFC] [PATCH 1/1] hrtimers: Cache next hrtimer Ashwin Chaugule
2009-08-27 21:56 ` Ashwin Chaugule [this message]
2009-08-27 22:51   ` Thomas Gleixner
2009-08-27 23:09     ` Ashwin Chaugule
2009-08-27 23:16       ` Thomas Gleixner
2009-08-28  5:56         ` Ashwin Chaugule
2009-08-28 11:17           ` Thomas Gleixner
2009-08-28 16:34             ` Ashwin Chaugule
2009-08-28 18:19               ` Thomas Gleixner
2009-08-28 20:27                 ` Ashwin Chaugule
2009-08-30  6:06                 ` Ashwin Chaugule
2009-08-30  8:36                   ` Thomas Gleixner
2009-08-31  4:17                     ` Ashwin Chaugule
2009-08-31  7:08                       ` Thomas Gleixner
2009-09-01  3:13                         ` Ashwin Chaugule
2009-09-03 17:48                         ` Ashwin Chaugule
2009-09-15  9:09                           ` [tip:timers/core] hrtimer: Eliminate needless reprogramming of clock events device tip-bot for Ashwin Chaugule
2009-09-15 15:19                           ` tip-bot for Ashwin Chaugule

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A970103.7010804@codeaurora.org \
    --to=ashwinc@codeaurora.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.