#!/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