1ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# SPDX-License-Identifier: Apache-2.0
2ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi#
3ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Copyright (C) 2015, ARM Limited and contributors.
4ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi#
5ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Licensed under the Apache License, Version 2.0 (the "License"); you may
6ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# not use this file except in compliance with the License.
7ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# You may obtain a copy of the License at
8ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi#
9ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# http://www.apache.org/licenses/LICENSE-2.0
10ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi#
11ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Unless required by applicable law or agreed to in writing, software
12ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# See the License for the specific language governing permissions and
15ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# limitations under the License.
16ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi#
17ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
18ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasifrom bart.common.Analyzer import Analyzer
19ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport collections
200328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackmanfrom collections import namedtuple
21ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport datetime
22ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport gzip
23ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport json
24ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport os
25ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport re
26ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport time
27ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport trappy
28204f03bccbd5482e459ceb46b397875956c63da5Chris Redpathfrom devlib import TargetError
29ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
30ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Configure logging
31ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport logging
32ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
33ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Add JSON parsing support
34ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasifrom conf import JsonConf
35ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
36ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiimport wlgen
37ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
389ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackmanfrom devlib import TargetError
399ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman
400328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan JackmanExperiment = namedtuple('Experiment', ['wload_name', 'wload',
410328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                                       'conf', 'iteration', 'out_dir'])
420328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman
43ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasiclass Executor():
447b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    """
457b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    Abstraction for running sets of experiments and gathering data from targets
467b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
477b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    An executor can be configured to run a set of workloads (wloads) in each
487b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    different target configuration of a specified set (confs). These wloads and
497b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    confs can be specified by the "experiments_conf" input dictionary. Each
507b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    (workload, conf, iteration) tuple is called an "experiment".
517b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
527b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    After the workloads have been run, the Executor object's `experiments`
537b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    attribute is a list of Experiment objects. The `out_dir` attribute of these
547b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    objects can be used to find the results of the experiment. This output
557b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    directory follows this format:
567b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
577b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        results/<test_id>/<wltype>:<conf>:<wload>/<run_id>
587b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
597b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    where:
607b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
617b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        test_id
627b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Is the "tid" defined by the experiments_conf, or a timestamp based
637b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            folder in case "tid" is not specified.
647b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        wltype
657b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Is the class of workload executed, e.g. rtapp or sched_perf.
667b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        conf
677b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Is the "tag" of one of the specified **confs**.
687b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        wload
697b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Is the identifier of one of the specified **wloads**.
707b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        run_id
717b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Is the progressive execution number from 1 up to the specified
727b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            **iterations**.
737b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
747b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    :param experiments_conf: Dict with experiment configuration. Keys are:
757b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
767b764f318505bd13991b37d650cf3b512531a872Brendan Jackman        **confs**
777b764f318505bd13991b37d650cf3b512531a872Brendan Jackman          Mandatory. Platform configurations to be tested. List of dicts,
787b764f318505bd13991b37d650cf3b512531a872Brendan Jackman          each with keys:
797b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
807b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            tag
817b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              String to identify this configuration. Required, may be empty.
827b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            flags
837b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              List of strings describing features required for this
847b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              conf. Available flags are:
857b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
867b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              "ftrace"
877b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  Enable collecting ftrace during the experiment.
887b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              "freeze_userspace"
897b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  Use the cgroups freezer to freeze as many userspace tasks as
907b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  possible during the experiment execution, in order to reduce
917b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  system noise. Some tasks cannot be frozen, such as those
927b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  required to maintain a connection to LISA.
937b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
947b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            sched_features
957b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              Optional list of features to be written to
967b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              /sys/kernel/debug/sched_features. Prepend "NO\_" to a feature to
977b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              actively disable it. Requires ``CONFIG_SCHED_DEBUG`` in target
987b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              kernel.
997b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            cpufreq
1007b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              Parameters to configure cpufreq via Devlib's cpufreq
1017b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              module. Dictionary with fields:
1027b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1037b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              .. TODO link to devlib cpufreq module docs (which don't exist)
1047b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1057b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              governor
1067b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                cpufreq governor to set (for all CPUs) before execution. The
1077b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                previous governor is not restored when execution is finished.
1087b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              governor_tunables
1097b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                Dictionary of governor-specific tunables, expanded and passed as
1107b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                kwargs to the cpufreq module's ``set_governor_tunables`` method.
1117b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              freq
1127b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                Requires "governor" to be "userspace". Dictionary mapping CPU
1137b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                numbers to frequencies. Exact frequencies should be available on
1147b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                those CPUs. It is not necessary to provide a frequency for every
1157b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                CPU - the frequency for unspecified CPUs is not affected. Note
1167b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                that cpufreq will transparrently set the frequencies of any
1177b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                other CPUs sharing a clock domain.
1187b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1197b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            cgroups
1207b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              Optional cgroups configuration. To use this, ensure the 'cgroups'
1217b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              devlib module is enabled in your test_conf Contains fields:
1227b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1237b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              .. TODO reference test_conf
1247b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              .. TODO link to devlib cgroup module's docs (which don't exist)
1257b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1267b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              conf
1277b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                Dict specifying the cgroup controllers, cgroups, and cgroup
1287b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                parameters to setup. If a controller listed here is not
1297b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                enabled in the target kernel, a message is logged and the
1307b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                configuration is **ignored**. Of the form:
1317b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1327b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                ::
1337b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1347b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  "<controller>" : {
1357b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                      "<group1>" : { "<group_param" : <value> }
1367b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                      "<group2>" : { "<group_param" : <value> }
1377b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                  }
1387b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1397b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                These cgroups can then be used in the "cgroup" field of workload
1407b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                specifications.
1417b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1427b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              default
1437b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                The default cgroup to run workloads in, if no "cgroup" is
1447b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                specified.
1457b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1467b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              For example, to create a cpuset cgroup named "/big" which
1477b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              restricts constituent tasks to CPUs 1 and 2:
1487b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1497b764f318505bd13991b37d650cf3b512531a872Brendan Jackman              ::
1507b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1517b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                "cgroups" : {
1527b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                    "conf" : {
1537b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                        "cpuset" : {
1547b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                            "/big" : {"cpus" : "1-2"},
1557b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                        }
1567b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                    },
1577b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                    "default" : "/",
1587b764f318505bd13991b37d650cf3b512531a872Brendan Jackman                }
1597b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1607b764f318505bd13991b37d650cf3b512531a872Brendan Jackman          **wloads**
1617b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            .. TODO document wloads field.
1627b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1637b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Mandatory. Workloads to run on each platform configuration
1647b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
1657b764f318505bd13991b37d650cf3b512531a872Brendan Jackman          **iterations**
1667b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            Number of iterations for each workload/conf combination. Default
1677b764f318505bd13991b37d650cf3b512531a872Brendan Jackman            is 1.
1687b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    :type experiments_conf: dict
1697b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    """
1707b764f318505bd13991b37d650cf3b512531a872Brendan Jackman
171cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman    critical_tasks = {
172cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        'linux': ['init', 'systemd', 'sh', 'ssh'],
173cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        'android': [
17441d37527c49ef0cba068ca5aafb6cd858bde7797Brendan Jackman            'sh', 'adbd',
175cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            'usb', 'transport',
176cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            # We don't actually need this task but on Google Pixel it apparently
177cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            # cannot be frozen, so the cgroup state gets stuck in FREEZING if we
178cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            # try to freeze it.
179cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            'thermal-engine'
180cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        ]
181cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman    }
1827b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    """
1837b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    Dictionary mapping OS name to list of task names that we can't afford to
1847b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    freeze when using freeeze_userspace.
1857b764f318505bd13991b37d650cf3b512531a872Brendan Jackman    """
186ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
1872bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman    def __init__(self, test_env, experiments_conf):
188ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Initialize globals
189145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi        self._default_cgroup = None
190ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._cgroup = None
191ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
192c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        # Setup logging
193c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log = logging.getLogger('Executor')
194c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi
195ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup test configuration
1962bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        if isinstance(experiments_conf, dict):
197c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Loading custom (inline) test configuration')
1982bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman            self._experiments_conf = experiments_conf
1992bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        elif isinstance(experiments_conf, str):
200c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Loading custom (file) test configuration')
2012bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman            json_conf = JsonConf(experiments_conf)
2022bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman            self._experiments_conf = json_conf.load()
203ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        else:
2042bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman            raise ValueError(
2052bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman                'experiments_conf must be either a dictionary or a filepath')
206ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
207ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Check for mandatory configurations
2082bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        if not self._experiments_conf.get('confs', None):
209c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi            raise ValueError('Configuration error: '
210c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                             'missing "conf" definitions')
2112bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        if not self._experiments_conf.get('wloads', None):
212c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi            raise ValueError('Configuration error: '
213c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                             'missing "wloads" definitions')
214ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
215324d7fa43f58a074292caca4f08e76a17ea94e75Brendan Jackman        self.te = test_env
216ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self.target = self.te.target
217ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
2182bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        self._iterations = self._experiments_conf.get('iterations', 1)
219ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Compute total number of experiments
220705db83c4e9ab166cc59b2d05bfb457cc6bb49baBrendan Jackman        self._exp_count = self._iterations \
2212bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman                * len(self._experiments_conf['wloads']) \
2222bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman                * len(self._experiments_conf['confs'])
223ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
224c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_section('Experiments configuration')
225ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
226c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Configured to run:')
227ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
228c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('   %3d target configurations:',
229c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                       len(self._experiments_conf['confs']))
2302bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        target_confs = [conf['tag'] for conf in self._experiments_conf['confs']]
231ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        target_confs = ', '.join(target_confs)
232c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('      %s', target_confs)
233ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
234c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('   %3d workloads (%d iterations each)',
235c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                       len(self._experiments_conf['wloads']),
236c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                       self._iterations)
2372bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        wload_confs = ', '.join(self._experiments_conf['wloads'])
238c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('      %s', wload_confs)
239ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
240c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Total: %d experiments', self._exp_count)
241ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
242c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Results will be collected under:')
243c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('      %s', self.te.res_dir)
244ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
245ace366e609c242665f584a4b9a94e8232839ded3Brendan Jackman        if any(wl['type'] == 'rt-app'
246ace366e609c242665f584a4b9a94e8232839ded3Brendan Jackman               for wl in self._experiments_conf['wloads'].values()):
247ace366e609c242665f584a4b9a94e8232839ded3Brendan Jackman            self._log.info('rt-app workloads found, installing tool on target')
248ace366e609c242665f584a4b9a94e8232839ded3Brendan Jackman            self.te.install_tools(['rt-app'])
249ace366e609c242665f584a4b9a94e8232839ded3Brendan Jackman
250ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def run(self):
251c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_section('Experiments execution')
252ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
2530328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman        self.experiments = []
2540328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman
255ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Run all the configured experiments
256ca9d9295cb18dfb04e85c29a12b5f28e8d8cf511Brendan Jackman        exp_idx = 0
2572bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        for tc in self._experiments_conf['confs']:
258ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            # TARGET: configuration
259ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if not self._target_configure(tc):
260ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                continue
2612bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman            for wl_idx in self._experiments_conf['wloads']:
262ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                # TEST: configuration
2630328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                wload, test_dir = self._wload_init(tc, wl_idx)
264705db83c4e9ab166cc59b2d05bfb457cc6bb49baBrendan Jackman                for itr_idx in range(1, self._iterations + 1):
2650328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                    exp = Experiment(
2660328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        wload_name=wl_idx,
2670328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        wload=wload,
2680328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        conf=tc,
2690328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        iteration=itr_idx,
2700328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        out_dir=os.path.join(test_dir, str(itr_idx)))
2710328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                    self.experiments.append(exp)
2720328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman
273ca9d9295cb18dfb04e85c29a12b5f28e8d8cf511Brendan Jackman                    # WORKLOAD: execution
274ca9d9295cb18dfb04e85c29a12b5f28e8d8cf511Brendan Jackman                    self._wload_run(exp_idx, exp)
275ca9d9295cb18dfb04e85c29a12b5f28e8d8cf511Brendan Jackman                    exp_idx += 1
2769ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman            self._target_cleanup(tc)
2779ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman
278c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_section('Experiments execution completed')
279c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Results available in:')
280c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('      %s', self.te.res_dir)
281ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
282ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
283ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
284ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Target Configuration
285ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
286ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
287ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _cgroups_init(self, tc):
288145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi        self._default_cgroup = None
289ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'cgroups' not in tc:
290ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return True
29156c6cd2564b37923e9cb7ee0df59b3135651ce13Patrick Bellasi        if 'cgroups' not in self.target.modules:
29256c6cd2564b37923e9cb7ee0df59b3135651ce13Patrick Bellasi            raise RuntimeError('CGroups module not available. Please ensure '
29356c6cd2564b37923e9cb7ee0df59b3135651ce13Patrick Bellasi                               '"cgroups" is listed in your target/test modules')
294c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Initialize CGroups support...')
295ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        errors = False
296ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        for kind in tc['cgroups']['conf']:
297c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Setup [%s] CGroup controller...', kind)
298ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            controller = self.target.cgroups.controller(kind)
299ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if not controller:
300c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                self._log.warning('CGroups controller [%s] NOT available',
301c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                  kind)
302ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                errors = True
303ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        return not errors
304ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
305ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_kernel(self, tc):
306ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Deploy kernel on the device
307ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self.te.install_kernel(tc, reboot=True)
308ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup the rootfs for the experiments
309ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._setup_rootfs(tc)
310ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
311ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_sched_features(self, tc):
312ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'sched_features' not in tc:
313c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.debug('Scheduler features configuration not provided')
314ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return
315ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        feats = tc['sched_features'].split(",")
316ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        for feat in feats:
317c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Set scheduler feature: %s', feat)
318750eb5a668cc85c89ec63e53614323dc3e9518f6Brendan Jackman            self.target.execute('echo {} > /sys/kernel/debug/sched_features'.format(feat),
319750eb5a668cc85c89ec63e53614323dc3e9518f6Brendan Jackman                                as_root=True)
320ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
321ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_rootfs(self, tc):
322ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Initialize CGroups if required
323ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._cgroups_init(tc)
324ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup target folder for experiments execution
325ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self.te.run_dir = os.path.join(
326ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                self.target.working_directory, TGT_RUN_DIR)
327ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Create run folder as tmpfs
328c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.debug('Setup RT-App run folder [%s]...', self.te.run_dir)
329ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self.target.execute('[ -d {0} ] || mkdir {0}'\
3309ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman                .format(self.te.run_dir))
331ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self.target.execute(
332ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                'grep schedtest /proc/mounts || '\
333ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                '  mount -t tmpfs -o size=1024m {} {}'\
334ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                .format('schedtest', self.te.run_dir),
335ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                as_root=True)
3369ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        # tmpfs mounts have an SELinux context with "tmpfs" as the type (while
3379ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        # other files we create have "shell_data_file"). That prevents non-root
3389ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        # users from creating files in tmpfs mounts. For now, just put SELinux
3399ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        # in permissive mode to get around that.
3409ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        try:
3419ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman            # First, save the old SELinux mode
3429ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman            self._old_selinux_mode = self.target.execute('getenforce')
343c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.warning('Setting target SELinux in permissive mode')
3449ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman            self.target.execute('setenforce 0', as_root=True)
34593bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman        except TargetError:
34693bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman            # Probably the target doesn't have SELinux, or there are no
34793bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman            # contexts set up. No problem.
34893bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman            self._log.warning("Couldn't set SELinux in permissive mode. "
34993bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman                                "This is probably fine.")
35093bad43d607bd6c8c0c73b1745bdf2f989900583Brendan Jackman            self._old_selinux_mode = None
351ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
352ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_cpufreq(self, tc):
353ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'cpufreq' not in tc:
354c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.warning('cpufreq governor not specified, '
355c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                              'using currently configured governor')
356ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return
357ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
358ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        cpufreq = tc['cpufreq']
359c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('Configuring all CPUs to use [%s] cpufreq governor',
360c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                       cpufreq['governor'])
361ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
3629883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli        self.target.cpufreq.set_all_governors(cpufreq['governor'])
3639883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli
364d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman        if 'freqs' in cpufreq:
365d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman            if cpufreq['governor'] != 'userspace':
366d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman                raise ValueError('Must use userspace governor to set CPU freqs')
367d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman            self._log.info(r'%14s - CPU frequencies: %s',
368d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman                    'CPUFreq', str(cpufreq['freqs']))
369d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman            for cpu, freq in cpufreq['freqs'].iteritems():
370d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman                self.target.cpufreq.set_frequency(cpu, freq)
371d20484c2660546c38b1ae1ef441eda293aec84b2Brendan Jackman
3729883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli        if 'params' in cpufreq:
373c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('governor params: %s', str(cpufreq['params']))
3749883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli            for cpu in self.target.list_online_cpus():
3759883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli                self.target.cpufreq.set_governor_tunables(
3769883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli                        cpu,
3779883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli                        cpufreq['governor'],
3789883f9edb93e5f8e818992e21f2518340135aa8fJuri Lelli                        **cpufreq['params'])
379ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
380ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_cgroups(self, tc):
381ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'cgroups' not in tc:
382ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return True
383ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup default CGroup to run tasks into
384ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'default' in tc['cgroups']:
385145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi            self._default_cgroup = tc['cgroups']['default']
386ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Configure each required controller
387ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'conf' not in tc['cgroups']:
388ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return True
389ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        errors = False
390ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        for kind in tc['cgroups']['conf']:
391ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            controller = self.target.cgroups.controller(kind)
392ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if not controller:
393c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                self._log.warning('Configuration error: '
394c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                  '[%s] contoller NOT supported',
395c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                  kind)
396ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                errors = True
397ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                continue
398ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            self._setup_controller(tc, controller)
399ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        return not errors
400ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
401ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_controller(self, tc, controller):
402ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        kind = controller.kind
403ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Configure each required groups for that controller
404ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        errors = False
405ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        for name in tc['cgroups']['conf'][controller.kind]:
406c9607f05deb81ce8be90a71adc9c71018f626028Patrick Bellasi            if name[0] != '/':
407c9607f05deb81ce8be90a71adc9c71018f626028Patrick Bellasi                raise ValueError('Wrong CGroup name [{}]. '
408c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                 'CGroups names must start by "/".'
409c9607f05deb81ce8be90a71adc9c71018f626028Patrick Bellasi                                 .format(name))
410ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            group = controller.cgroup(name)
411ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if not group:
412c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                self._log.warning('Configuration error: '
413c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                  '[%s/%s] cgroup NOT available',
414c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                  kind, name)
415ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                errors = True
416ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                continue
417ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            self._setup_group(tc, group)
418ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        return not errors
419ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
420ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _setup_group(self, tc, group):
421ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        kind = group.controller.kind
422ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        name = group.name
423ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Configure each required attribute
424ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        group.set(**tc['cgroups']['conf'][kind][name])
425ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
426204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath    def _setup_files(self, tc):
427204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath        if 'files' not in tc:
428204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            self._log.debug('\'files\' Configuration block not provided')
429204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            return True
430204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath        for name, value in tc['files'].iteritems():
431204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            check = False
432204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            if name.startswith('!/'):
433204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                check = True
434204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                name = name[1:]
435204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            self._log.info('File Write(check=%s): \'%s\' -> \'%s\'',
436204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                         check, value, name)
437204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            try:
438204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                self.target.write_value(name, value, True)
439204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath            except TargetError:
440204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                self._log.info('File Write Failed: \'%s\' -> \'%s\'',
441204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                         value, name)
442204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                if check:
443204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath                    raise
444204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath        return False
445204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath
446ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _target_configure(self, tc):
447c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_header(
448c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                'configuring target for [{}] experiments'\
449ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                .format(tc['tag']))
450ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._setup_kernel(tc)
451ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._setup_sched_features(tc)
452ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        self._setup_cpufreq(tc)
453204f03bccbd5482e459ceb46b397875956c63da5Chris Redpath        self._setup_files(tc)
454ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        return self._setup_cgroups(tc)
455ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
456ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _target_conf_flag(self, tc, flag):
457ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'flags' not in tc:
458ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            has_flag = False
459ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        else:
460ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            has_flag = flag in tc['flags']
461c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.debug('Check if target configuration [%s] has flag [%s]: %s',
462c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                        tc['tag'], flag, has_flag)
463ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        return has_flag
464ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
4659ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman    def _target_cleanup(self, tc):
4669ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman        if self._old_selinux_mode is not None:
467c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Restoring target SELinux mode: %s',
468c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                           self._old_selinux_mode)
4699ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman            self.target.execute('setenforce ' + self._old_selinux_mode,
4709ecfd1a4364b29b27dab6e766dee000820df8d48Brendan Jackman                                as_root=True)
471ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
472ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
473ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Workload Setup and Execution
474ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
475ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
476ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_cpus(self, wl_idx, wlspec):
477ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if not 'cpus' in wlspec['conf']:
478ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return None
479ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        cpus = wlspec['conf']['cpus']
480ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
481ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi        if type(cpus) == list:
482ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi            return cpus
483ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if type(cpus) == int:
484ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi            return [cpus]
485ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi
486ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi        # SMP target (or not bL module loaded)
487ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi        if not hasattr(self.target, 'bl'):
488ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi            if 'first' in cpus:
489ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi                return [ self.target.list_online_cpus()[0] ]
490ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi            if 'last' in cpus:
491ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi                return [ self.target.list_online_cpus()[-1] ]
492ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi            return self.target.list_online_cpus()
493ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi
494ea9ffe39f2296c9c1acd76ebede497a3a04a81e0Patrick Bellasi        # big.LITTLE target
495ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if cpus.startswith('littles'):
496ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if 'first' in cpus:
497ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                return [ self.target.bl.littles_online[0] ]
498ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if 'last' in cpus:
499ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                return [ self.target.bl.littles_online[-1] ]
500ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return self.target.bl.littles_online
501ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if cpus.startswith('bigs'):
502ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if 'first' in cpus:
503ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                return [ self.target.bl.bigs_online[0] ]
504ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            if 'last' in cpus:
505ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                return [ self.target.bl.bigs_online[-1] ]
506ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return self.target.bl.bigs_online
507c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi        raise ValueError('unsupported [{}] "cpus" value for [{}] '
508c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         'workload specification'
509c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         .format(cpus, wl_idx))
510ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
511ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_task_idxs(self, wl_idx, tasks):
512ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if type(tasks) == int:
513ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return range(tasks)
514ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if tasks == 'cpus':
515ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return range(len(self.target.core_names))
516ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if tasks == 'little':
517ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return range(len([t
518ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                for t in self.target.core_names
519ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                if t == self.target.little_core]))
520ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if tasks == 'big':
521ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return range(len([t
522ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                for t in self.target.core_names
523ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                if t == self.target.big_core]))
524c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi        raise ValueError('unsupported "tasks" value for [{}] RT-App '
525c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         'workload specification'
526c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         .format(wl_idx))
527ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
528ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_rtapp(self, wl_idx, wlspec, cpus):
529ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        conf = wlspec['conf']
530c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.debug('Configuring [%s] rt-app...', conf['class'])
531ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
532ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup a default "empty" task name prefix
533ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'prefix' not in conf:
534ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            conf['prefix'] = 'task_'
535ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
536ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup a default loadref CPU
537ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        loadref = None
538ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if 'loadref' in wlspec:
539ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            loadref = wlspec['loadref']
540ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
541ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if conf['class'] == 'profile':
542ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            params = {}
543ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            # Load each task specification
54443a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman            for task_name, task in conf['params'].items():
54569452dfb17022adbb7cd2a43d91ca2dcb625f645Patrick Bellasi                if task['kind'] not in wlgen.__dict__:
546c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                    self._log.error('RTA task of kind [%s] not supported',
547c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                                    task['kind'])
548c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                    raise ValueError('unsupported "kind" value for task [{}] '
549c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                                     'in RT-App workload specification'
550c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                                     .format(task))
55169452dfb17022adbb7cd2a43d91ca2dcb625f645Patrick Bellasi                task_ctor = getattr(wlgen, task['kind'])
55243a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman                num_tasks = task.get('tasks', 1)
55343a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman                task_idxs = self._wload_task_idxs(wl_idx, num_tasks)
55443a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman                for idx in task_idxs:
555045fa0359157b4adf833e1c7a2c84663f89611cbPatrick Bellasi                    idx_name = "_{}".format(idx) if len(task_idxs) > 1 else ""
55643a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman                    task_name_idx = conf['prefix'] + task_name + idx_name
55743a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman                    params[task_name_idx] = task_ctor(**task['params']).get()
55843a28826460dd192805df1d57128d34f19c3ef80Brendan Jackman
559ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp = wlgen.RTA(self.target,
560ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                        wl_idx, calibration = self.te.calibration())
561ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp.conf(kind='profile', params=params, loadref=loadref,
562f936d35ffe082d612542763bc7faac47f3605421Brendan Jackman                       cpus=cpus, run_dir=self.te.run_dir,
5632b88eb10421ba7423c54682e0bd7769cf989ba70Brendan Jackman                       duration=conf.get('duration'))
564ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return rtapp
565ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
566ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if conf['class'] == 'periodic':
567ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            task_idxs = self._wload_task_idxs(wl_idx, conf['tasks'])
568ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            params = {}
569ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            for idx in task_idxs:
570ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                task = conf['prefix'] + str(idx)
5714e98ca3154a8bb198b57f520d16cc510ace3fe5bJuri Lelli                params[task] = wlgen.Periodic(**conf['params']).get()
572ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp = wlgen.RTA(self.target,
573ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                        wl_idx, calibration = self.te.calibration())
574ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp.conf(kind='profile', params=params, loadref=loadref,
575f936d35ffe082d612542763bc7faac47f3605421Brendan Jackman                       cpus=cpus, run_dir=self.te.run_dir,
5762b88eb10421ba7423c54682e0bd7769cf989ba70Brendan Jackman                       duration=conf.get('duration'))
577ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return rtapp
578ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
579ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if conf['class'] == 'custom':
580ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp = wlgen.RTA(self.target,
581ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                        wl_idx, calibration = self.te.calib)
582ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            rtapp.conf(kind='custom',
583ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                    params=conf['json'],
584ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                    duration=conf['duration'],
585ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                    loadref=loadref,
586ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                    cpus=cpus, run_dir=self.te.run_dir)
587ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return rtapp
588ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
589c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi        raise ValueError('unsupported \'class\' value for [{}] '
590c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         'RT-App workload specification'
591c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         .format(wl_idx))
592ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
593ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_perf_bench(self, wl_idx, wlspec, cpus):
594ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        conf = wlspec['conf']
595c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.debug('Configuring perf_message...')
596ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
597ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if conf['class'] == 'messaging':
598ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            perf_bench = wlgen.PerfMessaging(self.target, wl_idx)
599ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            perf_bench.conf(**conf['params'])
600ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return perf_bench
601ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
602ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if conf['class'] == 'pipe':
603ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            perf_bench = wlgen.PerfPipe(self.target, wl_idx)
604ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            perf_bench.conf(**conf['params'])
605ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return perf_bench
606ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
607c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi        raise ValueError('unsupported "class" value for [{}] '
608c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         'perf bench workload specification'
609c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         .format(wl_idx))
610ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
611ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_conf(self, wl_idx, wlspec):
612ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
613ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # CPUS: setup execution on CPUs if required by configuration
614ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        cpus = self._wload_cpus(wl_idx, wlspec)
615ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
616145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi        # CGroup: setup CGroups if requried by configuration
617145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi        self._cgroup = self._default_cgroup
618145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi        if 'cgroup' in wlspec:
619145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi            if 'cgroups' not in self.target.modules:
620145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi                raise RuntimeError('Target not supporting CGroups or CGroups '
621145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi                                   'not configured for the current test configuration')
622145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi            self._cgroup = wlspec['cgroup']
623145b3cef7d5a6e509ec155216713e0545da65885Patrick Bellasi
624ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if wlspec['type'] == 'rt-app':
625ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return self._wload_rtapp(wl_idx, wlspec, cpus)
626ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if wlspec['type'] == 'perf_bench':
627ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            return self._wload_perf_bench(wl_idx, wlspec, cpus)
628ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
629ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
630c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi        raise ValueError('unsupported "type" value for [{}] '
631c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         'workload specification'
632c25cc8d70f24e6263b2a6b61b430e3f5ca34ed55Patrick Bellasi                         .format(wl_idx))
633ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
634ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    def _wload_init(self, tc, wl_idx):
635ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        tc_idx = tc['tag']
636ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
637ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Configure the test workload
6382bafed53a78810119b683ee1e83eb7ec972b8a96Brendan Jackman        wlspec = self._experiments_conf['wloads'][wl_idx]
639ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        wload = self._wload_conf(wl_idx, wlspec)
640ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
641ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Keep track of platform configuration
642d6ffaf98744ddbcac1ab58d7278ce8c6c34be88aBrendan Jackman        test_dir = '{}/{}:{}:{}'\
643ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            .format(self.te.res_dir, wload.wtype, tc_idx, wl_idx)
6440ec5fcf10e834fd1c5f6505430c81426f5b5188dBrendan Jackman        os.makedirs(test_dir)
645d6ffaf98744ddbcac1ab58d7278ce8c6c34be88aBrendan Jackman        self.te.platform_dump(test_dir)
646ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
647ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Keep track of kernel configuration and version
648ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        config = self.target.config
649d6ffaf98744ddbcac1ab58d7278ce8c6c34be88aBrendan Jackman        with gzip.open(os.path.join(test_dir, 'kernel.config'), 'wb') as fh:
650ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            fh.write(config.text)
651ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        output = self.target.execute('{} uname -a'\
652ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                .format(self.target.busybox))
653d6ffaf98744ddbcac1ab58d7278ce8c6c34be88aBrendan Jackman        with open(os.path.join(test_dir, 'kernel.version'), 'w') as fh:
654ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            fh.write(output)
655ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
656d6ffaf98744ddbcac1ab58d7278ce8c6c34be88aBrendan Jackman        return wload, test_dir
657ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
6580328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman    def _wload_run(self, exp_idx, experiment):
6590328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman        tc = experiment.conf
6600328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman        wload = experiment.wload
661ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        tc_idx = tc['tag']
662ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
663c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_title('Experiment {}/{}, [{}:{}] {}/{}'\
664ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi                .format(exp_idx, self._exp_count,
6650328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        tc_idx, experiment.wload_name,
6660328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman                        experiment.iteration, self._iterations))
667ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
668ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # Setup local results folder
669c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.debug('out_dir set to [%s]', experiment.out_dir)
6700328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman        os.system('mkdir -p ' + experiment.out_dir)
671ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
672cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        # Freeze all userspace tasks that we don't need for running tests
673cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        need_thaw = False
674cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        if self._target_conf_flag(tc, 'freeze_userspace'):
675cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            need_thaw = self._freeze_userspace()
676cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
677ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # FTRACE: start (if a configuration has been provided)
678ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if self.te.ftrace and self._target_conf_flag(tc, 'ftrace'):
679c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.warning('FTrace events collection enabled')
680ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            self.te.ftrace.start()
681ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
682ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # ENERGY: start sampling
683ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if self.te.emeter:
684ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            self.te.emeter.reset()
685ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
686ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # WORKLOAD: Run the configured workload
6870328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman        wload.run(out_dir=experiment.out_dir, cgroup=self._cgroup)
688ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
689ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # ENERGY: collect measurements
690ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if self.te.emeter:
6910328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman            self.te.emeter.report(experiment.out_dir)
692ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
693ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        # FTRACE: stop and collect measurements
694ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi        if self.te.ftrace and self._target_conf_flag(tc, 'ftrace'):
695ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi            self.te.ftrace.stop()
6962a61af85fcc950272762319d91c0462eb78fe409Patrick Bellasi
6970328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman            trace_file = experiment.out_dir + '/trace.dat'
6982a61af85fcc950272762319d91c0462eb78fe409Patrick Bellasi            self.te.ftrace.get_trace(trace_file)
699c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Collected FTrace binary trace:')
700c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('   %s',
701c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                           trace_file.replace(self.te.res_dir, '<res_dir>'))
7022a61af85fcc950272762319d91c0462eb78fe409Patrick Bellasi
7030328c6163c4c5f90ef2bfec1513ec1388ef6e232Brendan Jackman            stats_file = experiment.out_dir + '/trace_stat.json'
7042a61af85fcc950272762319d91c0462eb78fe409Patrick Bellasi            self.te.ftrace.get_stats(stats_file)
705c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('Collected FTrace function profiling:')
706c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info('   %s',
707c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi                           stats_file.replace(self.te.res_dir, '<res_dir>'))
708ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
709cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        # Unfreeze the tasks we froze
710cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        if need_thaw:
711cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            self._thaw_userspace()
712cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
713c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._print_footer()
714293aba12c7b69a2e9ba7808e7869c4692725b559Patrick Bellasi
715cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman    def _freeze_userspace(self):
716cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        if 'cgroups' not in self.target.modules:
717cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            raise RuntimeError(
718cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman                'Failed to freeze userspace. Ensure "cgroups" module is listed '
719cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman                'among modules in target/test configuration')
720cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        controllers = [s.name for s in self.target.cgroups.list_subsystems()]
721cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        if 'freezer' not in controllers:
722cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            self._log.warning('No freezer cgroup controller on target. '
723cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman                              'Not freezing userspace')
724cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman            return False
725cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
726cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        exclude = self.critical_tasks[self.te.target.os]
727cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        self._log.info('Freezing all tasks except: %s', ','.join(exclude))
728cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        self.te.target.cgroups.freeze(exclude)
729cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        return True
730cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
731cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
732cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman    def _thaw_userspace(self):
733cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        self._log.info('Un-freezing userspace tasks')
734cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman        self.te.target.cgroups.freeze(thaw=True)
735cd59861cead6ff46da93810531af786a9b68cf04Brendan Jackman
736ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
737ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Utility Functions
738ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
739ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
740c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi    def _print_section(self, message):
741c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('')
742c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(FMT_SECTION)
743c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(message)
744c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(FMT_SECTION)
745ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
746c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi    def _print_header(self, message):
747c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info('')
748c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(FMT_HEADER)
749c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(message)
750ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
751c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi    def _print_title(self, message):
752c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(FMT_TITLE)
753c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(message)
754ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
755c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi    def _print_footer(self, message=None):
756293aba12c7b69a2e9ba7808e7869c4692725b559Patrick Bellasi        if message:
757c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi            self._log.info(message)
758c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi        self._log.info(FMT_FOOTER)
759293aba12c7b69a2e9ba7808e7869c4692725b559Patrick Bellasi
760ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
761ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
762ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Globals
763ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi################################################################################
764ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
765ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Regular expression for comments
766ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick BellasiJSON_COMMENTS_RE = re.compile(
767ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    '(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
768ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi    re.DOTALL | re.MULTILINE
769ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi)
770ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
771ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Target specific paths
772ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick BellasiTGT_RUN_DIR = 'run_dir'
773ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
774ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# Logging formatters
775ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick BellasiFMT_SECTION = r'{:#<80}'.format('')
776ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick BellasiFMT_HEADER  = r'{:=<80}'.format('')
777ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick BellasiFMT_TITLE   = r'{:~<80}'.format('')
778293aba12c7b69a2e9ba7808e7869c4692725b559Patrick BellasiFMT_FOOTER  = r'{:-<80}'.format('')
779ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi
780ce73ce0f78dec8da6daa7c1355b1da988f39790dPatrick Bellasi# vim :set tabstop=4 shiftwidth=4 expandtab
781