mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-19 04:21:17 +00:00
Implementing dynamic device modules
Dynamic modules may be loaded automatically on device initialization if the device supports them. Dynamic modules implent probe() method to determine whether they are supported by a particular deviced. devcpufreq and cpuidle have been converted into dynamic modules
This commit is contained in:
parent
73d85c2b4e
commit
d9f45db71e
@ -107,6 +107,11 @@ class BaseLinuxDevice(Device): # pylint: disable=abstract-method
|
||||
value_name='tunables'),
|
||||
]
|
||||
|
||||
dynamic_modules = [
|
||||
'devcpufreq',
|
||||
'cpuidle',
|
||||
]
|
||||
|
||||
@property
|
||||
def abi(self):
|
||||
if not self._abi:
|
||||
|
@ -35,6 +35,7 @@ from collections import OrderedDict
|
||||
from contextlib import contextmanager
|
||||
|
||||
from wlauto.core.extension import Extension, ExtensionMeta, AttributeCollection, Parameter
|
||||
from wlauto.core.extension_loader import ExtensionLoader
|
||||
from wlauto.exceptions import DeviceError, ConfigError
|
||||
from wlauto.utils.types import list_of_integers, list_of, caseless_string
|
||||
|
||||
@ -93,10 +94,34 @@ class CoreParameter(RuntimeParameter):
|
||||
return params
|
||||
|
||||
|
||||
class DynamicModuleSpec(dict):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.keys()[0]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
dict.__init__(self)
|
||||
if args:
|
||||
if len(args) > 1:
|
||||
raise ValueError(args)
|
||||
value = args[0]
|
||||
else:
|
||||
value = kwargs
|
||||
if isinstance(value, basestring):
|
||||
self[value] = {}
|
||||
elif isinstance(value, dict) and len(value) == 1:
|
||||
for k, v in value.iteritems():
|
||||
self[k] = v
|
||||
else:
|
||||
raise ValueError(value)
|
||||
|
||||
|
||||
class DeviceMeta(ExtensionMeta):
|
||||
|
||||
to_propagate = ExtensionMeta.to_propagate + [
|
||||
('runtime_parameters', RuntimeParameter, AttributeCollection),
|
||||
('dynamic_modules', DynamicModuleSpec, AttributeCollection),
|
||||
]
|
||||
|
||||
|
||||
@ -157,6 +182,9 @@ class Device(Extension):
|
||||
]
|
||||
|
||||
runtime_parameters = []
|
||||
# dynamic modules are loaded or not based on whether the device supports
|
||||
# them (established at runtime by module probling the device).
|
||||
dynamic_modules = []
|
||||
|
||||
# These must be overwritten by subclasses.
|
||||
name = None
|
||||
@ -197,7 +225,17 @@ class Device(Extension):
|
||||
been connecte).
|
||||
|
||||
"""
|
||||
pass
|
||||
loader = ExtensionLoader()
|
||||
for module_spec in self.dynamic_modules:
|
||||
module = self._load_module(loader, module_spec)
|
||||
if not hasattr(module, 'probe'):
|
||||
message = 'Module {} does not have "probe" attribute; cannot be loaded dynamically'
|
||||
raise ValueError(message.format(module.name))
|
||||
if module.probe(self):
|
||||
self.logger.debug('Installing module "{}"'.format(module.name))
|
||||
self._install_module(module)
|
||||
else:
|
||||
self.logger.debug('Module "{}" is not supported by the device'.format(module.name))
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
|
@ -598,28 +598,8 @@ class Extension(object):
|
||||
for module_spec in modules:
|
||||
if not module_spec:
|
||||
continue
|
||||
if isinstance(module_spec, basestring):
|
||||
name = module_spec
|
||||
params = {}
|
||||
elif isinstance(module_spec, dict):
|
||||
if len(module_spec) != 1:
|
||||
message = 'Invalid module spec: {}; dict must have exctly one key -- the module name.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
name, params = module_spec.items()[0]
|
||||
else:
|
||||
message = 'Invalid module spec: {}; must be a string or a one-key dict.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
|
||||
if not isinstance(params, dict):
|
||||
message = 'Invalid module spec: {}; dict value must also be a dict.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
|
||||
module = loader.get_module(name, owner=self, **params)
|
||||
module.initialize(None)
|
||||
for capability in module.capabilities:
|
||||
if capability not in self.capabilities:
|
||||
self.capabilities.append(capability)
|
||||
self._modules.append(module)
|
||||
module = self._load_module(loader, module_spec)
|
||||
self._install_module(module)
|
||||
|
||||
def has(self, capability):
|
||||
"""Check if this extension has the specified capability. The alternative method ``can`` is
|
||||
@ -629,6 +609,33 @@ class Extension(object):
|
||||
|
||||
can = has
|
||||
|
||||
def _load_module(self, loader, module_spec):
|
||||
if isinstance(module_spec, basestring):
|
||||
name = module_spec
|
||||
params = {}
|
||||
elif isinstance(module_spec, dict):
|
||||
if len(module_spec) != 1:
|
||||
message = 'Invalid module spec: {}; dict must have exctly one key -- the module name.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
name, params = module_spec.items()[0]
|
||||
else:
|
||||
message = 'Invalid module spec: {}; must be a string or a one-key dict.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
|
||||
if not isinstance(params, dict):
|
||||
message = 'Invalid module spec: {}; dict value must also be a dict.'
|
||||
raise ValueError(message.format(module_spec))
|
||||
|
||||
module = loader.get_module(name, owner=self, **params)
|
||||
module.initialize(None)
|
||||
return module
|
||||
|
||||
def _install_module(self, module):
|
||||
for capability in module.capabilities:
|
||||
if capability not in self.capabilities:
|
||||
self.capabilities.append(capability)
|
||||
self._modules.append(module)
|
||||
|
||||
def __check_from_loader(self):
|
||||
"""
|
||||
There are a few things that need to happen in order to get a valide extension instance.
|
||||
|
@ -28,6 +28,10 @@ class CpufreqModule(Module):
|
||||
"""
|
||||
capabilities = ['cpufreq']
|
||||
|
||||
def probe(self, device): # pylint: disable=no-self-use
|
||||
path = '/sys/devices/system/cpu/cpufreq'
|
||||
return device.file_exists(path)
|
||||
|
||||
def initialize(self, context):
|
||||
# pylint: disable=W0201
|
||||
CpufreqModule._available_governors = {}
|
||||
|
@ -86,6 +86,9 @@ class Cpuidle(Module):
|
||||
|
||||
root_path = '/sys/devices/system/cpu/cpuidle'
|
||||
|
||||
def probe(self, device):
|
||||
return device.file_exists(self.root_path)
|
||||
|
||||
def initialize(self, context):
|
||||
self.device = self.root_owner
|
||||
signal.connect(self._on_device_init, signal.RUN_INIT, priority=1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user