1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

target: Speedup Target.write_value()

Avoid an execute() by doing the check in the same command. This also
allows to return early if the write is fast, and to extend for longer if
the write is slow. The speed at which you can observe a write in sysfs
depends on the backing kernel handlers, so there is a wide variety of
situations.

Also, make a more fine grained error detection by allowing the write
itself to fail, which can happen when writing invalid values to sysfs.
This commit is contained in:
Douglas Raillard 2021-08-20 10:59:40 +01:00 committed by Marc Bonnici
parent 0c1878786b
commit e979bafb50

View File

@ -50,7 +50,7 @@ from devlib.platform import Platform
from devlib.exception import (DevlibTransientError, TargetStableError,
TargetNotRespondingError, TimeoutError,
TargetTransientError, KernelConfigKeyError,
TargetError, HostError) # pylint: disable=redefined-builtin
TargetError, HostError, TargetCalledProcessError) # pylint: disable=redefined-builtin
from devlib.utils.ssh import SshConnection
from devlib.utils.android import AdbConnection, AndroidProperties, LogcatMonitor, adb_command, adb_disconnect, INTENT_FLAGS
from devlib.utils.misc import memoized, isiterable, convert_new_lines, groupby_value
@ -848,12 +848,44 @@ class Target(object):
def write_value(self, path, value, verify=True):
value = str(value)
self.execute('echo {} > {}'.format(quote(value), quote(path)), check_exit_code=False, as_root=True)
if verify:
output = self.read_value(path)
if not output == value:
message = 'Could not set the value of {} to "{}" (read "{}")'.format(path, value, output)
# Check in a loop for a while since updates to sysfs files can take
# some time to be observed, typically when a write triggers a
# lengthy kernel-side request, and the read is based on some piece
# of state that may take some time to be updated by the write
# request, such as hotplugging a CPU.
cmd = '''
orig=$(cat {path} 2>/dev/null || printf "")
printf "%s" {value} > {path} || exit 10
if [ {value} != "$orig" ]; then
trials=0
while [ "$(cat {path} 2>/dev/null)" != {value} ]; do
if [ $trials -ge 10 ]; then
cat {path}
exit 11
fi
sleep 0.01
trials=$((trials + 1))
done
fi
'''
else:
cmd = '{busybox} printf "%s" {value} > {path}'
cmd = cmd.format(busybox=quote(self.busybox), path=quote(path), value=quote(value))
try:
self.execute(cmd, check_exit_code=True, as_root=True)
except TargetCalledProcessError as e:
if e.returncode == 10:
raise TargetStableError('Could not write "{value}" to {path}: {e.output}'.format(
value=value, path=path, e=e))
elif verify and e.returncode == 11:
out = e.output
message = 'Could not set the value of {} to "{}" (read "{}")'.format(path, value, out)
raise TargetStableError(message)
else:
raise
def reset(self):
try: