mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-02-20 11:58:55 +00:00
wa/types: Add cpu_mask type
Add a cpu_mask type to allow for users to use a consistent way of representing a cpus mask with properties to provide conversions between the various required forms. The mask can be specified directly as a mask, as a list of cpus indexes or a sysfs-style string. Also add support for the type to be serialized/deserialzed for the json and yaml serializers.
This commit is contained in:
parent
a2b0705ff0
commit
670fe6fb83
@ -52,7 +52,7 @@ import dateutil.parser
|
||||
|
||||
from wa.framework.exception import SerializerSyntaxError
|
||||
from wa.utils.misc import isiterable
|
||||
from wa.utils.types import regex_type, none_type, level
|
||||
from wa.utils.types import regex_type, none_type, level, cpu_mask
|
||||
|
||||
|
||||
__all__ = [
|
||||
@ -91,6 +91,8 @@ class WAJSONEncoder(_json.JSONEncoder):
|
||||
return 'DATET:{}'.format(obj.isoformat())
|
||||
elif isinstance(obj, level):
|
||||
return 'LEVEL:{}:{}'.format(obj.name, obj.value)
|
||||
elif isinstance(obj, cpu_mask):
|
||||
return 'CPUMASK:{}'.format(obj.mask())
|
||||
else:
|
||||
return _json.JSONEncoder.default(self, obj)
|
||||
|
||||
@ -111,6 +113,9 @@ class WAJSONDecoder(_json.JSONDecoder):
|
||||
elif v.startswith('LEVEL:'):
|
||||
_, name, value = v.split(':', 2)
|
||||
return level(name, value)
|
||||
elif v.startswith('CPUMASK:'):
|
||||
_, value = v.split(':', 1)
|
||||
return cpu_mask(value)
|
||||
|
||||
return v
|
||||
|
||||
@ -156,6 +161,7 @@ class json(object):
|
||||
_mapping_tag = _yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
|
||||
_regex_tag = u'tag:wa:regex'
|
||||
_level_tag = u'tag:wa:level'
|
||||
_cpu_mask_tag = u'tag:wa:cpu_mask'
|
||||
|
||||
|
||||
def _wa_dict_representer(dumper, data):
|
||||
@ -170,6 +176,9 @@ def _wa_level_representer(dumper, data):
|
||||
text = '{}:{}'.format(data.name, data.level)
|
||||
return dumper.represent_scalar(_level_tag, text)
|
||||
|
||||
def _wa_cpu_mask_representer(dumper, data):
|
||||
return dumper.represent_scalar(_cpu_mask_tag, data.mask())
|
||||
|
||||
def _wa_dict_constructor(loader, node):
|
||||
pairs = loader.construct_pairs(node)
|
||||
seen_keys = set()
|
||||
@ -190,13 +199,19 @@ def _wa_level_constructor(loader, node):
|
||||
name, value = value.split(':', 1)
|
||||
return level(name, value)
|
||||
|
||||
def _wa_cpu_mask_constructor(loader, node):
|
||||
value = loader.construct_scalar(node)
|
||||
return cpu_mask(value)
|
||||
|
||||
|
||||
_yaml.add_representer(OrderedDict, _wa_dict_representer)
|
||||
_yaml.add_representer(regex_type, _wa_regex_representer)
|
||||
_yaml.add_representer(level, _wa_level_representer)
|
||||
_yaml.add_representer(cpu_mask, _wa_cpu_mask_representer)
|
||||
_yaml.add_constructor(_mapping_tag, _wa_dict_constructor)
|
||||
_yaml.add_constructor(_regex_tag, _wa_regex_constructor)
|
||||
_yaml.add_constructor(_level_tag, _wa_level_constructor)
|
||||
_yaml.add_constructor(_cpu_mask_tag, _wa_cpu_mask_constructor)
|
||||
|
||||
|
||||
class yaml(object):
|
||||
|
@ -36,7 +36,8 @@ from copy import copy
|
||||
|
||||
from devlib.utils.types import identifier, boolean, integer, numeric, caseless_string
|
||||
|
||||
from wa.utils.misc import isiterable
|
||||
from wa.utils.misc import (isiterable, list_to_ranges, list_to_mask,
|
||||
mask_to_list, ranges_to_list)
|
||||
|
||||
|
||||
def list_of_strs(value):
|
||||
@ -741,3 +742,61 @@ class ParameterDict(dict):
|
||||
else:
|
||||
for k, v in d.iteritems():
|
||||
self[k] = v
|
||||
|
||||
|
||||
class cpu_mask(object):
|
||||
"""
|
||||
A class to allow for a consistent way of representing a cpus mask with
|
||||
methods to provide conversions between the various required forms. The
|
||||
mask can be specified directly as a mask, as a list of cpus indexes or a
|
||||
sysfs-style string.
|
||||
"""
|
||||
@staticmethod
|
||||
def from_pod(pod):
|
||||
return cpu_mask(int(pod['cpu_mask']))
|
||||
|
||||
def __init__(self, cpus):
|
||||
self._mask = 0
|
||||
if isinstance(cpus, int):
|
||||
self._mask = cpus
|
||||
elif isinstance(cpus, basestring):
|
||||
if cpus[:2] == '0x' or cpus[:2] == '0X':
|
||||
self._mask = int(cpus, 16)
|
||||
else:
|
||||
self._mask = list_to_mask(ranges_to_list(cpus))
|
||||
elif isinstance(cpus, list):
|
||||
self._mask = list_to_mask(cpus)
|
||||
elif isinstance(cpus, cpu_mask):
|
||||
self._mask = cpus._mask
|
||||
else:
|
||||
msg = 'Unknown conversion from {} to cpu mask'
|
||||
raise ValueError(msg.format(cpus))
|
||||
|
||||
def __bool__(self):
|
||||
"""Allow for use in comparisons to check if a mask has been set"""
|
||||
return bool(self._mask)
|
||||
|
||||
__nonzero__ = __bool__
|
||||
|
||||
def __repr__(self):
|
||||
return 'cpu_mask: {}'.format(self.mask())
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
def list(self):
|
||||
"""Returns a list of the indexes of bits that are set in the mask."""
|
||||
return list(reversed(mask_to_list(self._mask)))
|
||||
|
||||
def mask(self, prefix=True):
|
||||
"""Returns a hex representation of the mask with an optional prefix"""
|
||||
if prefix:
|
||||
return hex(self._mask)
|
||||
else:
|
||||
return hex(self._mask)[2:]
|
||||
|
||||
def ranges(self):
|
||||
""""Returns a sysfs-style ranges string"""
|
||||
return list_to_ranges(self.list())
|
||||
|
||||
def to_pod(self):
|
||||
return {'cpu_mask': self._mask}
|
||||
|
Loading…
x
Reference in New Issue
Block a user