mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-04-20 09:40:50 +01: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'),
|
value_name='tunables'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
dynamic_modules = [
|
||||||
|
'devcpufreq',
|
||||||
|
'cpuidle',
|
||||||
|
]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def abi(self):
|
def abi(self):
|
||||||
if not self._abi:
|
if not self._abi:
|
||||||
|
@ -35,6 +35,7 @@ from collections import OrderedDict
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from wlauto.core.extension import Extension, ExtensionMeta, AttributeCollection, Parameter
|
from wlauto.core.extension import Extension, ExtensionMeta, AttributeCollection, Parameter
|
||||||
|
from wlauto.core.extension_loader import ExtensionLoader
|
||||||
from wlauto.exceptions import DeviceError, ConfigError
|
from wlauto.exceptions import DeviceError, ConfigError
|
||||||
from wlauto.utils.types import list_of_integers, list_of, caseless_string
|
from wlauto.utils.types import list_of_integers, list_of, caseless_string
|
||||||
|
|
||||||
@ -93,10 +94,34 @@ class CoreParameter(RuntimeParameter):
|
|||||||
return params
|
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):
|
class DeviceMeta(ExtensionMeta):
|
||||||
|
|
||||||
to_propagate = ExtensionMeta.to_propagate + [
|
to_propagate = ExtensionMeta.to_propagate + [
|
||||||
('runtime_parameters', RuntimeParameter, AttributeCollection),
|
('runtime_parameters', RuntimeParameter, AttributeCollection),
|
||||||
|
('dynamic_modules', DynamicModuleSpec, AttributeCollection),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -157,6 +182,9 @@ class Device(Extension):
|
|||||||
]
|
]
|
||||||
|
|
||||||
runtime_parameters = []
|
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.
|
# These must be overwritten by subclasses.
|
||||||
name = None
|
name = None
|
||||||
@ -197,7 +225,17 @@ class Device(Extension):
|
|||||||
been connecte).
|
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):
|
def reset(self):
|
||||||
"""
|
"""
|
||||||
|
@ -598,28 +598,8 @@ class Extension(object):
|
|||||||
for module_spec in modules:
|
for module_spec in modules:
|
||||||
if not module_spec:
|
if not module_spec:
|
||||||
continue
|
continue
|
||||||
if isinstance(module_spec, basestring):
|
module = self._load_module(loader, module_spec)
|
||||||
name = module_spec
|
self._install_module(module)
|
||||||
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)
|
|
||||||
|
|
||||||
def has(self, capability):
|
def has(self, capability):
|
||||||
"""Check if this extension has the specified capability. The alternative method ``can`` is
|
"""Check if this extension has the specified capability. The alternative method ``can`` is
|
||||||
@ -629,6 +609,33 @@ class Extension(object):
|
|||||||
|
|
||||||
can = has
|
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):
|
def __check_from_loader(self):
|
||||||
"""
|
"""
|
||||||
There are a few things that need to happen in order to get a valide extension instance.
|
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']
|
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):
|
def initialize(self, context):
|
||||||
# pylint: disable=W0201
|
# pylint: disable=W0201
|
||||||
CpufreqModule._available_governors = {}
|
CpufreqModule._available_governors = {}
|
||||||
|
@ -86,6 +86,9 @@ class Cpuidle(Module):
|
|||||||
|
|
||||||
root_path = '/sys/devices/system/cpu/cpuidle'
|
root_path = '/sys/devices/system/cpu/cpuidle'
|
||||||
|
|
||||||
|
def probe(self, device):
|
||||||
|
return device.file_exists(self.root_path)
|
||||||
|
|
||||||
def initialize(self, context):
|
def initialize(self, context):
|
||||||
self.device = self.root_owner
|
self.device = self.root_owner
|
||||||
signal.connect(self._on_device_init, signal.RUN_INIT, priority=1)
|
signal.connect(self._on_device_init, signal.RUN_INIT, priority=1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user