mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-11-04 00:52:08 +00:00 
			
		
		
		
	Target Manager Intial Commit
This commit is contained in:
		
							
								
								
									
										0
									
								
								wa/target/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								wa/target/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										20
									
								
								wa/target/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								wa/target/config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
from copy import copy
 | 
			
		||||
 | 
			
		||||
#Not going to be used for now.
 | 
			
		||||
 | 
			
		||||
class TargetConfig(dict):
 | 
			
		||||
    """
 | 
			
		||||
    Represents a configuration for a target.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, config=None):
 | 
			
		||||
        if isinstance(config, TargetConfig):
 | 
			
		||||
            self.__dict__ = copy(config.__dict__)
 | 
			
		||||
        elif hasattr(config, 'iteritems'):
 | 
			
		||||
            for k, v in config.iteritems:
 | 
			
		||||
                self.set(k, v)
 | 
			
		||||
        elif config:
 | 
			
		||||
            raise ValueError(config)
 | 
			
		||||
 | 
			
		||||
    def set(self, name, value):
 | 
			
		||||
        setattr(self, name, value)
 | 
			
		||||
							
								
								
									
										85
									
								
								wa/target/info.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								wa/target/info.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
from devlib.exception import TargetError
 | 
			
		||||
from devlib.target import KernelConfig, KernelVersion, Cpuinfo
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TargetInfo(object):
 | 
			
		||||
 | 
			
		||||
    hmp_config_dir = '/sys/kernel/hmp'
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.os = None
 | 
			
		||||
        self.kernel_version = None
 | 
			
		||||
        self.kernel_cmdline = None
 | 
			
		||||
        self.kernel_config = {}
 | 
			
		||||
        self.sched_features = []
 | 
			
		||||
        self.cpuinfo = None
 | 
			
		||||
        self.os_version = {}
 | 
			
		||||
        self.properties = {}
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def from_pod(pod):
 | 
			
		||||
        kconfig_text = '\n'.join('{}={}'.format(k, v) for k, v in pod['kernel_config'].iteritems())
 | 
			
		||||
        sections = []
 | 
			
		||||
        for section in pod['cpuinfo']:
 | 
			
		||||
            text = '\n'.join('{} : {}'.format(k, v) for k, v in section.iteritems())
 | 
			
		||||
            sections.append(text)
 | 
			
		||||
        cpuinfo_text = '\n\n'.join(sections)
 | 
			
		||||
 | 
			
		||||
        instance = TargetInfo()
 | 
			
		||||
        instance.os = pod['os']
 | 
			
		||||
        instance.kernel_version = KernelVersion(pod['kernel_version'])
 | 
			
		||||
        instance.kernel_cmdline = pod['kernel_cmdline']
 | 
			
		||||
        instance.kernel_config = KernelConfig(kconfig_text)
 | 
			
		||||
        instance.sched_features = pod['sched_features']
 | 
			
		||||
        instance.cpuinfo = Cpuinfo(cpuinfo_text)
 | 
			
		||||
        instance.os_version = pod['os_version']
 | 
			
		||||
        instance.properties = pod['properties']
 | 
			
		||||
        return instance
 | 
			
		||||
 | 
			
		||||
    def to_pod(self):
 | 
			
		||||
        kversion = str(self.kernel_version)
 | 
			
		||||
        kconfig = {k: v for k, v in self.kernel_config.iteritems()}
 | 
			
		||||
        return dict(
 | 
			
		||||
            os=self.os,
 | 
			
		||||
            kernel_version=kversion,
 | 
			
		||||
            kernel_cmdline=self.kernel_cmdline,
 | 
			
		||||
            kernel_config=kconfig,
 | 
			
		||||
            sched_features=self.sched_features,
 | 
			
		||||
            cpuinfo=self.cpuinfo.sections,
 | 
			
		||||
            os_version=self.os_version,
 | 
			
		||||
            properties=self.properties,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def load(self, target):
 | 
			
		||||
        self.os = target.os
 | 
			
		||||
        print target.is_rooted
 | 
			
		||||
        self.os_version = target.os_version
 | 
			
		||||
        self.kernel_version = target.kernel_version
 | 
			
		||||
        self.kernel_cmdline = target.execute('cat /proc/cmdline',
 | 
			
		||||
                                             as_root=target.is_rooted).strip()
 | 
			
		||||
        self.kernel_config = target.config
 | 
			
		||||
        self.cpuinfo = target.cpuinfo
 | 
			
		||||
        try:
 | 
			
		||||
            output = target.read_value('/sys/kernel/debug/sched_features')
 | 
			
		||||
            self.sched_features = output.strip().split()
 | 
			
		||||
        except TargetError:
 | 
			
		||||
            pass
 | 
			
		||||
        self.properties = self._get_properties(target)
 | 
			
		||||
 | 
			
		||||
    def _get_properties(self, target):
 | 
			
		||||
        props = {}
 | 
			
		||||
        if target.file_exists(self.hmp_config_dir):
 | 
			
		||||
            props['hmp'] = self._get_hmp_configuration(target)
 | 
			
		||||
        if target.os == 'android':
 | 
			
		||||
            props.update(target.getprop().iteritems())
 | 
			
		||||
        return props
 | 
			
		||||
 | 
			
		||||
    def _get_hmp_configuration(self, target):
 | 
			
		||||
        hmp_props = {}
 | 
			
		||||
        for entry in target.list_directory(self.hmp_config_dir):
 | 
			
		||||
            path = target.path.join(self.hmp_config_dir, entry)
 | 
			
		||||
            try:
 | 
			
		||||
                hmp_props[entry] = target.read_value(path)
 | 
			
		||||
            except TargetError:
 | 
			
		||||
                pass
 | 
			
		||||
        return hmp_props
 | 
			
		||||
							
								
								
									
										380
									
								
								wa/target/manager.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								wa/target/manager.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,380 @@
 | 
			
		||||
import logging
 | 
			
		||||
import tempfile
 | 
			
		||||
import threading
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from wa.framework.plugin import Parameter
 | 
			
		||||
from wa.framework import signal
 | 
			
		||||
from wa.framework.exception import WorkerThreadError, ConfigError
 | 
			
		||||
from wa.target.info import TargetInfo
 | 
			
		||||
from wa.target.runtime_config import (SysfileValuesRuntimeConfig,
 | 
			
		||||
                                      HotplugRuntimeConfig,
 | 
			
		||||
                                      CpufreqRuntimeConfig,
 | 
			
		||||
                                      CpuidleRuntimeConfig)
 | 
			
		||||
from wa.utils.serializer import json
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from devlib import LocalLinuxTarget, LinuxTarget, AndroidTarget
 | 
			
		||||
# from wa.target.manager import AndroidTargetManager, LinuxTargetManager
 | 
			
		||||
# from wa.framework.plugin import Plugin, Parameter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TargetManager(object):
 | 
			
		||||
    name = 'target-manager'
 | 
			
		||||
 | 
			
		||||
    description = """
 | 
			
		||||
    Instanciated the required target and performs configuration and validation of the device.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    parameters = [
 | 
			
		||||
        Parameter('disconnect', kind=bool, default=False,
 | 
			
		||||
                  description="""
 | 
			
		||||
                  Specifies whether the target should be disconnected from
 | 
			
		||||
                  at the end of the run.
 | 
			
		||||
                  """),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    DEVICE_MAPPING = {'test' : {'platform_name':'generic',
 | 
			
		||||
                               'target_name': 'android'},
 | 
			
		||||
                      'other':  {'platform_name':'test',
 | 
			
		||||
                                'target_name': 'linux'},
 | 
			
		||||
                      }
 | 
			
		||||
 | 
			
		||||
    runtime_config_cls = [
 | 
			
		||||
                            # order matters
 | 
			
		||||
                            SysfileValuesRuntimeConfig,
 | 
			
		||||
                            HotplugRuntimeConfig,
 | 
			
		||||
                            CpufreqRuntimeConfig,
 | 
			
		||||
                            CpuidleRuntimeConfig,
 | 
			
		||||
                          ]
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name, parameters):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.target = None
 | 
			
		||||
        self.assistant = None
 | 
			
		||||
        self.target_name = None
 | 
			
		||||
        self.platform_name = None
 | 
			
		||||
        self.parameters = parameters
 | 
			
		||||
        self.disconnect = parameters.get('disconnect')
 | 
			
		||||
        self.info = TargetInfo()
 | 
			
		||||
 | 
			
		||||
        # Determine platform and target based on passed name
 | 
			
		||||
        self._parse_name()
 | 
			
		||||
        # Create target
 | 
			
		||||
        self._getTarget()
 | 
			
		||||
        # Create an assistant to perform target specific configuration
 | 
			
		||||
        self._getAssistant()
 | 
			
		||||
 | 
			
		||||
        ### HERE FOR TESTING, WILL BE CALLED EXTERNALLY ###
 | 
			
		||||
        # Connect to device and retrieve details.
 | 
			
		||||
        # self.initialize()
 | 
			
		||||
        # self.add_parameters()
 | 
			
		||||
        # self.validate_parameters()
 | 
			
		||||
        # self.set_parameters()
 | 
			
		||||
 | 
			
		||||
    def initialize(self):
 | 
			
		||||
        self.runtime_configs = [cls(self.target) for cls in self.runtime_config_cls]
 | 
			
		||||
        # if self.parameters:
 | 
			
		||||
        # self.logger.info('Connecting to the device')
 | 
			
		||||
        with signal.wrap('TARGET_CONNECT'):
 | 
			
		||||
            self.target.connect()
 | 
			
		||||
            # self.info.load(self.target)
 | 
			
		||||
            # info_file = os.path.join(self.context.info_directory, 'target.json')
 | 
			
		||||
            # with open(info_file, 'w') as wfh:
 | 
			
		||||
            #     json.dump(self.info.to_pod(), wfh)
 | 
			
		||||
 | 
			
		||||
    def finalize(self):
 | 
			
		||||
        # self.logger.info('Disconnecting from the device')
 | 
			
		||||
        if self.disconnect:
 | 
			
		||||
            with signal.wrap('TARGET_DISCONNECT'):
 | 
			
		||||
                self.target.disconnect()
 | 
			
		||||
 | 
			
		||||
    def add_parameters(self, parameters=None):
 | 
			
		||||
        if parameters:
 | 
			
		||||
            self.parameters = parameters
 | 
			
		||||
        if not self.parameters:
 | 
			
		||||
            raise ConfigError('No Configuration Provided')
 | 
			
		||||
 | 
			
		||||
        for name in self.parameters.keys():
 | 
			
		||||
            for cfg in self.runtime_configs:
 | 
			
		||||
                # if name in cfg.supported_parameters:
 | 
			
		||||
                if any(parameter in name for parameter in cfg.supported_parameters):
 | 
			
		||||
                    cfg.add(name, self.parameters.pop(name))
 | 
			
		||||
 | 
			
		||||
    def validate_parameters(self):
 | 
			
		||||
        for cfg in self.runtime_configs:
 | 
			
		||||
            cfg.validate()
 | 
			
		||||
 | 
			
		||||
    def set_parameters(self):
 | 
			
		||||
        for cfg in self.runtime_configs:
 | 
			
		||||
            cfg.set()
 | 
			
		||||
 | 
			
		||||
    def clear_parameters(self):
 | 
			
		||||
        for cfg in self.runtime_configs:
 | 
			
		||||
            cfg.clear()
 | 
			
		||||
 | 
			
		||||
    def _parse_name(self):
 | 
			
		||||
        # Try and get platform and target
 | 
			
		||||
        if '-' in self.name:
 | 
			
		||||
            self.platform_name, self.target_name = self.name.split('-', 1)
 | 
			
		||||
        elif '_' in self.name:
 | 
			
		||||
            self.platform_name, self.target_name = self.name.split('_', 1)
 | 
			
		||||
        elif self.name in self.DEVICE_MAPPING:
 | 
			
		||||
            self.platform_name = self.DEVICE_MAPPING[self.name]['platform_name']
 | 
			
		||||
            self.target_name = self.DEVICE_MAPPING[self.name]['target_name']
 | 
			
		||||
        else:
 | 
			
		||||
            raise ConfigError('Unknown Device Specified {}'.format(self.name))
 | 
			
		||||
 | 
			
		||||
    def _get_target(self):
 | 
			
		||||
        # Create a corresponding target and target-assistant
 | 
			
		||||
        if self.target_name == 'android':
 | 
			
		||||
            self.target = AndroidTarget()
 | 
			
		||||
        elif self.target_name == 'linux':
 | 
			
		||||
            self.target = LinuxTarget()  # pylint: disable=redefined-variable-type
 | 
			
		||||
        elif self.target_name == 'localLinux':
 | 
			
		||||
            self.target = LocalLinuxTarget()
 | 
			
		||||
        else:
 | 
			
		||||
            raise ConfigError('Unknown Target Specified {}'.format(self.target_name))
 | 
			
		||||
 | 
			
		||||
    def _get_assistant(self):
 | 
			
		||||
        # Create a corresponding target and target-assistant to help with platformy stuff?
 | 
			
		||||
        if self.target_name == 'android':
 | 
			
		||||
            self.assistant = AndroidAssistant(self.target)
 | 
			
		||||
        elif self.target_name in ['linux', 'localLinux']:
 | 
			
		||||
            self.assistant = LinuxAssistant(self.target)  # pylint: disable=redefined-variable-type
 | 
			
		||||
        else:
 | 
			
		||||
            raise ConfigError('Unknown Target Specified {}'.format(self.target_name))
 | 
			
		||||
 | 
			
		||||
    # def validate_runtime_parameters(self, parameters):
 | 
			
		||||
    #     for  name, value in parameters.iteritems():
 | 
			
		||||
    #         self.add_parameter(name, value)
 | 
			
		||||
    #     self.validate_parameters()
 | 
			
		||||
 | 
			
		||||
    # def set_runtime_parameters(self, parameters):
 | 
			
		||||
    #     # self.clear()
 | 
			
		||||
    #     for  name, value in parameters.iteritems():
 | 
			
		||||
    #         self.add_parameter(name, value)
 | 
			
		||||
    #     self.set_parameters()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LinuxAssistant(object):
 | 
			
		||||
 | 
			
		||||
    name = 'linux-assistant'
 | 
			
		||||
 | 
			
		||||
    description = """
 | 
			
		||||
    Performs configuration, instrumentation, etc. during runs on Linux targets.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target, **kwargs):
 | 
			
		||||
        self.target = target
 | 
			
		||||
    # parameters = [
 | 
			
		||||
 | 
			
		||||
    #     Parameter('disconnect', kind=bool, default=False,
 | 
			
		||||
    #               description="""
 | 
			
		||||
    #               Specifies whether the target should be disconnected from
 | 
			
		||||
    #               at the end of the run.
 | 
			
		||||
    #               """),
 | 
			
		||||
    # ]
 | 
			
		||||
 | 
			
		||||
    # runtime_config_cls = [
 | 
			
		||||
    #     # order matters
 | 
			
		||||
    #     SysfileValuesRuntimeConfig,
 | 
			
		||||
    #     HotplugRuntimeConfig,
 | 
			
		||||
    #     CpufreqRuntimeConfig,
 | 
			
		||||
    #     CpuidleRuntimeConfig,
 | 
			
		||||
    # ]
 | 
			
		||||
 | 
			
		||||
    # def __init__(self, target, context, **kwargs):
 | 
			
		||||
    #     # super(LinuxTargetManager, self).__init__(target, context, **kwargs)
 | 
			
		||||
    #     self.target = target
 | 
			
		||||
    #     self.context = context
 | 
			
		||||
    #     self.info = TargetInfo()
 | 
			
		||||
    #     self.runtime_configs = [cls(target) for cls in self.runtime_config_cls]
 | 
			
		||||
 | 
			
		||||
    # def __init__(self):
 | 
			
		||||
    #     # super(LinuxTargetManager, self).__init__(target, context, **kwargs)
 | 
			
		||||
    #     self.target = target
 | 
			
		||||
    #     self.info = TargetInfo()
 | 
			
		||||
    #     self.parameters = parameters
 | 
			
		||||
 | 
			
		||||
        # self.info = TargetInfo()
 | 
			
		||||
        # self.runtime_configs = [cls(target) for cls in self.runtime_config_cls]
 | 
			
		||||
 | 
			
		||||
    # def initialize(self):
 | 
			
		||||
    #     # self.runtime_configs = [cls(self.target) for cls in self.runtime_config_cls]
 | 
			
		||||
    #     # if self.parameters:
 | 
			
		||||
    #     self.logger.info('Connecting to the device')
 | 
			
		||||
    #     with signal.wrap('TARGET_CONNECT'):
 | 
			
		||||
    #         self.target.connect()
 | 
			
		||||
    #         self.info.load(self.target)
 | 
			
		||||
    #         # info_file = os.path.join(self.context.info_directory, 'target.json')
 | 
			
		||||
    #         # with open(info_file, 'w') as wfh:
 | 
			
		||||
    #         #     json.dump(self.info.to_pod(), wfh)
 | 
			
		||||
 | 
			
		||||
    # def finalize(self, runner):
 | 
			
		||||
    #     self.logger.info('Disconnecting from the device')
 | 
			
		||||
    #     if self.disconnect:
 | 
			
		||||
    #         with signal.wrap('TARGET_DISCONNECT'):
 | 
			
		||||
    #             self.target.disconnect()
 | 
			
		||||
 | 
			
		||||
    # def _add_parameters(self):
 | 
			
		||||
    #     for name, value in self.parameters.iteritems():
 | 
			
		||||
    #         self.add_parameter(name, value)
 | 
			
		||||
 | 
			
		||||
    # def validate_runtime_parameters(self, parameters):
 | 
			
		||||
    #     self.clear()
 | 
			
		||||
    #     for  name, value in parameters.iteritems():
 | 
			
		||||
    #         self.add_parameter(name, value)
 | 
			
		||||
    #     self.validate_parameters()
 | 
			
		||||
 | 
			
		||||
    # def set_runtime_parameters(self, parameters):
 | 
			
		||||
    #     self.clear()
 | 
			
		||||
    #     for  name, value in parameters.iteritems():
 | 
			
		||||
    #         self.add_parameter(name, value)
 | 
			
		||||
    #     self.set_parameters()
 | 
			
		||||
 | 
			
		||||
    # def clear_parameters(self):
 | 
			
		||||
    #     for cfg in self.runtime_configs:
 | 
			
		||||
    #         cfg.clear()
 | 
			
		||||
 | 
			
		||||
    # def add_parameter(self, name, value):
 | 
			
		||||
    #     for cfg in self.runtime_configs:
 | 
			
		||||
    #         if name in cfg.supported_parameters:
 | 
			
		||||
    #             cfg.add(name, value)
 | 
			
		||||
    #             return
 | 
			
		||||
    #     raise ConfigError('Unexpected runtime parameter "{}".'.format(name))
 | 
			
		||||
 | 
			
		||||
    # def validate_parameters(self):
 | 
			
		||||
    #     for cfg in self.runtime_configs:
 | 
			
		||||
    #         cfg.validate()
 | 
			
		||||
 | 
			
		||||
    # def set_parameters(self):
 | 
			
		||||
    #     for cfg in self.runtime_configs:
 | 
			
		||||
    #         cfg.set()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AndroidAssistant(LinuxAssistant):
 | 
			
		||||
 | 
			
		||||
    name = 'android-assistant'
 | 
			
		||||
    description = """
 | 
			
		||||
    Extends ``LinuxTargetManager`` with Android-specific operations.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    parameters = [
 | 
			
		||||
        Parameter('logcat_poll_period', kind=int,
 | 
			
		||||
                  description="""
 | 
			
		||||
                  If specified, logcat will cached in a temporary file on the 
 | 
			
		||||
                  host every ``logcat_poll_period`` seconds. This is useful for
 | 
			
		||||
                  longer job executions, where on-device logcat buffer may not be 
 | 
			
		||||
                  big enough to capture output for the entire execution.
 | 
			
		||||
                  """),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target, **kwargs):
 | 
			
		||||
        super(AndroidAssistant, self).__init__(target)
 | 
			
		||||
        self.logcat_poll_period = kwargs.get('logcat_poll_period', None)
 | 
			
		||||
        if self.logcat_poll_period:
 | 
			
		||||
            self.logcat_poller = LogcatPoller(target, self.logcat_poll_period)
 | 
			
		||||
        else:
 | 
			
		||||
            self.logcat_poller = None
 | 
			
		||||
 | 
			
		||||
    # def __init__(self, target, context, **kwargs):
 | 
			
		||||
    #     super(AndroidAssistant, self).__init__(target, context, **kwargs)
 | 
			
		||||
    #     self.logcat_poll_period = kwargs.get('logcat_poll_period', None)
 | 
			
		||||
    #     if self.logcat_poll_period:
 | 
			
		||||
    #         self.logcat_poller = LogcatPoller(target, self.logcat_poll_period)
 | 
			
		||||
    #     else:
 | 
			
		||||
    #         self.logcat_poller = None
 | 
			
		||||
 | 
			
		||||
    # def next_job(self, job):
 | 
			
		||||
    #     super(AndroidAssistant, self).next_job(job)
 | 
			
		||||
    #     if self.logcat_poller:
 | 
			
		||||
    #         self.logcat_poller.start()
 | 
			
		||||
 | 
			
		||||
    # def job_done(self, job):
 | 
			
		||||
    #     super(AndroidAssistant, self).job_done(job)
 | 
			
		||||
    #     if self.logcat_poller:
 | 
			
		||||
    #         self.logcat_poller.stop()
 | 
			
		||||
    #     outfile = os.path.join(self.context.output_directory, 'logcat.log')
 | 
			
		||||
    #     self.logger.debug('Dumping logcat to {}'.format(outfile))
 | 
			
		||||
    #     self.dump_logcat(outfile)
 | 
			
		||||
    #     self.clear()
 | 
			
		||||
 | 
			
		||||
    def dump_logcat(self, outfile):
 | 
			
		||||
        if self.logcat_poller:
 | 
			
		||||
            self.logcat_poller.write_log(outfile)
 | 
			
		||||
        else:
 | 
			
		||||
            self.target.dump_logcat(outfile)
 | 
			
		||||
 | 
			
		||||
    def clear_logcat(self):
 | 
			
		||||
        if self.logcat_poller:
 | 
			
		||||
            self.logcat_poller.clear_buffer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LogcatPoller(threading.Thread):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target, period=60, timeout=30):
 | 
			
		||||
        super(LogcatPoller, self).__init__()
 | 
			
		||||
        self.target = target
 | 
			
		||||
        self.logger = logging.getLogger('logcat')
 | 
			
		||||
        self.period = period
 | 
			
		||||
        self.timeout = timeout
 | 
			
		||||
        self.stop_signal = threading.Event()
 | 
			
		||||
        self.lock = threading.Lock()
 | 
			
		||||
        self.buffer_file = tempfile.mktemp()
 | 
			
		||||
        self.last_poll = 0
 | 
			
		||||
        self.daemon = True
 | 
			
		||||
        self.exc = None
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        self.logger.debug('starting polling')
 | 
			
		||||
        try:
 | 
			
		||||
            while True:
 | 
			
		||||
                if self.stop_signal.is_set():
 | 
			
		||||
                    break
 | 
			
		||||
                with self.lock:
 | 
			
		||||
                    current_time = time.time()
 | 
			
		||||
                    if (current_time - self.last_poll) >= self.period:
 | 
			
		||||
                        self.poll()
 | 
			
		||||
                time.sleep(0.5)
 | 
			
		||||
        except Exception:  # pylint: disable=W0703
 | 
			
		||||
            self.exc = WorkerThreadError(self.name, sys.exc_info())
 | 
			
		||||
        self.logger.debug('polling stopped')
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        self.logger.debug('Stopping logcat polling')
 | 
			
		||||
        self.stop_signal.set()
 | 
			
		||||
        self.join(self.timeout)
 | 
			
		||||
        if self.is_alive():
 | 
			
		||||
            self.logger.error('Could not join logcat poller thread.')
 | 
			
		||||
        if self.exc:
 | 
			
		||||
            raise self.exc  # pylint: disable=E0702
 | 
			
		||||
 | 
			
		||||
    def clear_buffer(self):
 | 
			
		||||
        self.logger.debug('clearing logcat buffer')
 | 
			
		||||
        with self.lock:
 | 
			
		||||
            self.target.clear_logcat()
 | 
			
		||||
            with open(self.buffer_file, 'w') as _:  # NOQA
 | 
			
		||||
                pass
 | 
			
		||||
 | 
			
		||||
    def write_log(self, outfile):
 | 
			
		||||
        with self.lock:
 | 
			
		||||
            self.poll()
 | 
			
		||||
            if os.path.isfile(self.buffer_file):
 | 
			
		||||
                shutil.copy(self.buffer_file, outfile)
 | 
			
		||||
            else:  # there was no logcat trace at this time
 | 
			
		||||
                with open(outfile, 'w') as _:  # NOQA
 | 
			
		||||
                    pass
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        self.logger.debug('closing poller')
 | 
			
		||||
        if os.path.isfile(self.buffer_file):
 | 
			
		||||
            os.remove(self.buffer_file)
 | 
			
		||||
 | 
			
		||||
    def poll(self):
 | 
			
		||||
        self.last_poll = time.time()
 | 
			
		||||
        self.target.dump_logcat(self.buffer_file, append=True, timeout=self.timeout)
 | 
			
		||||
        self.target.clear_logcat()
 | 
			
		||||
							
								
								
									
										523
									
								
								wa/target/runtime_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										523
									
								
								wa/target/runtime_config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,523 @@
 | 
			
		||||
from collections import defaultdict, OrderedDict
 | 
			
		||||
 | 
			
		||||
from wa.framework.plugin import Plugin
 | 
			
		||||
from wa.framework.exception import ConfigError
 | 
			
		||||
 | 
			
		||||
from devlib.exception import TargetError
 | 
			
		||||
from devlib.utils.misc import unique
 | 
			
		||||
from devlib.utils.types import integer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RuntimeConfig(Plugin):
 | 
			
		||||
 | 
			
		||||
    kind = 'runtime-config'
 | 
			
		||||
 | 
			
		||||
    parameters = [
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
# class RuntimeConfig(object):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def supported_parameters(self):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def core_names(self):
 | 
			
		||||
        return unique(self.target.core_names)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target):
 | 
			
		||||
        super(RuntimeConfig, self).__init__()
 | 
			
		||||
        self.target = target
 | 
			
		||||
 | 
			
		||||
    def initialize(self, context):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def add(self, name, value):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def set(self):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HotplugRuntimeConfig(RuntimeConfig):
 | 
			
		||||
##### NOTE: Currently if initialized with cores hotplugged, this will fail trying to hotplug back in
 | 
			
		||||
    @property
 | 
			
		||||
    def supported_parameters(self):
 | 
			
		||||
        # params = ['cores'.format(c) for c in self.target.core_names]
 | 
			
		||||
        # params = ['{}_cores'.format(c) for c in self.target.core_names]
 | 
			
		||||
        params = ['cores']
 | 
			
		||||
        return params
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target):
 | 
			
		||||
        super(HotplugRuntimeConfig, self).__init__(target)
 | 
			
		||||
        self.num_cores = defaultdict(dict)
 | 
			
		||||
 | 
			
		||||
    def add(self, name, value):
 | 
			
		||||
        if not self.target.has('hotplug'):
 | 
			
		||||
            raise TargetError('Target does not support hotplug.')
 | 
			
		||||
        core, _ = split_parameter_name(name, self.supported_parameters)
 | 
			
		||||
 | 
			
		||||
        # cpus = cpusFromPrefix(core, self.target)
 | 
			
		||||
        # core = name.split('_')[0]
 | 
			
		||||
        value = integer(value)
 | 
			
		||||
        if core not in self.core_names:
 | 
			
		||||
            raise ValueError(name)
 | 
			
		||||
        max_cores = self.core_count(core)
 | 
			
		||||
        if value > max_cores:
 | 
			
		||||
            message = 'Cannot set number of {}\'s to {}; max is {}'
 | 
			
		||||
            raise ValueError(message.format(core, value, max_cores))
 | 
			
		||||
        self.num_cores[core] = value
 | 
			
		||||
        if all(v == 0 for v in self.num_cores.values()):
 | 
			
		||||
            raise ValueError('Cannot set number of all cores to 0')
 | 
			
		||||
 | 
			
		||||
    def set(self):
 | 
			
		||||
        for c, n in reversed(sorted(self.num_cores.iteritems(),
 | 
			
		||||
                                    key=lambda x: x[1])):
 | 
			
		||||
            self.set_num_online_cpus(c, n)
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        self.num_cores = defaultdict(dict)
 | 
			
		||||
 | 
			
		||||
    def set_num_online_cpus(self, core, number):
 | 
			
		||||
        indexes = [i for i, c in enumerate(self.target.core_names) if c == core]
 | 
			
		||||
        self.target.hotplug.online(*indexes[:number])
 | 
			
		||||
        self.target.hotplug.offline(*indexes[number:])
 | 
			
		||||
 | 
			
		||||
    def core_count(self, core):
 | 
			
		||||
        return sum(1 for c in self.target.core_names if c == core)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SysfileValuesRuntimeConfig(RuntimeConfig):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def supported_parameters(self):
 | 
			
		||||
        return ['sysfile_values']
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target):
 | 
			
		||||
        super(SysfileValuesRuntimeConfig, self).__init__(target)
 | 
			
		||||
        self.sysfile_values = OrderedDict()
 | 
			
		||||
 | 
			
		||||
    def add(self, name, value):
 | 
			
		||||
        for f, v in value.iteritems():
 | 
			
		||||
            if f.endswith('+'):
 | 
			
		||||
                f = f[:-1]
 | 
			
		||||
            elif f.endswith('+!'):
 | 
			
		||||
                f = f[:-2] + '!'
 | 
			
		||||
            else:
 | 
			
		||||
                if f.endswith('!'):
 | 
			
		||||
                    self._check_exists(f[:-1])
 | 
			
		||||
                else:
 | 
			
		||||
                    self._check_exists(f)
 | 
			
		||||
            self.sysfile_values[f] = v
 | 
			
		||||
 | 
			
		||||
    def set(self):
 | 
			
		||||
        for f, v in self.sysfile_values.iteritems():
 | 
			
		||||
            verify = True
 | 
			
		||||
            if f.endswith('!'):
 | 
			
		||||
                verify = False
 | 
			
		||||
                f = f[:-1]
 | 
			
		||||
            self.target.write_value(f, v, verify=verify)
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        self.sysfile_values = OrderedDict()
 | 
			
		||||
 | 
			
		||||
    def _check_exists(self, path):
 | 
			
		||||
        if not self.target.file_exists(path):
 | 
			
		||||
            raise ConfigError('Sysfile "{}" does not exist.'.format(path))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CpufreqRuntimeConfig(RuntimeConfig):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def supported_parameters(self):
 | 
			
		||||
        # params = ['{}_frequency'.format(c) for c in self.core_names]
 | 
			
		||||
        # params.extend(['{}_max_frequency'.format(c) for c in self.core_names])
 | 
			
		||||
        # params.extend(['{}_min_frequency'.format(c) for c in self.core_names])
 | 
			
		||||
        # params.extend(['{}_governor'.format(c) for c in self.core_names])
 | 
			
		||||
        # params.extend(['{}_governor_tunables'.format(c) for c in self.core_names])
 | 
			
		||||
 | 
			
		||||
        params = ['frequency']
 | 
			
		||||
        params.extend(['max_frequency'])
 | 
			
		||||
        params.extend(['min_frequency'])
 | 
			
		||||
        params.extend(['governor'])
 | 
			
		||||
        params.extend(['governor_tunables'])
 | 
			
		||||
 | 
			
		||||
        return params
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target):
 | 
			
		||||
        super(CpufreqRuntimeConfig, self).__init__(target)
 | 
			
		||||
        self.config = defaultdict(dict)
 | 
			
		||||
        self.supports_userspace = None
 | 
			
		||||
        self.supported_freqs = {}
 | 
			
		||||
        self.supported_govenors = {}
 | 
			
		||||
        self.min_supported_freq = {}
 | 
			
		||||
        self.max_supported_freq = {}
 | 
			
		||||
 | 
			
		||||
        for cpu in self.target.list_online_cpus():
 | 
			
		||||
            self.supported_freqs[cpu] = self.target.cpufreq.list_frequencies(cpu) or []
 | 
			
		||||
            self.supported_govenors[cpu] = self.target.cpufreq.list_governors(cpu) or []
 | 
			
		||||
 | 
			
		||||
    def add(self, name, value):
 | 
			
		||||
        if not self.target.has('cpufreq'):
 | 
			
		||||
            raise TargetError('Target does not support cpufreq.')
 | 
			
		||||
 | 
			
		||||
        prefix, parameter = split_parameter_name(name, self.supported_parameters)
 | 
			
		||||
        # Get list of valid cpus for a given prefix.
 | 
			
		||||
        cpus = uniqueDomainCpusFromPrefix(prefix, self.target)
 | 
			
		||||
 | 
			
		||||
        for cpu in cpus:
 | 
			
		||||
            # if cpu not in self.target.list_online_cpus():
 | 
			
		||||
            #     message = 'Unexpected core name "{}"; must be in {}'
 | 
			
		||||
            #     raise ConfigError(message.format(core, self.core_names))
 | 
			
		||||
            # try:
 | 
			
		||||
            #     cpu = self.target.list_online_cpus(core)[0]
 | 
			
		||||
            # except IndexError:
 | 
			
		||||
            #     message = 'Cannot retrieve frequencies for {} as no CPUs are online.'
 | 
			
		||||
            #     raise TargetError(message.format(core))
 | 
			
		||||
            if parameter.endswith('frequency'):
 | 
			
		||||
                try:
 | 
			
		||||
                    value = integer(value)
 | 
			
		||||
                except ValueError:
 | 
			
		||||
                    if value.upper() == 'MAX':
 | 
			
		||||
                        value = self.supported_freqs[cpu][-1]
 | 
			
		||||
                    elif value.upper() == 'MIN':
 | 
			
		||||
                        value = self.supported_freqs[cpu][0]
 | 
			
		||||
                    else:
 | 
			
		||||
                        msg = 'Invalid value {} specified for {}'
 | 
			
		||||
                        raise ConfigError(msg.format(value, parameter))
 | 
			
		||||
            self.config[cpu][parameter] = value
 | 
			
		||||
 | 
			
		||||
    def set(self):
 | 
			
		||||
        for cpu in self.config:
 | 
			
		||||
            config = self.config[cpu]
 | 
			
		||||
            if config.get('governor'):
 | 
			
		||||
                self.configure_governor(cpu,
 | 
			
		||||
                                        config.get('governor'),
 | 
			
		||||
                                        config.get('governor_tunables'))
 | 
			
		||||
            self.configure_frequency(cpu,
 | 
			
		||||
                                     config.get('frequency'),
 | 
			
		||||
                                     config.get('min_frequency'),
 | 
			
		||||
                                     config.get('max_frequency'))
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        self.config = defaultdict(dict)
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        for cpu in self.config:
 | 
			
		||||
            if cpu not in self.target.list_online_cpus():
 | 
			
		||||
                message = 'Cannot configure frequencies for {} as no CPUs are online.'
 | 
			
		||||
                raise TargetError(message.format(cpu))
 | 
			
		||||
 | 
			
		||||
            config = self.config[cpu]
 | 
			
		||||
            minf = config.get('min_frequency')
 | 
			
		||||
            maxf = config.get('max_frequency')
 | 
			
		||||
            freq = config.get('frequency')
 | 
			
		||||
            governor = config.get('governor')
 | 
			
		||||
            governor_tunables = config.get('governor_tunables')
 | 
			
		||||
 | 
			
		||||
            if maxf and minf > maxf:
 | 
			
		||||
                message = '{}: min_frequency ({}) cannot be greater than max_frequency ({})'
 | 
			
		||||
                raise ConfigError(message.format(cpu, minf, maxf))
 | 
			
		||||
            if maxf and freq > maxf:
 | 
			
		||||
                message = '{}: cpu frequency ({}) cannot be greater than max_frequency ({})'
 | 
			
		||||
                raise ConfigError(message.format(cpu, freq, maxf))
 | 
			
		||||
            if freq and minf > freq:
 | 
			
		||||
                message = '{}: min_frequency ({}) cannot be greater than cpu frequency ({})'
 | 
			
		||||
                raise ConfigError(message.format(cpu, minf, freq))
 | 
			
		||||
 | 
			
		||||
            # Check that either userspace governor is available or min and max do not differ to frequency
 | 
			
		||||
            if 'userspace' not in self.supported_govenors[cpu]:
 | 
			
		||||
                self.supports_userspace = False
 | 
			
		||||
                if minf and minf != freq:
 | 
			
		||||
                    message = '{}: "userspace" governor not available, min frequency ({}) cannot be different to frequency {}'
 | 
			
		||||
                    raise ConfigError(message.format(cpu, minf, freq))
 | 
			
		||||
                if maxf and maxf != freq:
 | 
			
		||||
                    message = '{}: "userspace" governor not available, max frequency ({}) cannot be different to frequency {}'
 | 
			
		||||
                    raise ConfigError(message.format(cpu, maxf, freq))
 | 
			
		||||
            else:
 | 
			
		||||
                self.supports_userspace = True
 | 
			
		||||
 | 
			
		||||
            # Check that specified values are available on the cpu
 | 
			
		||||
            if minf and not minf in self.supported_freqs[cpu]:
 | 
			
		||||
                msg = '{}: Minimum frequency {}Hz not available. Must be in {}'.format(cpu, minf, self.supported_freqs[cpu])
 | 
			
		||||
                raise TargetError(msg)
 | 
			
		||||
            if maxf and not maxf in self.supported_freqs[cpu]:
 | 
			
		||||
                msg = '{}: Maximum frequency {}Hz not available. Must be in {}'.format(cpu, maxf, self.supported_freqs[cpu])
 | 
			
		||||
                raise TargetError(msg)
 | 
			
		||||
            if freq and not freq in self.supported_freqs[cpu]:
 | 
			
		||||
                msg = '{}: Frequency {}Hz not available. Must be in {}'.format(cpu, freq, self.supported_freqs[cpu])
 | 
			
		||||
                raise TargetError(msg)
 | 
			
		||||
            if governor and governor not in self.supported_govenors[cpu]:
 | 
			
		||||
                raise TargetError('{}: {} governor not available'.format(cpu, governor))
 | 
			
		||||
            if governor_tunables and not governor:
 | 
			
		||||
                raise TargetError('{}: {} governor tunables cannot be provided without a governor'.format(cpu, governor))
 | 
			
		||||
 | 
			
		||||
            # Should check if governor is set to userspace if frequencies are being set?
 | 
			
		||||
            # Save a list of available frequencies on the device and check to see if matches?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def configure_frequency(self, cpu, freq=None, min_freq=None, max_freq=None):
 | 
			
		||||
        if cpu not in self.target.list_online_cpus():
 | 
			
		||||
            message = 'Cannot configure frequencies for {} as no CPUs are online.'
 | 
			
		||||
            raise TargetError(message.format(cpu))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        current_min_freq = self.target.cpufreq.get_min_frequency(cpu)
 | 
			
		||||
        current_freq = self.target.cpufreq.get_frequency(cpu)
 | 
			
		||||
        current_max_freq = self.target.cpufreq.get_max_frequency(cpu)
 | 
			
		||||
 | 
			
		||||
        if freq:
 | 
			
		||||
            # If 'userspace' governor is not available 'spoof' functionality
 | 
			
		||||
            if not self.supports_userspace:
 | 
			
		||||
                min_freq = max_freq = freq
 | 
			
		||||
            else: ##############################-- Probably shouldn't do this.
 | 
			
		||||
                # Set min/max frequency if required
 | 
			
		||||
                if not min_freq:
 | 
			
		||||
                    min_freq = self.target.cpufreq.get_min_frequency(cpu)
 | 
			
		||||
                if not max_freq:
 | 
			
		||||
                    max_freq = self.target.cpufreq.get_max_frequency(cpu)
 | 
			
		||||
 | 
			
		||||
            if freq < current_freq:
 | 
			
		||||
                self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
                if self.supports_userspace:
 | 
			
		||||
                    self.target.cpufreq.set_frequency(cpu, freq)
 | 
			
		||||
                self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
            else:
 | 
			
		||||
                self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
                if self.supports_userspace:
 | 
			
		||||
                    self.target.cpufreq.set_frequency(cpu, freq)
 | 
			
		||||
                self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if max_freq:
 | 
			
		||||
            if max_freq < current_min_freq:
 | 
			
		||||
                if min_freq:
 | 
			
		||||
                    self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
                    self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
                    min_freq_set = True
 | 
			
		||||
                else:
 | 
			
		||||
                    message = '{}: Cannot set max_frequency ({}) below current min frequency ({}).'
 | 
			
		||||
                    raise TargetError(message.format(cpu, max_freq, current_min_freq))
 | 
			
		||||
            else:
 | 
			
		||||
                self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
        if min_freq and not min_freq_set:
 | 
			
		||||
            current_max_freq = max_freq or current_max_freq
 | 
			
		||||
            if min_freq > current_max_freq:
 | 
			
		||||
                message = '{}: Cannot set min_frequency ({}) below current max frequency ({}).'
 | 
			
		||||
                raise TargetError(message.format(cpu, max_freq, current_min_freq))
 | 
			
		||||
            self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        # if freq:
 | 
			
		||||
        #     if not min_freq:
 | 
			
		||||
        #         min_freq = self.target.cpufreq.get_min_frequency(cpu)
 | 
			
		||||
        #         min_freq = freq
 | 
			
		||||
        #     if not max_freq:
 | 
			
		||||
        #         max_freq = self.target.cpufreq.get_max_frequency(cpu)
 | 
			
		||||
        #         max_freq = freq
 | 
			
		||||
        #     self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
        #     self.target.cpufreq.set_frequency(cpu, freq)
 | 
			
		||||
        #     self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
    #     #     return
 | 
			
		||||
    #     min_freq_set = False
 | 
			
		||||
    #     if max_freq:
 | 
			
		||||
    #         current_min_freq = self.target.cpufreq.get_min_frequency(cpu)
 | 
			
		||||
    #         if max_freq < current_min_freq:
 | 
			
		||||
    #             if min_freq:
 | 
			
		||||
    #                 self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
    #                 self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
    #                 min_freq_set = True
 | 
			
		||||
    #             else:
 | 
			
		||||
    #                 message = '{}: Cannot set max_frequency ({}) below current min frequency ({}).'
 | 
			
		||||
    #                 raise TargetError(message.format(core, max_freq, current_min_freq))
 | 
			
		||||
    #         else:
 | 
			
		||||
    #             self.target.cpufreq.set_max_frequency(cpu, max_freq)
 | 
			
		||||
    #     if min_freq and not min_freq_set:
 | 
			
		||||
    #         current_max_freq = max_freq or self.target.cpufreq.get_max_frequency(cpu)
 | 
			
		||||
    #         if min_freq > current_max_freq:
 | 
			
		||||
    #             message = '{}: Cannot set min_frequency ({}) below current max frequency ({}).'
 | 
			
		||||
    #             raise TargetError(message.format(core, max_freq, current_min_freq))
 | 
			
		||||
    #         self.target.cpufreq.set_min_frequency(cpu, min_freq)
 | 
			
		||||
 | 
			
		||||
    def configure_governor(self, cpu, governor, governor_tunables=None):
 | 
			
		||||
        if cpu not in self.target.list_online_cpus():
 | 
			
		||||
            message = 'Cannot configure governor for {} as no CPUs are online.'
 | 
			
		||||
            raise TargetError(message.format(cpu))
 | 
			
		||||
 | 
			
		||||
        # for cpu in self.target.list_online_cpus(cpu): #All cpus or only online?
 | 
			
		||||
        if governor not in self.supported_govenors[cpu]:
 | 
			
		||||
            raise TargetError('{}: {} governor not available'.format(cpu, governor))
 | 
			
		||||
        if governor_tunables:
 | 
			
		||||
            self.target.cpufreq.set_governor(cpu, governor, **governor_tunables)
 | 
			
		||||
        else:
 | 
			
		||||
            self.target.cpufreq.set_governor(cpu, governor)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CpuidleRuntimeConfig(RuntimeConfig):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def supported_parameters(self):
 | 
			
		||||
        params = ['idle_states']
 | 
			
		||||
        return params
 | 
			
		||||
 | 
			
		||||
    def __init__(self, target):
 | 
			
		||||
        super(CpuidleRuntimeConfig, self).__init__(target)
 | 
			
		||||
        self.config = defaultdict(dict)
 | 
			
		||||
        self.aliases = ['ENABLE_ALL', 'DISABLE_ALL']
 | 
			
		||||
        self.available_states = {}
 | 
			
		||||
 | 
			
		||||
        for cpu in self.target.list_online_cpus():
 | 
			
		||||
            self.available_states[cpu] = self.target.cpuidle.get_states(cpu) or []
 | 
			
		||||
 | 
			
		||||
    def add(self, name, values):
 | 
			
		||||
        if not self.target.has('cpufreq'):
 | 
			
		||||
            raise TargetError('Target does not support cpufreq.')
 | 
			
		||||
 | 
			
		||||
        prefix, _ = split_parameter_name(name, self.supported_parameters)
 | 
			
		||||
        cpus = uniqueDomainCpusFromPrefix(prefix, self.target)
 | 
			
		||||
        # core, _ = name.split('_', 1)
 | 
			
		||||
        # if core not in self.core_names:
 | 
			
		||||
        #     message = 'Unexpected core name "{}"; must be in {}'
 | 
			
		||||
        #     raise ConfigError(message.format(core, self.core_names))
 | 
			
		||||
 | 
			
		||||
        for cpu in cpus:
 | 
			
		||||
            if values in self.aliases:
 | 
			
		||||
                self.config[cpu] = [values]
 | 
			
		||||
            else:
 | 
			
		||||
                self.config[cpu] = values
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        for cpu in self.config:
 | 
			
		||||
            if cpu not in self.target.list_online_cpus():
 | 
			
		||||
                message = 'Cannot configure idle states for {} as no CPUs are online.'
 | 
			
		||||
                raise TargetError(message.format(cpu))
 | 
			
		||||
            for state in self.config[cpu]:
 | 
			
		||||
                state = state[1:] if state.startswith('~') else state
 | 
			
		||||
                # self.available_states.extend(self.aliases)
 | 
			
		||||
                if state not in self.available_states[cpu] + self.aliases:
 | 
			
		||||
                    message = 'Unexpected idle state "{}"; must be in {}'
 | 
			
		||||
                    raise ConfigError(message.format(state, self.available_states))
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        self.config = defaultdict(dict)
 | 
			
		||||
 | 
			
		||||
    def set(self):
 | 
			
		||||
        for cpu in self.config:
 | 
			
		||||
            for state in self.config[cpu]:
 | 
			
		||||
                self.configure_idle_state(state, cpu)
 | 
			
		||||
 | 
			
		||||
    def configure_idle_state(self, state, cpu=None):
 | 
			
		||||
        if cpu is not None:
 | 
			
		||||
            if cpu not in self.target.list_online_cpus():
 | 
			
		||||
                message = 'Cannot configure idle state for {} as no CPUs are online {}.'
 | 
			
		||||
                raise TargetError(message.format(self.target.core_names[cpu], self.target.list_online_cpus()))
 | 
			
		||||
        else:
 | 
			
		||||
            cpu = 0
 | 
			
		||||
 | 
			
		||||
        # Check for aliases
 | 
			
		||||
        if state == 'ENABLE_ALL':
 | 
			
		||||
            self.target.cpuidle.enable_all(cpu)
 | 
			
		||||
        elif state == 'DISABLE_ALL':
 | 
			
		||||
            self.target.cpuidle.disable_all(cpu)
 | 
			
		||||
        elif state.startswith('~'):
 | 
			
		||||
            self.target.cpuidle.disable(state[1:], cpu)
 | 
			
		||||
        else:
 | 
			
		||||
            self.target.cpuidle.enable(state, cpu)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# def cpusFromPrefix(name, target, params):
 | 
			
		||||
#     prefix = ''
 | 
			
		||||
#     print prefix
 | 
			
		||||
#     for param in params:
 | 
			
		||||
#         if len(name.split(param)) > 1:
 | 
			
		||||
#             print name
 | 
			
		||||
#             print param
 | 
			
		||||
#             print name.split(param)
 | 
			
		||||
#             prefix, _ = name.split(param)
 | 
			
		||||
#             prefix = prefix.replace('_', '')
 | 
			
		||||
#             break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TO BE MOVED TO UTILS FILE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Function to return the cpu prefix without the trailing underscore if
 | 
			
		||||
# present from a given list of parameters, and its matching parameter
 | 
			
		||||
def split_parameter_name(name, params):
 | 
			
		||||
    for param in sorted(params, key=len)[::-1]: # Try matching longest parameter first
 | 
			
		||||
        if len(name.split(param)) > 1:
 | 
			
		||||
            prefix, _ = name.split(param)
 | 
			
		||||
            return prefix[:-1], param
 | 
			
		||||
    message = 'Cannot split {}, must in the form [core_]parameter'
 | 
			
		||||
    raise ConfigError(message.format(name))
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
def cpusFromPrefix(prefix, target):   ##### DECIDE WHETHER TO INCLUDE OFFLINE CPUS?   ####
 | 
			
		||||
 | 
			
		||||
    # Deal with big little substitution
 | 
			
		||||
    if prefix.lower() == 'big':
 | 
			
		||||
        prefix = target.big_core
 | 
			
		||||
        if not prefix:
 | 
			
		||||
            raise ConfigError('big core name could not be retrieved')
 | 
			
		||||
    elif prefix.lower() == 'little':
 | 
			
		||||
        prefix = target.little_core
 | 
			
		||||
        if not prefix:
 | 
			
		||||
            raise ConfigError('little core name could not be retrieved')
 | 
			
		||||
 | 
			
		||||
    cpu_list = target.list_online_cpus() + target.list_offline_cpus()
 | 
			
		||||
 | 
			
		||||
    # Apply to all cpus
 | 
			
		||||
    if not prefix:
 | 
			
		||||
        cpus = cpu_list
 | 
			
		||||
 | 
			
		||||
    # Return all cores with specified name
 | 
			
		||||
    elif prefix in target.core_names:
 | 
			
		||||
        cpus = target.core_cpus(prefix)
 | 
			
		||||
 | 
			
		||||
    # Check if core number has been supplied.
 | 
			
		||||
    else:
 | 
			
		||||
        # core_no = prefix[4]
 | 
			
		||||
        core_no = re.match('cpu([0-9]+)', prefix, re.IGNORECASE)
 | 
			
		||||
        if core_no:
 | 
			
		||||
            cpus = [int(core_no.group(1))]
 | 
			
		||||
            if cpus[0] not in cpu_list:
 | 
			
		||||
                message = 'CPU{} is not available, must be in {}'
 | 
			
		||||
                raise ConfigError(message.format(cpus[0], cpu_list))
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            message = 'Unexpected core name "{}"'
 | 
			
		||||
            raise ConfigError(message.format(prefix))
 | 
			
		||||
    # Should this be applied for everything or just all cpus?
 | 
			
		||||
    # Make sure not to include any cpus within the same frequency domain
 | 
			
		||||
    # for cpu in cpus:
 | 
			
		||||
    #     if cpu not in cpus: # Already removed
 | 
			
		||||
    #         continue
 | 
			
		||||
    #     cpus = [c for c in cpus if (c is cpu) or
 | 
			
		||||
    #                 (c not in target.cpufreq.get_domain_cpus(cpu))]
 | 
			
		||||
    # print 'Final results ' + str(cpus)
 | 
			
		||||
    # return cpus
 | 
			
		||||
    return cpus
 | 
			
		||||
 | 
			
		||||
# Function to only return cpus list on different frequency domains.
 | 
			
		||||
def uniqueDomainCpusFromPrefix(prefix, target):
 | 
			
		||||
    cpus = cpusFromPrefix(prefix, target)
 | 
			
		||||
    for cpu in cpus:
 | 
			
		||||
        if cpu not in cpus: # Already removed
 | 
			
		||||
            continue
 | 
			
		||||
        cpus = [c for c in cpus if (c is cpu) or
 | 
			
		||||
                    (c not in target.cpufreq.get_domain_cpus(cpu))]
 | 
			
		||||
    return cpus
 | 
			
		||||
		Reference in New Issue
	
	Block a user