mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 15:12:25 +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:
		| @@ -52,7 +52,7 @@ import dateutil.parser | |||||||
|  |  | ||||||
| from wa.framework.exception import SerializerSyntaxError | from wa.framework.exception import SerializerSyntaxError | ||||||
| from wa.utils.misc import isiterable | 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__ = [ | __all__ = [ | ||||||
| @@ -91,6 +91,8 @@ class WAJSONEncoder(_json.JSONEncoder): | |||||||
|             return 'DATET:{}'.format(obj.isoformat()) |             return 'DATET:{}'.format(obj.isoformat()) | ||||||
|         elif isinstance(obj, level): |         elif isinstance(obj, level): | ||||||
|             return 'LEVEL:{}:{}'.format(obj.name, obj.value) |             return 'LEVEL:{}:{}'.format(obj.name, obj.value) | ||||||
|  |         elif isinstance(obj, cpu_mask): | ||||||
|  |             return 'CPUMASK:{}'.format(obj.mask()) | ||||||
|         else: |         else: | ||||||
|             return _json.JSONEncoder.default(self, obj) |             return _json.JSONEncoder.default(self, obj) | ||||||
|  |  | ||||||
| @@ -111,6 +113,9 @@ class WAJSONDecoder(_json.JSONDecoder): | |||||||
|                 elif v.startswith('LEVEL:'): |                 elif v.startswith('LEVEL:'): | ||||||
|                     _, name, value = v.split(':', 2) |                     _, name, value = v.split(':', 2) | ||||||
|                     return level(name, value) |                     return level(name, value) | ||||||
|  |                 elif v.startswith('CPUMASK:'): | ||||||
|  |                     _, value = v.split(':', 1) | ||||||
|  |                     return cpu_mask(value) | ||||||
|  |  | ||||||
|             return v |             return v | ||||||
|  |  | ||||||
| @@ -156,6 +161,7 @@ class json(object): | |||||||
| _mapping_tag = _yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG | _mapping_tag = _yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG | ||||||
| _regex_tag = u'tag:wa:regex' | _regex_tag = u'tag:wa:regex' | ||||||
| _level_tag = u'tag:wa:level' | _level_tag = u'tag:wa:level' | ||||||
|  | _cpu_mask_tag = u'tag:wa:cpu_mask' | ||||||
|  |  | ||||||
|  |  | ||||||
| def _wa_dict_representer(dumper, data): | def _wa_dict_representer(dumper, data): | ||||||
| @@ -170,6 +176,9 @@ def _wa_level_representer(dumper, data): | |||||||
|     text = '{}:{}'.format(data.name, data.level) |     text = '{}:{}'.format(data.name, data.level) | ||||||
|     return dumper.represent_scalar(_level_tag, text) |     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): | def _wa_dict_constructor(loader, node): | ||||||
|     pairs = loader.construct_pairs(node) |     pairs = loader.construct_pairs(node) | ||||||
|     seen_keys = set() |     seen_keys = set() | ||||||
| @@ -190,13 +199,19 @@ def _wa_level_constructor(loader, node): | |||||||
|     name, value = value.split(':', 1) |     name, value = value.split(':', 1) | ||||||
|     return level(name, value) |     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(OrderedDict, _wa_dict_representer) | ||||||
| _yaml.add_representer(regex_type, _wa_regex_representer) | _yaml.add_representer(regex_type, _wa_regex_representer) | ||||||
| _yaml.add_representer(level, _wa_level_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(_mapping_tag, _wa_dict_constructor) | ||||||
| _yaml.add_constructor(_regex_tag, _wa_regex_constructor) | _yaml.add_constructor(_regex_tag, _wa_regex_constructor) | ||||||
| _yaml.add_constructor(_level_tag, _wa_level_constructor) | _yaml.add_constructor(_level_tag, _wa_level_constructor) | ||||||
|  | _yaml.add_constructor(_cpu_mask_tag, _wa_cpu_mask_constructor) | ||||||
|  |  | ||||||
|  |  | ||||||
| class yaml(object): | class yaml(object): | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ from copy import copy | |||||||
|  |  | ||||||
| from devlib.utils.types import identifier, boolean, integer, numeric, caseless_string | 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): | def list_of_strs(value): | ||||||
| @@ -741,3 +742,61 @@ class ParameterDict(dict): | |||||||
|             else: |             else: | ||||||
|                 for k, v in d.iteritems(): |                 for k, v in d.iteritems(): | ||||||
|                     self[k] = v |                     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} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user