[PATCH] sched: mc/smt power savings sched policy

S.Çağlar Onur caglar at pardus.org.tr
Mon Jun 11 13:01:23 PDT 2007


Hi;

Following patch tries to add GetSchedPowerSavings/SetSchedPowerSavings methods 
to cpufreq-addon. 

This patch is nothing but a "i want to hear your comments one" :), so if this 
is acceptable i want to provide another patch in future to introduce CPU 
online/offlining with HAL, so kpowersave/gnome-power-manager can provide 
these features to users also.

For reference, "power savings sched policy" introduces following 
[@http://kernelnewbies.org/Linux_2_6_18]

Process scheduler

In machines with several multi core/smt "packages" (which will become 
increasingly common in the future), the power consumption can be improved by 
letting some packages idle while others do all the work, instead of spreading 
the tasks over all CPUs, so a optional power saving policy has been developed 
to make this possible. When this power savings policy is enabled - set to 1 
the sysfs entry 'sched_mc_power_savings' or 'sched_smt_power_savings' placed 
under /sys/devices/system/cpu/cpuX/ when enabled CONFIG_SCHED_MC / 
CONFIG_SCHED_SMT - and under light load conditions, the scheduler will 
minimize the physical packages/cpu cores carrying the load and thus 
conserving power, but impacting the performance depending on the workload 
characteristics (when there's lot of work to do all CPUs will be used, to 
completely disable individual CPUs use the already available CPU hot plugging 
feature by writing 0 to the "online" file in that sysfs directory). For more 
details on the effect of this policy read the "Chip Multi Processing (CMP) 
aware Linux Kernel Scheduler" talk from the OLS 2005 (page 201 and onwards) 
(commit)

And here it is;

diff --git a/hald/linux/addons/addon-cpufreq.c 
b/hald/linux/addons/addon-cpufreq.c
index b10edf9..c7e7c74 100644
--- a/hald/linux/addons/addon-cpufreq.c
+++ b/hald/linux/addons/addon-cpufreq.c
@@ -67,6 +67,12 @@ const char SYSFS_CPU_ONLINE_FILE[] =
 const char ONDEMAND_IGNORE_NICE_LOAD_FILE[] =
      "/sys/devices/system/cpu/cpu%u/cpufreq/ondemand/ignore_nice_load";
 
+const char SYSFS_SCHED_MC_POWER_SAVINGS_FILE[] =
+	 "/sys/devices/system/cpu/sched_mc_power_savings";
+
+const char SYSFS_SCHED_SMT_POWER_SAVINGS_FILE[] =
+	 "/sys/devices/system/cpu/sched_smt_power_savings";
+	 
 static gboolean dbus_raise_error(DBusConnection *connection, DBusMessage 
*message,
 				 const char *error_name, char *format, ...);
 
@@ -816,6 +822,80 @@ static gboolean get_governors(DBusConnection *connection, 
DBusMessage *message,
 
 	return TRUE;
 }
+
+/** 
+ * set_sched_power_savings:
+ * @connection:		connection to D-Bus
+ * @message:		Message
+ * @sched_power_savings:	pointer to return the current power savings value
+ * Returns: 		TRUE/FALSE
+ *
+ * @raises GeneralError
+ * 
+ * sets the MC/SMT power savings policy for the scheduler.
+ */
+ static gboolean set_sched_power_savings(DBusConnection *connection, 
DBusMessage *message,
+				int *sched_power_savings)
+{
+	int		status;
+	int		num_cpus;
+
+ 	num_cpus = sysconf(_SC_NPROCESSORS_CONF);
+	if (num_cpus < 2) {
+		dbus_raise_error(connection, message, CPUFREQ_ERROR_GENERAL,
+				 "No MC/SMT capable CPUs found in system");
+		HAL_WARNING(("No MC/SMT CPUs found in system"));
+		return FALSE;
+	}	
+	/* FIXME: Detect the topology properly instead of trying */
+	if (!write_line(SYSFS_SCHED_MC_POWER_SAVINGS_FILE, "%u", 
sched_power_savings)) {
+		if (!write_line(SYSFS_SCHED_SMT_POWER_SAVINGS_FILE, "%u", 
sched_power_savings)) {
+			dbus_raise_error(connection, message, CPUFREQ_ERROR_GENERAL,
+				 "Could not set current power savings policy for the scheduler");
+			return FALSE;
+		}
+	}
+	
+	return TRUE;
+}
+
+/** 
+ * get_sched_power_savings:
+ * @connection:		connection to D-Bus
+ * @message:		Message
+ * @sched_power_savings:	pointer to return the current power savings value
+ * Returns: 		TRUE/FALSE
+ *
+ * @raises GeneralError
+ * 
+ * gets the MC/SMT power savings policy for the scheduler.
+ */
+ static gboolean get_sched_power_savings(DBusConnection *connection, 
DBusMessage *message,
+				int *sched_power_savings)
+{
+	int		status;
+	int		num_cpus;
+	
+ 	num_cpus = sysconf(_SC_NPROCESSORS_CONF);
+	if (num_cpus < 2) {
+		dbus_raise_error(connection, message, CPUFREQ_ERROR_GENERAL,
+				 "No MC/SMT capable CPUs found in system");
+		HAL_WARNING(("No MC/SMT CPUs found in system"));
+		return FALSE;
+	}	
+
+	/* FIXME: Detect the topology properly instead of trying */
+	if (!read_line_int(SYSFS_SCHED_MC_POWER_SAVINGS_FILE, &status)) { 
+		if (!read_line_int(SYSFS_SCHED_SMT_POWER_SAVINGS_FILE, &status)) {
+			dbus_raise_error(connection, message, CPUFREQ_ERROR_GENERAL,
+				 "Could not read current power savings policy for the scheduler");
+			return FALSE;
+		}
+	}
+	*sched_power_savings = (int)status;
+	
+	return TRUE;
+}
 /********************* main interface end *********************/
 
 /********************* DBus stuff *********************/
@@ -1146,6 +1226,19 @@ static DBusHandlerResult 
dbus_filter_function(DBusConnection *connection,
 			dbus_send_reply(connection, message, DBUS_TYPE_INVALID, NULL);
 
 	} else if (dbus_message_is_method_call(message, DBUS_INTERFACE,
+					       "SetSchedPowerSavings")) {
+		int arg;
+
+		if (!dbus_get_argument(connection, message, &dbus_error,
+				       DBUS_TYPE_INT32, &arg)) {
+			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+		}
+ 		HAL_DEBUG(("Received argument: %d", arg));
+
+		if (set_sched_power_savings(connection, message, arg))
+			dbus_send_reply(connection, message, DBUS_TYPE_INVALID, NULL);
+
+	} else if (dbus_message_is_method_call(message, DBUS_INTERFACE,
 					       "GetCPUFreqGovernor")) {
 		char governor[MAX_LINE_SIZE + 1];
 		char *gov				= governor;
@@ -1174,7 +1267,14 @@ static DBusHandlerResult 
dbus_filter_function(DBusConnection *connection,
 		if (get_available_governors(connection, message, &governors))
 			dbus_send_reply_strlist(connection, message, governors);
 		g_strfreev(governors);
-
+		
+	} else if (dbus_message_is_method_call(message, DBUS_INTERFACE,
+					       "GetSchedPowerSavings")) {
+		int sched_power_savings = -1;
+		
+		if (get_sched_power_savings(connection, message, &sched_power_savings))
+			dbus_send_reply(connection, message, DBUS_TYPE_INT32, 
&sched_power_savings);
+			
 	} else {
 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 	}
@@ -1250,6 +1350,9 @@ gboolean dbus_init(void)
 		"    <method name=\"SetCPUFreqConsiderNice\">\n"
 		"      <arg name=\"value\" direction=\"in\" type=\"b\"/>\n"
 		"    </method>\n"
+		"    <method name=\"SetSchedPowerSavings\">\n"
+		"      <arg name=\"value\" direction=\"in\" type=\"i\"/>\n"
+		"    </method>\n"
 		"    <method name=\"GetCPUFreqGovernor\">\n"
 		"      <arg name=\"return_code\" direction=\"out\" type=\"s\"/>\n"
 		"    </method>\n"
@@ -1261,6 +1364,9 @@ gboolean dbus_init(void)
 		"    </method>\n"
 		"    <method name=\"GetCPUFreqAvailableGovernors\">\n"
 		"      <arg name=\"return_code\" direction=\"out\" type=\"as\"/>\n"
+		"    </method>\n"
+		"    <method name=\"GetSchedPowerSavings\">\n"
+		"      <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
 		"    </method>\n",
 		&dbus_error)) {
 


Cheers
-- 
S.Çağlar Onur <caglar at pardus.org.tr>
http://cekirdek.pardus.org.tr/~caglar/

Linux is like living in a teepee. No Windows, no Gates and an Apache in house!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url : http://lists.freedesktop.org/archives/hal/attachments/20070611/90094da1/attachment.pgp 


More information about the hal mailing list