mirror of
https://github.com/ARM-software/devlib.git
synced 2025-03-15 14:27:51 +00:00
On some systems this seems to have no effect, leaving the executed shell in the root cgroup. Before, this function would still execute and the end user would think the desired process was run in the cgroup when infact it had not.
370 lines
9.6 KiB
Plaintext
Executable File
370 lines
9.6 KiB
Plaintext
Executable File
CMD=$1
|
|
shift
|
|
|
|
BUSYBOX=${BUSYBOX:-__DEVLIB_BUSYBOX__}
|
|
FIND=${FIND:-$BUSYBOX find}
|
|
GREP=${GREP:-$BUSYBOX grep}
|
|
SED=${SED:-$BUSYBOX sed}
|
|
CAT=${CAT:-$BUSYBOX cat}
|
|
AWK=${AWK:-$BUSYBOX awk}
|
|
PS=${PS:-$BUSYBOX ps}
|
|
MOUNT=${MOUNT:-$BUSYBOX mount}
|
|
PRINTF=${PRINTF:-$BUSYBOX printf}
|
|
|
|
################################################################################
|
|
# 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_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
|
|
echo $GOV > $CPU/cpufreq/scaling_governor
|
|
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() {
|
|
local TRACEFS=$(get_tracefs_mount_point)
|
|
local FREQS=$($CAT /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq)
|
|
local CPU=0; for F in $FREQS; do
|
|
printf "%s\n" "cpu_frequency_devlib: state=$F cpu_id=$CPU" > $TRACEFS/trace_marker
|
|
CPU=$((CPU + 1))
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
# DevFrequency Utility Functions
|
|
################################################################################
|
|
|
|
devfreq_set_all_frequencies() {
|
|
FREQ=$1
|
|
for DEV in /sys/class/devfreq/*; do
|
|
echo $FREQ > $DEV/min_freq
|
|
echo $FREQ > $DEV/max_freq
|
|
done
|
|
}
|
|
|
|
devfreq_get_all_frequencies() {
|
|
for DEV in /sys/class/devfreq/*; do
|
|
echo "`basename $DEV` `cat $DEV/cur_freq`"
|
|
done
|
|
}
|
|
|
|
devfreq_set_all_governors() {
|
|
GOV=$1
|
|
for DEV in /sys/class/devfreq/*; do
|
|
echo $GOV > $DEV/governor
|
|
done
|
|
}
|
|
|
|
devfreq_get_all_governors() {
|
|
for DEV in /sys/class/devfreq/*; do
|
|
echo "`basename $DEV` `cat $DEV/governor`"
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
# CPUIdle Utility Functions
|
|
################################################################################
|
|
|
|
cpuidle_wake_all_cpus() {
|
|
CPU_PATHS=/sys/devices/system/cpu/cpu[0-9]*
|
|
MASK=0x1; for F in $CPU_PATHS; do
|
|
$BUSYBOX taskset $MASK true &
|
|
MASK=$($BUSYBOX printf '0x%x' $((MASK * 2)))
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
# FTrace Utility Functions
|
|
################################################################################
|
|
|
|
get_tracefs_mount_point() {
|
|
get_fs_mount_point tracefs || $PRINTF "%s" '/sys/kernel/debug/tracing'
|
|
}
|
|
|
|
ftrace_get_function_stats() {
|
|
local TRACEFS=$(get_tracefs_mount_point)
|
|
for CPU in $(ls $TRACEFS/trace_stat | sed 's/function//'); do
|
|
REPLACE_STRING="s/ Function/\n Function (CPU$CPU)/"
|
|
$CAT $TRACEFS/trace_stat/function$CPU \
|
|
| sed "$REPLACE_STRING"
|
|
done
|
|
}
|
|
|
|
|
|
################################################################################
|
|
# CGroups Utility Functions
|
|
################################################################################
|
|
|
|
cgroups_get_attributes() {
|
|
test $# -eq 2 || exit -1
|
|
CGROUP="$1"
|
|
CONTROLLER="$2"
|
|
# Check if controller is mounted with "noprefix" option, which is quite
|
|
# common on Android for backward compatibility
|
|
ls $CGROUP/$CONTROLLER\.* 2>&1 >/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
# no "noprefix" option, attributes format is:
|
|
# mnt_point/controller.attribute_name
|
|
$GREP '' $CGROUP/* | \
|
|
$GREP "$CONTROLLER\." | \
|
|
$SED -e "s|$CONTROLLER\.||" -e "s|$CGROUP/||"
|
|
else
|
|
# "noprefix" option, attribute format is:
|
|
# mnt_point/attribute_name
|
|
$GREP '' $(\
|
|
$FIND $CGROUP -type f -maxdepth 1 |
|
|
$GREP -v -e ".*tasks" -e ".*cgroup\..*") | \
|
|
$SED "s|$CGROUP/||"
|
|
fi
|
|
}
|
|
|
|
cgroups_run_into() {
|
|
|
|
# Control groups mount point
|
|
CGMOUNT=${CGMOUNT:-/sys/fs/cgroup}
|
|
# The control group we want to run into
|
|
CGP=${1}
|
|
shift 1
|
|
# The command to run
|
|
CMD="${@}"
|
|
|
|
# Execution under root CGgroup
|
|
if [ "x/" == "x$CGP" ]; then
|
|
|
|
$FIND $CGMOUNT -type d -maxdepth 0 | \
|
|
while read CGPATH; do
|
|
# Move this shell into that control group
|
|
echo $$ > $CGPATH/cgroup.procs
|
|
echo "Moving task into root CGroup ($CGPATH)"
|
|
# Check the move actually worked
|
|
$GREP -E "$$" $CGPATH/cgroup.procs >/dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: Process was not moved into $CGP"
|
|
exit 1
|
|
fi
|
|
done
|
|
if [ $? -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Execution under specified CGroup
|
|
else
|
|
|
|
# Check if the required CGroup exists
|
|
$FIND $CGMOUNT -type d -mindepth 1 | \
|
|
$GREP -E "^$CGMOUNT/devlib_cgh[0-9]{1,2}$CGP" >/dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: could not find any $CGP cgroup under $CGMOUNT"
|
|
exit 1
|
|
fi
|
|
|
|
$FIND $CGMOUNT -type d -mindepth 1 | \
|
|
$GREP -E "^$CGMOUNT/devlib_cgh[0-9]{1,2}$CGP$" | \
|
|
while read CGPATH; do
|
|
# Move this shell into that control group
|
|
echo $$ > $CGPATH/cgroup.procs
|
|
echo "Moving task into $CGPATH"
|
|
# Check the move actually worked
|
|
$GREP -E "$$" $CGPATH/cgroup.procs >/dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: Process was not moved into $CGP"
|
|
exit 1
|
|
fi
|
|
done
|
|
if [ $? -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Execute the command
|
|
exec $CMD
|
|
|
|
}
|
|
|
|
cgroups_tasks_move() {
|
|
SRC_GRP=${1}
|
|
DST_GRP=${2}
|
|
shift 2
|
|
FILTERS=$*
|
|
|
|
$CAT $SRC_GRP/tasks | while read TID; do
|
|
echo $TID > $DST_GRP/cgroup.procs
|
|
done
|
|
|
|
[ "x$FILTERS" = "x" ] && exit 0
|
|
|
|
PIDS=`$PS -o comm,pid | $GREP $FILTERS | $AWK '{print $2}'`
|
|
PIDS=`echo $PIDS`
|
|
echo "PIDs to save: [$PIDS]"
|
|
for TID in $PIDS; do
|
|
COMM=`$CAT /proc/$TID/comm`
|
|
echo "$TID : $COMM"
|
|
echo $TID > $SRC_GRP/cgroup.procs || true
|
|
done
|
|
}
|
|
|
|
cgroups_tasks_in() {
|
|
GRP=${1}
|
|
for TID in $($CAT $GRP/tasks); do
|
|
COMM=`$CAT /proc/$TID/comm 2>/dev/null`
|
|
[ "$COMM" != "" ] && CMDL=`$CAT /proc/$TID/cmdline 2>/dev/null`
|
|
[ "$COMM" != "" ] && echo "$TID,$COMM,$CMDL"
|
|
done
|
|
exit 0
|
|
}
|
|
|
|
cgroups_freezer_set_state() {
|
|
STATE=${1}
|
|
SYSFS_ENTRY=${2}/freezer.state
|
|
|
|
# Set the state of the freezer
|
|
echo $STATE > $SYSFS_ENTRY
|
|
|
|
# And check it applied cleanly
|
|
for i in `seq 1 10`; do
|
|
[ $($CAT $SYSFS_ENTRY) = $STATE ] && exit 0
|
|
sleep 1
|
|
done
|
|
|
|
# We have an issue
|
|
echo "ERROR: Freezer stalled while changing state to \"$STATE\"." >&2
|
|
exit 1
|
|
}
|
|
|
|
################################################################################
|
|
# Hotplug
|
|
################################################################################
|
|
|
|
hotplug_online_all() {
|
|
for path in /sys/devices/system/cpu/cpu[0-9]*; do
|
|
if [ $(cat $path/online) -eq 0 ]; then
|
|
echo 1 > $path/online
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
################################################################################
|
|
# Scheduler
|
|
################################################################################
|
|
|
|
sched_get_kernel_attributes() {
|
|
MATCH=${1:-'.*'}
|
|
[ -d /proc/sys/kernel/ ] || exit 1
|
|
$GREP '' /proc/sys/kernel/sched_* | \
|
|
$SED -e 's|/proc/sys/kernel/sched_||' | \
|
|
$GREP -e "$MATCH"
|
|
}
|
|
|
|
################################################################################
|
|
# Misc
|
|
################################################################################
|
|
|
|
read_tree_values() {
|
|
BASEPATH=$1
|
|
MAXDEPTH=$2
|
|
|
|
if [ ! -e $BASEPATH ]; then
|
|
echo "ERROR: $BASEPATH does not exist"
|
|
exit 1
|
|
fi
|
|
|
|
PATHS=$($BUSYBOX find $BASEPATH -follow -maxdepth $MAXDEPTH)
|
|
i=0
|
|
for path in $PATHS; do
|
|
i=$(expr $i + 1)
|
|
if [ $i -gt 1 ]; then
|
|
break;
|
|
fi
|
|
done
|
|
if [ $i -gt 1 ]; then
|
|
$BUSYBOX grep -s '' $PATHS
|
|
fi
|
|
}
|
|
|
|
read_tree_tgz_b64() {
|
|
BASEPATH=$1
|
|
MAXDEPTH=$2
|
|
TMPBASE=$3
|
|
|
|
if [ ! -e $BASEPATH ]; then
|
|
echo "ERROR: $BASEPATH does not exist"
|
|
exit 1
|
|
fi
|
|
|
|
cd $TMPBASE
|
|
TMP_FOLDER=$($BUSYBOX realpath $($BUSYBOX mktemp -d XXXXXX))
|
|
|
|
# 'tar' doesn't work as expected on debugfs, so copy the tree first to
|
|
# workaround the issue
|
|
cd $BASEPATH
|
|
for CUR_FILE in $($BUSYBOX find . -follow -type f -maxdepth $MAXDEPTH); do
|
|
$BUSYBOX cp --parents $CUR_FILE $TMP_FOLDER/ 2> /dev/null
|
|
done
|
|
|
|
cd $TMP_FOLDER
|
|
$BUSYBOX tar cz * 2>/dev/null | $BUSYBOX base64
|
|
|
|
# Clean-up the tmp folder since we won't need it any more
|
|
cd $TMPBASE
|
|
rm -rf $TMP_FOLDER
|
|
}
|
|
|
|
get_linux_system_id() {
|
|
kernel=$($BUSYBOX uname -r)
|
|
hardware=$($BUSYBOX ip a | $BUSYBOX grep 'link/ether' | $BUSYBOX sed 's/://g' | $BUSYBOX awk '{print $2}' | $BUSYBOX tr -d '\n')
|
|
filesystem=$(ls /dev/disk/by-uuid | $BUSYBOX tr '\n' '-' | $BUSYBOX sed 's/-$//')
|
|
echo "$hardware/$kernel/$filesystem"
|
|
}
|
|
|
|
get_android_system_id() {
|
|
kernel=$($BUSYBOX uname -r)
|
|
hardware=$($BUSYBOX ip a | $BUSYBOX grep 'link/ether' | $BUSYBOX sed 's/://g' | $BUSYBOX awk '{print $2}' | $BUSYBOX tr -d '\n')
|
|
filesystem=$(content query --uri content://settings/secure --projection value --where "name='android_id'" | $BUSYBOX cut -f2 -d=)
|
|
echo "$hardware/$kernel/$filesystem"
|
|
}
|
|
|
|
get_fs_mount_point() {
|
|
local path=$(LC_ALL=C $MOUNT -t "$1" | $SED -n "s/$1 on \(.*\) type $1 .*/\1/p;q")
|
|
if [ "$path" == "" ]; then
|
|
return 1
|
|
else
|
|
$PRINTF "%s" "$path"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Main Function Dispatcher
|
|
################################################################################
|
|
|
|
# Use a function instead of a subshell so "exit 1" works as expected
|
|
_command_not_found() {
|
|
echo "Command [$CMD] not supported"
|
|
exit 1
|
|
}
|
|
# Check the command exists
|
|
type "$CMD" >/dev/null 2>&1 || _command_not_found
|
|
|
|
"$CMD" "$@"
|
|
|
|
# vim: tabstop=4 shiftwidth=4
|