All of lore.kernel.org
 help / color / mirror / Atom feed
From: Venki Pallipadi <venkatesh.pallipadi@intel.com>
To: Len Brown <lenb@kernel.org>
Cc: Adam Belay <abelay@novell.com>, Len Brown <len.brown@intel.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@osdl.org>, Shaohua Li <shaohua.li@intel.com>,
	linux-acpi@vger.kernel.org
Subject: [PATCH 5/8] cpuidle: menu governor change the early break condition
Date: Wed, 6 Jun 2007 13:53:53 -0700	[thread overview]
Message-ID: <20070606205353.GE23906@linux-os.sc.intel.com> (raw)



Change the C-state early break out algorithm in menu governor.

We only look at early breakouts that result in wakeups shorter than idle state's
target_residency. If such a breakout is frequent enough, eliminate the
particular idle state upto a timeout period.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>

Index: linux-2.6.22-rc-mm/drivers/cpuidle/governors/menu.c
===================================================================
--- linux-2.6.22-rc-mm.orig/drivers/cpuidle/governors/menu.c	2007-06-05 09:39:27.000000000 -0700
+++ linux-2.6.22-rc-mm/drivers/cpuidle/governors/menu.c	2007-06-05 15:46:34.000000000 -0700
@@ -14,19 +14,20 @@
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 
-#define BM_HOLDOFF	20000	/* 20 ms */
+#define BM_HOLDOFF			20000	/* 20 ms */
+#define DEMOTION_THRESHOLD		5
+#define DEMOTION_TIMEOUT_MULTIPLIER	1000
 
 struct menu_device {
 	int		last_state_idx;
-	int		deepest_bm_state;
 
-	int		break_last_us;
-	int		break_elapsed_us;
+	int		deepest_break_state;
+	struct timespec break_expire_time_ts;
+	int		break_last_cnt;
 
+	int		deepest_bm_state;
 	int		bm_elapsed_us;
 	int		bm_holdoff_us;
-
-	unsigned long	idle_jiffies;
 };
 
 static DEFINE_PER_CPU(struct menu_device, menu_devices);
@@ -45,7 +46,6 @@
 
 	/* determine the expected residency time */
 	expected_us = (s32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
-	expected_us = min(expected_us, data->break_last_us);
 
 	/* determine the maximum state compatible with current BM status */
 	if (cpuidle_get_bm_activity())
@@ -53,17 +53,33 @@
 	if (data->bm_elapsed_us <= data->bm_holdoff_us)
 		max_state = data->deepest_bm_state + 1;
 
+	/* determine the maximum state compatible with recent idle breaks */
+	if (data->deepest_break_state >= 0) {
+		struct timespec now;
+		ktime_get_ts(&now);
+		if (timespec_compare(&data->break_expire_time_ts, &now) > 0) {
+			max_state = min(max_state,
+					data->deepest_break_state + 1);
+		} else {
+			data->deepest_break_state = -1;
+		}
+	}
+	
 	/* find the deepest idle state that satisfies our constraints */
 	for (i = 1; i < max_state; i++) {
 		struct cpuidle_state *s = &dev->states[i];
+
 		if (s->target_residency > expected_us)
 			break;
+
 		if (s->exit_latency > system_latency_constraint())
 			break;
 	}
 
+	if (data->last_state_idx != i - 1)
+		data->break_last_cnt = 0;
+
 	data->last_state_idx = i - 1;
-	data->idle_jiffies = tick_nohz_get_idle_jiffies();
 	return i - 1;
 }
 
@@ -91,14 +107,27 @@
 		measured_us = USEC_PER_SEC / HZ;
 
 	data->bm_elapsed_us += measured_us;
-	data->break_elapsed_us += measured_us;
+
+	if (data->last_state_idx == 0)
+		return;
 
 	/*
-	 * Did something other than the timer interrupt cause the break event?
+	 * Did something other than the timer interrupt
+	 * cause an early break event?
 	 */
-	if (tick_nohz_get_idle_jiffies() == data->idle_jiffies) {
-		data->break_last_us = data->break_elapsed_us;
-		data->break_elapsed_us = 0;
+	if (unlikely(measured_us < target->target_residency)) {
+		if (data->break_last_cnt > DEMOTION_THRESHOLD) {
+			data->deepest_break_state = data->last_state_idx - 1;
+			ktime_get_ts(&data->break_expire_time_ts);
+			timespec_add_ns(&data->break_expire_time_ts,
+						target->target_residency *
+						DEMOTION_TIMEOUT_MULTIPLIER);
+		} else {
+			data->break_last_cnt++;
+		}
+	} else {
+		if (data->break_last_cnt > 0)
+			data->break_last_cnt--;
 	}
 }
 
@@ -112,10 +141,9 @@
 	int i;
 
 	data->last_state_idx = 0;
-	data->break_last_us = 0;
-	data->break_elapsed_us = 0;
 	data->bm_elapsed_us = 0;
 	data->bm_holdoff_us = BM_HOLDOFF;
+	data->deepest_break_state = -1;
 
 	for (i = 1; i < dev->state_count; i++)
 		if (dev->states[i].flags & CPUIDLE_FLAG_CHECK_BM)

                 reply	other threads:[~2007-06-06 20:57 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20070606205353.GE23906@linux-os.sc.intel.com \
    --to=venkatesh.pallipadi@intel.com \
    --cc=abelay@novell.com \
    --cc=akpm@osdl.org \
    --cc=len.brown@intel.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=shaohua.li@intel.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.