diff --git a/profiles/latency-performance/tuned.conf b/profiles/latency-performance/tuned.conf
index 054c554..4cd69a1 100644
--- a/profiles/latency-performance/tuned.conf
+++ b/profiles/latency-performance/tuned.conf
@@ -6,7 +6,7 @@
summary=Optimize for deterministic performance at the cost of increased power consumption
[cpu]
-force_latency=1
+force_latency=cstate.id:1|1
governor=performance
energy_perf_bias=performance
min_perf_pct=100
diff --git a/profiles/sap-hana/tuned.conf b/profiles/sap-hana/tuned.conf
index 9afac82..d74250b 100644
--- a/profiles/sap-hana/tuned.conf
+++ b/profiles/sap-hana/tuned.conf
@@ -7,7 +7,7 @@ summary=Optimize for SAP HANA
include=throughput-performance
[cpu]
-force_latency=70
+force_latency=cstate.id:3|70
[vm]
transparent_hugepages=never
diff --git a/profiles/virtual-host/tuned.conf b/profiles/virtual-host/tuned.conf
index ca493d6..8acb92d 100644
--- a/profiles/virtual-host/tuned.conf
+++ b/profiles/virtual-host/tuned.conf
@@ -18,4 +18,4 @@ kernel.sched_migration_cost_ns = 5000000
[cpu]
# Setting C3 state sleep mode/power savings
-force_latency=70
+force_latency=cstate.id:3|70
diff --git a/tuned/plugins/plugin_cpu.py b/tuned/plugins/plugin_cpu.py
index 77e9448..04c7b19 100644
--- a/tuned/plugins/plugin_cpu.py
+++ b/tuned/plugins/plugin_cpu.py
@@ -12,8 +12,7 @@ import procfs
log = tuned.logs.get()
-# TODO: force_latency -> command
-# intel_pstate
+cpuidle_states_path = "/sys/devices/system/cpu/cpu0/cpuidle"
class CPULatencyPlugin(base.Plugin):
"""
@@ -210,13 +209,74 @@ class CPULatencyPlugin(base.Plugin):
def _instance_unapply_dynamic(self, instance, device):
pass
+ def _str2int(self, s):
+ try:
+ return int(s)
+ except (ValueError, TypeError):
+ return None
+
+ def _read_cstates_latency(self):
+ self.cstates_latency = {}
+ for d in os.listdir(cpuidle_states_path):
+ cstate_path = cpuidle_states_path + "/%s/" % d
+ name = self._cmd.read_file(cstate_path + "name", err_ret = None, no_error = True)
+ latency = self._cmd.read_file(cstate_path + "latency", err_ret = None, no_error = True)
+ if name is not None and latency is not None:
+ latency = self._str2int(latency)
+ if latency is not None:
+ self.cstates_latency[name.strip()] = latency
+
+ def _get_latency_by_cstate_name(self, name):
+ log.debug("getting latency for cstate with name '%s'" % name)
+ if self.cstates_latency is None:
+ log.debug("reading cstates latency table")
+ self._read_cstates_latency()
+ latency = self.cstates_latency.get(name, None)
+ log.debug("cstate name mapped to latency: %s" % str(latency))
+ return latency
+
+ def _get_latency_by_cstate_id(self, lid):
+ log.debug("getting latency for cstate with ID '%s'" % str(lid))
+ lid = self._str2int(lid)
+ if lid is None:
+ log.debug("cstate ID is invalid")
+ return None
+ latency_path = cpuidle_states_path + "/%s/latency" % ("state%d" % lid)
+ latency = self._str2int(self._cmd.read_file(latency_path, err_ret = None, no_error = True))
+ log.debug("cstate ID mapped to latency: %s" % str(latency))
+ return latency
+
+ def _parse_latency(self, latency):
+ self.cstates_latency = None
+ latencies = str(latency).split("|")
+ log.debug("parsing latency")
+ for latency in latencies:
+ try:
+ latency = int(latency)
+ log.debug("parsed directly specified latency value: %d" % latency)
+ except ValueError:
+ if latency[0:10] == "cstate.id:":
+ latency = self._get_latency_by_cstate_id(latency[10:])
+ elif latency[0:12] == "cstate.name:":
+ latency = self._get_latency_by_cstate_name(latency[12:])
+ else:
+ latency = None
+ log.debug("invalid latency specified: '%s'" % str(latency))
+ if latency is not None:
+ break
+ return latency
+
def _set_latency(self, latency):
- latency = int(latency)
- if self._has_pm_qos and self._latency != latency:
- log.info("setting new cpu latency %d" % latency)
- latency_bin = struct.pack("i", latency)
- os.write(self._cpu_latency_fd, latency_bin)
- self._latency = latency
+ latency = self._parse_latency(latency)
+ if self._has_pm_qos:
+ if latency is None:
+ log.error("unable to evaluate latency value (probably wrong settings in the 'cpu' section of current profile), disabling PM QoS")
+ self._has_pm_qos = False
+ elif self._latency != latency:
+ log.info("setting new cpu latency %d" % latency)
+ latency_bin = struct.pack("i", latency)
+ os.write(self._cpu_latency_fd, latency_bin)
+ self._latency = latency
def _get_available_governors(self, device):
return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split()