mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
devlib: Use async Target API
Make use of the new async API to speedup other parts of devlib.
This commit is contained in:
parent
18ab9f80b0
commit
2c4b16f280
@ -28,6 +28,7 @@ from devlib.collector import (CollectorBase, CollectorOutput,
|
|||||||
from devlib.host import PACKAGE_BIN_DIRECTORY
|
from devlib.host import PACKAGE_BIN_DIRECTORY
|
||||||
from devlib.exception import TargetStableError, HostError
|
from devlib.exception import TargetStableError, HostError
|
||||||
from devlib.utils.misc import check_output, which, memoized
|
from devlib.utils.misc import check_output, which, memoized
|
||||||
|
from devlib.utils.asyn import asyncf
|
||||||
|
|
||||||
|
|
||||||
TRACE_MARKER_START = 'TRACE_MARKER_START'
|
TRACE_MARKER_START = 'TRACE_MARKER_START'
|
||||||
@ -243,7 +244,8 @@ class FtraceCollector(CollectorBase):
|
|||||||
self.target.write_value(self.function_profile_file, 0, verify=False)
|
self.target.write_value(self.function_profile_file, 0, verify=False)
|
||||||
self._reset_needed = False
|
self._reset_needed = False
|
||||||
|
|
||||||
def start(self):
|
@asyncf
|
||||||
|
async def start(self):
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
if self._reset_needed:
|
if self._reset_needed:
|
||||||
self.reset()
|
self.reset()
|
||||||
@ -282,14 +284,17 @@ class FtraceCollector(CollectorBase):
|
|||||||
self.target.cpuidle.perturb_cpus()
|
self.target.cpuidle.perturb_cpus()
|
||||||
# Enable kernel function profiling
|
# Enable kernel function profiling
|
||||||
if self.functions and self.tracer is None:
|
if self.functions and self.tracer is None:
|
||||||
self.target.execute('echo nop > {}'.format(self.current_tracer_file),
|
target = self.target
|
||||||
as_root=True)
|
await target.async_manager.concurrently(
|
||||||
self.target.execute('echo 0 > {}'.format(self.function_profile_file),
|
execute.asyn('echo nop > {}'.format(self.current_tracer_file),
|
||||||
as_root=True)
|
as_root=True),
|
||||||
self.target.execute('echo {} > {}'.format(self.function_string, self.ftrace_filter_file),
|
execute.asyn('echo 0 > {}'.format(self.function_profile_file),
|
||||||
as_root=True)
|
as_root=True),
|
||||||
self.target.execute('echo 1 > {}'.format(self.function_profile_file),
|
execute.asyn('echo {} > {}'.format(self.function_string, self.ftrace_filter_file),
|
||||||
as_root=True)
|
as_root=True),
|
||||||
|
execute.asyn('echo 1 > {}'.format(self.function_profile_file),
|
||||||
|
as_root=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -19,11 +19,13 @@ from collections import namedtuple
|
|||||||
from shlex import quote
|
from shlex import quote
|
||||||
import itertools
|
import itertools
|
||||||
import warnings
|
import warnings
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from devlib.module import Module
|
from devlib.module import Module
|
||||||
from devlib.exception import TargetStableError
|
from devlib.exception import TargetStableError
|
||||||
from devlib.utils.misc import list_to_ranges, isiterable
|
from devlib.utils.misc import list_to_ranges, isiterable
|
||||||
from devlib.utils.types import boolean
|
from devlib.utils.types import boolean
|
||||||
|
from devlib.utils.asyn import asyncf
|
||||||
|
|
||||||
|
|
||||||
class Controller(object):
|
class Controller(object):
|
||||||
@ -55,7 +57,8 @@ class Controller(object):
|
|||||||
self.mount_point = None
|
self.mount_point = None
|
||||||
self._cgroups = {}
|
self._cgroups = {}
|
||||||
|
|
||||||
def mount(self, target, mount_root):
|
@asyncf
|
||||||
|
async def mount(self, target, mount_root):
|
||||||
|
|
||||||
mounted = target.list_file_systems()
|
mounted = target.list_file_systems()
|
||||||
if self.mount_name in [e.device for e in mounted]:
|
if self.mount_name in [e.device for e in mounted]:
|
||||||
@ -68,16 +71,16 @@ class Controller(object):
|
|||||||
else:
|
else:
|
||||||
# Mount the controller if not already in use
|
# Mount the controller if not already in use
|
||||||
self.mount_point = target.path.join(mount_root, self.mount_name)
|
self.mount_point = target.path.join(mount_root, self.mount_name)
|
||||||
target.execute('mkdir -p {} 2>/dev/null'\
|
await target.execute.asyn('mkdir -p {} 2>/dev/null'\
|
||||||
.format(self.mount_point), as_root=True)
|
.format(self.mount_point), as_root=True)
|
||||||
target.execute('mount -t cgroup -o {} {} {}'\
|
await target.execute.asyn('mount -t cgroup -o {} {} {}'\
|
||||||
.format(','.join(self.clist),
|
.format(','.join(self.clist),
|
||||||
self.mount_name,
|
self.mount_name,
|
||||||
self.mount_point),
|
self.mount_point),
|
||||||
as_root=True)
|
as_root=True)
|
||||||
|
|
||||||
# Check if this controller uses "noprefix" option
|
# Check if this controller uses "noprefix" option
|
||||||
output = target.execute('mount | grep "{} "'.format(self.mount_name))
|
output = await target.execute.asyn('mount | grep "{} "'.format(self.mount_name))
|
||||||
if 'noprefix' in output:
|
if 'noprefix' in output:
|
||||||
self._noprefix = True
|
self._noprefix = True
|
||||||
# self.logger.debug('Controller %s using "noprefix" option',
|
# self.logger.debug('Controller %s using "noprefix" option',
|
||||||
@ -394,11 +397,12 @@ class CgroupsModule(Module):
|
|||||||
# Initialize controllers
|
# Initialize controllers
|
||||||
self.logger.info('Available controllers:')
|
self.logger.info('Available controllers:')
|
||||||
self.controllers = {}
|
self.controllers = {}
|
||||||
for ss in subsys:
|
|
||||||
|
async def register_controller(ss):
|
||||||
hid = ss.hierarchy
|
hid = ss.hierarchy
|
||||||
controller = Controller(ss.name, hid, hierarchy[hid])
|
controller = Controller(ss.name, hid, hierarchy[hid])
|
||||||
try:
|
try:
|
||||||
controller.mount(self.target, self.cgroup_root)
|
await controller.mount.asyn(self.target, self.cgroup_root)
|
||||||
except TargetStableError:
|
except TargetStableError:
|
||||||
message = 'Failed to mount "{}" controller'
|
message = 'Failed to mount "{}" controller'
|
||||||
raise TargetStableError(message.format(controller.kind))
|
raise TargetStableError(message.format(controller.kind))
|
||||||
@ -406,6 +410,14 @@ class CgroupsModule(Module):
|
|||||||
controller.mount_point)
|
controller.mount_point)
|
||||||
self.controllers[ss.name] = controller
|
self.controllers[ss.name] = controller
|
||||||
|
|
||||||
|
asyncio.run(
|
||||||
|
target.async_manager.map_concurrently(
|
||||||
|
register_controller,
|
||||||
|
subsys,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def list_subsystems(self):
|
def list_subsystems(self):
|
||||||
subsystems = []
|
subsystems = []
|
||||||
for line in self.target.execute('{} cat /proc/cgroups'\
|
for line in self.target.execute('{} cat /proc/cgroups'\
|
||||||
|
@ -13,10 +13,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from operator import itemgetter
|
||||||
|
|
||||||
from devlib.module import Module
|
from devlib.module import Module
|
||||||
from devlib.exception import TargetStableError
|
from devlib.exception import TargetStableError
|
||||||
from devlib.utils.misc import memoized
|
from devlib.utils.misc import memoized
|
||||||
|
import devlib.utils.asyn as asyn
|
||||||
|
|
||||||
|
|
||||||
# a dict of governor name and a list of it tunables that can't be read
|
# a dict of governor name and a list of it tunables that can't be read
|
||||||
@ -30,44 +32,52 @@ class CpufreqModule(Module):
|
|||||||
name = 'cpufreq'
|
name = 'cpufreq'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def probe(target):
|
@asyn.asyncf
|
||||||
|
async def probe(target):
|
||||||
|
paths = [
|
||||||
# x86 with Intel P-State driver
|
# x86 with Intel P-State driver
|
||||||
if target.abi == 'x86_64':
|
(target.abi == 'x86_64', '/sys/devices/system/cpu/intel_pstate'),
|
||||||
path = '/sys/devices/system/cpu/intel_pstate'
|
|
||||||
if target.file_exists(path):
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Generic CPUFreq support (single policy)
|
# Generic CPUFreq support (single policy)
|
||||||
path = '/sys/devices/system/cpu/cpufreq/policy0'
|
(True, '/sys/devices/system/cpu/cpufreq/policy0'),
|
||||||
if target.file_exists(path):
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Generic CPUFreq support (per CPU policy)
|
# Generic CPUFreq support (per CPU policy)
|
||||||
path = '/sys/devices/system/cpu/cpu0/cpufreq'
|
(True, '/sys/devices/system/cpu/cpu0/cpufreq'),
|
||||||
return target.file_exists(path)
|
]
|
||||||
|
paths = [
|
||||||
|
path[1] for path in paths
|
||||||
|
if path[0]
|
||||||
|
]
|
||||||
|
|
||||||
|
exists = await target.async_manager.map_concurrently(
|
||||||
|
target.file_exists.asyn,
|
||||||
|
paths,
|
||||||
|
)
|
||||||
|
|
||||||
|
return any(exists.values())
|
||||||
|
|
||||||
def __init__(self, target):
|
def __init__(self, target):
|
||||||
super(CpufreqModule, self).__init__(target)
|
super(CpufreqModule, self).__init__(target)
|
||||||
self._governor_tunables = {}
|
self._governor_tunables = {}
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def list_governors(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def list_governors(self, cpu):
|
||||||
"""Returns a list of governors supported by the cpu."""
|
"""Returns a list of governors supported by the cpu."""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_available_governors'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_available_governors'.format(cpu)
|
||||||
output = self.target.read_value(sysfile)
|
output = await self.target.read_value.asyn(sysfile)
|
||||||
return output.strip().split()
|
return output.strip().split()
|
||||||
|
|
||||||
def get_governor(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def get_governor(self, cpu):
|
||||||
"""Returns the governor currently set for the specified CPU."""
|
"""Returns the governor currently set for the specified CPU."""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_governor'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_governor'.format(cpu)
|
||||||
return self.target.read_value(sysfile)
|
return await self.target.read_value.asyn(sysfile)
|
||||||
|
|
||||||
def set_governor(self, cpu, governor, **kwargs):
|
@asyn.asyncf
|
||||||
|
async def set_governor(self, cpu, governor, **kwargs):
|
||||||
"""
|
"""
|
||||||
Set the governor for the specified CPU.
|
Set the governor for the specified CPU.
|
||||||
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
||||||
@ -90,15 +100,15 @@ class CpufreqModule(Module):
|
|||||||
"""
|
"""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
supported = self.list_governors(cpu)
|
supported = await self.list_governors.asyn(cpu)
|
||||||
if governor not in supported:
|
if governor not in supported:
|
||||||
raise TargetStableError('Governor {} not supported for cpu {}'.format(governor, cpu))
|
raise TargetStableError('Governor {} not supported for cpu {}'.format(governor, cpu))
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_governor'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_governor'.format(cpu)
|
||||||
self.target.write_value(sysfile, governor)
|
await self.target.write_value.asyn(sysfile, governor)
|
||||||
self.set_governor_tunables(cpu, governor, **kwargs)
|
return await self.set_governor_tunables.asyn(cpu, governor, **kwargs)
|
||||||
|
|
||||||
@contextmanager
|
@asyn.asynccontextmanager
|
||||||
def use_governor(self, governor, cpus=None, **kwargs):
|
async def use_governor(self, governor, cpus=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Use a given governor, then restore previous governor(s)
|
Use a given governor, then restore previous governor(s)
|
||||||
|
|
||||||
@ -111,66 +121,97 @@ class CpufreqModule(Module):
|
|||||||
:Keyword Arguments: Governor tunables, See :meth:`set_governor_tunables`
|
:Keyword Arguments: Governor tunables, See :meth:`set_governor_tunables`
|
||||||
"""
|
"""
|
||||||
if not cpus:
|
if not cpus:
|
||||||
cpus = self.target.list_online_cpus()
|
cpus = await self.target.list_online_cpus.asyn()
|
||||||
|
|
||||||
# Setting a governor & tunables for a cpu will set them for all cpus
|
async def get_cpu_info(cpu):
|
||||||
# in the same clock domain, so only manipulating one cpu per domain
|
return await self.target.async_manager.concurrently((
|
||||||
# is enough
|
self.get_affected_cpus.asyn(cpu),
|
||||||
domains = set(self.get_affected_cpus(cpu)[0] for cpu in cpus)
|
self.get_governor.asyn(cpu),
|
||||||
prev_governors = {cpu : (self.get_governor(cpu), self.get_governor_tunables(cpu))
|
self.get_governor_tunables.asyn(cpu),
|
||||||
for cpu in domains}
|
# We won't always use the frequency, but it's much quicker to
|
||||||
|
# do concurrently anyway so do it now
|
||||||
|
self.get_frequency.asyn(cpu),
|
||||||
|
))
|
||||||
|
|
||||||
# Special case for userspace, frequency is not seen as a tunable
|
cpus_infos = await self.target.async_manager.map_concurrently(get_cpu_info, cpus)
|
||||||
userspace_freqs = {}
|
|
||||||
for cpu, (prev_gov, _) in prev_governors.items():
|
|
||||||
if prev_gov == "userspace":
|
|
||||||
userspace_freqs[cpu] = self.get_frequency(cpu)
|
|
||||||
|
|
||||||
for cpu in domains:
|
# Setting a governor & tunables for a cpu will set them for all cpus in
|
||||||
self.set_governor(cpu, governor, **kwargs)
|
# the same cpufreq policy, so only manipulating one cpu per domain is
|
||||||
|
# enough
|
||||||
|
domains = set(
|
||||||
|
info[0][0]
|
||||||
|
for info in cpus_infos.values()
|
||||||
|
)
|
||||||
|
|
||||||
|
await self.target.async_manager.concurrently(
|
||||||
|
self.set_governor.asyn(cpu, governor, **kwargs)
|
||||||
|
for cpu in domains
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
for cpu, (prev_gov, tunables) in prev_governors.items():
|
async def set_gov(cpu):
|
||||||
self.set_governor(cpu, prev_gov, **tunables)
|
domain, prev_gov, tunables, freq = cpus_infos[cpu]
|
||||||
|
await self.set_governor.asyn(cpu, prev_gov, **tunables)
|
||||||
|
# Special case for userspace, frequency is not seen as a tunable
|
||||||
if prev_gov == "userspace":
|
if prev_gov == "userspace":
|
||||||
self.set_frequency(cpu, userspace_freqs[cpu])
|
await self.set_frequency.asyn(cpu, freq)
|
||||||
|
|
||||||
def list_governor_tunables(self, cpu):
|
await self.target.async_manager.concurrently(
|
||||||
|
set_gov(cpu)
|
||||||
|
for cpu in domains
|
||||||
|
)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def list_governor_tunables(self, cpu):
|
||||||
"""Returns a list of tunables available for the governor on the specified CPU."""
|
"""Returns a list of tunables available for the governor on the specified CPU."""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
governor = self.get_governor(cpu)
|
governor = await self.get_governor.asyn(cpu)
|
||||||
if governor not in self._governor_tunables:
|
if governor not in self._governor_tunables:
|
||||||
try:
|
try:
|
||||||
tunables_path = '/sys/devices/system/cpu/{}/cpufreq/{}'.format(cpu, governor)
|
tunables_path = '/sys/devices/system/cpu/{}/cpufreq/{}'.format(cpu, governor)
|
||||||
self._governor_tunables[governor] = self.target.list_directory(tunables_path)
|
self._governor_tunables[governor] = await self.target.list_directory.asyn(tunables_path)
|
||||||
except TargetStableError: # probably an older kernel
|
except TargetStableError: # probably an older kernel
|
||||||
try:
|
try:
|
||||||
tunables_path = '/sys/devices/system/cpu/cpufreq/{}'.format(governor)
|
tunables_path = '/sys/devices/system/cpu/cpufreq/{}'.format(governor)
|
||||||
self._governor_tunables[governor] = self.target.list_directory(tunables_path)
|
self._governor_tunables[governor] = await self.target.list_directory.asyn(tunables_path)
|
||||||
except TargetStableError: # governor does not support tunables
|
except TargetStableError: # governor does not support tunables
|
||||||
self._governor_tunables[governor] = []
|
self._governor_tunables[governor] = []
|
||||||
return self._governor_tunables[governor]
|
return self._governor_tunables[governor]
|
||||||
|
|
||||||
def get_governor_tunables(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def get_governor_tunables(self, cpu):
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
governor = self.get_governor(cpu)
|
governor, tunable_list = await self.target.async_manager.concurrently((
|
||||||
|
self.get_governor.asyn(cpu),
|
||||||
|
self.list_governor_tunables.asyn(cpu)
|
||||||
|
))
|
||||||
|
|
||||||
|
write_only = set(WRITE_ONLY_TUNABLES.get(governor, []))
|
||||||
|
tunable_list = [
|
||||||
|
tunable
|
||||||
|
for tunable in tunable_list
|
||||||
|
if tunable not in write_only
|
||||||
|
]
|
||||||
|
|
||||||
tunables = {}
|
tunables = {}
|
||||||
for tunable in self.list_governor_tunables(cpu):
|
async def get_tunable(tunable):
|
||||||
if tunable not in WRITE_ONLY_TUNABLES.get(governor, []):
|
|
||||||
try:
|
try:
|
||||||
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
||||||
tunables[tunable] = self.target.read_value(path)
|
x = await self.target.read_value.asyn(path)
|
||||||
except TargetStableError: # May be an older kernel
|
except TargetStableError: # May be an older kernel
|
||||||
path = '/sys/devices/system/cpu/cpufreq/{}/{}'.format(governor, tunable)
|
path = '/sys/devices/system/cpu/cpufreq/{}/{}'.format(governor, tunable)
|
||||||
tunables[tunable] = self.target.read_value(path)
|
x = await self.target.read_value.asyn(path)
|
||||||
|
return x
|
||||||
|
|
||||||
|
tunables = await self.target.async_manager.map_concurrently(get_tunable, tunable_list)
|
||||||
return tunables
|
return tunables
|
||||||
|
|
||||||
def set_governor_tunables(self, cpu, governor=None, **kwargs):
|
@asyn.asyncf
|
||||||
|
async def set_governor_tunables(self, cpu, governor=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Set tunables for the specified governor. Tunables should be specified as
|
Set tunables for the specified governor. Tunables should be specified as
|
||||||
keyword arguments. Which tunables and values are valid depends on the
|
keyword arguments. Which tunables and values are valid depends on the
|
||||||
@ -191,34 +232,35 @@ class CpufreqModule(Module):
|
|||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
if governor is None:
|
if governor is None:
|
||||||
governor = self.get_governor(cpu)
|
governor = await self.get_governor.asyn(cpu)
|
||||||
valid_tunables = self.list_governor_tunables(cpu)
|
valid_tunables = await self.list_governor_tunables.asyn(cpu)
|
||||||
for tunable, value in kwargs.items():
|
for tunable, value in kwargs.items():
|
||||||
if tunable in valid_tunables:
|
if tunable in valid_tunables:
|
||||||
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
||||||
try:
|
try:
|
||||||
self.target.write_value(path, value)
|
await self.target.write_value.asyn(path, value)
|
||||||
except TargetStableError:
|
except TargetStableError:
|
||||||
if self.target.file_exists(path):
|
if await self.target.file_exists.asyn(path):
|
||||||
# File exists but we did something wrong
|
# File exists but we did something wrong
|
||||||
raise
|
raise
|
||||||
# Expected file doesn't exist, try older sysfs layout.
|
# Expected file doesn't exist, try older sysfs layout.
|
||||||
path = '/sys/devices/system/cpu/cpufreq/{}/{}'.format(governor, tunable)
|
path = '/sys/devices/system/cpu/cpufreq/{}/{}'.format(governor, tunable)
|
||||||
self.target.write_value(path, value)
|
await self.target.write_value.asyn(path, value)
|
||||||
else:
|
else:
|
||||||
message = 'Unexpected tunable {} for governor {} on {}.\n'.format(tunable, governor, cpu)
|
message = 'Unexpected tunable {} for governor {} on {}.\n'.format(tunable, governor, cpu)
|
||||||
message += 'Available tunables are: {}'.format(valid_tunables)
|
message += 'Available tunables are: {}'.format(valid_tunables)
|
||||||
raise TargetStableError(message)
|
raise TargetStableError(message)
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def list_frequencies(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def list_frequencies(self, cpu):
|
||||||
"""Returns a sorted list of frequencies supported by the cpu or an empty list
|
"""Returns a sorted list of frequencies supported by the cpu or an empty list
|
||||||
if not could be found."""
|
if not could be found."""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
try:
|
try:
|
||||||
cmd = 'cat /sys/devices/system/cpu/{}/cpufreq/scaling_available_frequencies'.format(cpu)
|
cmd = 'cat /sys/devices/system/cpu/{}/cpufreq/scaling_available_frequencies'.format(cpu)
|
||||||
output = self.target.execute(cmd)
|
output = await self.target.execute.asyn(cmd)
|
||||||
available_frequencies = list(map(int, output.strip().split())) # pylint: disable=E1103
|
available_frequencies = list(map(int, output.strip().split())) # pylint: disable=E1103
|
||||||
except TargetStableError:
|
except TargetStableError:
|
||||||
# On some devices scaling_frequencies is not generated.
|
# On some devices scaling_frequencies is not generated.
|
||||||
@ -226,7 +268,7 @@ class CpufreqModule(Module):
|
|||||||
# Fall back to parsing stats/time_in_state
|
# Fall back to parsing stats/time_in_state
|
||||||
path = '/sys/devices/system/cpu/{}/cpufreq/stats/time_in_state'.format(cpu)
|
path = '/sys/devices/system/cpu/{}/cpufreq/stats/time_in_state'.format(cpu)
|
||||||
try:
|
try:
|
||||||
out_iter = iter(self.target.read_value(path).split())
|
out_iter = (await self.target.read_value.asyn(path)).split()
|
||||||
except TargetStableError:
|
except TargetStableError:
|
||||||
if not self.target.file_exists(path):
|
if not self.target.file_exists(path):
|
||||||
# Probably intel_pstate. Can't get available freqs.
|
# Probably intel_pstate. Can't get available freqs.
|
||||||
@ -254,7 +296,8 @@ class CpufreqModule(Module):
|
|||||||
freqs = self.list_frequencies(cpu)
|
freqs = self.list_frequencies(cpu)
|
||||||
return min(freqs) if freqs else None
|
return min(freqs) if freqs else None
|
||||||
|
|
||||||
def get_min_frequency(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def get_min_frequency(self, cpu):
|
||||||
"""
|
"""
|
||||||
Returns the min frequency currently set for the specified CPU.
|
Returns the min frequency currently set for the specified CPU.
|
||||||
|
|
||||||
@ -268,9 +311,10 @@ class CpufreqModule(Module):
|
|||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_min_freq'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_min_freq'.format(cpu)
|
||||||
return self.target.read_int(sysfile)
|
return await self.target.read_int.asyn(sysfile)
|
||||||
|
|
||||||
def set_min_frequency(self, cpu, frequency, exact=True):
|
@asyn.asyncf
|
||||||
|
async def set_min_frequency(self, cpu, frequency, exact=True):
|
||||||
"""
|
"""
|
||||||
Set's the minimum value for CPU frequency. Actual frequency will
|
Set's the minimum value for CPU frequency. Actual frequency will
|
||||||
depend on the Governor used and may vary during execution. The value should be
|
depend on the Governor used and may vary during execution. The value should be
|
||||||
@ -289,7 +333,7 @@ class CpufreqModule(Module):
|
|||||||
"""
|
"""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
available_frequencies = self.list_frequencies(cpu)
|
available_frequencies = await self.list_frequencies.asyn(cpu)
|
||||||
try:
|
try:
|
||||||
value = int(frequency)
|
value = int(frequency)
|
||||||
if exact and available_frequencies and value not in available_frequencies:
|
if exact and available_frequencies and value not in available_frequencies:
|
||||||
@ -297,11 +341,12 @@ class CpufreqModule(Module):
|
|||||||
value,
|
value,
|
||||||
available_frequencies))
|
available_frequencies))
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_min_freq'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_min_freq'.format(cpu)
|
||||||
self.target.write_value(sysfile, value)
|
await self.target.write_value.asyn(sysfile, value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
||||||
|
|
||||||
def get_frequency(self, cpu, cpuinfo=False):
|
@asyn.asyncf
|
||||||
|
async def get_frequency(self, cpu, cpuinfo=False):
|
||||||
"""
|
"""
|
||||||
Returns the current frequency currently set for the specified CPU.
|
Returns the current frequency currently set for the specified CPU.
|
||||||
|
|
||||||
@ -321,9 +366,10 @@ class CpufreqModule(Module):
|
|||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/{}'.format(
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/{}'.format(
|
||||||
cpu,
|
cpu,
|
||||||
'cpuinfo_cur_freq' if cpuinfo else 'scaling_cur_freq')
|
'cpuinfo_cur_freq' if cpuinfo else 'scaling_cur_freq')
|
||||||
return self.target.read_int(sysfile)
|
return await self.target.read_int.asyn(sysfile)
|
||||||
|
|
||||||
def set_frequency(self, cpu, frequency, exact=True):
|
@asyn.asyncf
|
||||||
|
async def set_frequency(self, cpu, frequency, exact=True):
|
||||||
"""
|
"""
|
||||||
Set's the minimum value for CPU frequency. Actual frequency will
|
Set's the minimum value for CPU frequency. Actual frequency will
|
||||||
depend on the Governor used and may vary during execution. The value should be
|
depend on the Governor used and may vary during execution. The value should be
|
||||||
@ -347,23 +393,24 @@ class CpufreqModule(Module):
|
|||||||
try:
|
try:
|
||||||
value = int(frequency)
|
value = int(frequency)
|
||||||
if exact:
|
if exact:
|
||||||
available_frequencies = self.list_frequencies(cpu)
|
available_frequencies = await self.list_frequencies.asyn(cpu)
|
||||||
if available_frequencies and value not in available_frequencies:
|
if available_frequencies and value not in available_frequencies:
|
||||||
raise TargetStableError('Can\'t set {} frequency to {}\nmust be in {}'.format(cpu,
|
raise TargetStableError('Can\'t set {} frequency to {}\nmust be in {}'.format(cpu,
|
||||||
value,
|
value,
|
||||||
available_frequencies))
|
available_frequencies))
|
||||||
if self.get_governor(cpu) != 'userspace':
|
if await self.get_governor.asyn(cpu) != 'userspace':
|
||||||
raise TargetStableError('Can\'t set {} frequency; governor must be "userspace"'.format(cpu))
|
raise TargetStableError('Can\'t set {} frequency; governor must be "userspace"'.format(cpu))
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_setspeed'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_setspeed'.format(cpu)
|
||||||
self.target.write_value(sysfile, value, verify=False)
|
await self.target.write_value.asyn(sysfile, value, verify=False)
|
||||||
cpuinfo = self.get_frequency(cpu, cpuinfo=True)
|
cpuinfo = await self.get_frequency.asyn(cpu, cpuinfo=True)
|
||||||
if cpuinfo != value:
|
if cpuinfo != value:
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
'The cpufreq value has not been applied properly cpuinfo={} request={}'.format(cpuinfo, value))
|
'The cpufreq value has not been applied properly cpuinfo={} request={}'.format(cpuinfo, value))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
||||||
|
|
||||||
def get_max_frequency(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def get_max_frequency(self, cpu):
|
||||||
"""
|
"""
|
||||||
Returns the max frequency currently set for the specified CPU.
|
Returns the max frequency currently set for the specified CPU.
|
||||||
|
|
||||||
@ -376,9 +423,10 @@ class CpufreqModule(Module):
|
|||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_max_freq'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_max_freq'.format(cpu)
|
||||||
return self.target.read_int(sysfile)
|
return await self.target.read_int.asyn(sysfile)
|
||||||
|
|
||||||
def set_max_frequency(self, cpu, frequency, exact=True):
|
@asyn.asyncf
|
||||||
|
async def set_max_frequency(self, cpu, frequency, exact=True):
|
||||||
"""
|
"""
|
||||||
Set's the minimum value for CPU frequency. Actual frequency will
|
Set's the minimum value for CPU frequency. Actual frequency will
|
||||||
depend on the Governor used and may vary during execution. The value should be
|
depend on the Governor used and may vary during execution. The value should be
|
||||||
@ -397,7 +445,7 @@ class CpufreqModule(Module):
|
|||||||
"""
|
"""
|
||||||
if isinstance(cpu, int):
|
if isinstance(cpu, int):
|
||||||
cpu = 'cpu{}'.format(cpu)
|
cpu = 'cpu{}'.format(cpu)
|
||||||
available_frequencies = self.list_frequencies(cpu)
|
available_frequencies = await self.list_frequencies.asyn(cpu)
|
||||||
try:
|
try:
|
||||||
value = int(frequency)
|
value = int(frequency)
|
||||||
if exact and available_frequencies and value not in available_frequencies:
|
if exact and available_frequencies and value not in available_frequencies:
|
||||||
@ -405,45 +453,53 @@ class CpufreqModule(Module):
|
|||||||
value,
|
value,
|
||||||
available_frequencies))
|
available_frequencies))
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_max_freq'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_max_freq'.format(cpu)
|
||||||
self.target.write_value(sysfile, value)
|
await self.target.write_value.asyn(sysfile, value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
raise ValueError('Frequency must be an integer; got: "{}"'.format(frequency))
|
||||||
|
|
||||||
def set_governor_for_cpus(self, cpus, governor, **kwargs):
|
@asyn.asyncf
|
||||||
|
async def set_governor_for_cpus(self, cpus, governor, **kwargs):
|
||||||
"""
|
"""
|
||||||
Set the governor for the specified list of CPUs.
|
Set the governor for the specified list of CPUs.
|
||||||
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
||||||
|
|
||||||
:param cpus: The list of CPU for which the governor is to be set.
|
:param cpus: The list of CPU for which the governor is to be set.
|
||||||
"""
|
"""
|
||||||
for cpu in cpus:
|
await self.target.async_manager.map_concurrently(
|
||||||
self.set_governor(cpu, governor, **kwargs)
|
self.set_governor(cpu, governor, **kwargs)
|
||||||
|
for cpu in sorted(set(cpus))
|
||||||
|
)
|
||||||
|
|
||||||
def set_frequency_for_cpus(self, cpus, freq, exact=False):
|
@asyn.asyncf
|
||||||
|
async def set_frequency_for_cpus(self, cpus, freq, exact=False):
|
||||||
"""
|
"""
|
||||||
Set the frequency for the specified list of CPUs.
|
Set the frequency for the specified list of CPUs.
|
||||||
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
|
||||||
|
|
||||||
:param cpus: The list of CPU for which the frequency has to be set.
|
:param cpus: The list of CPU for which the frequency has to be set.
|
||||||
"""
|
"""
|
||||||
for cpu in cpus:
|
await self.target.async_manager.map_concurrently(
|
||||||
self.set_frequency(cpu, freq, exact)
|
self.set_frequency(cpu, freq, exact)
|
||||||
|
for cpu in sorted(set(cpus))
|
||||||
|
)
|
||||||
|
|
||||||
def set_all_frequencies(self, freq):
|
@asyn.asyncf
|
||||||
|
async def set_all_frequencies(self, freq):
|
||||||
"""
|
"""
|
||||||
Set the specified (minimum) frequency for all the (online) CPUs
|
Set the specified (minimum) frequency for all the (online) CPUs
|
||||||
"""
|
"""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
return self.target._execute_util(
|
return await self.target._execute_util.asyn(
|
||||||
'cpufreq_set_all_frequencies {}'.format(freq),
|
'cpufreq_set_all_frequencies {}'.format(freq),
|
||||||
as_root=True)
|
as_root=True)
|
||||||
|
|
||||||
def get_all_frequencies(self):
|
@asyn.asyncf
|
||||||
|
async def get_all_frequencies(self):
|
||||||
"""
|
"""
|
||||||
Get the current frequency for all the (online) CPUs
|
Get the current frequency for all the (online) CPUs
|
||||||
"""
|
"""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
output = self.target._execute_util(
|
output = await self.target._execute_util.asyn(
|
||||||
'cpufreq_get_all_frequencies', as_root=True)
|
'cpufreq_get_all_frequencies', as_root=True)
|
||||||
frequencies = {}
|
frequencies = {}
|
||||||
for x in output.splitlines():
|
for x in output.splitlines():
|
||||||
@ -453,32 +509,34 @@ class CpufreqModule(Module):
|
|||||||
frequencies[kv[0]] = kv[1]
|
frequencies[kv[0]] = kv[1]
|
||||||
return frequencies
|
return frequencies
|
||||||
|
|
||||||
def set_all_governors(self, governor):
|
@asyn.asyncf
|
||||||
|
async def set_all_governors(self, governor):
|
||||||
"""
|
"""
|
||||||
Set the specified governor for all the (online) CPUs
|
Set the specified governor for all the (online) CPUs
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
return self.target._execute_util(
|
return await self.target._execute_util.asyn(
|
||||||
'cpufreq_set_all_governors {}'.format(governor),
|
'cpufreq_set_all_governors {}'.format(governor),
|
||||||
as_root=True)
|
as_root=True)
|
||||||
except TargetStableError as e:
|
except TargetStableError as e:
|
||||||
if ("echo: I/O error" in str(e) or
|
if ("echo: I/O error" in str(e) or
|
||||||
"write error: Invalid argument" in str(e)):
|
"write error: Invalid argument" in str(e)):
|
||||||
|
|
||||||
cpus_unsupported = [c for c in self.target.list_online_cpus()
|
cpus_unsupported = [c for c in await self.target.list_online_cpus.asyn()
|
||||||
if governor not in self.list_governors(c)]
|
if governor not in await self.list_governors.asyn(c)]
|
||||||
raise TargetStableError("Governor {} unsupported for CPUs {}".format(
|
raise TargetStableError("Governor {} unsupported for CPUs {}".format(
|
||||||
governor, cpus_unsupported))
|
governor, cpus_unsupported))
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_all_governors(self):
|
@asyn.asyncf
|
||||||
|
async def get_all_governors(self):
|
||||||
"""
|
"""
|
||||||
Get the current governor for all the (online) CPUs
|
Get the current governor for all the (online) CPUs
|
||||||
"""
|
"""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
output = self.target._execute_util(
|
output = await self.target._execute_util.asyn(
|
||||||
'cpufreq_get_all_governors', as_root=True)
|
'cpufreq_get_all_governors', as_root=True)
|
||||||
governors = {}
|
governors = {}
|
||||||
for x in output.splitlines():
|
for x in output.splitlines():
|
||||||
@ -488,14 +546,16 @@ class CpufreqModule(Module):
|
|||||||
governors[kv[0]] = kv[1]
|
governors[kv[0]] = kv[1]
|
||||||
return governors
|
return governors
|
||||||
|
|
||||||
def trace_frequencies(self):
|
@asyn.asyncf
|
||||||
|
async def trace_frequencies(self):
|
||||||
"""
|
"""
|
||||||
Report current frequencies on trace file
|
Report current frequencies on trace file
|
||||||
"""
|
"""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
return self.target._execute_util('cpufreq_trace_all_frequencies', as_root=True)
|
return await self.target._execute_util.asyn('cpufreq_trace_all_frequencies', as_root=True)
|
||||||
|
|
||||||
def get_affected_cpus(self, cpu):
|
@asyn.asyncf
|
||||||
|
async def get_affected_cpus(self, cpu):
|
||||||
"""
|
"""
|
||||||
Get the online CPUs that share a frequency domain with the given CPU
|
Get the online CPUs that share a frequency domain with the given CPU
|
||||||
"""
|
"""
|
||||||
@ -504,10 +564,12 @@ class CpufreqModule(Module):
|
|||||||
|
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/affected_cpus'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/affected_cpus'.format(cpu)
|
||||||
|
|
||||||
return [int(c) for c in self.target.read_value(sysfile).split()]
|
content = await self.target.read_value.asyn(sysfile)
|
||||||
|
return [int(c) for c in content.split()]
|
||||||
|
|
||||||
@memoized
|
@asyn.asyncf
|
||||||
def get_related_cpus(self, cpu):
|
@asyn.memoized_method
|
||||||
|
async def get_related_cpus(self, cpu):
|
||||||
"""
|
"""
|
||||||
Get the CPUs that share a frequency domain with the given CPU
|
Get the CPUs that share a frequency domain with the given CPU
|
||||||
"""
|
"""
|
||||||
@ -516,10 +578,11 @@ class CpufreqModule(Module):
|
|||||||
|
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/related_cpus'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/related_cpus'.format(cpu)
|
||||||
|
|
||||||
return [int(c) for c in self.target.read_value(sysfile).split()]
|
return [int(c) for c in (await self.target.read_value.asyn(sysfile)).split()]
|
||||||
|
|
||||||
@memoized
|
@asyn.asyncf
|
||||||
def get_driver(self, cpu):
|
@asyn.memoized_method
|
||||||
|
async def get_driver(self, cpu):
|
||||||
"""
|
"""
|
||||||
Get the name of the driver used by this cpufreq policy.
|
Get the name of the driver used by this cpufreq policy.
|
||||||
"""
|
"""
|
||||||
@ -528,15 +591,16 @@ class CpufreqModule(Module):
|
|||||||
|
|
||||||
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_driver'.format(cpu)
|
sysfile = '/sys/devices/system/cpu/{}/cpufreq/scaling_driver'.format(cpu)
|
||||||
|
|
||||||
return self.target.read_value(sysfile).strip()
|
return (await self.target.read_value.asyn(sysfile)).strip()
|
||||||
|
|
||||||
def iter_domains(self):
|
@asyn.asyncf
|
||||||
|
async def iter_domains(self):
|
||||||
"""
|
"""
|
||||||
Iterate over the frequency domains in the system
|
Iterate over the frequency domains in the system
|
||||||
"""
|
"""
|
||||||
cpus = set(range(self.target.number_of_cpus))
|
cpus = set(range(self.target.number_of_cpus))
|
||||||
while cpus:
|
while cpus:
|
||||||
cpu = next(iter(cpus)) # pylint: disable=stop-iteration-return
|
cpu = next(iter(cpus)) # pylint: disable=stop-iteration-return
|
||||||
domain = self.target.cpufreq.get_related_cpus(cpu)
|
domain = await self.target.cpufreq.get_related_cpus.asyn(cpu)
|
||||||
yield domain
|
yield domain
|
||||||
cpus = cpus.difference(domain)
|
cpus = cpus.difference(domain)
|
||||||
|
@ -22,6 +22,7 @@ from devlib.module import Module
|
|||||||
from devlib.exception import TargetStableError
|
from devlib.exception import TargetStableError
|
||||||
from devlib.utils.types import integer, boolean
|
from devlib.utils.types import integer, boolean
|
||||||
from devlib.utils.misc import memoized
|
from devlib.utils.misc import memoized
|
||||||
|
import devlib.utils.asyn as asyn
|
||||||
|
|
||||||
|
|
||||||
class CpuidleState(object):
|
class CpuidleState(object):
|
||||||
@ -59,19 +60,23 @@ class CpuidleState(object):
|
|||||||
self.id = self.target.path.basename(self.path)
|
self.id = self.target.path.basename(self.path)
|
||||||
self.cpu = self.target.path.basename(self.target.path.dirname(path))
|
self.cpu = self.target.path.basename(self.target.path.dirname(path))
|
||||||
|
|
||||||
def enable(self):
|
@asyn.asyncf
|
||||||
self.set('disable', 0)
|
async def enable(self):
|
||||||
|
await self.set.asyn('disable', 0)
|
||||||
|
|
||||||
def disable(self):
|
@asyn.asyncf
|
||||||
self.set('disable', 1)
|
async def disable(self):
|
||||||
|
await self.set.asyn('disable', 1)
|
||||||
|
|
||||||
def get(self, prop):
|
@asyn.asyncf
|
||||||
|
async def get(self, prop):
|
||||||
property_path = self.target.path.join(self.path, prop)
|
property_path = self.target.path.join(self.path, prop)
|
||||||
return self.target.read_value(property_path)
|
return await self.target.read_value.asyn(property_path)
|
||||||
|
|
||||||
def set(self, prop, value):
|
@asyn.asyncf
|
||||||
|
async def set(self, prop, value):
|
||||||
property_path = self.target.path.join(self.path, prop)
|
property_path = self.target.path.join(self.path, prop)
|
||||||
self.target.write_value(property_path, value)
|
await self.target.write_value.asyn(property_path, value)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, CpuidleState):
|
if isinstance(other, CpuidleState):
|
||||||
@ -96,8 +101,9 @@ class Cpuidle(Module):
|
|||||||
root_path = '/sys/devices/system/cpu/cpuidle'
|
root_path = '/sys/devices/system/cpu/cpuidle'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def probe(target):
|
@asyn.asyncf
|
||||||
return target.file_exists(Cpuidle.root_path)
|
async def probe(target):
|
||||||
|
return await target.file_exists.asyn(Cpuidle.root_path)
|
||||||
|
|
||||||
def __init__(self, target):
|
def __init__(self, target):
|
||||||
super(Cpuidle, self).__init__(target)
|
super(Cpuidle, self).__init__(target)
|
||||||
@ -148,29 +154,39 @@ class Cpuidle(Module):
|
|||||||
return s
|
return s
|
||||||
raise ValueError('Cpuidle state {} does not exist'.format(state))
|
raise ValueError('Cpuidle state {} does not exist'.format(state))
|
||||||
|
|
||||||
def enable(self, state, cpu=0):
|
@asyn.asyncf
|
||||||
self.get_state(state, cpu).enable()
|
async def enable(self, state, cpu=0):
|
||||||
|
await self.get_state(state, cpu).enable.asyn()
|
||||||
|
|
||||||
def disable(self, state, cpu=0):
|
@asyn.asyncf
|
||||||
self.get_state(state, cpu).disable()
|
async def disable(self, state, cpu=0):
|
||||||
|
await self.get_state(state, cpu).disable.asyn()
|
||||||
|
|
||||||
def enable_all(self, cpu=0):
|
@asyn.asyncf
|
||||||
for state in self.get_states(cpu):
|
async def enable_all(self, cpu=0):
|
||||||
state.enable()
|
await self.target.async_manager.concurrently(
|
||||||
|
state.enable.asyn()
|
||||||
|
for state in self.get_states(cpu)
|
||||||
|
)
|
||||||
|
|
||||||
def disable_all(self, cpu=0):
|
@asyn.asyncf
|
||||||
for state in self.get_states(cpu):
|
async def disable_all(self, cpu=0):
|
||||||
state.disable()
|
await self.target.async_manager.concurrently(
|
||||||
|
state.disable.asyn()
|
||||||
|
for state in self.get_states(cpu)
|
||||||
|
)
|
||||||
|
|
||||||
def perturb_cpus(self):
|
@asyn.asyncf
|
||||||
|
async def perturb_cpus(self):
|
||||||
"""
|
"""
|
||||||
Momentarily wake each CPU. Ensures cpu_idle events in trace file.
|
Momentarily wake each CPU. Ensures cpu_idle events in trace file.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self.target._execute_util('cpuidle_wake_all_cpus')
|
await self.target._execute_util.asyn('cpuidle_wake_all_cpus')
|
||||||
|
|
||||||
def get_driver(self):
|
@asyn.asyncf
|
||||||
return self.target.read_value(self.target.path.join(self.root_path, 'current_driver'))
|
async def get_driver(self):
|
||||||
|
return await self.target.read_value.asyn(self.target.path.join(self.root_path, 'current_driver'))
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def list_governors(self):
|
def list_governors(self):
|
||||||
@ -179,12 +195,13 @@ class Cpuidle(Module):
|
|||||||
output = self.target.read_value(sysfile)
|
output = self.target.read_value(sysfile)
|
||||||
return output.strip().split()
|
return output.strip().split()
|
||||||
|
|
||||||
def get_governor(self):
|
@asyn.asyncf
|
||||||
|
async def get_governor(self):
|
||||||
"""Returns the currently selected idle governor."""
|
"""Returns the currently selected idle governor."""
|
||||||
path = self.target.path.join(self.root_path, 'current_governor_ro')
|
path = self.target.path.join(self.root_path, 'current_governor_ro')
|
||||||
if not self.target.file_exists(path):
|
if not await self.target.file_exists.asyn(path):
|
||||||
path = self.target.path.join(self.root_path, 'current_governor')
|
path = self.target.path.join(self.root_path, 'current_governor')
|
||||||
return self.target.read_value(path)
|
return await self.target.read_value.asyn(path)
|
||||||
|
|
||||||
def set_governor(self, governor):
|
def set_governor(self, governor):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user