linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] [PATCH 1/1] hrtimers: Cache next hrtimer
@ 2009-08-27 21:51 Ashwin Chaugule
  2009-08-27 21:56 ` Ashwin Chaugule
  0 siblings, 1 reply; 18+ messages in thread
From: Ashwin Chaugule @ 2009-08-27 21:51 UTC (permalink / raw)
  To: linux-kernel, mingo, tglx

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]



[-- Attachment #2: hrtimer-cache.patch --]
[-- Type: text/x-patch, Size: 7620 bytes --]

>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


^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2009-09-15 15:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-27 21:51 [RFC] [PATCH 1/1] hrtimers: Cache next hrtimer Ashwin Chaugule
2009-08-27 21:56 ` Ashwin Chaugule
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).