mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
config/functions: add multi-threaded helpers
This commit is contained in:
parent
2e3ac4899f
commit
c5e17fe2c9
144
config/functions
144
config/functions
@ -1175,7 +1175,7 @@ add_group() {
|
||||
}
|
||||
|
||||
# Usage: enable_service <unit> [target]
|
||||
enable_service () {
|
||||
enable_service() {
|
||||
local unit="$1"
|
||||
local unit_dir="/usr/lib/systemd/system"
|
||||
local target="$2"
|
||||
@ -1197,6 +1197,148 @@ enable_service () {
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
### MULTI-THREADED FUNCTION HELPERS ###
|
||||
# Prevent concurrent modifications to a package (unpack) or
|
||||
# package:target (install/build).
|
||||
#
|
||||
# If a package is already locked and the owner is ourselves
|
||||
# then assume we already have the required lock.
|
||||
pkg_lock() {
|
||||
[ "${MTWITHLOCKS}" != "yes" ] && return 0
|
||||
|
||||
local pkg="$1" task="$2" parent_pkg="$3"
|
||||
local this_job="${MTJOBID}"
|
||||
local lock_job lock_task lock_pkg
|
||||
|
||||
exec 98>"${THREAD_CONTROL}/locks/${pkg}.${task}"
|
||||
if ! flock --nonblock --exclusive 98; then
|
||||
while [ : ]; do
|
||||
read -r lock_job lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/${pkg}.${task}.owner" 2>/dev/null)
|
||||
[ -n "${lock_job}" ] && break || sleep 1
|
||||
done
|
||||
|
||||
if [ ${lock_job} != ${this_job} ]; then
|
||||
pkg_lock_status "STALLED" "${parent_pkg}" "${task}" "$(printf "waiting on [%02d] %s %s" ${lock_job} "${lock_task}" "${lock_pkg}")"
|
||||
flock --exclusive 98
|
||||
fi
|
||||
fi
|
||||
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${pkg}.${task}.owner"
|
||||
|
||||
pkg_lock_status "LOCKED" "${pkg}" "${task}"
|
||||
}
|
||||
|
||||
# Log additional information for a locked package.
|
||||
pkg_lock_status() {
|
||||
[ "${MTWITHLOCKS}" != "yes" ] && return 0
|
||||
|
||||
local status="$1" pkg="$2" task="$3" msg="$4"
|
||||
local this_job="${MTJOBID}" line
|
||||
|
||||
printf -v line "%s: <%05d> [%02d/%0*d] %-7s %-7s %-35s" \
|
||||
"$(date +%Y-%m-%d\ %H:%M:%S.%N)" $$ ${this_job} ${#MTMAXJOBS} ${PARALLEL_SEQ:-0} "${status}" "${task}" "${pkg}"
|
||||
[ -n "${msg}" ] && line+=" (${msg})"
|
||||
|
||||
echo "${line}" >>"${THREAD_CONTROL}/history"
|
||||
|
||||
[ "${DASHBOARD}" != "no" ] && update_dashboard "${status}" "${pkg}" "${task}" "${msg}"
|
||||
}
|
||||
|
||||
update_dashboard() {
|
||||
local status="$1" pkg="$2" task="$3" msg="$4"
|
||||
local line sedline preamble num elapsed projdevarch
|
||||
local boldred boldgreen boldyellow endcolor
|
||||
|
||||
(
|
||||
flock --exclusive 97
|
||||
|
||||
[ -n "${MTJOBID}" ] && sedline=$((MTJOBID + 2)) || sedline=1
|
||||
|
||||
num=$(cat "${THREAD_CONTROL}/status" | wc -l)
|
||||
while [ ${num} -lt ${sedline} ]; do echo "" >>"${THREAD_CONTROL}/status"; num=$((num + 1)); done
|
||||
|
||||
num=$(($(cat "${THREAD_CONTROL}/progress.prev") + 1))
|
||||
projdevarch="${PROJECT}/"
|
||||
[ -n "${DEVICE}" ] && projdevarch+="${DEVICE}/"
|
||||
projdevarch+="${TARGET_ARCH}"
|
||||
TZ=UTC0 printf -v elapsed "%(%H:%M:%S)T" $(($(date +%s) - MTBUILDSTART))
|
||||
printf -v preamble "%s Dashboard (%s) - %d of %d jobs completed, %s elapsed" "${DISTRONAME}" "${projdevarch}" ${num} ${MTMAXJOBS} "${elapsed}"
|
||||
printf -v preamble "%b%-105s %s" "\e[2J\e[0;0H" "${preamble//\//\\/}" "$(date "+%Y-%m-%d %H:%M:%S")"
|
||||
|
||||
# Only update the header when caller is not a worker thread
|
||||
if [ -z "${MTJOBID}" ]; then
|
||||
sed -e "1s/.*/${preamble}/" -i "${THREAD_CONTROL}/status"
|
||||
else
|
||||
if [ "${DISABLE_COLORS}" != "yes" ]; then
|
||||
boldred="\e[1;31m"
|
||||
boldgreen="\e[1;32m"
|
||||
boldyellow="\e[1;33m"
|
||||
white="\e[0;37m"
|
||||
endcolor="\e[0m"
|
||||
|
||||
case "${status}" in
|
||||
IDLE) color="${white}";;
|
||||
STALLED) color="${boldyellow}";;
|
||||
MUTEX/W) color="${boldyellow}";;
|
||||
FAILED ) color="${boldred}";;
|
||||
*) color="${boldgreen}";;
|
||||
esac
|
||||
fi
|
||||
|
||||
printf -v line "[%02d\/%0*d] %b%-7s%b %-7s %-35s" ${MTJOBID} ${#MTMAXJOBS} ${PARALLEL_SEQ:-0} "${color}" "${status//\//\\/}" "${endcolor}" "${task}" "${pkg}"
|
||||
[ -n "${msg}" ] && line+=" ${msg//\//\\/}"
|
||||
sed -e "1s/.*/${preamble}/;${sedline}s/.*/${line}/" -i "${THREAD_CONTROL}/status"
|
||||
fi
|
||||
) 97>"${THREAD_CONTROL}/locks/.status"
|
||||
}
|
||||
|
||||
# Thread concurrency helpers to avoid concurrency issues with some code,
|
||||
# eg. when Python installs directly into $TOOLCHAIN.
|
||||
# Test MTJOBID so that these functions are a no-op during non-multithreaded builds.
|
||||
acquire_exclusive_lock() {
|
||||
[ "${MTWITHLOCKS}" != "yes" ] && return 0
|
||||
|
||||
local pkg="$1" task="$2" lockfile="${3:-.global}"
|
||||
local this_job="${MTJOBID}"
|
||||
local lock_job lock_task lock_pkg
|
||||
|
||||
exec 96>"${THREAD_CONTROL}/locks/${lockfile}"
|
||||
if ! flock --nonblock --exclusive 96; then
|
||||
while [ : ]; do
|
||||
read -r lock_job lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/${lockfile}.owner" 2>/dev/null)
|
||||
[ -n "${lock_job}" ] && break || sleep 1
|
||||
done
|
||||
|
||||
if [ ${lock_job} != ${this_job} ]; then
|
||||
pkg_lock_status "MUTEX/W" "${pkg}" "${task}" "$(printf "mutex: %s; waiting on [%02d] %s %s" "${lockfile}" ${lock_job} "${lock_task}" "${lock_pkg}")"
|
||||
flock --exclusive 96
|
||||
fi
|
||||
fi
|
||||
echo "${this_job} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${lockfile}.owner"
|
||||
|
||||
pkg_lock_status "MUTEX" "${pkg}" "${task}" "mutex: ${lockfile}"
|
||||
}
|
||||
|
||||
release_exclusive_lock() {
|
||||
[ "${MTWITHLOCKS}" != "yes" ] && return 0
|
||||
|
||||
local pkg="$1" task="$2"
|
||||
|
||||
flock --unlock 96 2>/dev/null
|
||||
|
||||
pkg_lock_status "ACTIVE" "${pkg}" "${task}"
|
||||
}
|
||||
|
||||
# Execute single command using mutex
|
||||
exec_thread_safe() {
|
||||
local result
|
||||
acquire_exclusive_lock "${PKG_NAME:exec}" "execcmd"
|
||||
$@
|
||||
result=$?
|
||||
release_exclusive_lock "${PKG_NAME:exec}" "execcmd"
|
||||
return ${result}
|
||||
}
|
||||
|
||||
# Use distribution functions if any
|
||||
if [ -f "distributions/$DISTRO/config/functions" ]; then
|
||||
. distributions/$DISTRO/config/functions
|
||||
|
Loading…
x
Reference in New Issue
Block a user