From f2eac51c694de18edbf1be569a52a3de08fdc51a Mon Sep 17 00:00:00 2001 From: Patrick Bellasi Date: Fri, 27 Nov 2015 16:35:57 +0000 Subject: [PATCH 1/3] target: add support for target side scripts Some complex operations are faster if executed on the target side with the help of a small script. For example, reading the current frequency and or governor for all the online CPUs. This patch adds a support script to be deployed on the target as well as an internal utility function which allows to call functions provided by that support script. The support script has to be cross platform, thus: 1. only a limited set of shell functions can be used, which must be supported both in BASH and the Android shell 2. some paths needs to be defined depending on the specific target To address the last constrain, this patch provides a "template" script which contains some tokens "__DEVLIB___" that are replaced right before to push the script on the target. Signed-off-by: Patrick Bellasi --- .gitignore | 1 + devlib/bin/scripts/shutils.in | 21 +++++++++++++++++++++ devlib/target.py | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100755 devlib/bin/scripts/shutils.in diff --git a/.gitignore b/.gitignore index d15a155..6475149 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.orig .ropeproject *.egg-info +devlib/bin/scripts/shutils diff --git a/devlib/bin/scripts/shutils.in b/devlib/bin/scripts/shutils.in new file mode 100755 index 0000000..33bb0e1 --- /dev/null +++ b/devlib/bin/scripts/shutils.in @@ -0,0 +1,21 @@ +#!__DEVLIB_SHELL__ + +CMD=$1 +shift + +BUSYBOX=${BUSYBOX:-__DEVLIB_BUSYBOX__} +GREP=${GREP:-$BUSYBOX grep} +SED=${SED:-$BUSYBOX sed} + + +################################################################################ +# Main Function Dispatcher +################################################################################ + +case $CMD in +*) + echo "Command [$CMD] not supported" + exit -1 +esac + +# vim: tabstop=4 shiftwidth=4 diff --git a/devlib/target.py b/devlib/target.py index e744110..b0a3737 100644 --- a/devlib/target.py +++ b/devlib/target.py @@ -197,6 +197,22 @@ class Target(object): self.execute('mkdir -p {}'.format(self.working_directory)) self.execute('mkdir -p {}'.format(self.executables_directory)) self.busybox = self.install(os.path.join(PACKAGE_BIN_DIRECTORY, self.abi, 'busybox')) + + # Setup shutils script for the target + shutils_ifile = os.path.join(PACKAGE_BIN_DIRECTORY, 'scripts', 'shutils.in') + shutils_ofile = os.path.join(PACKAGE_BIN_DIRECTORY, 'scripts', 'shutils') + shell_path = '/bin/sh' + if self.os == 'android': + shell_path = '/system/bin/sh' + with open(shutils_ifile) as fh: + lines = fh.readlines() + with open(shutils_ofile, 'w') as ofile: + for line in lines: + line = line.replace("__DEVLIB_SHELL__", shell_path) + line = line.replace("__DEVLIB_BUSYBOX__", self.busybox) + ofile.write(line) + self.shutils = self.install(os.path.join(PACKAGE_BIN_DIRECTORY, 'scripts', 'shutils')) + for host_exe in (executables or []): # pylint: disable=superfluous-parens self.install(host_exe) @@ -227,6 +243,10 @@ class Target(object): # execution + def _execute_util(self, command, timeout=None, check_exit_code=True, as_root=False): + command = '{} {}'.format(self.shutils, command) + return self.conn.execute(command, timeout, check_exit_code, as_root) + def execute(self, command, timeout=None, check_exit_code=True, as_root=False): return self.conn.execute(command, timeout, check_exit_code, as_root) From cf761317bd8ed87154a4a0245c1f243f66809b3a Mon Sep 17 00:00:00 2001 From: Patrick Bellasi Date: Fri, 27 Nov 2015 16:38:30 +0000 Subject: [PATCH 2/3] cpufreq: switch to usage of shutils functions This patch convert some functions to the usage of shutils provided calls. This approach is more portable and allows to use these calls also on an Android target. Signed-off-by: Patrick Bellasi --- devlib/bin/scripts/shutils.in | 34 ++++++++++++++++++++++++++++++++++ devlib/module/cpufreq.py | 35 ++++++++++++++++------------------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/devlib/bin/scripts/shutils.in b/devlib/bin/scripts/shutils.in index 33bb0e1..1ae9a4f 100755 --- a/devlib/bin/scripts/shutils.in +++ b/devlib/bin/scripts/shutils.in @@ -7,12 +7,46 @@ BUSYBOX=${BUSYBOX:-__DEVLIB_BUSYBOX__} GREP=${GREP:-$BUSYBOX grep} SED=${SED:-$BUSYBOX sed} +################################################################################ +# CPUFrequency Utility Functions +################################################################################ + +cpufreq_set_all_frequencies() { + FREQ=$1 + for CPU in /sys/devices/system/cpu/cpu[0-9]*; do + echo $FREQ > $CPU/cpufreq/scaling_cur_freq + done +} + +cpufreq_set_all_governors() { + GOV=$1 + for CPU in /sys/devices/system/cpu/cpu[0-9]*; do + echo $GOV > $CPU/cpufreq/scaling_governor + done +} + +cpufreq_trace_all_frequencies() { + FREQS=$(cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq) + CPU=0; for F in $FREQS; do + echo "cpu_frequency: state=$F cpu_id=$CPU" > /sys/kernel/debug/tracing/trace_marker + CPU=$((CPU + 1)) + done +} ################################################################################ # Main Function Dispatcher ################################################################################ case $CMD in +cpufreq_set_all_frequencies) + cpufreq_set_all_frequencies $* + ;; +cpufreq_set_all_governors) + cpufreq_set_all_governors $* + ;; +cpufreq_trace_all_frequencies) + cpufreq_trace_all_frequencies $* + ;; *) echo "Command [$CMD] not supported" exit -1 diff --git a/devlib/module/cpufreq.py b/devlib/module/cpufreq.py index 5a55213..ed2f2e5 100644 --- a/devlib/module/cpufreq.py +++ b/devlib/module/cpufreq.py @@ -349,30 +349,27 @@ class CpufreqModule(Module): for cpu in online_cpus: self.set_frequency(cpu, freq, exact) - def set_all_frequencies(self, freq, exact=False): - self.target.execute( - "for CPU in /sys/devices/system/cpu/cpu[0-9]*; do "\ - "echo {} > $CPU/cpufreq/scaling_cur_freq; "\ - "done"\ - .format(freq), as_root=True) + def set_all_frequencies(self, freq): + """ + Set the specified (minimum) frequency for all the (online) CPUs + """ + return self.target._execute_util( + 'cpufreq_set_all_frequencies {}'.format(freq), + as_root=True) + def set_all_governors(self, governor): - self.target.execute( - "for CPU in /sys/devices/system/cpu/cpu[0-9]*; do "\ - "echo {} > $CPU/cpufreq/scaling_governor; "\ - "done"\ - .format(governor), as_root=True) + """ + Set the specified governor for all the (online) CPUs + """ + return self.target._execute_util( + 'cpufreq_set_all_governors {}'.format(governor), + as_root=True) + def trace_frequencies(self): """ Report current frequencies on trace file """ - self.target.execute( - 'FREQS=$(cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq); ' - 'CPU=0; for F in $FREQS; do ' - ' echo "cpu_frequency: state=$F cpu_id=$CPU" > /sys/kernel/debug/tracing/trace_marker; ' - ' let CPU++; ' - 'done', - as_root=True - ) + return self.target._execute_util('cpufreq_trace_all_frequencies', as_root=True) From 51b7f01d360c36cf620c28f06608c7e64714746a Mon Sep 17 00:00:00 2001 From: Patrick Bellasi Date: Fri, 27 Nov 2015 16:40:58 +0000 Subject: [PATCH 3/3] cpufreq: add functions to get frequencies and governors for all online CPUs This patch adds a couple of shutils functions to efficiently read all the frequencies/governors and returne them into a dictionary indexed by CPU id. The shutils functions are returning a line per each CPU that can be easily converted into a dictionary in the host side. Signed-off-by: Patrick Bellasi --- devlib/bin/scripts/shutils.in | 16 ++++++++++++++++ devlib/module/cpufreq.py | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/devlib/bin/scripts/shutils.in b/devlib/bin/scripts/shutils.in index 1ae9a4f..0023a5e 100755 --- a/devlib/bin/scripts/shutils.in +++ b/devlib/bin/scripts/shutils.in @@ -18,6 +18,11 @@ cpufreq_set_all_frequencies() { done } +cpufreq_get_all_frequencies() { + $GREP '' /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq | \ + $SED -e 's|/sys/devices/system/cpu/cpu||' -e 's|/cpufreq/scaling_cur_freq:| |' +} + cpufreq_set_all_governors() { GOV=$1 for CPU in /sys/devices/system/cpu/cpu[0-9]*; do @@ -25,6 +30,11 @@ cpufreq_set_all_governors() { done } +cpufreq_get_all_governors() { + $GREP '' /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor | \ + $SED -e 's|/sys/devices/system/cpu/cpu||' -e 's|/cpufreq/scaling_governor:| |' +} + cpufreq_trace_all_frequencies() { FREQS=$(cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq) CPU=0; for F in $FREQS; do @@ -41,9 +51,15 @@ case $CMD in cpufreq_set_all_frequencies) cpufreq_set_all_frequencies $* ;; +cpufreq_get_all_frequencies) + cpufreq_get_all_frequencies + ;; cpufreq_set_all_governors) cpufreq_set_all_governors $* ;; +cpufreq_get_all_governors) + cpufreq_get_all_governors + ;; cpufreq_trace_all_frequencies) cpufreq_trace_all_frequencies $* ;; diff --git a/devlib/module/cpufreq.py b/devlib/module/cpufreq.py index ed2f2e5..31aa9db 100644 --- a/devlib/module/cpufreq.py +++ b/devlib/module/cpufreq.py @@ -357,6 +357,19 @@ class CpufreqModule(Module): 'cpufreq_set_all_frequencies {}'.format(freq), as_root=True) + def get_all_frequencies(self): + """ + Get the current frequency for all the (online) CPUs + """ + output = self.target._execute_util( + 'cpufreq_get_all_frequencies', as_root=True) + frequencies = {} + for x in output.splitlines(): + kv = x.split(' ') + if kv[0] == '': + break + frequencies[kv[0]] = kv[1] + return frequencies def set_all_governors(self, governor): """ @@ -366,6 +379,19 @@ class CpufreqModule(Module): 'cpufreq_set_all_governors {}'.format(governor), as_root=True) + def get_all_governors(self): + """ + Get the current governor for all the (online) CPUs + """ + output = self.target._execute_util( + 'cpufreq_get_all_governors', as_root=True) + governors = {} + for x in output.splitlines(): + kv = x.split(' ') + if kv[0] == '': + break + governors[kv[0]] = kv[1] + return governors def trace_frequencies(self): """