mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 15:12:25 +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