Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1943

kernel-2.6.18-238.el5.src.rpm

From: George Beshers <gbeshers@redhat.com>
Date: Thu, 11 Sep 2008 17:53:42 -0400
Subject: [misc] holdoffs in hrtimer_run_queues
Message-id: 20080911214233.23760.97225.sendpatchset@dhcp-100-2-194.bos.redhat.com
O-Subject: [RHEL5.3 PATCH 1/2] [v3] BZ442148: holdoffs in hrtimer_run_queues
Bugzilla: 442148
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Jason Baron <jbaron@redhat.com>

BZ#442148: holdoffs in hrtimer_run_queues on >64p systems

Upstream:
http://git2.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=833883d9ac4cfb31c1c4419335e68e6895a05b6b
http://git2.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=259aae864ceeb2b34e7bafa1ce18d096a357fab2

Brew with both patches:
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1467867

Patch 1/2:

hrtimer: reduce calls to hrtimer_get_softirq_time()

It seems that hrtimer_run_queues() is calling hrtimer_get_softirq_time() more
often than it needs to.  This can cause frequent contention on systems with
large numbers of processors/cores.

With this patch, hrtimer_run_queues only calls hrtimer_get_softirq_time() if
there is a pending timer in one of the hrtimer bases, and only once.

This also combines hrtimer_run_queues() and the inline run_hrtimer_queue()
into one function.

Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

hrtimer: optimize the softirq time optimization

The previous optimization did not take the case into account where a
clock provides its own softirq_get_time() function.

Check for the availablitiy of the clock get time function first and
then check if we need to retrieve the time for both clocks via
hrtimer_softirq_gettime() to avoid a double evaluation of time in that
case as well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 46ee71f..f543284 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -605,59 +605,61 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
 EXPORT_SYMBOL_GPL(hrtimer_get_res);
 
 /*
- * Expire the per base hrtimer-queue:
+ * Called from timer softirq every jiffy, expire hrtimers.
+ *
+ * Expire the per base hrtimer-queues:
  */
-static inline void run_hrtimer_queue(struct hrtimer_base *base)
+void hrtimer_run_queues(void)
 {
 	struct rb_node *node;
+	struct hrtimer_base *cpu_base = __get_cpu_var(hrtimer_bases);
+	struct hrtimer_base *base;
+	int index;
+	int gst = 1;
 
-	if (!base->first)
-		return;
 
-	if (base->get_softirq_time)
-		base->softirq_time = base->get_softirq_time();
+	for (index = 0; index < MAX_HRTIMER_BASES; index++) {
+		base = &cpu_base[index];
 
-	spin_lock_irq(&base->lock);
+		if (!base->first)
+			continue;
 
-	while ((node = base->first)) {
-		struct hrtimer *timer;
-		int (*fn)(struct hrtimer *);
-		int restart;
+		if (gst) {
+			hrtimer_get_softirq_time(cpu_base);
+			gst = 0;
+		}
 
-		timer = rb_entry(node, struct hrtimer, node);
-		if (base->softirq_time.tv64 <= timer->expires.tv64)
-			break;
+		if (base->get_softirq_time)
+			base->softirq_time = base->get_softirq_time();
 
-		fn = timer->function;
-		set_curr_timer(base, timer);
-		__remove_hrtimer(timer, base);
-		spin_unlock_irq(&base->lock);
+		spin_lock_irq(&base->lock);
 
-		restart = fn(timer);
+		while ((node = base->first)) {
+			struct hrtimer *timer;
+			int (*fn)(struct hrtimer *);
+			int restart;
 
-		spin_lock_irq(&base->lock);
+			timer = rb_entry(node, struct hrtimer, node);
+			if (base->softirq_time.tv64 <= timer->expires.tv64)
+				break;
 
-		if (restart != HRTIMER_NORESTART) {
-			BUG_ON(hrtimer_active(timer));
-			enqueue_hrtimer(timer, base);
-		}
-	}
-	set_curr_timer(base, NULL);
-	spin_unlock_irq(&base->lock);
-}
+			fn = timer->function;
+			set_curr_timer(base, timer);
+			__remove_hrtimer(timer, base);
+			spin_unlock_irq(&base->lock);
 
-/*
- * Called from timer softirq every jiffy, expire hrtimers:
- */
-void hrtimer_run_queues(void)
-{
-	struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
-	int i;
+			restart = fn(timer);
 
-	hrtimer_get_softirq_time(base);
+			spin_lock_irq(&base->lock);
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++)
-		run_hrtimer_queue(&base[i]);
+			if (restart != HRTIMER_NORESTART) {
+				BUG_ON(hrtimer_active(timer));
+				enqueue_hrtimer(timer, base);
+			}
+		}
+		set_curr_timer(base, NULL);
+		spin_unlock_irq(&base->lock);
+	}
 }
 
 /*