diff --git a/config.py b/config.py index e75acc8..f6cf686 100644 --- a/config.py +++ b/config.py @@ -9,10 +9,7 @@ from typing import NamedTuple, Optional class TriggerTuple(NamedTuple): name: str interval_in_seconds: int - - -class MissingConfig(Exception): - pass + governor: str class Config: @@ -53,10 +50,12 @@ class Config: for trigger in _triggers: name = trigger.xpath('name').pop().text interval_in_seconds = trigger.xpath('intervalInSeconds').pop().text + governor = trigger.xpath('governor').pop().text ret_val.append( TriggerTuple( name=name, - interval_in_seconds=int(interval_in_seconds) + interval_in_seconds=int(interval_in_seconds), + governor=governor ) ) diff --git a/cpu_governor_auto_adjust.xml b/cpu_governor_auto_adjust.xml index 75975ea..f222d6a 100644 --- a/cpu_governor_auto_adjust.xml +++ b/cpu_governor_auto_adjust.xml @@ -6,6 +6,7 @@ roon 2 + performance diff --git a/exceptions.py b/exceptions.py new file mode 100644 index 0000000..72b44a0 --- /dev/null +++ b/exceptions.py @@ -0,0 +1,10 @@ +class TriggerImportError(Exception): + pass + + +class MissingConfig(Exception): + pass + + +class GovernorNotFound(Exception): + pass diff --git a/governor.py b/governor.py index 06dcfde..e30e939 100644 --- a/governor.py +++ b/governor.py @@ -1,17 +1,41 @@ from app_class import AppClass from config import Config -from cpufreq import cpuFreq +from cpufreq import cpuFreq, cpufreq from functools import cached_property +from mapping import governor_priority_mapping +from exceptions import GovernorNotFound +from typing import Optional class Governor(AppClass): def __init__(self, _config: Config) -> None: super().__init__(_config) + self.log.info("current governor is: %s", self.current_governor) @cached_property - def _cpufreq(self) -> cpuFreq: - return cpuFreq() + def _cpufreq(self) -> Optional[cpuFreq]: + try: + return cpuFreq() + except cpufreq.CPUFreqErrorInit: + self.log.warning("cpu architecture has no governor support") + return None + @property + def current_governor(self) -> Optional[str]: + if self._cpufreq is None: + return None + _governor = set(self._cpufreq.get_governors().values()) + _governor_to_return = list(_governor)[0] + if len(_governor) == 0: + raise GovernorNotFound("Unable to retrieve current governor") + if len(_governor) > 1: + self.log.error("multiple governors have been set, which is not expected.") + # returning governor with highest priority based on performance + for gov in _governor: + if governor_priority_mapping[gov] < governor_priority_mapping[_governor_to_return]: + _governor_to_return == gov + return _governor_to_return + def set_governor(self, governor_name: str) -> None: self.log.debug( "setting cpu governor to %s by using command self._cpufreq.set_governors(%s)", diff --git a/mapping.py b/mapping.py index 9dd8023..c9c66e8 100644 --- a/mapping.py +++ b/mapping.py @@ -1,7 +1,18 @@ from types import MappingProxyType from triggers import RoonTrigger -_dict_mapping = { +_trigger_mapping = { 'roon': RoonTrigger } -trigger_mapping = MappingProxyType(_dict_mapping) \ No newline at end of file +trigger_mapping = MappingProxyType(_trigger_mapping) + +_governor_priority_mapping = { + 'performance': 0, + 'schedutil': 1, + 'ondemand': 2, + 'conservative': 3, + 'userspace': 4, + 'performance': 5 +} + +governor_priority_mapping = MappingProxyType(_governor_priority_mapping) diff --git a/trigger.py b/trigger.py index 151d7c5..d5e69a2 100644 --- a/trigger.py +++ b/trigger.py @@ -1,9 +1,6 @@ from app_class import AppClass -from config import Config, TriggerTuple, MissingConfig - - -class TriggerImportError(Exception): - pass +from config import Config, TriggerTuple +from exceptions import MissingConfig, TriggerImportError class Trigger(AppClass):