From 14757677eb6c56bfef33b5ec2e5b466af8b565b8 Mon Sep 17 00:00:00 2001 From: Chris Redpath Date: Mon, 12 Jun 2017 14:33:14 +0100 Subject: [PATCH 1/3] utils/env: Move freeze/thaw_userspace methods to TestEnv from Executor It would be useful to be able to call freeze methods without needing a test class based upon Executor. Move the required methods and data. Signed-off-by: Chris Redpath --- libs/utils/env.py | 53 ++++++++++++++++++++++++++++++++++++++++++ libs/utils/executor.py | 52 ++--------------------------------------- 2 files changed, 55 insertions(+), 50 deletions(-) diff --git a/libs/utils/env.py b/libs/utils/env.py index ca025c238..22d97c49b 100644 --- a/libs/utils/env.py +++ b/libs/utils/env.py @@ -150,6 +150,33 @@ class TestEnv(ShareState): :type force_new: bool """ + critical_tasks = { + 'linux': [ + 'init', + 'systemd', + 'dbus', + 'sh', + 'ssh', + 'rsyslogd', + 'jbd2' + ], + 'android': [ + 'sh', 'adbd', + 'usb', 'transport', + # We don't actually need this task but on Google Pixel it apparently + # cannot be frozen, so the cgroup state gets stuck in FREEZING if we + # try to freeze it. + 'thermal-engine', + # Similar issue with HiKey960, the board will crash if this is frozen + # for too long. + 'watchdogd', + ] + } + """ + Dictionary mapping OS name to list of task names that we can't afford to + freeze when using freeeze_userspace. + """ + _initialized = False def __init__(self, target_conf=None, test_conf=None, wipe=True, @@ -1082,6 +1109,32 @@ class TestEnv(ShareState): def _feature(self, feature): return feature in self.conf['__features__'] + def freeze_userspace(self): + self.need_thaw = False + if 'cgroups' not in self.target.modules: + raise RuntimeError( + 'Failed to freeze userspace. Ensure "cgroups" module is listed ' + 'among modules in target/test configuration') + controllers = [s.name for s in self.target.cgroups.list_subsystems()] + if 'freezer' not in controllers: + self._log.warning('No freezer cgroup controller on target. ' + 'Not freezing userspace') + return False + + exclude = self.critical_tasks[self.target.os] + self._log.info('Freezing all tasks except: %s', ','.join(exclude)) + self.target.cgroups.freeze(exclude) + self.need_thaw = True + return True + + def thaw_userspace(self): + if self.need_thaw: + self._log.info('Un-freezing userspace tasks') + self.target.cgroups.freeze(thaw=True) + else: + self._log.error('Trying to un-freeze tasks without first freezing. ' + 'Not unfreezing userspace') + IFCFG_BCAST_RE = re.compile( r'Bcast:(.*) ' ) diff --git a/libs/utils/executor.py b/libs/utils/executor.py index bacc26a22..8ee218e80 100644 --- a/libs/utils/executor.py +++ b/libs/utils/executor.py @@ -175,33 +175,6 @@ class Executor(): """ - critical_tasks = { - 'linux': [ - 'init', - 'systemd', - 'dbus', - 'sh', - 'ssh', - 'rsyslogd', - 'jbd2' - ], - 'android': [ - 'sh', 'adbd', - 'usb', 'transport', - # We don't actually need this task but on Google Pixel it apparently - # cannot be frozen, so the cgroup state gets stuck in FREEZING if we - # try to freeze it. - 'thermal-engine', - # Similar issue with HiKey960, the board will crash if this is frozen - # for too long. - 'watchdogd', - ] - } - """ - Dictionary mapping OS name to list of task names that we can't afford to - freeze when using freeeze_userspace. - """ - def __init__(self, test_env, experiments_conf): # Initialize globals self._default_cgroup = None @@ -698,7 +671,7 @@ class Executor(): # Freeze all userspace tasks that we don't need for running tests need_thaw = False if self._target_conf_flag(tc, 'freeze_userspace'): - need_thaw = self._freeze_userspace() + need_thaw = self.te.freeze_userspace() # FTRACE: start (if a configuration has been provided) if self.te.ftrace and self._target_conf_flag(tc, 'ftrace'): @@ -734,31 +707,10 @@ class Executor(): # Unfreeze the tasks we froze if need_thaw: - self._thaw_userspace() + self.te.thaw_userspace() self._print_footer() - def _freeze_userspace(self): - if 'cgroups' not in self.target.modules: - raise RuntimeError( - 'Failed to freeze userspace. Ensure "cgroups" module is listed ' - 'among modules in target/test configuration') - controllers = [s.name for s in self.target.cgroups.list_subsystems()] - if 'freezer' not in controllers: - self._log.warning('No freezer cgroup controller on target. ' - 'Not freezing userspace') - return False - - exclude = self.critical_tasks[self.te.target.os] - self._log.info('Freezing all tasks except: %s', ','.join(exclude)) - self.te.target.cgroups.freeze(exclude) - return True - - - def _thaw_userspace(self): - self._log.info('Un-freezing userspace tasks') - self.te.target.cgroups.freeze(thaw=True) - ################################################################################ # Utility Functions ################################################################################ -- GitLab From cdf25f2961e22d5cc8b97c68c5a121a54b09adc8 Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Fri, 23 Feb 2018 14:28:12 +0000 Subject: [PATCH 2/3] utils/env: Context-manager-ify freeze/thaw_userspace() The current way of handling userspace freezing is as follows: ``` te.freeze_userspace() te.thaw_userspace() ``` Should the workload cause an issue, or should the device crash for some reason, the userspace will remain frozen and this will very likely block following test/workload executions. As such, this functionality is now squashed inside a context manager: ``` with te.freeze_userspace(): ``` This ensures that should any problem occur during the workload execution, the userspace will be thawed to restore the target to its previous status. --- libs/utils/env.py | 18 +++++++++--------- libs/utils/executor.py | 15 +++++---------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/libs/utils/env.py b/libs/utils/env.py index 22d97c49b..cda7b4ed1 100644 --- a/libs/utils/env.py +++ b/libs/utils/env.py @@ -24,6 +24,7 @@ import shutil import sys import time import unittest +import contextlib import devlib from devlib.utils.misc import memoized, which @@ -1109,31 +1110,30 @@ class TestEnv(ShareState): def _feature(self, feature): return feature in self.conf['__features__'] + @contextlib.contextmanager def freeze_userspace(self): - self.need_thaw = False if 'cgroups' not in self.target.modules: raise RuntimeError( 'Failed to freeze userspace. Ensure "cgroups" module is listed ' 'among modules in target/test configuration') + controllers = [s.name for s in self.target.cgroups.list_subsystems()] if 'freezer' not in controllers: self._log.warning('No freezer cgroup controller on target. ' 'Not freezing userspace') - return False + yield + return exclude = self.critical_tasks[self.target.os] self._log.info('Freezing all tasks except: %s', ','.join(exclude)) self.target.cgroups.freeze(exclude) - self.need_thaw = True - return True - def thaw_userspace(self): - if self.need_thaw: + try: + yield + + finally: self._log.info('Un-freezing userspace tasks') self.target.cgroups.freeze(thaw=True) - else: - self._log.error('Trying to un-freeze tasks without first freezing. ' - 'Not unfreezing userspace') IFCFG_BCAST_RE = re.compile( r'Bcast:(.*) ' diff --git a/libs/utils/executor.py b/libs/utils/executor.py index 8ee218e80..952a27962 100644 --- a/libs/utils/executor.py +++ b/libs/utils/executor.py @@ -263,7 +263,11 @@ class Executor(): self.experiments.append(exp) # WORKLOAD: execution - self._wload_run(exp_idx, exp) + if self._target_conf_flag(tc, 'freeze_userspace'): + with self.te.freeze_userspace(): + self._wload_run(exp_idx, exp) + else: + self._wload_run(exp_idx, exp) exp_idx += 1 self._target_cleanup(tc) @@ -668,11 +672,6 @@ class Executor(): self._log.debug('out_dir set to [%s]', experiment.out_dir) os.system('mkdir -p ' + experiment.out_dir) - # Freeze all userspace tasks that we don't need for running tests - need_thaw = False - if self._target_conf_flag(tc, 'freeze_userspace'): - need_thaw = self.te.freeze_userspace() - # FTRACE: start (if a configuration has been provided) if self.te.ftrace and self._target_conf_flag(tc, 'ftrace'): self._log.warning('FTrace events collection enabled') @@ -705,10 +704,6 @@ class Executor(): self._log.info(' %s', stats_file.replace(self.te.res_dir, '')) - # Unfreeze the tasks we froze - if need_thaw: - self.te.thaw_userspace() - self._print_footer() ################################################################################ -- GitLab From 0384833743c85e088868852eb4fc022a361dcb5a Mon Sep 17 00:00:00 2001 From: Chris Redpath Date: Mon, 12 Jun 2017 14:45:41 +0100 Subject: [PATCH 3/3] tests/eas/capacity_capping: add support for freezing userspace tasks A high level of tasks running during this test can cause significant disturbance as this test ensures that during a simulated thermal capping event less than 1% of the time is spent running tasks on the cpus which have been capped. In the case that the uncapped cpus are very busy, it is still reasonable to put the test tasks on the capped cpus which counts as a failure but is probably the correct schedule. Now that we have moved freezing into TestEnv, we can make direct use of it. Signed-off-by: Chris Redpath --- tests/eas/capacity_capping.config | 5 +++-- tests/eas/capacity_capping.py | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/eas/capacity_capping.config b/tests/eas/capacity_capping.config index d2515deb6..15bb4506a 100644 --- a/tests/eas/capacity_capping.config +++ b/tests/eas/capacity_capping.config @@ -5,11 +5,12 @@ "MIGRATION_WINDOW": 0.75, "EXPECTED_BUSY_TIME_PCT": 99, "TEST_CONF": { - "modules": ["bl", "cpufreq"], + "modules": ["bl", "cpufreq", "cgroups" ], "tools": ["rt-app"], "ftrace" : { "events" : ["sched_switch"], "buffsize" : 10240 - } + }, + "flags" : [ "ftrace" ] } } diff --git a/tests/eas/capacity_capping.py b/tests/eas/capacity_capping.py index 3f828e3a5..d911bfb66 100644 --- a/tests/eas/capacity_capping.py +++ b/tests/eas/capacity_capping.py @@ -83,6 +83,7 @@ class CapacityCappingTest(unittest.TestCase): """ + @classmethod def setUpClass(cls): cls.params = {} @@ -90,7 +91,8 @@ class CapacityCappingTest(unittest.TestCase): cls.trace_file = os.path.join(cls.env.res_dir, "cap_cap.dat") cls.populate_params() - cls.run_workload() + with cls.env.freeze_userspace(): + cls.run_workload() trace = trappy.FTrace(cls.trace_file) cls.sa = SchedMultiAssert(trace, cls.env.topology, -- GitLab