318 lines
8.3 KiB
Bash
318 lines
8.3 KiB
Bash
#!/bin/bash
|
|
### BEGIN INIT INFO
|
|
# Provides: realtime
|
|
# Required-Start: $remote_fs $syslog
|
|
# Required-Stop: $remote_fs $syslog
|
|
# Default-Start:
|
|
# Default-Stop: 0 1 6
|
|
# Short-Description: enable realtime capabilities when needed
|
|
# Description: The rtai module is loaded when needed and
|
|
# removed when the job has ended and is used throughout the LinuxCNC
|
|
# infrastructure. The script has no effect for the PREEMPT realtime kernel.
|
|
# The script is not meant to be started a boot time - it could be, though.
|
|
# X-Interactive: false
|
|
### END INIT INFO
|
|
#
|
|
# @configure_input@
|
|
# on @DATE@
|
|
#
|
|
|
|
export LANG=C
|
|
|
|
GREP=@GREP@
|
|
PS=@PS@
|
|
|
|
CheckKernel() {
|
|
# Shellcheck doesn't know about substitution
|
|
# shellcheck disable=SC2194
|
|
case "@KERNEL_VERS@" in
|
|
"")
|
|
;;
|
|
*)
|
|
if [ "$(uname -r)" != "@KERNEL_VERS@" ]; then
|
|
cat 1>&2 << EOF
|
|
RTAPI requires the real-time kernel @KERNEL_VERS@ to run. Before running
|
|
this realtime application, reboot and choose this kernel at the boot menu.
|
|
EOF
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
RUN_IN_PLACE=@RUN_IN_PLACE@
|
|
if [ $RUN_IN_PLACE = yes ]; then
|
|
# When using RIP make sure PATH includes the directory where rtapi_app
|
|
# resides
|
|
PATH=@EMC2_HOME@/bin:$PATH; export PATH
|
|
fi
|
|
|
|
CheckConfig(){
|
|
# Shellcheck doesn't know about substitution
|
|
# shellcheck disable=SC2034
|
|
prefix=@prefix@
|
|
# shellcheck disable=SC2034
|
|
exec_prefix=@exec_prefix@
|
|
sysconfdir=@sysconfdir@
|
|
if [ "$RUN_IN_PLACE" = "yes" ]; then
|
|
RTAPICONF=
|
|
# check in the LinuxCNC scripts directory
|
|
# $0 is the command to run this script
|
|
# strip the script name to leave the path
|
|
SCRIPT_DIR=${0%/*}
|
|
# the path might be relative
|
|
# convert it to an absolute path
|
|
SCRIPT_DIR=$(realpath "$SCRIPT_DIR")
|
|
# now look for rtapi.conf there
|
|
if [ -f "$SCRIPT_DIR/rtapi.conf" ] ; then
|
|
RTAPICONF=$SCRIPT_DIR/rtapi.conf
|
|
fi
|
|
else
|
|
if [ -f "$sysconfdir/linuxcnc/rtapi.conf" ]; then
|
|
RTAPICONF=$sysconfdir/linuxcnc/rtapi.conf
|
|
fi
|
|
fi
|
|
if [ -z "$RTAPICONF" ] ; then
|
|
echo "Missing rtapi.conf. Check your installation." 1>&2
|
|
exit 1
|
|
fi
|
|
INSMOD="@INSMOD@"
|
|
RMMOD="@RMMOD@"
|
|
LSMOD="@LSMOD@"
|
|
FUSER="@FUSER@"
|
|
|
|
# Import the config
|
|
source "$RTAPICONF"
|
|
if [ ! -e "$RTLIB_DIR/.runinfo" ] && [ -e "$RTLIB_DIR/emc2/.runinfo" ]; then
|
|
# installed system: we don't want our modules mixed up with rtai
|
|
RTLIB_DIR=$RTLIB_DIR/emc2
|
|
fi
|
|
# Export the module path specified in the config.
|
|
export MODPATH
|
|
# Generate module lists for loading and unloading
|
|
# lists contain RTOS modules plus RTAPI and HAL
|
|
# unload list is in reverse order
|
|
# any module names that are symlinks are resolved to their real names
|
|
MODULES_LOAD=
|
|
MODULES_UNLOAD=
|
|
case $RTPREFIX in
|
|
uspace)
|
|
SHM_DEV=/dev/zero
|
|
;;
|
|
esac
|
|
for MOD in $MODULES ; do
|
|
eval MOD="\${MODPATH_${MOD}}"
|
|
if [ -z "$MOD" ]; then continue; fi
|
|
if [ -L "$MOD" ]; then
|
|
MOD=${MOD%/*}/$(readlink "$MOD")
|
|
fi
|
|
MODULES_LOAD="$MODULES_LOAD $MOD"
|
|
MOD="${MOD##*/}"
|
|
MOD="${MOD%.*}"
|
|
MODULES_UNLOAD="$MOD $MODULES_UNLOAD"
|
|
done
|
|
case $RTPREFIX in
|
|
*rtai*)
|
|
MODULES_LOAD="$MODULES_LOAD $RTLIB_DIR/rtapi$MODULE_EXT $RTLIB_DIR/hal_lib$MODULE_EXT"
|
|
MODULES_UNLOAD="hal_lib rtapi $MODULES_UNLOAD"
|
|
SHM_DEV=/dev/rtai_shm
|
|
;;
|
|
*)
|
|
MODULES_UNLOAD=
|
|
;;
|
|
esac
|
|
}
|
|
|
|
CheckStatus(){
|
|
case $RTPREFIX in
|
|
uspace)
|
|
if rtapi_app ping; then
|
|
echo rtapi_app is running
|
|
return 0
|
|
elif [ -n "$($PS -o stat= -o comm= -C rtapi_app | $GREP -v '^Z')" ]; then
|
|
echo rtapi_app is running but not reachable
|
|
return 1
|
|
else
|
|
echo rtapi_app is not running
|
|
return 1
|
|
fi
|
|
;;
|
|
*)
|
|
# check loaded/unloaded status of modules
|
|
unset NOTLOADED
|
|
for MOD in $MODULES_UNLOAD ; do
|
|
if "$LSMOD" | awk '{print $1}' | $GREP -x "$MOD" >/dev/null ; then
|
|
echo "$MOD is loaded"
|
|
else
|
|
echo "$MOD is not loaded"
|
|
NOTLOADED=NOT
|
|
fi
|
|
done
|
|
if [ -z "$NOTLOADED" ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
CheckMem(){
|
|
# check for user space processes using shared memory
|
|
if [ -e /dev/mbuff ] ; then
|
|
# device file exists, check for processes using it
|
|
if $FUSER -s /dev/mbuff 2>/dev/null; then
|
|
# at least one process is using it
|
|
echo "ERROR: Can't remove RTLinux modules, kill the following process(es) first"
|
|
$FUSER -v /dev/mbuff
|
|
exit 1
|
|
fi
|
|
elif [ -e /dev/rtai_shm ] ; then
|
|
# device file exists, check for processes using it
|
|
if $FUSER -s /dev/rtai_shm 2>/dev/null; then
|
|
# at least one process is using it
|
|
echo "ERROR: Can't remove RTAI modules, kill the following process(es) first"
|
|
$FUSER -v /dev/rtai_shm
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
Load(){
|
|
CheckKernel
|
|
case $RTPREFIX in
|
|
uspace)
|
|
rtapi_app start
|
|
;;
|
|
*rtai*)
|
|
for MOD in $MODULES_LOAD ; do
|
|
if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then
|
|
$INSMOD "$MOD" || return $?
|
|
fi
|
|
done
|
|
if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then
|
|
echo "$DEBUG" > /proc/rtapi/debug
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
CheckLoaded(){
|
|
# this abomination is needed because udev sometimes doesn't
|
|
# have the device ready for us in time.
|
|
n=0
|
|
while [ $n -lt 100 ]; do
|
|
[ -w "$SHM_DEV" ] && return 0
|
|
echo "." 1>&2
|
|
sleep .1
|
|
n=$((n + 1))
|
|
done
|
|
echo "Can't write to $SHM_DEV - aborting" 1>&2
|
|
exit 1
|
|
}
|
|
|
|
Unload(){
|
|
CheckKernel
|
|
|
|
case $RTPREFIX in
|
|
uspace)
|
|
rtapi_app exit
|
|
|
|
# wait 5 seconds for rtapi_app to die and be reaped by its parent
|
|
START=$SECONDS
|
|
local NPROCS
|
|
while [ 5 -gt $((SECONDS-START)) ]; do
|
|
NPROCS=$(ps -C rtapi_app -o stat= -o comm= | $GREP -v '^Z' | wc -l)
|
|
if [ "$NPROCS" -eq 0 ]; then
|
|
break
|
|
fi
|
|
sleep 0.1
|
|
done
|
|
NPROCS=$(ps -C rtapi_app -o stat= -o comm= | $GREP -v '^Z' | wc -l)
|
|
if [ "$NPROCS" -gt 0 ]; then
|
|
echo "ERROR: rtapi_app failed to die" 1>&2
|
|
fi
|
|
|
|
ipcrm -M 0x48414c32 2>/dev/null ;# HAL_KEY
|
|
ipcrm -M 0x90280A48 2>/dev/null ;# RTAPI_KEY
|
|
ipcrm -M 0x48484c34 2>/dev/null ;# UUID_KEY
|
|
;;
|
|
esac
|
|
|
|
for module in $MODULES_UNLOAD ; do
|
|
$RMMOD "$module"
|
|
done
|
|
}
|
|
|
|
Verify(){
|
|
HAS_REALTIME=false
|
|
case $RTPREFIX in
|
|
uspace)
|
|
rtapi_app check_rt && HAS_REALTIME=true
|
|
;;
|
|
*rtai*)
|
|
echo "RTAI"
|
|
HAS_REALTIME=true
|
|
;;
|
|
esac
|
|
|
|
if [ $HAS_REALTIME = true ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
CheckUnloaded(){
|
|
# checks to see if all modules were unloaded
|
|
STATUS=
|
|
for module in $MODULES_UNLOAD ; do
|
|
# check to see if the module is installed
|
|
if "$LSMOD" | awk '{print $1}' | $GREP -x "$module" >/dev/null ; then
|
|
echo "ERROR: Could not unload '$module'"
|
|
STATUS=error
|
|
fi
|
|
done
|
|
if [ -n "$STATUS" ] ; then
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
CMD=$1
|
|
|
|
case "$CMD" in
|
|
start|load)
|
|
CheckConfig
|
|
Load || exit $?
|
|
CheckLoaded
|
|
;;
|
|
restart|force-reload)
|
|
CheckConfig
|
|
CheckMem
|
|
Unload
|
|
CheckUnloaded
|
|
Load || exit $?
|
|
CheckLoaded
|
|
;;
|
|
stop|unload)
|
|
CheckConfig
|
|
CheckMem
|
|
Unload || exit $?
|
|
;;
|
|
status)
|
|
CheckConfig
|
|
CheckStatus || exit $?
|
|
;;
|
|
verify)
|
|
CheckConfig
|
|
Verify || exit $?
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status|verify}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
exit 0
|
|
|