diff --git a/.gitignore b/.gitignore index ea8b7ee7f5..b4b9755270 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ src/hal/cython/machinekit/*.c /machinekit-build-deps_*.deb .directory *.9icomp +# install artifacts +/include/ diff --git a/debian/.gitignore b/debian/.gitignore index 277c5fe558..a33ff7c3f0 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -1,19 +1,20 @@ # files generated from debian/configure /control -/rules -/files /configure.cmdline /machinekit*.install /machinekit*.postinst + +# generated by scripts/build_source_package /changelog # directory artifacts /tmp -/machinekit*/ +/machinekit-hal*/ # file artifacts /*substvars /*.debhelper /shlibs.local +/files !/changelog.in diff --git a/debian/changelog.in b/debian/changelog.in index d884eee82b..0c81f85411 100644 --- a/debian/changelog.in +++ b/debian/changelog.in @@ -1,3 +1,11 @@ +machinekit-hal (0.3.0) stretch; urgency=low + + * Separate rtapi_app_ now merged into single binary + * RT thread flavor now chosen at run-time + * Separate flavor RT modules now common + + -- John Morris Thu, 11 Jul 2019 02:32:05 -0500 + machinekit-hal (0.2.0) stretch; urgency=low * HAL stack split out from machinekit diff --git a/debian/configure b/debian/configure index c30365043e..29b05cb142 100755 --- a/debian/configure +++ b/debian/configure @@ -4,13 +4,12 @@ # # Configure source package dependencies -# List of supported kernel arches for kthreads -KTHREAD_ARCHES="i386 amd64" -if test -x /usr/bin/lsb_release; then - DISTRO_ID=$(lsb_release -is) # Debian or Ubuntu - DISTRO_RELEASE=$(lsb_release -rs) # 8.1, 14.04, etc. - DISTRO_CODENAME=$(lsb_release -cs) # wheezy | jessie | stretch | buster -fi +# Distro info +# +# This should run on non-Debian distros; lsb_release is only used for +# TCL/TK version detection, which can be passed in through the '-t +# VERSION' switch +DISTRO_CODENAME=$(lsb_release -cs) # jessie | stretch | buster # Work out of the debian/ directory cd "$(dirname $0)" @@ -19,64 +18,18 @@ cd "$(dirname $0)" # re-run echo $0 $* > configure.cmdline -rules_enable_threads() { - # enable thread flavors in debian/rules; e.g. - # THREADS_POSIX = --with-posix - FLAVOR=$1 - FLAVOR_VAR=THREADS_$(echo $FLAVOR | tr 'a-z-' 'A-Z_') - sed -i rules \ - -e "s/^${FLAVOR_VAR}[^_].*/${FLAVOR_VAR} = --with-${FLAVOR}/" - echo "debian/rules: enabled ${FLAVOR} threads" >&2 -} - -guess_arch_from_kver() { - # utility to make a guess at the kernel header arch from the - # kernel version; this works for Debian kernels, and 'any' is - # correct for the RTAI kernel packages in the Machinekit Debian - # archive - KVER=$1 - case $KVER in - *-?86 | *-?86-pae) echo i386 ;; - *-amd64) echo amd64 ;; - *) echo any ;; # For non-Debian kernel package naming - esac -} - -do_posix() { - cat control.d/control.posix.hdr control.d/control.$DISTRO_CODENAME.in control.d/control.posix.ftr >> control - echo "debian/control: added POSIX threads package" >&2 - rules_enable_threads posix - HAVE_FLAVOR=true -} - -do_rt-preempt() { - cat control.d/control.rt-preempt.hdr control.d/control.$DISTRO_CODENAME.in control.d/control.rt-preempt.ftr >> control - echo "debian/control: added RT_PREEMPT threads package" >&2 - rules_enable_threads rt-preempt - HAVE_FLAVOR=true -} - -do_xenomai() { - cat control.d/control.xenomai.hdr control.d/control.$DISTRO_CODENAME.in control.d/control.xenomai.ftr >> control -# sed -i "s|yapps2-runtime|yapps2-runtime, xenomai-runtime|" control - echo "debian/control: added xenomai threads package for Jessie" >&2 - # Be sure the -dev files only appear once - BUILD_DEPS="${BUILD_DEPS/libxenomai-dev, /}libxenomai-dev, " - echo "debian/control: added Xenomai (userland) threads package" \ - "with Build-Depends:" >&2 - echo " libxenomai-dev" >&2 - rules_enable_threads xenomai - HAVE_FLAVOR=true -} - -## Set version for packages by altering changelog -## Write new version info then prepend existing one, for use in changes file -## Allows command line builds and builds outside of Travis environment to set meaningful version numbers +## Set version for packages by altering changelog Write new version +## info then prepend existing one, for use in changes file Allows +## command line builds and builds outside of Travis environment to set +## meaningful version numbers do_changelog() { - DISTRO_UC="$(echo $DISTRO_CODENAME | sed 's/^[[:space:]]*//g' | sed -e 's/\b\(.\)/\u\1/g')" + DISTRO_UC="$(echo $DISTRO_CODENAME | sed 's/^[[:space:]]*//g' | + sed -e 's/\b\(.\)/\u\1/g')" DISTRO_LC="$(echo $DISTRO_CODENAME | sed 's/^[[:space:]]*//g')" - MKVERSION="$(git show HEAD:VERSION | cut -d ' ' -f 1).$(git rev-list --count master)-1.git$(git rev-parse --short HEAD)~${DISTRO_LC}" + MKVERSION="$(git show HEAD:VERSION | cut -d ' ' -f 1).$( + git rev-list --count master)-1.git$( + git rev-parse --short HEAD)~${DISTRO_LC}" COMMITTER="$(git show -s --pretty=%an $(git rev-parse --short HEAD))" EMAIL="$(git show -s --format='%ae' $(git rev-parse --short HEAD))" @@ -95,31 +48,30 @@ cat changelog.in >> changelog echo "New package version number added to changelog" } -## Create source orig tarball in format required for creation of debian tarball and .dsc file -## Allows non binary package builds from command line or outside Travis environment +## Create source orig tarball in format required for creation of +## debian tarball and .dsc file Allows non binary package builds from +## command line or outside Travis environment do_source_tarball() { -#version based on major version plus commit number only, without suffixed -1 or commit hash -MK_VERSION="$(git show HEAD:VERSION | cut -d ' ' -f 1).$(git rev-list --count master)" - -OWD=$PWD -cd ../ -git archive HEAD | bzip2 -z > ../machinekit-hal_${MK_VERSION}.orig.tar.bz2 -echo "Source tarball created" -cd $OWD + #version based on major version plus commit number only, without + #suffixed -1 or commit hash + MK_VERSION="$(git show HEAD:VERSION | cut -d ' ' -f 1).$( + git rev-list --count master)" + + OWD=$PWD + cd ../ + git archive HEAD | bzip2 -z > ../machinekit-hal_${MK_VERSION}.orig.tar.bz2 + echo "Source tarball created" + cd $OWD } usage() { { test -z "$1" || echo "$1" echo "Usage: $0 [ arg ... ]" - echo " arg: function:" - echo " -p build POSIX threads" - echo " -r build RT_PREEMPT threads" - echo " -x build Xenomai threads" - echo " -c rewrite changelog to set package version from git commit" - echo " -s create source tarball for non binary package builds" - echo " *** Argument may be repeated for multiple kernels" + echo " arg: function:" + echo " -c rewrite changelog to set package version from git commit" + echo " -s create source tarball for non binary package builds" } >&2 exit 1 } @@ -131,50 +83,57 @@ test "$1" != --help || usage # These need to be in a certain order: # - Base template copy first # - do_ functions next -# - replace BUILD_DEPS and *_KERNEL_HEADERS last +# - replace BUILD_DEPS last # (when lists are fully populated) # set defaults BUILD_DEPS= # List of Build-Depends -DEPS= # List of Depends -HAVE_FLAVOR=false -HAVE_KTHREADS_FLAVOR=false - -cp control.d/control.in control -echo "debian/control: copied base template" >&2 - -cp postinst.in machinekit-hal-posix.postinst -cp postinst.in machinekit-hal-rt-preempt.postinst -cp postinst.in machinekit-hal-xenomai.postinst - -cp rules.in rules; chmod +x rules -echo "debian/rules: copied base template" >&2 - -cp changelog.in changelog -echo "debian/rules: copied base changelog" >&2 +DEPS= # List of Depends + +## copy base templates into place + +case "$DISTRO_CODENAME" in + buster) + BUILD_DEPS+=', libck-dev' + ;; + stretch|sid) + DEPS+=", python-gtksourceview2" + BUILD_DEPS+=', libck-dev' + ;; + jessie) + DEPS+=", python-gtksourceview2" + ;; + *) + DEPS+=", python-gtksourceview2" + BUILD_DEPS+=', libck-dev' + ;; +esac + +# Configure Xenomai threads +configure_xenomai() { + if ! dpkg-query -W | grep -q libxenomai-dev; then + echo "Not configuring build for Xenomai (no libxenomai-dev package)" >&2 + return + fi + + echo "debian/control: Adding xenomai threads configuration" >&2 + BUILD_DEPS+=", libxenomai-dev" + DEPS+=", xenomai-runtime" +} # read command line options - d is a dummy to stop args being req -while getopts csprxd:?h ARG; do +while getopts csh ARG; do case $ARG in - p) do_posix ;; - r) do_rt-preempt ;; - x) do_xenomai ;; c) do_changelog ;; # set new changelog with package versions from git s) do_source_tarball ;; # create tarball for non binary builds - ?|h) usage ;; + h) usage ;; *) usage "Unknown arg: '-$ARG'" ;; esac done -if test "$DISTRO_CODENAME" != jessie; then - BUILD_DEPS+='libck-dev, ' -fi - # Set control Build-Depends: -sed -i control \ +configure_xenomai +sed >control &2 - -# Warn if no flavor configured -$HAVE_FLAVOR || usage "WARNING: No thread flavors configured" diff --git a/debian/control.d/control.buster.in b/debian/control.d/control.buster.in deleted file mode 100644 index b4c70894bc..0000000000 --- a/debian/control.d/control.buster.in +++ /dev/null @@ -1,7 +0,0 @@ -Depends: libavahi-client3 (>= 0.6.16), libavahi-common3 (>= 0.6.16), libc6 (>= 2.27), libcgroup1 (>= 0.36.2), libczmq4 (>= 3.0.2), libfontconfig1 (>= 2.12.6), libfreetype6 (>= 2.2.1), - libgcc1 (>= 1:4.2), libgl1, libglib2.0-0 (>= 2.12.0), libjansson4 (>= 2.2), libmodbus5 (>= 3.0.2), libprotobuf17, libreadline7 (>= 6.0), libstdc++6 (>= 5.2), libtk8.6 (>= 8.6.0), - libudev1 (>= 183), libusb-1.0-0 (>= 2:1.0.9), libuuid1 (>= 2.16), libx11-6, libxext6, libxft2 (>> 2.1.1), libxinerama1, libxss1, libzmq5 (>= 3.2.3+dfsg), zlib1g (>= 1:1.1.4), - python (<< 2.8), python (>= 2.7~), python:any (<< 2.8), python:any (>= 2.7~), libboost-python1.62.0 | libboost-python1.67.0, libboost-system1.62.0 | libboost-system1.67.0, - libboost-thread1.62.0 | libboost-thread1.67.0, - bc, cgroup-tools, libtk-img (>= 1.13), procps, psmisc, python-tk, python-numpy, python-xlib, - python-gtkglext1, python-configobj, python-zmq, python-protobuf (>= 2.4.1), python-avahi, python-simplejson, python-pyftpdlib, tclreadline, tcl8.6, tk8.6, uuid-runtime, yapps2 diff --git a/debian/control.d/control.in b/debian/control.d/control.in deleted file mode 100644 index b49cb1e745..0000000000 --- a/debian/control.d/control.in +++ /dev/null @@ -1,22 +0,0 @@ -Source: machinekit-hal -Section: misc -Priority: extra -Maintainer: ArcEye -Build-Depends: debhelper (>= 6), - autoconf (>= 2.63), automake, libboost-python-dev, libgl1-mesa-dev, - libglu1-mesa-dev, libmodbus-dev (>= 3.0), - libncurses-dev, libreadline-dev, libusb-1.0-0-dev, libxmu-dev, - libxmu-headers, python (>= 2.6.6-3~), python-dev (>= 2.6.6-3~), - cython (>= 0.19), dh-python, - pkg-config, psmisc, python-tk, libxaw7-dev, libboost-serialization-dev, - libzmq3-dev (>= 4.0.4), libczmq-dev (>= 4.0.2), libjansson-dev (>= 2.5), - libwebsockets-dev (>= 1.2.2), - python-zmq (>= 14.0.1), procps, - liburiparser-dev, libssl-dev, python-setuptools, - uuid-dev, uuid-runtime, libavahi-client-dev, - libprotobuf-dev (>= 2.4.1), protobuf-compiler (>= 2.4.1), - python-protobuf (>= 2.4.1), libprotoc-dev (>= 2.4.1), - python-simplejson, libboost-thread-dev, libcgroup-dev, - yapps2-runtime | python-yapps, yapps2, - python-pyftpdlib, @BUILD_DEPS@ -Standards-Version: 2.1.0 diff --git a/debian/control.d/control.jessie.in b/debian/control.d/control.jessie.in deleted file mode 100644 index 931a9d9d7b..0000000000 --- a/debian/control.d/control.jessie.in +++ /dev/null @@ -1,6 +0,0 @@ -Depends: libavahi-client3 (>= 0.6.16), libavahi-common3 (>= 0.6.16), libc6 (>= 2.15), libcgroup1 (>= 0.36.2), libczmq4 (>= 3.0.2), libfontconfig1 (>= 2.11), libfreetype6 (>= 2.2.1), - libgcc1 (>= 1:4.1.1), libgl1-mesa-glx | libgl1, libglib2.0-0 (>= 2.12.0), libjansson4 (>= 2.2), libmodbus5 (>= 3.0.2), libprotobuf9, libreadline6 (>= 6.0), libstdc++6 (>= 4.9), - libtk8.6 (>= 8.6.0), libudev1 (>= 183), libusb-1.0-0 (>= 2:1.0.9), libuuid1 (>= 2.16), libx11-6, libxext6, libxft2 (>> 2.1.1), libxinerama1, libxss1, libzmq3 (>= 3.2.3+dfsg), - zlib1g (>= 1:1.1.4), python (<< 2.8), python (>= 2.7~), python:any (>= 2.7.5-5~), libboost-python1.55.0, libboost-thread1.55.0, libboost-system1.55.0, - bc, cgroup-tools, libtk-img (>=1.13), procps, psmisc, python-tk, python-numpy, python-xlib, python-gtkglext1, python-configobj, python-zmq, python-protobuf (>= 2.4.1), - python-avahi, python-simplejson, python-pyftpdlib, tclreadline, tcl8.6, tk8.6, uuid-runtime, yapps2-runtime diff --git a/debian/control.d/control.posix.ftr b/debian/control.d/control.posix.ftr deleted file mode 100644 index c04087d852..0000000000 --- a/debian/control.d/control.posix.ftr +++ /dev/null @@ -1,4 +0,0 @@ -Description: HAL stack split from Machinekit - . - This package provides components and drivers that run on a non-realtime - (Posix) system. diff --git a/debian/control.d/control.posix.hdr b/debian/control.d/control.posix.hdr deleted file mode 100644 index 7f9745c5c5..0000000000 --- a/debian/control.d/control.posix.hdr +++ /dev/null @@ -1,6 +0,0 @@ - -Package: machinekit-hal-posix -Architecture: any -Provides: machinekit-hal -Conflicts: machinekit, machinekit-hal-rt-preempt, machinekit-hal-xenomai -Suggests: hostmot2-firmware-all [!armhf] diff --git a/debian/control.d/control.rt-preempt.ftr b/debian/control.d/control.rt-preempt.ftr deleted file mode 100644 index 451c71f2ed..0000000000 --- a/debian/control.d/control.rt-preempt.ftr +++ /dev/null @@ -1,5 +0,0 @@ - ,linux-image-rt-686-pae [i386], linux-image-rt-amd64 [amd64] -Description: HAL stack split from Machinekit - . - This package provides components and drivers that run on a realtime - (PREEMPT RT) system. diff --git a/debian/control.d/control.rt-preempt.hdr b/debian/control.d/control.rt-preempt.hdr deleted file mode 100644 index 01ad8a7b40..0000000000 --- a/debian/control.d/control.rt-preempt.hdr +++ /dev/null @@ -1,6 +0,0 @@ - -Package: machinekit-hal-rt-preempt -Architecture: any -Provides: machinekit-hal -Conflicts: machinekit, machinekit-hal-posix, machinekit-hal-xenomai -Suggests: hostmot2-firmware-all [!armhf] diff --git a/debian/control.d/control.stretch.in b/debian/control.d/control.stretch.in deleted file mode 100644 index 3b9ca76878..0000000000 --- a/debian/control.d/control.stretch.in +++ /dev/null @@ -1,6 +0,0 @@ -Depends: libavahi-client3 (>= 0.6.16), libavahi-common3 (>= 0.6.16), libc6 (>= 2.15), libcgroup1 (>= 0.36.2), libczmq4 (>= 3.0.2), libfontconfig1 (>= 2.11), libfreetype6 (>= 2.2.1), - libgcc1 (>= 1:4.2), libgl1-mesa-glx | libgl1, libglib2.0-0 (>= 2.12.0), libjansson4 (>= 2.2), libmodbus5 (>= 3.0.2), libprotobuf10, libreadline7 (>= 6.0), libstdc++6 (>= 5.2), libtk8.6 (>= 8.6.0), - libudev1 (>= 183), libusb-1.0-0 (>= 2:1.0.9), libuuid1 (>= 2.16), libx11-6, libxext6, libxft2 (>> 2.1.1), libxinerama1, libxss1, libzmq5 (>= 3.2.3+dfsg), zlib1g (>= 1:1.1.4), - python (<< 2.8), python (>= 2.7~), python:any (<< 2.8), python:any (>= 2.7.5-5~), libboost-python1.62.0, libboost-thread1.62.0, libboost-system1.62.0, - bc, cgroup-tools, libtk-img (>= 1.13), procps, psmisc, python-tk, python-numpy, python-xlib, - python-gtkglext1, python-configobj, python-zmq, python-protobuf (>= 2.4.1), python-avahi, python-simplejson, python-pyftpdlib, tclreadline, tcl8.6, tk8.6, uuid-runtime, yapps2-runtime diff --git a/debian/control.d/control.xenomai.ftr b/debian/control.d/control.xenomai.ftr deleted file mode 100644 index 00d061e61b..0000000000 --- a/debian/control.d/control.xenomai.ftr +++ /dev/null @@ -1,5 +0,0 @@ - , xenomai-runtime -Description: HAL stack split from Machinekit - . - This package provides components and drivers that run on a realtime - (XENOMAI 2) system. diff --git a/debian/control.d/control.xenomai.hdr b/debian/control.d/control.xenomai.hdr deleted file mode 100644 index e04c297cc7..0000000000 --- a/debian/control.d/control.xenomai.hdr +++ /dev/null @@ -1,6 +0,0 @@ - -Package: machinekit-hal-xenomai -Architecture: any -Provides: machinekit-hal -Conflicts: machinekit, machinekit-hal-posix, machinekit-hal-rt-preempt -Suggests: hostmot2-firmware-all [!armhf] diff --git a/debian/control.in b/debian/control.in new file mode 100644 index 0000000000..b77797e72d --- /dev/null +++ b/debian/control.in @@ -0,0 +1,97 @@ +Source: machinekit-hal +Section: misc +Priority: extra +Maintainer: ArcEye +Build-Depends: debhelper (>= 6), + autoconf (>= 2.63), automake, libboost-python-dev, libgl1-mesa-dev, + libglu1-mesa-dev, libmodbus-dev (>= 3.0), + libgtk2.0-dev, libudev-dev, + libncurses-dev, libreadline-dev, libusb-1.0-0-dev, libxmu-dev, + libxmu-headers, python (>= 2.6.6), python-dev (>= 2.6.6), + cython (>= 0.19), dh-python, + pkg-config, psmisc, python-tk, libxaw7-dev, libboost-serialization-dev, + libzmq3-dev (>= 4.0.4), libczmq-dev (>= 4.0.2), libjansson-dev (>= 2.5), + libwebsockets-dev (>= 1.2.2), + python-zmq (>= 14.0.1), procps, + liburiparser-dev, libssl-dev, python-setuptools, + uuid-dev, uuid-runtime, libavahi-client-dev, + libprotobuf-dev (>= 2.4.1), protobuf-compiler (>= 2.4.1), + python-protobuf (>= 2.4.1), libprotoc-dev (>= 2.4.1), + python-simplejson, libboost-thread-dev, libcgroup-dev, + yapps2-runtime | python-yapps, yapps2, + python-pyftpdlib @BUILD_DEPS@ +Standards-Version: 2.1.0 + +Package: machinekit-hal +Breaks: linuxcnc +Replaces: linuxcnc +Conflicts: machinekit +Architecture: any +Depends: ${shlibs:Depends}, + tcl8.6, tk8.6, + bwidget (>= 1.7), libtk-img (>=1.13), + ${python:Depends}, ${misc:Depends}, + python-tk, python-imaging, python-imaging-tk, + python-gnome2, python-glade2, + python-numpy, python-gtksourceview2, + python-vte, python-xlib, python-gtkglext1, python-configobj, + python-zmq, python-protobuf (>= 2.4.1), + python-avahi, python-simplejson, python-pyftpdlib, + python-pydot, xdot, + tclreadline, bc, procps, psmisc, cgroup-tools, + python-gst-1.0 | python-gst0.10, + python-imaging | python-pil, + python-imaging-tk | python-pil.imagegtk, + uuid-runtime @DEPS@ +Description: Machinekit HAL stack + . + Machinekit is the next-generation Machine Controller. It provides + motion and other control for atomation, robot and CNC machine tool + applications. + +Package: machinekit-hal-dev +Architecture: any +Depends: make, g++, + ${misc:Depends}, + machinekit-hal (= ${binary:Version}), + yapps2-runtime | python-yapps +Section: libs +Description: PC based motion controller for real-time Linux + Machinekit is the next-generation Enhanced Machine Controller which + provides motion control for CNC machine tools and robotic + applications (milling, cutting, routing, etc.). + . + This package includes files needed to build new realtime components and + alternate front-ends for machinekit + +Package: machinekit-hal-rt-preempt +Architecture: any +Suggests: hostmot2-firmware-all [!armhf] +Depends: + machinekit-hal, + linux-image-rt-686-pae [i386], linux-image-rt-amd64 [amd64] +Description: Machinekit HAL RT_PREEMPT + . + This metapackage provides components and drivers that run on a realtime + (PREEMPT RT) system. + + +Package: machinekit-hal-posix +Architecture: any +Suggests: hostmot2-firmware-all [!armhf] +Description: HAL stack split from Machinekit + . + This package provides components and drivers that run on a non-realtime + (Posix) system. +Depends: + machinekit-hal + +Package: machinekit-hal-xenomai +Architecture: any +Suggests: hostmot2-firmware-all [!armhf] +Description: HAL stack split from Machinekit + . + This package provides components and drivers that run on a realtime + (XENOMAI 2) system. +Depends: + machinekit-hal, xenomai-runtime diff --git a/debian/machinekit-hal-dev.install b/debian/machinekit-hal-dev.install new file mode 100644 index 0000000000..0e7188c44a --- /dev/null +++ b/debian/machinekit-hal-dev.install @@ -0,0 +1,4 @@ +usr/bin/comp +usr/include/linuxcnc +usr/lib/lib*.so +usr/share/linuxcnc/Makefile.* diff --git a/debian/machinekit-hal-posix.install.in b/debian/machinekit-hal-posix.install.in deleted file mode 100644 index 2429930664..0000000000 --- a/debian/machinekit-hal-posix.install.in +++ /dev/null @@ -1,24 +0,0 @@ -etc/linuxcnc/* -etc/rsyslog.d/linuxcnc.conf -etc/security/limits.d/machinekit.conf -etc/udev/rules.d/50-shmdrv.rules -usr/lib/*.so.* -usr/bin/* -usr/lib/python*/*/*.py -usr/lib/python*/*/*.so -usr/lib/python*/*/*/*.py -usr/lib/python*/*/*/*.so -usr/lib/python*/*/machinetalk/protobuf/* -usr/lib/python*/*/machinetalk/*.py -usr/lib/python*/*/machinekit/nosetests/*.py -usr/lib/python*/*/gladevcp/* -usr/lib/linuxcnc/posix/* -usr/include/linuxcnc/*.h -usr/include/linuxcnc/*.hh -usr/libexec/linuxcnc -etc/modprobe.d/linuxcnc.conf -usr/lib/*.so -usr/lib/linuxcnc/ulapi-posix.so -usr/lib/tcltk/linuxcnc/hal.so -usr/share/linuxcnc/Makefile.* -usr/share/linuxcnc/udev/*.rules diff --git a/debian/machinekit-hal-rt-preempt.install.in b/debian/machinekit-hal-rt-preempt.install.in deleted file mode 100644 index ef7b53786f..0000000000 --- a/debian/machinekit-hal-rt-preempt.install.in +++ /dev/null @@ -1,24 +0,0 @@ -etc/linuxcnc/* -etc/rsyslog.d/linuxcnc.conf -etc/security/limits.d/machinekit.conf -etc/udev/rules.d/50-shmdrv.rules -usr/lib/*.so.* -usr/bin/* -usr/lib/python*/*/*.py -usr/lib/python*/*/*.so -usr/lib/python*/*/*/*.py -usr/lib/python*/*/*/*.so -usr/lib/python*/*/machinetalk/protobuf/* -usr/lib/python*/*/machinetalk/*.py -usr/lib/python*/*/machinekit/nosetests/*.py -usr/lib/python*/*/gladevcp/* -usr/lib/linuxcnc/rt-preempt/* -usr/include/linuxcnc/*.h -usr/include/linuxcnc/*.hh -usr/libexec/linuxcnc -etc/modprobe.d/linuxcnc.conf -usr/lib/*.so -usr/lib/linuxcnc/ulapi-rt-preempt.so -usr/lib/tcltk/linuxcnc/hal.so -usr/share/linuxcnc/Makefile.* -usr/share/linuxcnc/udev/*.rules diff --git a/debian/machinekit-hal-xenomai.install.in b/debian/machinekit-hal-xenomai.install.in deleted file mode 100644 index b58c24de2b..0000000000 --- a/debian/machinekit-hal-xenomai.install.in +++ /dev/null @@ -1,24 +0,0 @@ -etc/linuxcnc/* -etc/rsyslog.d/linuxcnc.conf -etc/security/limits.d/machinekit.conf -etc/udev/rules.d/50-shmdrv.rules -usr/lib/*.so.* -usr/bin/* -usr/lib/python*/*/*.py -usr/lib/python*/*/*.so -usr/lib/python*/*/*/*.py -usr/lib/python*/*/*/*.so -usr/lib/python*/*/machinetalk/protobuf/* -usr/lib/python*/*/machinetalk/*.py -usr/lib/python*/*/machinekit/nosetests/*.py -usr/lib/python*/*/gladevcp/* -usr/lib/linuxcnc/xenomai/* -usr/include/linuxcnc/*.h -usr/include/linuxcnc/*.hh -usr/libexec/linuxcnc -etc/modprobe.d/linuxcnc.conf -usr/lib/*.so -usr/lib/linuxcnc/ulapi-xenomai.so -usr/lib/tcltk/linuxcnc/hal.so -usr/share/linuxcnc/Makefile.* -usr/share/linuxcnc/udev/*.rules diff --git a/debian/machinekit-hal.install b/debian/machinekit-hal.install new file mode 100644 index 0000000000..fb833de328 --- /dev/null +++ b/debian/machinekit-hal.install @@ -0,0 +1,24 @@ +etc/linuxcnc/rtapi.ini +etc/linuxcnc/machinekit.ini +etc/modprobe.d/linuxcnc.conf +etc/rsyslog.d/linuxcnc.conf +etc/security/limits.d/machinekit.conf +usr/bin/* +usr/lib/*.so.* +usr/lib/compat.so +usr/lib/hal.so +usr/lib/linuxcnc +usr/lib/rtapi.so +usr/lib/shmcommon.so +usr/lib/python*/*/*.py +usr/lib/python*/*/*.so +usr/lib/python*/*/*/*.py +usr/lib/python*/*/machinekit/*.so +usr/lib/python*/*/machinetalk/protobuf/*.py +usr/lib/python*/*/machinetalk/*.py +usr/lib/python*/*/machinekit/nosetests/*.py +usr/lib/python*/dist-packages/gladevcp +usr/lib/tcltk/linuxcnc/hal.so +usr/libexec/linuxcnc +usr/share/linuxcnc +usr/share/machinekit \ No newline at end of file diff --git a/debian/postinst.in b/debian/machinekit-hal.postinst similarity index 89% rename from debian/postinst.in rename to debian/machinekit-hal.postinst index 8bf7dc91c8..51c76c6937 100755 --- a/debian/postinst.in +++ b/debian/machinekit-hal.postinst @@ -1,11 +1,13 @@ #!/bin/bash # postinst script for machinekit-hal +#DEBHELPER# + +# if it doesnt exist, create /var/log/linuxcnc.log and make it publically readable touch /var/log/linuxcnc.log chmod 666 /var/log/linuxcnc.log -# restart services -service udev restart 2>/dev/null || true +# restart the rsyslogd to start logging to /var/log/linuxcnc.conf service rsyslog restart 2>/dev/null || true @@ -46,9 +48,9 @@ if [ -f $INIFILE ]; then else echo "ERROR: $INIFILE not found" fi - + # Ensure mkuuid file holds same UUID - + echo "$NEWUUID" > /etc/linuxcnc/mkuuid - -################################################################################ \ No newline at end of file + +################################################################################ diff --git a/debian/machinekit.sharedmimeinfo b/debian/machinekit.sharedmimeinfo deleted file mode 100644 index 209cdf2dc3..0000000000 --- a/debian/machinekit.sharedmimeinfo +++ /dev/null @@ -1,9 +0,0 @@ - - - - G-Code File - - - - - diff --git a/debian/posix-postinst.add b/debian/posix-postinst.add deleted file mode 100644 index 7fdefcbc73..0000000000 --- a/debian/posix-postinst.add +++ /dev/null @@ -1,13 +0,0 @@ - -# ensure the links do not pre-exist, from previous installs. -# or user work-arounds, which will produce error messages -rm -f /usr/lib/linuxcnc/posix/pru_generic.bin -rm -f /usr/lib/linuxcnc/posix/pru_generic.dbg -rm -f /usr/lib/linuxcnc/posix/pru_decamux.bin -rm -f /usr/lib/linuxcnc/posix/pru_decamux.dbg - -# make symlinks to BBB pru_*.* -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.bin /usr/lib/linuxcnc/posix/pru_generic.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.dbg /usr/lib/linuxcnc/posix/pru_generic.dbg -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.bin /usr/lib/linuxcnc/posix/pru_decamux.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.dbg /usr/lib/linuxcnc/posix/pru_decamux.dbg diff --git a/debian/rt-preempt-postinst.add b/debian/rt-preempt-postinst.add deleted file mode 100644 index 9eec2b68c2..0000000000 --- a/debian/rt-preempt-postinst.add +++ /dev/null @@ -1,13 +0,0 @@ - -# ensure the links do not pre-exist, from previous installs -# or user work-arounds, which will produce error messages -rm -f /usr/lib/linuxcnc/rt-preempt/pru_generic.bin -rm -f /usr/lib/linuxcnc/rt-preempt/pru_generic.dbg -rm -f /usr/lib/linuxcnc/rt-preempt/pru_decamux.bin -rm -f /usr/lib/linuxcnc/rt-preempt/pru_decamux.dbg - -# make symlinks to BBB pru_*.* -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.bin /usr/lib/linuxcnc/rt-preempt/pru_generic.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.dbg /usr/lib/linuxcnc/rt-preempt/pru_generic.dbg -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.bin /usr/lib/linuxcnc/rt-preempt/pru_decamux.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.dbg /usr/lib/linuxcnc/rt-preempt/pru_decamux.dbg diff --git a/debian/rules.in b/debian/rules similarity index 64% rename from debian/rules.in rename to debian/rules index 6bd7cce353..dabb0e7491 100755 --- a/debian/rules.in +++ b/debian/rules @@ -29,25 +29,14 @@ SHLIBDEPS_X := # add patterns here # "can't extract name and version from library name 'libtk8.6.so' SHLIBDEPS_X += linuxcnc.so _togl.so # -# libcanterp.so.0 and librs274.so.0: hack for now: see -# https://github.com/machinekit/machinekit/issues/324 -# "symbol ... used by ... found in none of the libraries" -SHLIBDEPS_X += libcanterp.so.0 librs274.so.0 -# -# halmeter classicladder halscope link to $(GTK_LIBS), which includes +# halmeter halscope link to $(GTK_LIBS), which includes # several libs that aren't used (but several that are needed) -SHLIBDEPS_X += halmeter classicladder halscope - -# Enable/disable thread flavors; all flavors disabled by default -THREADS_POSIX = --without-posix -THREADS_RT_PREEMPT = --without-rt-preempt -THREADS_XENOMAI = --without-xenomai - -# Kernel threads need a list of configured header source directories -# for each architecture -# -# Multiples should be space-separated +SHLIBDEPS_X += halmeter halscope # +# mb2hal gs2_vfd hy_vfd link to libglib-2.0.so.0; similar to above +SHLIBDEPS_X += mb2hal gs2_vfd hy_vfd + +# Cross-compile variables DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) # Parallel make @@ -87,9 +76,6 @@ build-stamp: debian/control ./configure --prefix=/usr \ --build=$(DEB_BUILD_MULTIARCH) \ --host=$(DEB_HOST_MULTIARCH) \ - $(THREADS_POSIX) \ - $(THREADS_RT_PREEMPT) \ - $(THREADS_XENOMAI) \ --sysconfdir=/etc cd src && $(MAKE) $(COMPILE_ENV) $(MAKEFLAGS) V=$(DH_VERBOSE) touch build-stamp @@ -107,9 +93,6 @@ ifneq ($(wildcard src/configure src/Makefile.inc),) ./configure --prefix=/usr \ --build=$(DEB_BUILD_MULTIARCH) \ --host=$(DEB_HOST_MULTIARCH) \ - $(THREADS_POSIX) \ - $(THREADS_RT_PREEMPT) \ - $(THREADS_XENOMAI) \ --sysconfdir=/etc cd src && $(MAKE) clean -s # # Manually remove things left by './configure' @@ -133,6 +116,7 @@ ifneq ($(wildcard src/configure src/Makefile.inc),) src/configure \ src/machinekitcfg.py-tmp rm -rf src/autom4te.cache etc + endif # # Remove package artifacts @@ -140,25 +124,6 @@ endif install: build - -# # have to test after build or Makefile.inc will not exist ## - cp debian/machinekit-hal-posix.install.in debian/machinekit-hal-posix.install - cp debian/machinekit-hal-rt-preempt.install.in debian/machinekit-hal-rt-preempt.install - cp debian/machinekit-hal-xenomai.install.in debian/machinekit-hal-xenomai.install - - if (grep ^USERMODE_PCI=yes src/Makefile.inc -q); then \ - echo "usr/include/linuxcnc/userpci/*.h" >> debian/machinekit-hal-posix.install; \ - echo "usr/include/linuxcnc/userpci/*.h" >> debian/machinekit-hal-rt-preempt.install; \ - echo "usr/include/linuxcnc/userpci/*.h" >> debian/machinekit-hal-xenomai.install; \ - fi - -# # only want this for armhf builds ## - if [ "$(DEB_HOST_ARCH)" = "armhf" ] ; then \ - echo "usr/lib/linuxcnc/prubin/*" >> debian/machinekit-hal-posix.install; \ - echo "usr/lib/linuxcnc/prubin/*" >> debian/machinekit-hal-rt-preempt.install; \ - echo "usr/lib/linuxcnc/prubin/*" >> debian/machinekit-hal-xenomai.install; \ - fi - dh_testdir dh_testroot dh_prep @@ -169,30 +134,22 @@ install: build mkdir -p debian/tmp (cd debian/extras && cp -a * ../tmp) (cd src; export DESTDIR=`pwd`/../debian/tmp; $(MAKE) V=$(DH_VERBOSE) $@) - mkdir -p debian/tmp/usr/lib debian/tmp/usr/include/linuxcnc \ + mkdir -p \ + debian/tmp/usr/lib/linuxcnc/modules \ + debian/tmp/usr/include/linuxcnc \ debian/tmp/usr/include/linuxcnc/machinetalk/nanopb \ debian/tmp/usr/include/linuxcnc/machinetalk/protobuf - -#ifneq (,$(wildcard debian/machinekit-*-kernel-*.install)) - mkdir -p debian/tmp/etc/udev/rules.d - cp src/rtapi/shmdrv/shmdrv.rules \ - debian/tmp/etc/udev/rules.d/50-shmdrv.rules -#endif mkdir -p debian/tmp/etc/security/limits.d cp src/rtapi/shmdrv/limits.d-machinekit.conf \ debian/tmp/etc/security/limits.d/machinekit.conf -# # only want this for armhf builds too ## - if [ "$(DEB_HOST_ARCH)" = "armhf" ] ; then \ - mkdir -p debian/tmp/usr/lib/linuxcnc/prubin; \ - cp rtlib/prubin/* debian/tmp/usr/lib/linuxcnc/prubin; \ - cat debian/posix-postinst.add >> debian/machinekit-hal-posix.postinst; \ - cat debian/rt-preempt-postinst.add >> debian/machinekit-hal-rt-preempt.postinst; \ - cat debian/xenomai-postinst.add >> debian/machinekit-hal-xenomai.postinst; \ - fi + mkdir -p debian/tmp/usr/lib/linuxcnc/prubin - dh_install --sourcedir=debian/tmp --fail-missing -Xusr/bin/pasm + dh_install --sourcedir=debian/tmp -Xusr/bin/pasm --fail-missing -v + # Eventually this will replace the above + # dh_install -Xusr/bin/pasm -v + # dh_missing --fail-missing # Build architecture-independent files here. binary-indep: build install @@ -210,13 +167,11 @@ binary-arch: build install dh_strip dh_compress -X.pdf -X.txt -X.hal -X.ini -X.clp -X.var -X.nml \ -X.tbl -X.xml -Xsample-configs - dh_fixperms -X/linuxcnc_module_helper -X/rtapi_app_ + dh_fixperms -X/rtapi_app_ dh_python2 --ignore-shebangs --no-guessing-versions --no-ext-rename dh_makeshlibs dh_installdeb - cat debian/machinekit-hal-posix/DEBIAN/shlibs debian/shlibs.pre > \ - debian/shlibs.local #enable buster builds to work with problematic shlib deps in current packages dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info \ $(foreach p, $(SHLIBDEPS_X), -X $(p)) -X hal.so @@ -225,5 +180,6 @@ binary-arch: build install dh_md5sums dh_builddeb + binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/xenomai-postinst.add b/debian/xenomai-postinst.add deleted file mode 100644 index d895fb1e2c..0000000000 --- a/debian/xenomai-postinst.add +++ /dev/null @@ -1,13 +0,0 @@ - -# ensure the links do not pre-exist, from previous installs. -# or user work-arounds, which will produce error messages -rm -f /usr/lib/linuxcnc/xenomai/pru_generic.bin -rm -f /usr/lib/linuxcnc/xenomai/pru_generic.dbg -rm -f /usr/lib/linuxcnc/xenomai/pru_decamux.bin -rm -f /usr/lib/linuxcnc/xenomai/pru_decamux.dbg - -# make symlinks to BBB pru_*.* -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.bin /usr/lib/linuxcnc/xenomai/pru_generic.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_generic.dbg /usr/lib/linuxcnc/xenomai/pru_generic.dbg -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.bin /usr/lib/linuxcnc/xenomai/pru_decamux.bin -ln -sf /usr/lib/linuxcnc/prubin/pru_decamux.dbg /usr/lib/linuxcnc/xenomai/pru_decamux.dbg diff --git a/scripts/build_docker b/scripts/build_docker index b3d1c73f8a..d8a6503668 100755 --- a/scripts/build_docker +++ b/scripts/build_docker @@ -54,16 +54,6 @@ case ${TAG} in *) echo "Warning: unknown tag '${TAG}'" >&2 ;; esac -# Distro-specific: -case ${TAG} in - *_8) - PKG_CONFIGURE_ARGS="-prx" # Enable Xenomai - ;; - *) - PKG_CONFIGURE_ARGS="-pr" # Build posix and preempt-rt threads - ;; -esac - # Distro specific warnings level case ${TAG} in *_8|*_9) @@ -124,7 +114,7 @@ case $CMD in BUILD_CL=( bash -xec " # configure source package - debian/configure ${PKG_CONFIGURE_ARGS}; + debian/configure; # update Changelog and build source package $SCRIPT_DIR/build_source_package $BUILD_SOURCE @@ -144,7 +134,7 @@ case $CMD in ( cd src; ./autogen.sh; - ./configure --host=\$HOST_MULTIARCH --with-posix; + ./configure --host=\$HOST_MULTIARCH; ) # Build @@ -156,7 +146,6 @@ case $CMD in echo -e 'ANNOUNCE_IPV4=0\nANNOUNCE_IPV6=0' >> \ etc/linuxcnc/machinekit.ini; tail -2 etc/linuxcnc/machinekit.ini; - flavor; # Run regression tests ${RUN_TESTS} ${TEST_ARGS}" diff --git a/scripts/check-build-vs-configure-sha.in b/scripts/check-build-vs-configure-sha.in deleted file mode 100644 index fb7a1e0420..0000000000 --- a/scripts/check-build-vs-configure-sha.in +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# -# helper for src/Makefile: compare build and configure SHA's -# -# trap the common error of checking out a different branch and forgetting to make clean/configure -# -# @configure_input@ -# on @DATE@ -# - -GIT_CONFIG_SHA=@GIT_CONFIG_SHA@ -GIT_BUILD_SHA=`../scripts/get-git-sha` - -if test "$GIT_CONFIG_SHA" != "$GIT_BUILD_SHA"; then - - echo 1>&2 - echo "***********************************************************" 1>&2 - - echo WARNING: configure was last run at @DATE@ at git version "$GIT_CONFIG_SHA" 1>&2 - echo WARNING: now the git version is: "$GIT_BUILD_SHA" 1>&2 - echo WARNING: consider executing "'make clean; sh autogen.sh; ./configure '" before running make 1>&2 - - echo "***********************************************************" 1>&2 - echo 1>&2 - exit 1 -fi - -exit 0 - diff --git a/scripts/check-system-configuration.sh b/scripts/check-system-configuration.sh index 1bdb4fb547..53a5cb0fe4 100755 --- a/scripts/check-system-configuration.sh +++ b/scripts/check-system-configuration.sh @@ -133,7 +133,7 @@ check-ulimits() { echo " $ sudo cp rtapi/shmdrv/limits.d-machinekit.conf /etc/security/limits.d/machinekit.conf" return 1 fi - + # Next, check the 'memlock' value looks sane if test $memlock != unlimited && test $memlock -lt $reasonable_memlock; then echo "Warning: Config 'memlock' value $memlock too small" @@ -145,8 +145,6 @@ check-ulimits() { fi } -HAVE_KERNEL_THREADS=false - res=0 check-rsyslog || res=1 check-ulimits || res=1 diff --git a/scripts/gen-rtapi.ini.sh.in.tmpl b/scripts/gen-rtapi.ini.sh.in.tmpl index b42bec8fd2..c87dc26455 100644 --- a/scripts/gen-rtapi.ini.sh.in.tmpl +++ b/scripts/gen-rtapi.ini.sh.in.tmpl @@ -46,18 +46,16 @@ sysconfdir=@sysconfdir@ # Makefile.inc paths EMC2_HOME=@EMC2_HOME@ RTLIB_DIR=@EMC2_RTLIB_DIR@ +MODULES_DIR=@EMC2_MODULES_DIR@ SYSTEM_CONFIG_DIR=@EMC2_SYSTEM_CONFIG_DIR@ LIBEXEC_DIR=@EMC2_LIBEXEC_DIR@ BIN_DIR=@EMC2_BIN_DIR@ # Makefile.inc parameters USE_PORTABLE_PARPORT_IO=@USE_PORTABLE_PARPORT_IO@ -TARGET_PLATFORM=@TARGET_PLATFORM@ GIT_VERSION=@GIT_VERSION@ RUN_IN_PLACE=@RUN_IN_PLACE@ PIDOF=@PIDOF@ -RTAI_KERNEL_THREADS_RTS="@RTAI_KERNEL_THREADS_RTS@" -USE_SHMDRV=@USE_SHMDRV@ ################################################# @@ -77,21 +75,18 @@ cat <&2 +fi + # Helper function to get variables from config getvar() { - # getvar [ --flavor ] - # set variable from rtapi_ini; - # with --flavor, if $FLAVOR is set, look in the [flavor_$FLAVOR] section + # getvar + # set variable from rtapi_ini var=$1 - flav_var=$2 - - if test "$flav_var" = "--flavor" -a ! -z "$FLAVOR"; then - SEC="-sec flavor_$FLAVOR" - else - SEC="" - fi - - eval "$var='$($INIVAR -var $var -ini $RTAPI_INI $SEC 2>/dev/null)'" + eval "$var='$($INIVAR -var $var -ini $RTAPI_INI 2>/dev/null)'" } -# Fill in other variable values -# -# Executables -getvar flavor -getvar linuxcnc_module_helper -getvar rtapi_msgd -#getvar halcmd - -# Flavor configuration -FLAVOR=$($flavor) -BUILD_SYS=`${flavor} -b` -getvar MODULES --flavor -getvar rtapi_app --flavor - -# catch this common error early on: -if ! test -u ${rtapi_app} -then - echo Warning - ${rtapi_app} not setuid >&2 - echo "'sudo make setuid' missing?" >&2 -fi - -# Other, overridable by environment variables -if [ "$USE_SHMDRV" == "" ] ; then - getvar USE_SHMDRV -fi - if [ "$HAL_SIZE" == "" ] ; then getvar HAL_SIZE fi @@ -85,13 +55,6 @@ if [ "$DEBUG" == "" ] ; then fi DEBUG=$((10#0$DEBUG)) # be sure $DEBUG is some base-10 number -# SHMDRV_OPTS: -# suggested use: SHMDRV_OPTS='debug=3' -# which will log shmdrv operations to the kernel log -if [ "$SHMDRV_OPTS" != "" ] ; then - MSGD_OPTS="$MSGD_OPTS --shmdrv_opts=$SHMDRV_OPTS" -fi - # SYSLOG_TO_STDERR: when set, log to stdout instead of syslog if test -n "$SYSLOG_TO_STDERR"; then MSGD_OPTS+=" -s" @@ -107,19 +70,6 @@ else fi -# Compute module lists -# -# kernel threads also need the rtapi and hal_lib kernel modules -test $BUILD_SYS = kbuild && MODULES="$MODULES rtapi hal_lib" -# -# reverse list of modules for unloading -MODULES_UNLOAD= -for MOD in $MODULES; do - MODULES_UNLOAD="$MOD $MODULES_UNLOAD" -done - - - # wait for a process to exit anywait(){ proc_name=$1 @@ -186,38 +136,12 @@ CheckStatus(){ fi done - if test $BUILD_SYS = kbuild; then - # check loaded/unloaded status of modules - for MOD in $MODULES_UNLOAD ; do - if $LSMOD | awk '{print $1}' | grep -x $MOD >/dev/null ; then - echo "$MOD loaded" >&2 - else - echo "$MOD not loaded" >&2 - res=1 - fi - done - fi - - # check if shmdrv is loaded, when applicable - if test $BUILD_SYS = 'kbuild' -o $USE_SHMDRV = yes; then - if CheckShm -l; then - echo "shmdrv loaded" >&2 - else - echo "shmdrv not loaded" >&2 - res=1 - fi - fi - return $res } Load(){ - # kernel threads must have shmdrv.ko loaded - # userland threads optionally may use the shmdrv module. - # The shmdrv module is loaded by rtapi_msgd if needed. - # rtapi_msgd creates the global segment containing the error ring buffer # so start this first: @@ -230,8 +154,7 @@ Load(){ "${cmd[@]}" || ( e=$?; echo "rtapi_msgd startup failed - aborting" >&2; exit $e) - # rtapi_app_ now handles the kernel module loading - # for kthreads as needed + # rtapi_app local cmd=(${rtapi_app} --instance=$MK_INSTANCE --debug=$DEBUG $RTAPI_APP_OPTS) if [ $DEBUG -gt 0 ] ; then echo "rtapi_app command: ${cmd[@]}" >&2 @@ -244,68 +167,8 @@ Load(){ # wait until rtapi_app responds, meaning setup is complete # this avoids startup races halcmd ping - - if test BUILD_SYS = 'kbuild'; then - # help debugging startup issues for kthreads - if [ $DEBUG -gt 0 ] && [ -w /proc/rtapi/debug ] ; then - echo "$DEBUG" > /proc/rtapi/debug - fi - fi } -CheckShm(){ - # -l: return success if shmdrv device exists - # -w: wait for shmdrv to be loaded; return success if loaded - - # Skip checks if shmdrv is not applicable - test $BUILD_SYS = 'user-dso' -a $USE_SHMDRV = no && return 0 - - case "$1" in - -l) - # success if shmdrv device exists - test -c $SHM_DEV; return ;; - - -w) - # wait for shmdrv to be loaded; 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 - sleep .1 - done - - # $SHM_DEV never became writable after ten seconds - return 1;; - esac -} - - - -RemoveModules(){ - # Remove a list of modules recursively - # - # When RTAPI shuts down uncleanly, not only hal_lib and rtapi may - # still be loaded, but also comp, motmod, or other modules that - # depend on those. - # - # Check for loaded modules dependent on hal_lib and unload them - # first. - - for MODULE in $*; do - # recurse on any dependent modules in /proc/modules - DEP_MODULES=$(cat /proc/modules | \ - awk '/^'$MODULE' / { mods=$4; gsub(","," ",mods); print mods }') - test "$DEP_MODULES" = - || RemoveModules $DEP_MODULES - - # remove module if still loaded - grep -q "^$MODULE " /proc/modules && \ - $linuxcnc_module_helper remove $MODULE - - done -} - - Unload(){ # shutdown rtapi if it exists @@ -318,14 +181,11 @@ Unload(){ fi fi - if test $USE_SHMDRV = no; then + # remove any linuxcnc-specific POSIX shm segments if they exist + # see src/rtapi/rtapi_shmkeys.h: SHM_FMT - # remove any linuxcnc-specific POSIX shm segments if they exist - # see src/rtapi/rtapi_shmkeys.h: SHM_FMT - - INSTKEY=`printf 'linuxcnc-%d-' $MK_INSTANCE` - rm -f /dev/shm/${INSTKEY}* >/dev/null 2>&1 - fi + INSTKEY=`printf 'linuxcnc-%d-' $MK_INSTANCE` + rm -f /dev/shm/${INSTKEY}* >/dev/null 2>&1 # wait until rtapi_msgd has vanished. This assures @@ -355,28 +215,12 @@ Unload(){ kill -KILL $(FindRunningProcs msgd:$MK_INSTANCE) fi fi - - RemoveModules $MODULES_UNLOAD - - # unload shmdrv, if applicable - if test $BUILD_SYS = 'kbuild' -o $USE_SHMDRV = yes; then - if CheckShm -l; then - # module is loaded; try to force unload, always return success - if test $DEBUG -gt 1; then - echo "realtime unload: notice: attempting to unload shmdrv" >&2 - fi - $linuxcnc_module_helper remove shmdrv 2>/dev/null || true - else - echo -n "realtime unload: warning: " >&2 - echo "shmdrv expected to be loaded, but wasn't" 1>&2 - fi - fi } CheckUnloaded(){ - # if msgd:$MK_INSTANCE is still around, this might still be a running instance - # after all - this applies to all flavors - msgd is always there, so cop out + # if msgd:$MK_INSTANCE is still around, this might still be a running instance + # after all - msgd is always there, so cop out if CheckRunningProcs msgd:$MK_INSTANCE; then @@ -388,7 +232,6 @@ CheckUnloaded(){ # if msgd:$MK_INSTANCE isnt running but rtapi:$MK_INSTANCE is, that's bad - msgd # should be last to exit - # this is a noop in kthreads, but clearly an error in uthreads if CheckRunningProcs rtapi:$MK_INSTANCE; then RTAPI_PID=`FindRunningProcs rtapi:$MK_INSTANCE` @@ -398,9 +241,9 @@ CheckUnloaded(){ exit 1 fi - # regardless if shmdrv is loaded or not, Posix shm segments for this - # particular instance should not exist and be in use at this point, which - # could be the case if a HAL usercomp were still hanging around + # Posix shm segments for this particular instance should not exist + # and be in use at this point, which could be the case if a HAL + # usercomp were still hanging around # if any, determine if a process is still using it; complain if so, # else remove with a note @@ -417,24 +260,6 @@ CheckUnloaded(){ rm -f $seg fi done - - # TBD: if fuser /dev/shm indicates a process is using shmdrv, then - # this is likely another instance, so dont try to unload shmdrv - # because it's going to fail anyway - - # 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'" >&2 - STATUS=error - fi - done - if [ -n "$STATUS" ] ; then - exit 1 - fi } CMD=$1 @@ -459,12 +284,6 @@ case "$CMD" in unloadcheck) CheckUnloaded ;; - # for script debugging - shmcheck) - if CheckShm -l; then - echo "shmdrv loaded" >&2; exit 0 - fi - ;; *) echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status}" >&2 exit 1 @@ -472,4 +291,3 @@ case "$CMD" in esac exit 0 - diff --git a/src/Makefile b/src/Makefile index 6dc6d48a96..5ad4c96fb8 100755 --- a/src/Makefile +++ b/src/Makefile @@ -66,18 +66,6 @@ ECHO=@true VECHO=true endif -ifeq ($(threads),) -# if $(threads) wasn't passed in on the command line, rerun make for -# each flavor/(optional)kernel-source combo -BUILD_ALL_FLAVORS = yes -BUILD_THREAD_MODULES = no -else -# $(threads) was passed in; build modules for this flavor and (if -# applicable) kernel-source -BUILD_ALL_FLAVORS = no -BUILD_THREAD_MODULES = yes -endif # $(threads) - BUILD_KBUILD = no # extract the version from the kernel source version.h @@ -98,58 +86,15 @@ export PYTHONPATH else include $(BASEPWD)/Makefile.inc endif -ifeq ($(BUILD_THREAD_FLAVORS),) -$(error Makefile.inc must specify 'BUILD_THREAD_FLAVORS' and other variables) -endif -# prevent typos -ifeq "$(filter $(threads),$(BUILD_THREAD_FLAVORS))" "" -$(error "$(threads)" is not a valid RTOS flavor; please pick one of:\ - $(BUILD_THREAD_FLAVORS)) -endif # default target: put before everything else default: -########################################################################################### - -ifeq ($(BUILD_ALL_FLAVORS),yes) -# Top-level modules target -# -# Re-run 'make modules', once for each configured userland threads -# flavor, and once for each detected kernel for each configured kernel -# threads flavor. Set 'threads' and where applicable 'KERNELDIR'. -# -# Following tradition, this incarnation of the modules recipe is -# placed far away from all others. - -modules: userspace - for f in $(BUILD_THREAD_FLAVORS); do \ - $(MAKE) modules threads=$$f; \ - done; \ - -ifeq ($(RUN_IN_PLACE)+$(BUILD_DRIVERS),yes+yes) - for f in $(BUILD_THREAD_FLAVORS); do \ - test -f ../libexec/rtapi_app_$$f -a \ - \( 0`stat -c %u ../libexec/rtapi_app_$$f 2>/dev/null` \ - -ne 0 -o ! -u ../libexec/rtapi_app_$$f \) \ - && need_setuid=1; \ - ln -sf $(EMC2_HOME)/rtlib/prubin/pru_generic.bin ../rtlib/$$f/pru_generic.bin; \ - ln -sf $(EMC2_HOME)/rtlib/prubin/pru_generic.dbg ../rtlib/$$f/pru_generic.dbg; \ - ln -sf $(EMC2_HOME)/rtlib/prubin/pru_decamux.bin ../rtlib/$$f/pru_decamux.bin; \ - ln -sf $(EMC2_HOME)/rtlib/prubin/pru_decamux.dbg ../rtlib/$$f/pru_decamux.dbg; \ - done; \ - test "$$need_setuid" = 1 && \ - $(VECHO) -n "You now need to run 'sudo make setuid' " && \ - $(VECHO) "in order to run in place." || true -endif - -endif # BUILD_ALL_FLAVORS - ############################################################################################# -OBJDIR := objects/$(RTDIR_EXT) -DEPDIR := depends/$(RTDIR_EXT) -RTLIBDIR := ../rtlib/$(RTDIR_EXT) +OBJDIR := objects/modules +DEPDIR := depends/modules +RTLIBDIR := ../rtlib/modules DEP = $(1) $(CPPFLAGS) -MM -MG -MT "$(2)" $(4) -o $(3).tmp && \ mv -f "$(3)".tmp "$(3)" @@ -164,9 +109,7 @@ cc-option = $(shell \ ############################################################################################# -ifeq ($(KERNELRELEASE),) -# When KERNELRELEASE is not defined, this is the userspace build. -# The "modules" target is the gateway to the kernel module build. + default: userspace modules # Print 'entering' all the time @@ -178,8 +121,6 @@ INCLUDE_PREFIX = . # as a "substitute at assignment time" variable TARGETS := PYTARGETS := -# Add to this list directories to be created during 'make install' -INSTALL_DIRS := # Submakefiles from each of these directories will be included if they exist SUBDIRS := \ @@ -251,6 +192,7 @@ INCLUDES := . INCLUDES += include/ USERSRCS := +RTSRCS := PROGRAMS := # When used like $(call TOxxx, ...) these turn a list of source files @@ -267,9 +209,71 @@ TODEPS = $(patsubst %.cc,depends/%$(2).d,$(patsubst %.c,depends/%$(2).d,$(1))) TOOBJSDEPS = $(call TOOBJS,$(1),$(2)) $(call TODEPS, $(1),$(2)) +# Same, but for RT objects in OBJDIR, compiled with -DRTAPI +TORTOBJS = $(patsubst %.cc,$(OBJDIR)/%$(2).o,$(patsubst %.c,$(OBJDIR)/%$(2).o,$(1))) + +# This macro generates build rules for C components +# Example call & resulting rules: +# $$(eval $(call c_comp_build_rules,hal/components/encoder.o,hal/components/othersrc.o)) +# obj-m += encoder.o +# encoder-objs := hal/components/encoder.o hal/components/othersrc.o +# $(RTLIBDIR)/encoder.so: \ +# hal/components/encoder.o hal/components/othersrc.o +define c_comp_build_rules +obj-m += $$(patsubst $$(dir $(1))%.o,%.o,$(1)) +$$(patsubst $$(dir $(1))%.o,%-objs,$(1)) += $(1) $(2) +$$(patsubst $$(dir $(1))%.o,$(RTLIBDIR)/%.so,$(1)): \ + $$(addprefix $(OBJDIR)/,$(1) $(2)) + +endef +# Debugging +#$$(info $(call c_comp_build_rules,hal/components/encoderv2.o)) + +############################################################################### +# C unit test setup +# +# This macro generates rules for C unit tests; e.g. +# +# $(eval $(call setup_test, \ +# dir/test_src, RTAPI, dir/ulapi_srcs.c, dir/rtapi_srcs.c), ../lib/lib.so, \ +# -lfoo, wrap_funct) +# +# expands to: +# +# RTSRCS += dir/main_src.c +# objects/dir/test_src_RTAPI: \ +# objects/dir/ulapi_srcs.o \ +# $(OBJDIR)/dir/rtapi_srcs.o $(OBJDIR)/dir/test_src.o \ +# ../lib/lib.so +# @mkdir -p objects/dir +# @echo Linking test objects/dir/test_src_RTAPI +# $(Q)gcc -o objects/dir/test_src_RTAPI -g -DRTAPI \ +# $(OBJDIR)/dir/test_src.o \ +# objects/dir/ulapi_srcs.o $(OBJDIR)/dir/rtapi_srcs.o \ +# ../lib/lib.so -lfoo -Wl,--wrap=wrap_funct +# CMOCKA_TESTS += dir/test_src_RTAPI +# +# ...and does the equivalent for ULAPI as well. + +WL_WRAP = -Wl,--wrap= +define setup_test +$$(if $$(filter RTAPI,$(2)),RTSRCS,USERSRCS) += $(1).c +objects/$(1)_$(strip $(2)): \ + $$(call $$(if $$(filter RTAPI,$(2)),TORTOBJS,TOOBJS), $(1).c) \ + $$(call TOOBJS, $(3)) $$(call TORTOBJS, $(4)) $(5) + @mkdir -p objects/$$(dir $(1)) + @echo Linking test objects/$(1)_$(strip $(2)) + $(Q)gcc -o $$@ -g $$^ -lcmocka $(6) $$(addprefix $$(WL_WRAP),$(7)) +CMOCKA_TESTS += $(1)_$(strip $(2)) + +endef + +############################################################################### + SUBMAKEFILES := $(patsubst %,%/Submakefile,$(SUBDIRS)) #$(info SUBMAKEFILES=$(SUBMAKEFILES)) -include $(wildcard $(SUBMAKEFILES)) +$(info All Submakefiles included) # This checks that all the things listed in USERSRCS are either C files # or C++ files @@ -280,7 +284,7 @@ $(call ASSERT_EMPTY,$(filter-out %.c %.cc %.p %.js %.ph %.proto, $(USERSRCS))) else $(call ASSERT_EMPTY,$(filter-out %.c %.cc %.js %.proto, $(USERSRCS))) endif -$(call ASSERT_EMPTY,$(filter-out %.c %.proto, $(RTSRCS))) +$(call ASSERT_EMPTY,$(filter-out %.c, $(RTSRCS))) ifeq ($(BUILD_PYTHON),yes) $(call TOOBJS,$(PYSRCS)) : EXTRAFLAGS += -fPIC $(call cc-option,-fno-strict-aliasing) @@ -340,9 +344,6 @@ endif # see configure.ac GIT_CONFIG_SHA for the configure-time string GIT_BUILD_SHA := $(shell ../scripts/get-git-sha) -# complain if SHA's dont match -$(info $(shell ../scripts/check-build-vs-configure-sha)) - # Compilation options. Perhaps some of these should come from Makefile.inc? (CXXFLAGS now does) INTEGER_OVERFLOW_FLAGS := $(call cc-option,-fwrapv) $(call cc-option, -fno-strict-overflow) OPT := $(INTEGER_OVERFLOW_FLAGS) @@ -396,7 +397,7 @@ $(sort $(CUSEROBJS_BUILD)) : objects/%_build.o: %.c $< -o $@ $(sort $(CXXUSEROBJS)) : objects/%.o: %.cc - $(ECHO) Compiling $< + $(ECHO) Compiling ++ $< @mkdir -p $(dir $@) @rm -f $@ $(Q)$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $(EXTRAFLAGS) \ @@ -522,7 +523,6 @@ HEADERS := \ rtapi/rtapi_compat.h \ rtapi/rtapi_hexdump.h \ rtapi/rtapi_int.h \ - rtapi/rtapi_kdetect.h \ rtapi/rtapi_limits.h \ rtapi/rtapi_math.h \ rtapi/rtapi_math64.h \ @@ -535,15 +535,17 @@ HEADERS := \ rtapi/rtapi_errno.h \ rtapi/rtapi_string.h \ rtapi/rtapi_pci.h \ - rtapi/rtapi_proc.h \ rtapi/rtapi_heap.h \ rtapi/rtapi_heap_private.h \ rtapi/ring.h \ rtapi/triple-buffer.h \ rtapi/multiframe.h \ rtapi/rtapi_mbarrier.h \ - rtapi/$(THREADS_SOURCE).h \ - rtapi/shmdrv/shmdrv.h + rtapi/shmdrv/shmdrv.h \ + rtapi/flavor/rtapi_flavor.h \ + rtapi/flavor/xenomai.h \ + rtapi/flavor/rt-preempt.h \ + rtapi/flavor/ulapi.h @@ -580,43 +582,11 @@ userspace: python clean: pythonclean cscopeclean endif -# This is the gateway into the crazy world of "kbuild", the linux 2.6 system -# for building kernel modules. Other kernel module build styles need to be -# accomodated here. -# -# (don't build when 'BUILD_ALL_FLAVORS' or 'BUILD_THREADS_MODULES' are set; -# these are intermediate make runs) - -# It looks almost impossible to coerce kbuild into putting build -# artifacts outside the source tree. The universal build needs to -# keep these artifacts separate for each kthread flavor. To solve -# this, create a link tree in objects/rtapi- with everything -# needed to build kernel modules. -# -# Then in the above 'modules:' target, cd to the link tree and call -# kbuild. -MODULE_SOURCE_DIRS = emc hal rtapi workaround machinetalk ## libnml -MODULE_SOURCES = Makefile* config* modsilent.py -$(OBJDIR)/.separate-kbuild-artifacts-hack.stamp: - mkdir -p $(OBJDIR) - # hard-link contents of $(MODULE_SOURCE_DIRS) to # $(OBJDIR) - # never follow symbolic links - cp -rlfd $(MODULE_SOURCE_DIRS) $(OBJDIR) - cp -lf $(MODULE_SOURCES) $(OBJDIR) - ln -sf $(BASEPWD)/../bin $(OBJDIR)/.. - ln -sf $(BASEPWD)/../scripts $(OBJDIR)/.. - touch $@ - # These rules clean things up. 'modclean' cleans files generated by 'modules' # (except that it doesn't remove the modules that were copied to rtlib) # 'clean' cleans everything but dependency files, and 'depclean' cleans them # too. modclean: - find -name '.*.cmd' -or -name '*.ko' -or -name '*.mod.c' -or -name '*.mod.o' | xargs rm -f - -rm -rf .tmp_versions - -rm -rf halcomp-srcs - find . -name .tmp_versions |xargs rm -rf - -rm -f $(RTLIBDIR)/*.ko -rm -f $(RTLIBDIR)/*.so depclean: @@ -630,13 +600,10 @@ clean: depclean modclean docclean find . -name '*.o' |xargs rm -f -rm -rf objects -rm -f $(TARGETS) - for flav in $(BUILD_THREAD_FLAVORS); do \ - rm -rf ../lib/$$flav; \ - done -rm -rf ../rtlib ../libexec rm -f ../etc/linuxcnc/rtapi.ini -rm -f $(COPY_CONFIGS) - -rm -f $(RTLIBDIR)/*.$(MODULE_EXT) + -rm -f $(RTLIBDIR)/*.so -rm -f hal/components/conv_*.comp -rm -f hal/i_components/conv_*.icomp -rm -f hal/components/*_bin.h # generated by pasm for bb platform @@ -647,18 +614,15 @@ clean: depclean modclean docclean # So that nothing is built as root, this rule does not depend on the touched # files (Note that files in depends/ might be rebuilt, and there's little that # can be done about it) -fix_perms = test -f $(1) && chown root $(1) && chmod 4750 $(1) || true +fix_perms = test ! -f $(1) || (chown root $(1) && chmod 4750 $(1)) ifeq ($(BUILD_DRIVERS),yes) setuid: -ifeq ($(USERMODE_PCI),yes) +ifeq ($(HAS_SYS_IO),yes) $(call fix_perms,../libexec/pci_read) $(call fix_perms,../libexec/pci_write) endif - $(foreach f,$(BUILD_THREAD_FLAVORS),\ - $(call fix_perms,../libexec/rtapi_app_$(f));) -# check system configuration: logging, ulimits, udev - @-../scripts/check-system-configuration.sh $(CHECK_KFLAV_SWITCH) + $(call fix_perms,../libexec/rtapi_app) else setuid: @echo "'make setuid' is not needed if hardware drivers are not used" @@ -735,16 +699,15 @@ install-dirs: $(DESTDIR)$(sysconfdir)/rsyslog.d \ $(DESTDIR)$(sysconfdir)/security/limits.d \ $(DESTDIR)$(sysconfdir)/udev/rules.d \ - $(DESTDIR)$(sampleconfsdir) \ - $(addprefix $(DESTDIR), $(INSTALL_DIRS)) + $(DESTDIR)$(sampleconfsdir) ifeq ($(BUILD_EMCWEB),yes) $(DIR) $(DESTDIR)$(datadir)/linuxcnc/doc-root/css/images \ $(DESTDIR)$(datadir)/linuxcnc/doc-root/js \ $(DESTDIR)$(datadir)/linuxcnc/doc-root/res endif -ifeq ($(USERMODE_PCI),yes) $(DIR) $(DESTDIR)$(includedir)/linuxcnc/userpci -endif +# # Create machinekit->linuxcnc symlink in /usr/share + ln -s linuxcnc $(DESTDIR)$(datadir)/machinekit install-kernel-indep: install-dirs $(EXE) ../scripts/realtime $(DESTDIR)$(bindir) @@ -753,21 +716,16 @@ install-kernel-indep: install-dirs $(EXE) $(filter ../bin/%,$(TARGETS)) $(DESTDIR)$(bindir) $(FILE) $(filter ../lib/%.a ../lib/%.so.0,$(TARGETS)) $(DESTDIR)$(libdir) cp --no-dereference $(filter ../lib/%.so, $(TARGETS)) $(DESTDIR)$(libdir) - $(FILE) ../rtlib/ulapi-*.so $(DESTDIR)$(EMC2_RTLIB_BASE_DIR) # # don't run ldconfig under fakeroot (silence dpkg-build warning) -test -n "$$FAKED_MODE" || ldconfig $(DESTDIR)$(libdir) $(FILE) $(HEADERS) $(DESTDIR)$(includedir)/linuxcnc/ -ifeq ($(USERMODE_PCI),yes) $(FILE) $(USERPCI_HEADERS) $(DESTDIR)$(includedir)/linuxcnc/userpci -endif $(FILE) Makefile.modinc $(DESTDIR)$(datadir)/linuxcnc $(FILE) Makefile.inc $(DESTDIR)$(datadir)/linuxcnc $(FILE) rtapi/rsyslogd-linuxcnc.conf $(DESTDIR)$(sysconfdir)/rsyslog.d/linuxcnc.conf $(FILE) rtapi/shmdrv/limits.d-machinekit.conf \ $(DESTDIR)$(sysconfdir)/security/limits.d/machinekit.conf - $(FILE) rtapi/shmdrv/shmdrv.rules \ - $(DESTDIR)$(sysconfdir)/udev/rules.d/50-shmdrv.rules $(FILE) ../etc/linuxcnc/machinekit.ini $(DESTDIR)$(sysconfdir)/linuxcnc $(EXE) ../bin/mank $(DESTDIR)$(bindir) @@ -805,42 +763,31 @@ install-python: install-dirs endif install-kernel-dep: install-dirs - $(SETUID) ../libexec/rtapi_app_* $(DESTDIR)$(EMC2_LIBEXEC_DIR) -ifeq ($(USERMODE_PCI),yes) + $(SETUID) ../libexec/rtapi_app $(DESTDIR)$(EMC2_LIBEXEC_DIR) +ifeq ($(BUILD_DRIVERS),yes) +ifeq ($(HAS_SYS_IO),yes) $(SETUID) ../libexec/pci_write $(DESTDIR)$(EMC2_LIBEXEC_DIR) $(SETUID) ../libexec/pci_read $(DESTDIR)$(EMC2_LIBEXEC_DIR) +endif endif $(EXE) ../libexec/inivar $(DESTDIR)$(EMC2_LIBEXEC_DIR) $(EXE) ../libexec/rtapi_msgd $(DESTDIR)$(EMC2_LIBEXEC_DIR) - $(EXE) ../libexec/flavor $(DESTDIR)$(EMC2_LIBEXEC_DIR) $(FILE) ../etc/linuxcnc/rtapi.ini $(DESTDIR)$(sysconfdir)/linuxcnc # RTAPI modules: install userland flavor .so modules into - # e.g. /usr/lib/linuxcnc/modules and kthread flavor .ko - # modules for each kver into e.g. /lib/modules//linuxcnc - for flavor in $(BUILD_THREAD_FLAVORS); do \ - if test $${flavor%-kernel} = $${flavor}; then \ - echo Installing modules for userland flavor $$flavor; \ - $(DIR) $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/$$flavor; \ - $(FILE) ../rtlib/$$flavor/* \ - $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/$$flavor; \ - else \ - echo Installing modules for kthreads flavor $$flavor; \ - for srcdir in ../rtlib/$$flavor/*; do \ - kver=`basename $$srcdir`; \ - echo Installing modules for flavor $$flavor, kver $$kver; \ - $(DIR) $(DESTDIR)/lib/modules/$$kver/linuxcnc; \ - $(FILE) $$srcdir/* $(DESTDIR)/lib/modules/$$kver/linuxcnc; \ - done; \ - fi; \ - done -endif # RUN_IN_PLACE + # e.g. /usr/lib/linuxcnc/modules + + echo Installing modules + $(DIR) $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/modules + $(FILE) ../rtlib/modules/* \ + $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/modules + +endif # ! RUN_IN_PLACE CONF=../configs COMMON=$(CONF)/common CONFILES=$(addsuffix /$(1), $(filter-out $(COMMON) $(CONF),\ ${shell find ${CONF} -type d -print})) -endif # userspace ################################################################################################################# @@ -857,6 +804,7 @@ EXTRA_CFLAGS = $(RTFLAGS) \ -I$(INCLUDE_PREFIX)/libnml/buffer \ -I$(INCLUDE_PREFIX)/libnml/posemath \ -I$(INCLUDE_PREFIX)/rtapi \ + -I$(INCLUDE_PREFIX)/rtapi/flavor \ -I$(INCLUDE_PREFIX)/hal/lib \ -I$(INCLUDE_PREFIX)/machinetalk/nanopb \ -I$(INCLUDE_PREFIX)/machinetalk/build \ @@ -869,296 +817,26 @@ ifdef TARGET_PLATFORM_BEAGLEBONE EXTRA_CFLAGS += -I$(INCLUDE_PREFIX)/hal/support/pru endif -# For each module, there's an addition to obj-m or obj-$(CONFIG_foo) -# plus a definition of foo-objs, which contains the full path to the -# object file(s) that the module contains. Unfortunately, this setup pollutes -# the source directory with object files and other temporaries, but I can't -# find a way around it. - -# These lists would be best moved to their respective subdirectories' -# Submakefiles to make this more modular and avoid maintaining -# multiple lists of the same things. This won't work as-is right now -# because the Submakefiles are included in a conditional block that is -# not evaluated during kernel module build. - -# Subdirectory: rtapi - -# obj-$(CONFIG_RTAPI) += rtapi.o - -# # Sources for all thread systems -# rtapi-objs := \ -# rtapi/instance.o \ -# rtapi/rtapi_support.o \ -# rtapi/rtapi_common.o \ -# rtapi/rtapi_task.o \ -# rtapi/rtapi_shmem.o \ -# rtapi/rtapi_ring.o \ -# rtapi/rtapi_time.o \ -# rtapi/rtapi_io.o \ -# rtapi/$(THREADS_SOURCE).o - -# Subdirectory: rtapi/examples (unneeded?) - -# Subdirectory: hal/components -#obj-$(CONFIG_BOSS_PLC) += boss_plc.o -#boss_plc-objs := hal/components/boss_plc.o $(MATHSTUB) -obj-$(CONFIG_ENCODER) += encoder.o -encoder-objs := hal/components/encoder.o $(MATHSTUB) - -obj-$(CONFIG_ENCODER) += encoderv2.o -encoderv2-objs := hal/components/encoderv2.o $(MATHSTUB) - -obj-$(CONFIG_COUNTER) += counter.o -counter-objs := hal/components/counter.o $(MATHSTUB) -obj-$(CONFIG_ENCODER_RATIO) += encoder_ratio.o -encoder_ratio-objs := hal/components/encoder_ratio.o $(MATHSTUB) -obj-$(CONFIG_ENCODER_RATIO) += encoder_ratiov2.o -encoder_ratiov2-objs := hal/components/encoder_ratiov2.o $(MATHSTUB) -obj-$(CONFIG_STEPGEN) += stepgen.o -stepgen-objs := hal/components/stepgen.o $(MATHSTUB) -obj-$(CONFIG_STEPGEN) += stepgenv2.o -stepgenv2-objs := hal/components/stepgenv2.o $(MATHSTUB) -obj-$(CONFIG_LCD) += lcd.o -lcd-objs := hal/components/lcd.o $(MATHSTUB) -obj-$(CONFIG_MATRIX_KB) += matrix_kb.o -matrix_kb-objs := hal/components/matrix_kb.o $(MATHSTUB) -obj-$(CONFIG_MUX_GENERIC) += mux_generic.o -mux_generic-objs := hal/components/mux_generic.o $(MATHSTUB) -obj-$(CONFIG_PWMGEN) += pwmgen.o -pwmgen-objs := hal/components/pwmgen.o $(MATHSTUB) -obj-$(CONFIG_PWMGEN) += pwmgenv2.o -pwmgenv2-objs := hal/components/pwmgenv2.o $(MATHSTUB) -obj-$(CONFIG_SIGGEN) += siggen.o -siggen-objs := hal/components/siggen.o $(MATHSTUB) -obj-$(CONFIG_PID) += threads.o -threads-objs := hal/components/threads.o $(MATHSTUB) -obj-$(CONFIG_SIM_ENCODER) += sim_encoder.o -sim_encoder-objs := hal/components/sim_encoder.o $(MATHSTUB) -obj-$(CONFIG_STREAMER) += streamer.o -streamer-objs := hal/components/streamer.o $(MATHSTUB) -obj-$(CONFIG_SAMPLER) += sampler.o -sampler-objs := hal/components/sampler.o $(MATHSTUB) - -# Subdirectory: hal/support -ifdef TARGET_PLATFORM_BEAGLEBONE -ifeq ($(BUILD_SYS),user-dso) -obj-m += hal_pru.o -hal_pru-objs := hal/components/hal_pru.o hal/support/pru/prussdrv.o $(LIBPTHREAD) -obj-m += hal_prudebug.o -hal_prudebug-objs := hal/components/hal_prudebug.o hal/support/pru/prussdrv.o $(LIBPTHREAD) -endif -endif - -# Subdirectory: hal/drivers -ifeq ($(BUILD_DRIVERS),yes) -#ifeq ($(BUILD_SYS),kbuild) -obj-$(CONFIG_HAL_PARPORT) += hal_parport.o -hal_parport-objs := hal/drivers/hal_parport.o $(MATHSTUB) -obj-$(CONFIG_HAL_VTI) += hal_vti.o -hal_vti-objs := hal/drivers/hal_vti.o $(MATHSTUB) -#obj-$(CONFIG_HAL_EVOREG) += hal_evoreg.o -#hal_evoreg-objs := hal/drivers/hal_evoreg.o $(MATHSTUB) -obj-$(CONFIG_HAL_MOTENC) += hal_motenc.o -hal_motenc-objs := hal/drivers/hal_motenc.o $(MATHSTUB) - -ifdef TARGET_PLATFORM_PC -obj-$(CONFIG_HAL_SPEAKER) += hal_speaker.o -hal_speaker-objs := hal/drivers/hal_speaker.o $(MATHSTUB) -endif - -ifeq ($(USERMODE_PCI),yes) -obj-$(CONFIG_PCI_8255) += pci_8255.o -pci_8255-objs := hal/drivers/pci_8255.o -obj-$(CONFIG_HAL_TIRO) += hal_tiro.o -hal_tiro-objs := hal/drivers/hal_tiro.o $(MATHSTUB) -obj-$(CONFIG_HAL_STG) += hal_stg.o -hal_stg-objs := hal/drivers/hal_stg.o $(MATHSTUB) -obj-$(CONFIG_HAL_AX521H) += hal_ax5214h.o -hal_ax5214h-objs := hal/drivers/hal_ax5214h.o $(MATHSTUB) -obj-$(CONFIG_HAL_SKELETON) += hal_skeleton.o -hal_skeleton-objs := hal/drivers/hal_skeleton.o $(MATHSTUB) -endif - -ifdef TARGET_PLATFORM_RASPBERRY -obj-$(CONFIG_HAL_GPIO) += hal_gpio.o -hal_gpio-objs := hal/drivers/hal_gpio.o hal/drivers/cpuinfo.o -obj-$(CONFIG_HAL_SPI) += hal_spi.o -hal_spi-objs := hal/drivers/hal_spi.o -endif - -ifdef TARGET_PLATFORM_SOCFPGA -ifeq ($(BUILD_SYS),user-dso) -obj-$(CONFIG_HM2_SOC_OL) += hm2_soc_ol.o -hm2_soc_ol-objs := hal/drivers/mesa-hostmot2/hm2_soc_ol.o -endif -endif - -ifdef TARGET_PLATFORM_BEAGLEBONE -ifeq ($(BUILD_SYS),user-dso) -obj-$(CONFIG_HAL_GPIO) += hal_bb_gpio.o -hal_bb_gpio-objs := hal/drivers/hal_bb_gpio/hal_bb_gpio.o -obj-$(CONFIG_PEPPER) += pepper.o -pepper-objs := hal/components/pepper.o $(MATHSTUB) -# Silence warning in GCC 4.4 -$(OBJDIR)/hal/components/pepper.o: EXTRA_CFLAGS += -Wno-packed-bitfield-compat -endif - -obj-m += hal_arm335xQEP.o -hal_arm335xQEP-objs := hal/drivers/hal_arm335xQEP.o $(MATHSTUB) -endif - -ifdef TARGET_PLATFORM_H3 -obj-$(CONFIG_HAL_GPIO) += hal_gpio_h3.o -hal_gpio_h3-objs := hal/drivers/hal_gpio_h3.o -endif - -ifdef TARGET_PLATFORM_CHIP -obj-$(CONFIG_HAL_GPIO) += hal_chip_gpio.o -hal_chip_gpio-objs := hal/drivers/hal_chip_gpio.o hal/drivers/chip/mmap_gpio.o -endif - -ifdef TARGET_PLATFORM_ZEDBOARD -obj-$(CONFIG_HAL_GPIO) += hal_zed_gpio.o -hal_zed_gpio-objs := hal/drivers/hal_zed_gpio.o -obj-$(CONFIG_HAL_CAN) += hal_zed_can.o -hal_zed_can-objs := hal/drivers/hal_zed_can.o -endif - -# hal_pru_generic driver -ifdef TARGET_PLATFORM_BEAGLEBONE -ifeq ($(BUILD_SYS),user-dso) -obj-m += hal_pru_generic.o -hal_pru_generic-objs := \ - hal/drivers/hal_pru_generic/hal_pru_generic.o \ - hal/drivers/hal_pru_generic/pwmgen.o \ - hal/drivers/hal_pru_generic/stepgen.o \ - hal/drivers/hal_pru_generic/encoder.o \ - hal/support/pru/prussdrv.o \ - $(LIBPTHREAD) -endif -endif - -# these won't compile as-is with userland threading -###################################################### -#ifneq ($(BUILD_SYS),user-dso) -#obj-$(CONFIG_HAL_M5I20) += hal_m5i20.o -#hal_m5i20-objs := hal/drivers/hal_m5i20.o $(MATHSTUB) -#obj-$(CONFIG_HAL_PPMC) += hal_ppmc.o -#hal_ppmc-objs := hal/drivers/hal_ppmc.o $(MATHSTUB) -#obj-$(CONFIG_OPTO_AC5) += opto_ac5.o -#opto_ac5-objs := hal/drivers/opto_ac5.o $(MATHSTUB) -#obj-$(CONFIG_HAL_GM) += hal_gm.o -#hal_gm-objs := hal/drivers/hal_gm.o $(MATHSTUB) -#endif -#################################################### - -obj-$(CONFIG_HOSTMOT2) += hostmot2.o hm2_test.o setsserial.o hm2_eth.o -ifeq ($(USERMODE_PCI),yes) -obj-$(CONFIG_HOSTMOT2) += hm2_7i43.o hm2_7i90.o hm2_pci.o -endif - -hm2_eth-objs := \ - hal/drivers/mesa-hostmot2/hm2_eth.o \ - $(MATHSTUB) -hostmot2-objs += \ - hal/drivers/mesa-hostmot2/hostmot2.o \ - hal/drivers/mesa-hostmot2/backported-strings.o \ - hal/drivers/mesa-hostmot2/ioport.o \ - hal/drivers/mesa-hostmot2/encoder.o \ - hal/drivers/mesa-hostmot2/abs_encoder.o\ - hal/drivers/mesa-hostmot2/resolver.o \ - hal/drivers/mesa-hostmot2/pwmgen.o \ - hal/drivers/mesa-hostmot2/tp_pwmgen.o \ - hal/drivers/mesa-hostmot2/sserial.o \ - hal/drivers/mesa-hostmot2/stepgen.o \ - hal/drivers/mesa-hostmot2/bspi.o \ - hal/drivers/mesa-hostmot2/dbspi.o \ - hal/drivers/mesa-hostmot2/uart.o \ - hal/drivers/mesa-hostmot2/pktuart.o \ - hal/drivers/mesa-hostmot2/watchdog.o \ - hal/drivers/mesa-hostmot2/pins.o \ - hal/drivers/mesa-hostmot2/dpll.o \ - hal/drivers/mesa-hostmot2/irq.o \ - hal/drivers/mesa-hostmot2/led.o \ - hal/drivers/mesa-hostmot2/fwid.o \ - hal/drivers/mesa-hostmot2/tram.o \ - hal/drivers/mesa-hostmot2/raw.o \ - hal/drivers/mesa-hostmot2/nano_soc_adc.o \ - hal/drivers/mesa-hostmot2/capsense.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - rtapi/userpci/device.o \ - rtapi/userpci/firmware.o \ - rtapi/userpci/string.o \ - $(MATHSTUB) -hm2_7i90-objs := \ - hal/drivers/mesa-hostmot2/hm2_7i90.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - $(MATHSTUB) -hm2_7i43-objs := \ - hal/drivers/mesa-hostmot2/hm2_7i43.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - $(MATHSTUB) -hm2_pci-objs := \ - hal/drivers/mesa-hostmot2/hm2_pci.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - $(MATHSTUB) -hm2_test-objs := \ - hal/drivers/mesa-hostmot2/hm2_test.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - $(MATHSTUB) -setsserial-objs += \ - hal/drivers/mesa-hostmot2/setsserial.o \ - rtapi/userpci/device.o \ - rtapi/userpci/firmware.o \ - rtapi/userpci/string.o \ - $(MATHSTUB) -hm2_pci-objs := \ - hal/drivers/mesa-hostmot2/hm2_pci.o \ - hal/drivers/mesa-hostmot2/bitfile.o \ - $(MATHSTUB) - -obj-$(CONFIG_PROBE_PARPORT) += probe_parport.o -probe_parport-objs := hal/drivers/probe_parport.o $(MATHSTUB) -endif # BUILD_DRIVERS=yes - -obj-m += scope_rt.o -scope_rt-objs := hal/utils/scope_rt.o $(MATHSTUB) - - -# obj-m += vtexport.o -# vtexport-objs := hal/vtable-example/vtexport.o -# vtexport-objs += hal/vtable-example/vcode.o - -obj-m += jplan.o -jplan-objs := hal/jplanner/jplan.o machinetalk/build/machinetalk/protobuf/jplan.npb.o - -obj-m += sample_channel_pb.o -sample_channel_pb-objs := hal/sample_channel/sample_channel_pb.o machinetalk/build/machinetalk/protobuf/sample.npb.o - -obj-m += interpolate.o -interpolate-objs := hal/interpolator/interpolate.o machinetalk/build/machinetalk/protobuf/ros.npb.o - -obj-m += icomp.o -icomp-objs := hal/icomp-example/icomp.o - +################################################################################ +# Misc C components in directories with no Submakefile +$(eval $(call c_comp_build_rules,hal/jplanner/jplan.o)) +$(eval $(call c_comp_build_rules,hal/interpolator/interpolate.o, \ + machinetalk/build/machinetalk/protobuf/ros.npb.o)) +$(eval $(call c_comp_build_rules,hal/icomp-example/icomp.o)) # clashes with component in i_components -obj-m += lutn-demo.o -lutn-demo-objs := hal/icomp-example/lutn-demo.o - -obj-m += ufdemo.o -ufdemo-objs := hal/userfunct-example/ufdemo.o +$(eval $(call c_comp_build_rules,hal/icomp-example/lutn-demo.o)) -TORTOBJS = $(foreach file,$($(patsubst %.o,%,$(1))-objs), $(OBJDIR)/$(file)) +TOCOMPRTOBJS = $(foreach file,$($(patsubst %.o,%,$(1))-objs), $(OBJDIR)/$(file)) ####################################################################################################### -# USER_DSO module building -# (don't build when 'BUILD_ALL_FLAVORS' or 'BUILD_THREADS_MODULES' are set; -# these are intermediate make runs) -ifeq ($(BUILD_SYS)+$(BUILD_THREAD_MODULES),user-dso+yes) +# Module building EXTRA_CFLAGS += -fPIC -RTOBJS := $(sort $(foreach mod,$(obj-m),$(call TORTOBJS,$(mod)))) +# Non-module RT objects +RTOBJS = $(call TORTOBJS,$(RTSRCS)) +# Module RT objects +RTOBJS += $(sort $(foreach mod,$(obj-m),$(call TOCOMPRTOBJS,$(mod)))) RTDEPS := $(sort $(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d, $(RTOBJS))) @@ -1233,9 +911,21 @@ RTDEPS := $(sort $(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d, $(RTOBJS))) # it means that symbols referenced are resolved within the object first, instead of looking # at any symbols exported (maybe by accident) by rtap_app proper. # + +modules: +ifeq ($(RUN_IN_PLACE)+$(BUILD_DRIVERS),yes+yes) + @test -f ../libexec/rtapi_app -a \ + \( 0`stat -c %u ../libexec/rtapi_app 2>/dev/null` \ + -ne 0 -o ! -u ../libexec/rtapi_app \) \ + && need_setuid=1; \ + test "$$need_setuid" = 1 && \ + $(VECHO) -n "You now need to run 'sudo make setuid' " && \ + $(VECHO) "in order to run in place." || true +endif + modules: $(patsubst %.o,$(RTLIBDIR)/%.so,$(obj-m)) $(RTLIBDIR)/%.so: - $(ECHO) Linking realtime $(threads) $(notdir $@) + $(ECHO) Linking realtime $(notdir $@) @mkdir -p $(dir $@) @# link all objects files into a single .so $(Q)$(LD) -d -r -o $(OBJDIR)/$*.tmp $^ @@ -1248,14 +938,14 @@ $(RTLIBDIR)/%.so: $(sort $(RTDEPS)): $(DEPDIR)/%.d: %.c @mkdir -p $(dir $@) - $(ECHO) Depending realtime $(threads) $< + $(ECHO) Depending realtime $< $(Q)$(call DEP,$(CC),$@ \ $(patsubst depends/%.d,objects/%.o,$@),$@,$(OPT) \ $(DEBUG) $(CPPFLAGS) $(EXTRA_CFLAGS) $<) # Rules to make .o (object) files $(sort $(RTOBJS)) : $(OBJDIR)/%.o : %.c $(DEPDIR)/%.d - $(ECHO) Compiling realtime $(threads) $< + $(ECHO) Compiling realtime $< @rm -f $@ @mkdir -p $(dir $@) $(Q)$(CC) -c $(OPT) $(DPKG_CFLAGS) $(DEBUG) $(CPPFLAGS) \ @@ -1269,156 +959,6 @@ $(sort $(CXXRTOBJS)) : $(OBJDIR)/%.o : %.cc $(DEPDIR)/%.d $(Q)$(CXX) -c $(OPT) $(DEBUG) $(RT_CXXFLAGS) $(CPPFLAGS) \ $(EXTRA_CFLAGS) $< -o $@ -endif # end BUILD_SYS=user-dso - -#################################################################################################################################################### - -# # ------ not used anymore ------------- -# ifeq ($(BUILD_SYS),normal) -# modules: $(patsubst %,$(RTLIBDIR)/%,$(obj-m)) -# RTOBJS := $(sort $(foreach mod,$(obj-m),$(call TORTOBJS,$(mod)))) -# RTDEPS := $(sort $(patsubst objects/%.o,depends/%.d, $(RTOBJS))) - -# $(sort $(RTDEPS)): $(DEPDIR)/%.d: %.c -# @mkdir -p $(dir $@) -# $(ECHO) Depending $< -# $(Q)$(call DEP,$(CC),$@ $(patsubst depends/%.d,objects/%.o,$@),$@,$(EXTRA_CFLAGS) $<) - - -# # Rules to make .o (object) files -# $(sort $(RTOBJS)) : $(OBJDIR)/%.o : %.c -# $(ECHO) Compiling realtime $< -# @mkdir -p $(dir $@) -# $(Q)$(CC) -c -DRTAPI -nostdinc -isystem $(shell $(CC) -print-file-name=include) -I$(KERNELDIR)/include $(EXTRA_CFLAGS) $< -o $@ - -# $(RTLIBDIR)/%.o: -# $(ECHO) Linking $@ -# $(Q)ld -r -static -S $(LDFLAGS) -o $@ $^ $(EXTRALINK) -# endif # end 'normal' - -############################################################################################## - -# build kernel RTAPI modules -ifneq "$(filter normal user-dso,$(BUILD_SYS))" "" -#$(RTLIBDIR)/instance$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(instance-objs)) -#$(RTLIBDIR)/rtapi$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(rtapi-objs)) -$(RTLIBDIR)/boss_plc$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(boss_plc-objs)) -$(RTLIBDIR)/encoder$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(encoder-objs)) -$(RTLIBDIR)/encoderv2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(encoderv2-objs)) -$(RTLIBDIR)/counter$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(counter-objs)) -$(RTLIBDIR)/encoder_ratio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(encoder_ratio-objs)) -$(RTLIBDIR)/encoder_ratiov2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(encoder_ratiov2-objs)) -$(RTLIBDIR)/stepgen$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(stepgen-objs)) -$(RTLIBDIR)/stepgenv2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(stepgenv2-objs)) -$(RTLIBDIR)/lcd$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(lcd-objs)) -$(RTLIBDIR)/matrix_kb$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(matrix_kb-objs)) -$(RTLIBDIR)/mux_generic$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(mux_generic-objs)) -$(RTLIBDIR)/freqgen$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(freqgen-objs)) -$(RTLIBDIR)/pwmgen$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pwmgen-objs)) -$(RTLIBDIR)/pwmgenv2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pwmgenv2-objs)) -$(RTLIBDIR)/siggen$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(siggen-objs)) -$(RTLIBDIR)/at_pid$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(at_pid-objs)) -$(RTLIBDIR)/threads$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(threads-objs)) -$(RTLIBDIR)/supply$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(supply-objs)) -$(RTLIBDIR)/sim_encoder$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(sim_encoder-objs)) -$(RTLIBDIR)/watchdog$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(watchdog-objs)) -$(RTLIBDIR)/modmath$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(modmath-objs)) -$(RTLIBDIR)/streamer$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(streamer-objs)) -$(RTLIBDIR)/sampler$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(sampler-objs)) -$(RTLIBDIR)/probe_parport$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(probe_parport-objs)) - -$(RTLIBDIR)/hostmot2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hostmot2-objs)) -$(RTLIBDIR)/hm2_test$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_test-objs)) -$(RTLIBDIR)/setsserial$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(setsserial-objs)) -$(RTLIBDIR)/hm2_eth$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_eth-objs)) -ifeq ($(USERMODE_PCI),yes) -$(RTLIBDIR)/hm2_7i43$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_7i43-objs)) -$(RTLIBDIR)/hm2_7i90$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_7i90-objs)) -$(RTLIBDIR)/hm2_pci$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_pci-objs)) -endif - -ifdef TARGET_PLATFORM_PC -$(RTLIBDIR)/hal_parport$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_parport-objs)) -endif - -ifdef TARGET_PLATFORM_SOCFPGA -$(RTLIBDIR)/hostmot2$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hostmot2-objs)) -$(RTLIBDIR)/hm2_soc_ol$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hm2_soc_ol-objs)) -endif - -ifdef TARGET_PLATFORM_BEAGLEBONE -$(RTLIBDIR)/hal_pru$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_pru-objs)) -$(RTLIBDIR)/hal_pru_generic$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_pru_generic-objs)) -$(RTLIBDIR)/hal_prudebug$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_prudebug-objs)) -$(RTLIBDIR)/hal_gpio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_gpio-objs)) -$(RTLIBDIR)/hal_bb_gpio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_bb_gpio-objs)) -$(RTLIBDIR)/pepper$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pepper-objs)) -$(RTLIBDIR)/hal_arm335xQEP$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_arm335xQEP-objs)) -endif - -ifdef TARGET_PLATFORM_H3 -$(RTLIBDIR)/hal_gpio_h3$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_gpio_h3-objs)) -endif - -ifdef TARGET_PLATFORM_CHIP -$(RTLIBDIR)/hal_chip_gpio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_chip_gpio-objs)) -endif - -ifdef TARGET_PLATFORM_RASPBERRY -$(RTLIBDIR)/hal_gpio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_gpio-objs)) -$(RTLIBDIR)/hal_spi$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_spi-objs)) -endif - -ifdef TARGET_PLATFORM_ZEDBOARD -$(RTLIBDIR)/hal_zed_gpio$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_zed_gpio-objs)) -$(RTLIBDIR)/hal_zed_can$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_zed_can-objs)) -endif - -$(RTLIBDIR)/pci_8255$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pci_8255-objs)) -$(RTLIBDIR)/hal_tiro$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_tiro-objs)) -$(RTLIBDIR)/hal_stg$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_stg-objs)) -$(RTLIBDIR)/hal_vti$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_vti-objs)) -#$(RTLIBDIR)/hal_evoreg$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_evoreg-objs)) -$(RTLIBDIR)/hal_motenc$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_motenc-objs)) -$(RTLIBDIR)/hal_ax5214h$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_ax5214h-objs)) -$(RTLIBDIR)/hal_ppmc$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_ppmc-objs)) -$(RTLIBDIR)/hal_skeleton$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_skeleton-objs)) -$(RTLIBDIR)/hal_speaker$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_speaker-objs)) -$(RTLIBDIR)/opto_ac5$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(opto_ac5-objs)) -$(RTLIBDIR)/scope_rt$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(scope_rt-objs)) -$(RTLIBDIR)/motmod$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(motmod-objs)) -$(RTLIBDIR)/trivkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(trivkins-objs)) -$(RTLIBDIR)/XYZACkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(XYZACkins-objs)) -$(RTLIBDIR)/5axiskins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(5axiskins-objs)) -$(RTLIBDIR)/maxkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(maxkins-objs)) -$(RTLIBDIR)/gantrykins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(gantrykins-objs)) -$(RTLIBDIR)/rotatekins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(rotatekins-objs)) -$(RTLIBDIR)/tripodkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(tripodkins-objs)) -$(RTLIBDIR)/lineardeltakins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(lineardeltakins-objs)) -$(RTLIBDIR)/genhexkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(genhexkins-objs)) -$(RTLIBDIR)/genserkins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(genserkins-objs)) -$(RTLIBDIR)/pumakins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pumakins-objs)) -$(RTLIBDIR)/scarakins$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(scarakins-objs)) -$(RTLIBDIR)/hal_gm$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_gm-objs)) - -$(RTLIBDIR)/tp$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(tp-objs)) -$(RTLIBDIR)/ufdemo$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(ufdemo-objs)) -$(RTLIBDIR)/jplan$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(jplan-objs)) -$(RTLIBDIR)/sample_channel_pb$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(sample_channel_pb-objs)) -$(RTLIBDIR)/interpolate$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(interpolate-objs)) -$(RTLIBDIR)/icomp$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(icomp-objs)) -$(RTLIBDIR)/lutn-demo$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(lutn-demo-objs)) - - -ifeq ($(TRIVIAL_BUILD),no) -READ_RTDEPS = $(wildcard $(RTDEPS)) -$(shell echo 1>&2 Reading $(words $(READ_RTDEPS))/$(words $(RTDEPS)) realtime dependency files) --include $(READ_RTDEPS) -$(shell echo 1>&2 Done reading realtime dependencies) -endif - -endif # build kernel RTAPI modules - ############################################################################################### @@ -1490,9 +1030,13 @@ objects/var-%: Makefile $(wildcard $(SUBMAKEFILES)) Makefile.inc @echo $($*) > $@.tmp @sh move-if-change $@.tmp $@ +# Link shared libs ../lib/%.so: ../lib/%.so.0 $(ECHO) Symlinking $(notdir $<) to $(notdir $@) $(Q)ln -sf $(notdir $<) $@ +# - Be sure the setuid message comes last +ALL_SHLIBS=$(filter ../%.so.0,$(TARGETS)) $(filter ../%.so,$(TARGETS)) +modules: $(ALL_SHLIBS) cscope: cscope -Rb @@ -1503,3 +1047,14 @@ cscope/man/: NOSETESTS := $(wildcard ../nosetests/*.py) nosetest: $(foreach var,$(NOSETESTS),nosetests -v $(var);) + +############################################################################### +# C unit tests +# +# Run with `make cmocka_tests` + +cmocka_tests: $(addprefix objects/, $(CMOCKA_TESTS)) + @for test in $^; do \ + echo "\nRunning test $$test"; \ + $$test; \ + done diff --git a/src/Makefile.inc.in b/src/Makefile.inc.in index c42a843d1d..70fc3a365e 100644 --- a/src/Makefile.inc.in +++ b/src/Makefile.inc.in @@ -1,5 +1,5 @@ # -*-makefile-gmake-*- -# @configure_input@ +# @configure_input@ # on @DATE@ # @@ -10,39 +10,14 @@ EMC2_LIBEXEC_DIR=@EMC2_LIBEXEC_DIR@ # Threads systems ################# -# List of thread flavors to build modules -BUILD_THREAD_FLAVORS=@BUILD_THREAD_FLAVORS@ - -# If $(threads) is not set already, try running 'flavor'; if the -# result is empty or not in $(BUILD_THREAD_FLAVORS), pick the first -# item from $(BUILD_THREAD_FLAVORS). -threads ?= $(shell echo $(BUILD_THREAD_FLAVORS) | \ - awk -v f="`${EMC2_LIBEXEC_DIR}/flavor 2>/dev/null`" '\ - { \ - found=$$1; \ - split($$0,flavs); \ - for (val in flavs) \ - if (flavs[val] == f) found=f; \ - print found; \ - }') - -# Uppercase version of flavor name for use in variables -THREADS = $(shell echo $(threads) | tr a-z- A-Z_) - -HAVE_POSIX_THREADS=@HAVE_POSIX_THREADS@ -HAVE_RT_PREEMPT_THREADS=@HAVE_RT_PREEMPT_THREADS@ -HAVE_XENOMAI_THREADS=@HAVE_XENOMAI_THREADS@ -HAVE_KERNEL_THREADS=no +THREADS_LDFLAGS = @THREADS_LDFLAGS@ +THREADS_RTFLAGS = @THREADS_RTFLAGS@ -POSIX_THREADS_FLAVOR_ID=@POSIX_THREADS_FLAVOR_ID@ -RT_PREEMPT_THREADS_FLAVOR_ID=@RT_PREEMPT_THREADS_FLAVOR_ID@ -XENOMAI_THREADS_FLAVOR_ID=@XENOMAI_THREADS_FLAVOR_ID@ -THREAD_FLAVOR_ID=$($(THREADS)_THREADS_FLAVOR_ID) +HAVE_XENOMAI_THREADS=@HAVE_XENOMAI_THREADS@ +XENOMAI_THREADS_RTS=@XENOMAI_THREADS_RTS@ +XENOMAI_LDFLAGS = @XENOMAI_LDFLAGS@ +XENOMAI_RTFLAGS = @XENOMAI_RTFLAGS@ -POSIX_THREADS_BUILD_SYS = user-dso -RT_PREEMPT_THREADS_BUILD_SYS = user-dso -XENOMAI_THREADS_BUILD_SYS = user-dso -BUILD_SYS = $($(THREADS)_THREADS_BUILD_SYS) # Directories ############# @@ -53,8 +28,6 @@ exec_prefix=@exec_prefix@ EMC2_HOME=@EMC2_HOME@ LIB_DIR=@EMC2_HOME@/lib -RTDIR_EXT=$(threads) - #used for install stuff #but have them here as reference #build system only uses EMC2_RTLIB_DIR when creating rtapi.ini @@ -62,7 +35,7 @@ EMC2_BIN_DIR=@EMC2_BIN_DIR@ EMC2_TCL_DIR=@EMC2_TCL_DIR@ EMC2_HELP_DIR=@EMC2_HELP_DIR@ EMC2_RTLIB_BASE_DIR=@EMC2_RTLIB_DIR@ -EMC2_RTLIB_DIR=$(EMC2_RTLIB_BASE_DIR)/$(RTDIR_EXT) +EMC2_RTLIB_DIR=$(EMC2_RTLIB_BASE_DIR)/modules EMC2_USER_CONFIG_DIR=~/emc2/configs EMC2_SYSTEM_CONFIG_DIR=@EMC2_SYSTEM_CONFIG_DIR@ EMC2_NCFILES_DIR=@EMC2_NCFILES_DIR@ @@ -104,43 +77,10 @@ ARCH_CFLAGS=@ARCH_CFLAGS@ RTOPT:=-O2 $(ARCH_CFLAGS) ULOPT:=-O2 $(ARCH_CFLAGS) RUN_IN_PLACE = @RUN_IN_PLACE@ -POSIX_THREADS_LDFLAGS = @POSIX_THREADS_LDFLAGS@ -RT_PREEMPT_THREADS_LDFLAGS = @RT_PREEMPT_THREADS_LDFLAGS@ -XENOMAI_THREADS_LDFLAGS = @XENOMAI_THREADS_LDFLAGS@ -RT_LDFLAGS = $($(THREADS)_THREADS_LDFLAGS) - -XENOMAI_THREADS_RTS=@XENOMAI_THREADS_RTS@ -XENOMAI_KERNEL_THREADS_RTS=@XENOMAI_KERNEL_THREADS_RTS@ -RTAI_KERNEL_THREADS_RTS=@RTAI_KERNEL_THREADS_RTS@ - -SHMDRV_KERNEL_DIRS = @SHMDRV_KERNEL_DIRS@ -KERNEL_DIRS = $($(THREADS)_THREADS_KERNEL_DIRS) - -XENOMAI_KERNEL_THREADS_EXTRA_SYMBOLS = @XENOMAI_KERNEL_THREADS_EXTRA_SYMBOLS@ -RTAI_KERNEL_THREADS_EXTRA_SYMBOLS = @RTAI_KERNEL_THREADS_EXTRA_SYMBOLS@ -KBUILD_EXTRA_SYMBOLS = $($(THREADS)_THREADS_EXTRA_SYMBOLS) \ - $(EMC2_RTLIB_DIR)/Module.symvers - -POSIX_THREADS_RTFLAGS = @POSIX_THREADS_RTFLAGS@ -RT_PREEMPT_THREADS_RTFLAGS = @RT_PREEMPT_THREADS_RTFLAGS@ -XENOMAI_THREADS_RTFLAGS = @XENOMAI_THREADS_RTFLAGS@ -THREADS_RTFLAGS = $($(THREADS)_THREADS_RTFLAGS) \ - -DTHREAD_FLAVOR_ID=$(THREAD_FLAVOR_ID) - -RTFLAGS := -I. $(THREADS_RTFLAGS) \ - -DRTAPI -D_GNU_SOURCE -D_FORTIFY_SOURCE=0 - -KERNEL_MATH_CFLAGS = $($(THREADS)_THREADS_KERNEL_MATH_CFLAGS) +RTFLAGS := -I. -DRTAPI -D_GNU_SOURCE -D_FORTIFY_SOURCE=0 $(THREADS_RTFLAGS) ULFLAGS = -D_GNU_SOURCE -DLOCALE_DIR=\"$(localedir)\" -DPACKAGE=\"$(package)\" -POSIX_THREADS_BUILD_SYS = @POSIX_THREADS_BUILD_SYS@ -RT_PREEMPT_THREADS_BUILD_SYS = @RT_PREEMPT_THREADS_BUILD_SYS@ -XENOMAI_THREADS_BUILD_SYS = @XENOMAI_THREADS_BUILD_SYS@ -BUILD_SYS = $($(THREADS)_THREADS_BUILD_SYS) - -MODULE_EXT = .so - CC = @CC@ CC_FOR_BUILD = @CC_FOR_BUILD@ OBJCOPY = @OBJCOPY@ @@ -151,11 +91,6 @@ YAPPS2 = @YAPPS2@ MANDB = @MANDB@ HIDRAW_H_USABLE = @HIDRAW_H_USABLE@ -POSIX_THREADS_SOURCE = @POSIX_THREADS_SOURCE@ -RT_PREEMPT_THREADS_SOURCE = @RT_PREEMPT_THREADS_SOURCE@ -XENOMAI_THREADS_SOURCE = @XENOMAI_THREADS_SOURCE@ -THREADS_SOURCE = $($(THREADS)_THREADS_SOURCE) - BUILD_DRIVERS = @BUILD_DRIVERS@ USE_PORTABLE_PARPORT_IO = @USE_PORTABLE_PARPORT_IO@ TARGET_PLATFORM_PC = @TARGET_PLATFORM_PC@ @@ -169,8 +104,6 @@ TARGET_PLATFORM_H3 = @TARGET_PLATFORM_H3@ HARDY_AMD64_WORKAROUND=@HARDY_AMD64_WORKAROUND@ PRECISE_MULTILIB_BUG=@PRECISE_MULTILIB_BUG@ -USERMODE_PCI=@USERMODE_PCI@ - # example programs BUILD_EXAMPLES=@BUILD_EXAMPLES@ @@ -186,9 +119,6 @@ BUILD_DEV=@BUILD_DEV@ # enable not-yet-ported NML parts BUILD_NMLDEP=@BUILD_NMLDEP@ -# shared memory kernel driver -USE_SHMDRV=@USE_SHMDRV@ - # example programs BUILD_EXAMPLES=@BUILD_EXAMPLES@ @@ -240,7 +170,7 @@ USE_UUID=@USE_UUID@ LIBBACKTRACE = @LIBBACKTRACE@ -#libudev for if USERMODE_PCI==yes +#libudev LIBUDEV_CFLAGS=@LIBUDEV_CFLAGS@ LIBUDEV_LIBS=@LIBUDEV_LIBS@ @@ -316,7 +246,7 @@ LTTNG_UST_CFLAGS = @LTTNG_UST_CFLAGS@ # To disable compilation of any particular module, # edit the following lines replacing "m" with "n". -ifeq ($(TARGET_PLATFORM_PC),yes) +ifeq ($(HAS_SYS_IO),yes) CONFIG_PLATFORM_PC=m else CONFIG_PLATFORM_PC=n @@ -366,21 +296,21 @@ CONFIG_RINGLOAD=m # HAL drivers CONFIG_UPARPORT=m -CONFIG_HAL_PARPORT=$(CONFIG_PLATFORM_PC) +CONFIG_HAL_PARPORT=m CONFIG_PROBE_PARPORT=m -CONFIG_HAL_TIRO=$(CONFIG_PLATFORM_PC) +CONFIG_HAL_TIRO=m CONFIG_HAL_EVOREG=m CONFIG_HAL_MOTENC=m -CONFIG_HAL_SKELETON=$(CONFIG_PLATFORM_PC) +CONFIG_HAL_SKELETON=m CONFIG_HAL_GPIO=m CONFIG_HM2_SOC_OL=m CONFIG_HAL_SPI=m -CONFIG_HAL_SPEAKER=$(CONFIG_PLATFORM_PC) -CONFIG_HAL_STG=$(CONFIG_PLATFORM_PC) +CONFIG_HAL_SPEAKER=m +CONFIG_HAL_STG=m CONFIG_HAL_VTI=m -CONFIG_HAL_AX521H=$(CONFIG_PLATFORM_PC) +CONFIG_HAL_AX521H=m CONFIG_HAL_PPMC=m -CONFIG_PCI_8255=$(CONFIG_PLATFORM_PC) +CONFIG_PCI_8255=m CONFIG_HOSTMOT2=m CONFIG_OPTO_AC5=m CONFIG_HAL_GM=m @@ -401,4 +331,3 @@ BOOST_THREAD_LIB=@BOOST_THREAD_LIB@ BOOST_SYSTEM_LIB=@BOOST_SYSTEM_LIB@ #### END CONFIG #### - diff --git a/src/Makefile.modinc.in b/src/Makefile.modinc.in index bd05553408..1e1cf4e46c 100644 --- a/src/Makefile.modinc.in +++ b/src/Makefile.modinc.in @@ -13,13 +13,13 @@ # An example Makefile using Makefile.modinc to build one kernel module from a # single source file would read: -# +# # obj-m += example.o # include .../Makefile.modinc # An example Makefile using Makefile.modinc to build one kernel module from # several source files would read: -# +# # obj-m += complex.o # complex-objs := complex1.o complex2.o complex_main.o # include .../Makefile.modinc @@ -80,7 +80,7 @@ EXTRA_CFLAGS := $(RTFLAGS) $(EXTRA_RTFLAGS) \ ifeq ($(RUN_IN_PLACE),yes) EXTRA_CFLAGS += -I$(EMC2_HOME)/include -RTLIBDIR := $(EMC2_HOME)/rtlib/$(RTDIR_EXT) +RTLIBDIR := $(EMC2_HOME)/rtlib/modules LIBDIR := $(EMC2_HOME)/lib else EXTRA_CFLAGS += -I$(includedir)/linuxcnc diff --git a/src/README.config-changes b/src/README.config-changes index 5e7b3e3766..cc4b0a3838 100644 --- a/src/README.config-changes +++ b/src/README.config-changes @@ -64,7 +64,8 @@ arise during merge, also with the consequence of an even more incoherent set of Build system: there are two styles, 'kbuild' (kernel modules) and 'user-dso' (userland shared objects). The thread style implies a build system: posix, xenomai, rt-preempt imply 'user-dso', the others imply 'kbuild'. -Building hardware drivers can be controlled with --enable-drivers. It is default 'yes' except for --with-threads=posix. Some hardware drivers will build as kernel modules only, some as user shared objects, some may build as both; in that case the Submakefile needs to test for BUILD_SYS having the proper value. +Building hardware drivers can be controlled with --enable-drivers. It +is default 'yes'. The cpp symbols 'SIM', 'SIMULATOR', and 'RTAPI_SIM' have been removed as they do not make sense any more. A simulator configuration is '--with-threads=posix', which is now implied by --enable-simulator. @@ -74,8 +75,6 @@ THREADS= one of: POSIX, RT_PREEMPT, XENOMAI, XENOMAI_KERNEL, RTAI BUILD_DRIVERS=yes or no -BUILD_SYSTEM=kbuild or user-dso - THREADS is reflected in config.h as one of the following defined: @@ -93,13 +92,6 @@ RTAPI_RTAI BUILD_DRIVERS is conditionally defined in config.h too. - -BUILD_SYSTEM is reflected in config.h as either - -BUILD_SYSTEM_KBUILD or - -BUILD_SYSTEM_USER_DSO defined. - == hal_parport == The experimental usermode parport driver from master: src/hal/simdrivers has been integrated into the main hal_parport.c/.h code using conditionals from above. diff --git a/src/configure.ac b/src/configure.ac index cb32067c78..837c6a6f61 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -25,7 +25,6 @@ AC_PREREQ(2.53) AC_INIT([LinuxCNC],[m4_normalize(esyscmd(cat ../VERSION))],[emc-developers@lists.sourceforge.net]) -#AC_CONFIG_SRCDIR(emc/motion/motion.c) if test "$srcdir" != "."; then AC_MSG_ERROR([Building outside of srcdir is not supported]) fi @@ -118,177 +117,14 @@ AC_CONFIG_MACRO_DIR(/usr/share/aclocal) ############################################################################## # Section 2 # # RealTime checking # -# Subsection 2.1 - init basic thread style params and declare m4 macros # # Subsection 2.2 - documentation of threads variables to be configured # -# Subsection 2.3 - misc basic features: platform, shmdrv, parport I/O, etc. # +# Subsection 2.3 - misc basic features: platform, parport I/O, etc. # # Subsection 2.4 - kernel detection and RT capability probing # # Subsection 2.5 - thread style configuration # # Subsection 2.6 - userland PCI driver configuration # # Subsection 2.7 - pass configuration into config.h, Makefile.inc.in, etc. # ############################################################################## -############################################################################## -# Subsection 2.1 # -# init basic thread style params # -# - the [_cfg_flavor_params] m4 macro lists all flavors # -# - for each flavor, lists name, flavor_id, build_sys and threads_source # -# # -# define several m4 macros to help manipulate the list # -############################################################################## - - -dnl #--------------------------------------------------------# -dnl # list of all thread styles with FLAVOR_ID and BUILD_SYS # -dnl # # -dnl # each thread style needs a 4-item m4 tuple set here: # -dnl # flavor-name, flavor-id, build-sys, threads-headers # -dnl # # -dnl # flavor-name: lower-case with hyphens # -dnl # flavor-id: a unique integer # -dnl # build-sys: one of kbuild or user-dso # -dnl # threads-headers: header file from rtapi/*.h (w/o '.h') # -dnl # mod_ext: RTAPI module extension, .so or .ko # -dnl # so_ext: ULAPI module extension, .so # -dnl # flags: see rtapi.h; combine with '|' operator, or 0 # -dnl # extra_kmods: list of extra kmodules to load # -dnl # # -dnl # these are used in both Makefiles and in config.h, # -dnl # and are the single authoritative source for these data # -dnl #--------------------------------------------------------# -AC_DEFUN([_cfg_flavor_params], - [[[posix],[0],[user-dso],[rt-preempt],[.so],[.so],[0]], - [[rt-preempt],[1],[user-dso],[rt-preempt],[.so],[.so],[0]], - [[xenomai],[2],[user-dso],[xenomai],[.so],[.so],[FLAVOR_DOES_IO]], - [[xenomai-kernel],[3],[kbuild],[xenomai-kernel],[.ko],[.so],dnl -[FLAVOR_DOES_IO|FLAVOR_KERNEL_BUILD],[rtapi_math]], - [[rtai-kernel],[4],[kbuild],[rtai-kernel],[.ko],[.so],dnl -[FLAVOR_DOES_IO|FLAVOR_KERNEL_BUILD],dnl -[rtai_hal rtai_sched rtapi_math]]]) - - -dnl #--------------------------------------------------------# -dnl # m4 convenience macros for accessing above data # - -dnl list of all thread styles to be used in macros -dnl posix,rt-preempt,xenomai,xenomai-kernel,rtai -AC_DEFUN([_cfg_all_flavors], - m4_map_sep([m4_car],[[,]],[_cfg_flavor_params])) - -dnl _cfg_flavor_id(flavor): return THREAD_FLAVOR_ID -dnl _cfg_flavor_id(xenomai) => 2; _cfg_flavor_id(rtai) => 4 -AC_DEFUN([_cfg_flavor_tuple_id],[$2]) -AC_DEFUN([_cfg_flavor_id], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_id],[flav]))])]) - -dnl _cfg_flavor_build_sys(flavor): return BUILD_SYS: kbuild or user-dso -dnl for use in Makefiles -dnl _cfg_flavor_build_sys(xenomai) => user-dso; -dnl _cfg_flavor_build_sys(xenomai-kernel) => kbuild; -AC_DEFUN([_cfg_flavor_tuple_build_sys],[$3]) -AC_DEFUN([_cfg_flavor_build_sys], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_build_sys],[flav]))])]) - -dnl _cfg_flavor_threads_headers(flavor): return THREADS_HEADERS -dnl for use in config.h -dnl _cfg_flavor_threads_headers(xenomai) => rtapi/xenomai.h; -dnl _cfg_flavor_threads_headers(posix) => rtapi/rt-preempt.h; -AC_DEFUN([_cfg_flavor_tuple_threads_headers],[$4]) -AC_DEFUN([_cfg_flavor_threads_headers], - rtapi/[m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_threads_headers],[flav]))])].h) - -dnl _cfg_flavor_mod_ext(flavor): return RT module extension: .ko or .so -dnl for use in rtapi.ini -dnl _cfg_flavor_mod_ext(xenomai) => .so; -dnl _cfg_flavor_mod_ext(xenomai-kernel) => .ko; -AC_DEFUN([_cfg_flavor_tuple_mod_ext],[$5]) -AC_DEFUN([_cfg_flavor_mod_ext], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_mod_ext],[flav]))])]) - -dnl _cfg_flavor_so_ext(flavor): return plugin filename extension: .so -dnl for use in rtapi.ini -dnl _cfg_flavor_so_ext(xenomai) => .so -AC_DEFUN([_cfg_flavor_tuple_so_ext],[$6]) -AC_DEFUN([_cfg_flavor_so_ext], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_so_ext],[flav]))])]) - -dnl _cfg_flavor_flags(flavor): flavor flags: integer expression -dnl for use in rtapi.ini -dnl _cfg_flavor_flags(rt-preempt) => 0 -dnl _cfg_flavor_flags(xenomai) => FLAVOR_DOES_IO -dnl _cfg_flavor_flags(xenomai-kernel) => FLAVOR_DOES_IO|FLAVOR_KERNEL_BUILD -AC_DEFUN([_cfg_flavor_tuple_flags],[$7]) -AC_DEFUN([_cfg_flavor_flags], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_flags],[flav]))])]) - -dnl _cfg_flavor_extra_kmods(flavor): extra kernel modules to load for kthreads -dnl for use in rtapi.ini -dnl _cfg_flavor_extra_kmods(xenomai-kernel) => rtapi_math -AC_DEFUN([_cfg_flavor_tuple_extra_kmods],[$8]) -AC_DEFUN([_cfg_flavor_extra_kmods], - [m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(m4_car(flav),$1, - m4_apply([_cfg_flavor_tuple_extra_kmods],[flav]))])]) - -dnl _cfg_flavor_upcase(flavor): return uppercase, and dashes->underscores -dnl used to generate C preprocessor macro names -dnl _cfg_flavor_ucase(xenomai-kernel) => XENOMAI_KERNEL -AC_DEFUN([_cfg_flavor_upcase],[m4_translit([$*],[a-z-],[A-Z_])]) - -dnl _cfg_flavor_underscored(flavor): return dashes->underscores -dnl used to generate e.g. $with_xenomai_kernel -AC_DEFUN([_cfg_flavor_underscored],[m4_translit([$*],[-],[_])]) - -dnl _cfg_flavor_BUILD_SYS(flavor): return BUILD_SYS_{KBUILD,USER_DSO} -dnl for use in config.h -dnl _cfg_flavor_BUILD_SYS(xenomai) => BUILD_SYS_USER_DSO; -dnl _cfg_flavor_BUILD_SYS(xenomai-kernel) => BUILD_SYS_KBUILD; -AC_DEFUN([_cfg_flavor_BUILD_SYS], - [BUILD_SYS_[]_cfg_flavor_upcase(_cfg_flavor_build_sys($1))]) - -dnl _cfg_kbuild_flavors: list of kbuild RT thread flavors -AC_DEFUN([_cfg_flavor_tuple_name],[$1]) -m4_foreach([flav],[_cfg_flavor_params], - [m4_cond(_cfg_flavor_build_sys(flav),[kbuild], - [m4_append_uniq([_cfg_tmp],_cfg_flavor_tuple_name(flav),[[ ]])] -)]) - -dnl _cfg_kbuild_flavors => xenomai-kernel,rtai -AC_DEFUN([_cfg_kbuild_flavors],m4_split(_cfg_tmp)) - - -#--------------------------------------------------------# -# Universal build variables and macros -# -# new thread systems introduced here: -# http://wiki.linuxcnc.org/cgi-bin/wiki.pl?RealtimeConfiguratonProposal -# -# at the shell script/makefile level, we have: -# -# $(threads) - one of 'rtai-kernel', 'posix', 'xenomai', 'xenomai-kernel', -# 'rt-preempt' in shell/Makefile -# -# the Makefile will run '$(MAKE) threads= modules' once for -# each flavor configured here. -# -# This is used to generate the upper-case, underscored $(THREADS), -# which is e.g. POSIX or RTAI_KERNEL. -# -# $(THREADS) in turn is used to select the correct configuration -# variables out of Makefile.inc. For example, THREADS_RTFLAGS is set -# to RT_PREEMPT_THREADS_RTFLAGS for the rt-preempt flavor. - ############################################################################## # Subsection 2.2 # @@ -303,12 +139,6 @@ AC_DEFUN([_cfg_kbuild_flavors],m4_split(_cfg_tmp)) # RT system Makefile variables defined by configure: # -# BUILD_THREAD_FLAVORS -# -# a list of all configured threads systems to build; the complete -# possible list is 'posix rt-preempt xenomai xenomai-kernel -# rtai-kernel' -# # _THREADS_RTS # # a script like /usr/realtime/foo-config, which can be used to extract @@ -319,67 +149,20 @@ AC_DEFUN([_cfg_kbuild_flavors],m4_split(_cfg_tmp)) # 'yes' or 'no' depending on whether the thread system was able to be # configured # -# _THREADS_FLAVOR_ID -# -# 0..4, depending on the _cfg_flavor_params macro defined earlier; -# this is used in config.h to set flavor-specific macros, and set in -# cflags for any compile that #includes config.h -# -# _THREADS_BUILD_SYS -# -# 'kbuild' for kernel threads, 'user-dso' for user threads +# THREADS_RTFLAGS # -# _THREADS_SOURCE -# -# the basename of the flavor's file in src/rtapi; this is usually the -# name of the flavor, except in the case of posix threads, which use -# the rt-preempt sources -# -# _THREADS_RTFLAGS -# -# list of CFLAGS specific to the threads system; some flavors +# list of CFLAGS specific to threads systems; some flavors # determine this with _THREADS_RTS --cflags # -# _THREADS_LDFLAGS +# THREADS_LDFLAGS # # list of LDFLAGS specific to the threads system; also obtained partly # from _THREADS_RTS --ldflags # -# _THREADS_KERNEL_DIRS -# -# for kbuild flavors only (currently); list of directory paths for the -# flavor's configured kernel source trees -# -# paths may be explicitly set on the ./configure command line using -# '--with-xenomai-kernel-sources' or '--with-rtai-kernel-sources' -# -# otherwise kernel sources are automatically detected from standard -# locations, which may be extended using '--with-extra-kernel-sources' -# -# SHMDRV_KERNEL_DIRS -# -# similar to above, a list of directory paths for which to build the -# shmdrv.ko module -# -# as above, paths may be set using '--with-shmdrv-kernel-sources' -# -# --enable-shmdrv builds shmdrv.ko for all configured kernels, -# regardless of whether other kthreads modules will be built; -# shmdrv.ko is always built for kthreads modules -# -# _THREADS_EXTRA_SYMBOLS -# # path name to a Module.symvers file needed by kbuild # -# _THREADS_KERNEL_MATH_CFLAGS -# # math-related CFLAGS used in RTAPI compiles; partly obtained by # _THREADS_RTS -# -# RTAI_KERNEL_THREADS_RTDIR -# -# RTAI only; the directory RTAI modules are contained in, such as -# /usr/realtime/modules, obtained by RTAI_KERNEL_THREADS_RTS --prefix #--------------------------------------------------------# # config.h macros # @@ -390,34 +173,6 @@ AC_DEFUN([_cfg_kbuild_flavors],m4_split(_cfg_tmp)) # # flavor macros from config.h, set appropriately for each '$(MAKE) # threads= modules' run: -# -# RTAPI_ -# -# for example '#ifdef RTAPI_RTAI_KERNEL' to test if the current flavor -# being built is rtai-kernel - -# THREAD_FLAVOR_NAME -# -# the name of the current flavor, quoted, e.g. "posix" or "rt-preempt" - -# BUILD_SYS_USER_DSO or BUILD_SYS_KBUILD -# -# The former will be defined for userland threads, the latter for -# kernel threads -# -# THREADS_HEADERS -# -# Used by the rtapi system to #include the correct headers for the -# flavor currently being built, e.g. "rtapi/xenomai.h" - -# RTAPI__ID -# -# Always present for all flavors. Equal to -# _THREADS_FLAVOR_ID. - -# RTAPI__NAME -# -# Always present for all flavors. Equal to $(threads) # GIT_VERSION # @@ -445,26 +200,10 @@ AC_DEFUN([_cfg_kbuild_flavors],m4_split(_cfg_tmp)) # ./configure will attempt to configure driver building unless # explicitly disabled with '--disable-drivers'. # -# To reduce the surprise factor of a simulator config suddenly talking -# to ports, drivers will be disabled by default for posix threads and -# enabled for others in rtapi.ini. -# # reflected in config.h as follows: # /* build hardware drivers */ # #define BUILD_DRIVERS /**/ # -# -KSOURCE_LOCATION_HINTS=$(echo \ - /usr/src/kernels/* \ - /usr/src/linux-headers-* \ - /lib/modules/*/build \ - ) -# -# Places to look for Xeno and RTAI kernel headers -# -# RedHat-derivatives: (/usr/src/kernels/`uname -r`), -# Debian-derivatives: (/usr/src/linux-headers-`uname -r`) -# Vanilla kernel install: (/lib/modules/`uname -r`/build) # USE_PORTABLE_PARPORT_IO="no" @@ -523,6 +262,22 @@ cmdl_enab_msg="enabled on command line" cmdl_disab_msg="disabled on command line" cmdl_notspec_msg="not specified on command line" +AS_CASE([$host_cpu], + [arm64], + [ + HAS_SYS_IO=no + ], + [aarch64], + [ + HAS_SYS_IO=no + ], + [*], + [ + HAS_SYS_IO=yes + AC_DEFINE([SYS_IO_DEFINED], [1], + [The sys/io header exists.]) + ]) + AC_ARG_WITH(platform-pc, [AS_HELP_STRING( [--with-platform-pc], @@ -543,15 +298,14 @@ AC_ARG_WITH(platform-pc, [ case $host_cpu in (x86_64) - TARGET_PLATFORM_PC=unk - ARCH_CFLAGS="-m64" + ARCH_CFLAGS="-m64" + TARGET_PLATFORM_PC=unk ;; (i?86) - ARCH_CFLAGS="-m32" - TARGET_PLATFORM_PC=unk + ARCH_CFLAGS="-m32" + TARGET_PLATFORM_PC=unk ;; - (*) TARGET_PLATFORM_PC=false platform_pc_reason="$arch_disab_msg" @@ -805,6 +559,7 @@ else fi fi + # Print messages about what platforms are to be enabled or disabled AC_MSG_CHECKING(platform-pc) AC_MSG_RESULT([$platform_pc_reason]) @@ -901,29 +656,6 @@ AC_ARG_ENABLE(proto-js, ]) -AC_MSG_CHECKING(whether to use the common shared memory driver) -AC_ARG_ENABLE(shmdrv, - [ --enable-shmdrv use the common shared memory driver kernel module], - [ - case "$enableval" in - Y*|y*) - USE_SHMDRV=yes - AC_MSG_RESULT([explicitly configuring for common shared memory driver kernel module]) - ;; - N*|n*) - USE_SHMDRV=no - AC_MSG_RESULT([explicitly disabling shared memory driver kernel module]) - ;; - esac - if test -z "USE_SHMDRV"; then - AC_MSG_ERROR([ I dont understand $enableval, just yes or no ]) - fi - ], - [ - USE_SHMDRV=no - AC_MSG_RESULT([default is no]) - ]) - AC_MSG_CHECKING(whether to use inb/outb or ppdev ioctl on the x86 for parport I/O) AC_ARG_ENABLE(portable-parport, [ --enable-portable-parport Build hal_parport using the ppdev ioctl instead of inb/outb], @@ -984,6 +716,11 @@ PKG_CHECK_MODULES( [true], dnl libck is optional ) +PKG_CHECK_MODULES([ZMQ], [libzmq], + [ + AC_DEFINE(HAVE_ZMQ, [], [zeroMQ library available]) + USE_ZMQ=yes + ],) PKG_CHECK_MODULES([CZMQ], [libczmq > 4.0], [ @@ -1097,264 +834,6 @@ AC_PYTHON_MODULE(pyftpdlib.servers, failed to import pyftpdlib.servers - python-pyftpdlib package missing or too old? ) -############################################################################## -# Subsection 2.4 # -# Kernel detection # -# Find all kernels on system and assess realtime capabilities # -############################################################################## - -check_kernel_source_configured() { - # Check if a path is a configured kernel source - local ksrc_dir=${1} - if test -z "$ksrc_dir"; then - AC_MSG_ERROR([check_kernel_source_configured() given empty ksrc_dir]) - fi - - AC_MSG_CHECKING([for configured kernel source in $ksrc_dir]) - # if .config and version.h both exist, then assume it's configured - if test -f "$ksrc_dir/.config" -a \ - \( -f "$ksrc_dir/include/linux/version.h" -o \ - -f "$ksrc_dir/include/generated/uapi/linux/version.h" \); then - AC_MSG_RESULT([found]) - return 0 - else - AC_MSG_RESULT([not found]) - return 1 - fi -} - -check_kernel_source_version() { - # get kernel version from version.h; set variable KVER - # assume check_source_configured() already done - - # Unfortunately, many distributions (redhat, mandrake) have - # #defines inside version.h, so a simple cat|grep|cut test won't - # work... But then again, RH & Mandrake kernels are notorious for - # their use of patches that break the RT patching - Both RTAI and - # RTLinux strongly recommend using a virgin source from - # kernel.org. - - local ksrc_dir=${1} - if test -z "$ksrc_dir"; then - AC_MSG_ERROR([check_kernel_source_version() given empty ksrc_dir]) - fi - - # Get the kernel version from version.h - AC_MSG_CHECKING([kernel version string in $ksrc_dir]) - - if test -e $ksrc_dir/include/linux/utsrelease.h; then - VERSION_FILE=$ksrc_dir/include/linux/utsrelease.h - elif test -e $ksrc_dir/include/generated/utsrelease.h; then - VERSION_FILE=$ksrc_dir/include/generated/utsrelease.h - else - VERSION_FILE=$ksrc_dir/include/linux/version.h - fi - KVER=`$CC -E -dM ${VERSION_FILE} | grep UTS | cut -d '"' -f 2` - - if test -z "$KVER"; then - AC_MSG_RESULT([not found]) - else - AC_MSG_RESULT([$KVER]) - fi -} - -check_xenomai_kernel_source() { - # check if kernel source is a xenomai kernel source - # assume check_source_configured() already done - - local ksrc_dir=${1} - if test -z "$ksrc_dir"; then - AC_MSG_ERROR([check_xenomai_kernel_source() given empty ksrc_dir]) - fi - - # look for CONFIG_XENOMAI variable - AC_MSG_CHECKING(if $ksrc_dir is a xenomai kernel) - if test -f "$ksrc_dir/.config" && \ - grep -q '^CONFIG_XENOMAI=' "$ksrc_dir/.config"; then - AC_MSG_RESULT([yes]) - return 0 - else - AC_MSG_RESULT([no]) - return 1 - fi - -} - -check_rtai_kernel_source() { - # check if kernel source is an rtai kernel source - # assume check_source_configured() already done - - local ksrc_dir=${1} - if test -z "$ksrc_dir"; then - AC_MSG_ERROR([check_rtai_kernel_source() given empty ksrc_dir]) - fi - - - # look for rt_daemonize (older RTAI) or rtai_irq_handler (at least - # RTAI 4.0) or rtai_syscall_hook (RTAI 4.1) function definition - AC_MSG_CHECKING(if $ksrc_dir is an RTAI kernel) - if test -f "$ksrc_dir/Module.symvers" && \ - grep -q '\(rt_daemonize\|rtai_irq_handler\|rtai_syscall_hook\)' \ - "$ksrc_dir/Module.symvers"; then - AC_MSG_RESULT([yes]) - return 0 - else - AC_MSG_RESULT([no]) - return 1 - fi - -} - -# xenomai kernel modules will be built for these kernels if -# xenomai-kernel threads are enabled -xenomai_kernels='' -# RTAI kernel modules will be built for these kernels if -# rtai-kernel threads are enabled -rtai_kernels='' -# shmdrv kernel modules will be built for these kernels if -# shmdrv and at least one userspace threads are enabled -shmdrv_kernels='' -# -# list of kernel sources seen, so we don't check the same ones repeatedly -seen_kernels=' ' -# ...and a function to check and add new -kernel_seen() { - if test "${seen_kernels/ $1 /}" = "$seen_kernels"; then - # not seen - seen_kernels="$seen_kernels $1 " - return 1 - else - # seen - return 0 - fi -} - -# check any xenomai sources specified on command line now -# if any found, only build xenomai modules for these kernels -AC_ARG_WITH(xenomai-kernel-sources, - [AS_HELP_STRING([--with-xenomai-kernel-sources=" ..."], - [directory paths of xenomai kernel source(s), space-separated])], - [# check directories now - if test $with_xenomai_kernel_sources = no; then - # ignore this - with_xenomai_kernel_sources='' - else - for ksrc_dir in $with_xenomai_kernel_sources; do - ksrc_dir=$(readlink -f $ksrc_dir) - # add only configured, confirmed Xenomai sources - if check_kernel_source_configured $ksrc_dir && \ - check_xenomai_kernel_source $ksrc_dir; then - shmdrv_kernels="shmdrv_kernels $ksrc_dir" - xenomai_kernels="$xenomai_kernels $ksrc_dir" - # note this one's been seen - kernel_seen $ksrc_dir - else - AC_MSG_ERROR([invalid xenomai kernel source: $ksrc_dir]) - fi - done - fi - ], - [with_xenomai_kernel_sources='']) - -# check any RTAI sources specified on command line now -# if any found, only build RTAI modules for these kernels -AC_ARG_WITH(rtai-kernel-sources, - [AS_HELP_STRING([--with-rtai-kernel-sources=" ..."], - [directory paths of RTAI kernel source(s), space-separated])], - [# check directories now - if test $with_rtai_kernel_sources = no; then - # ignore this - with_rtai_kernel_sources='' - else - for ksrc_dir in $with_rtai_kernel_sources; do - ksrc_dir=$(readlink -f $ksrc_dir) - # add only configured, confirmed RTAI sources - if check_kernel_source_configured $ksrc_dir && \ - check_rtai_kernel_source $ksrc_dir; then - shmdrv_kernels="$shmdrv_kernels $ksrc_dir" - rtai_kernels="$rtai_kernels $ksrc_dir" - # note this one's been seen - kernel_seen $ksrc_dir - else - AC_MSG_ERROR([invalid RTAI kernel source: $ksrc_dir]) - fi - done - fi - ], - [with_rtai_kernel_sources='']) - -# check any shmdrv sources specified on command line now -# if any found, build shmdrv modules for these kernels -AC_ARG_WITH(shmdrv-kernel-sources, - [AS_HELP_STRING([--with-shmdrv-kernel-sources=" ..."], - [directory paths of kernel source(s) to build shmdrv module for])], - [# check directories now - if test $with_shmdrv_kernel_sources = no; then - # ignore --without-shmdrv-kernel-sources - with_shmdrv_kernel_sources='' - else - for ksrc_dir in $with_shmdrv_kernel_sources; do - ksrc_dir=$(readlink -f $ksrc_dir) - # add only new, configured sources - if ! kernel_seen $ksrc_dir && \ - check_kernel_source_configured $ksrc_dir; then - shmdrv_kernels="$shmdrv_kernels $ksrc_dir" - else - AC_MSG_ERROR([invalid kernel source: $ksrc_dir]) - fi - done - fi - ], - [with_shmdrv_kernel_sources='']) - -AC_ARG_WITH(extra_kernel_sources, - [AS_HELP_STRING( - [--with-extra-kernel-sources=" ..."], - [list of extra kernel source directories to search])], - [KSOURCE_LOCATION_HINTS="$KSOURCE_LOCATION_HINTS - $with_extra_kernel_sources"]) - - -find_kernels() { - # find all kernel directories from hints if not told on cmdline - # check kernel source is a valid, configured tree - # add all valid trees to $shmdrv_kernels - # add all valid xenomai and rtai trees to $xenomai_kernels and - # $rtai_kernels, respectively - location_list='' - for location in $KSOURCE_LOCATION_HINTS; do - location=$(readlink -f $location) - - # be sure $location is a directory not already in the list - test -d "$location" || continue - test "${location_list/$location/}" = "${location_list}" || continue - - # if kernel source has been seen, ignore it - kernel_seen $location && continue - - # if kernel source unconfigured, ignore it - check_kernel_source_configured $location || continue - - # if --with-shmdrv-kernel-sources not explicitly on cmdline, add it - test -z "$with_shmdrv_kernel_sources" && \ - shmdrv_kernels="$shmdrv_kernels $location" - # if --with-xenomai-kernel-sources not explicitly on cmdline - # and xenomai kernel detected, add it - test -z "$with_xenomai_kernel_sources" && \ - check_xenomai_kernel_source $location && \ - xenomai_kernels="$xenomai_kernels $location" - # if --with-rtai-kernel-sources not explicitly on cmdline and - # RTAI kernel detected, add it - test -z "$with_rtai_kernel_sources" && \ - check_rtai_kernel_source $location && \ - rtai_kernels="$rtai_kernels $location" - done -} - - -find_kernels - - ############################################################################## # Subsection 2.5 # # Flavor configuration # @@ -1362,26 +841,7 @@ find_kernels # - Sanity checks and configuration generation # ############################################################################## -# By default, build all flavors. If a --with- arg is found, -# do not build all by default. -all_flavors_default=yes - -# Set to 'yes' when either xenomai or rt-preempt will be built -with_userland_rt_threads=no - AC_PRESERVE_HELP_ORDER() -AC_ARG_WITH(posix, - [AS_HELP_STRING([--with-posix], - [build POSIX (simulator) non-realtime threads modules - (enabled by default)])], - [test $withval = yes && all_flavors_default=no], - [with_posix=check]) - -AC_ARG_WITH(rt-preempt, - [AS_HELP_STRING([--with-rt-preempt], - [build RT_PREEMPT threads modules])], - [test $withval = yes && all_flavors_default=no], - [with_rt_preempt=check]) AC_ARG_WITH(xenomai, [AS_HELP_STRING([--with-xenomai], @@ -1390,101 +850,7 @@ AC_ARG_WITH(xenomai, test $withval = yes && all_flavors_default=no], [with_xenomai=check]) -AC_ARG_WITH(xenomai-kernel, - [AS_HELP_STRING([--with-xenomai-kernel], - [build Xenomai kernel-space realtime threads (deprecated)])], - [xenomai_kernel_from_cmdline=$withval - test $withval = yes && all_flavors_default=no], - [with_xenomai_kernel=check]) -# XENOMAI_THREADS_RTS: locate the 'xeno-config' executable -AC_ARG_WITH(xeno-config, - [AS_HELP_STRING([--with-xeno-config=], - [location of the xeno-config executable])], - [xeno_config_from_cmdline=yes], - [ - with_xenomai_config="" - ]) - -AC_ARG_WITH(rtai-kernel, - [AS_HELP_STRING([--with-rtai-kernel], - [build RTAI kernel-space realtime threads modules])], - [test $withval = yes && all_flavors_default=no], - [with_rtai_kernel=check]) -# RTAI_KERNEL_THREADS_RTS: locate the 'rtai-config' executable -AC_ARG_WITH(rtai-config, - [AS_HELP_STRING([--with-rtai-config=], - [location of the rtai-config executable])], - [rtai_config_from_cmdline=yes], - [ - with_rtai_config="" - ]) - - -# If a --with- flag was found, disable all flavors not -# explicitly enabled -if test $all_flavors_default = no; then - for f in posix rt_preempt xenomai xenomai_kernel rtai_kernel; do - if eval "test \$with_$f = check"; then - eval "with_$f=no" - fi - done -fi - - -############################################################################## -# POSIX and RT_PREEMPT flavor checks -if test "$with_rt_preempt" != no -o "$with_posix" != no; then - LIBS_hold=$LIBS - LIBS="$LIBS -lrt" - - AC_MSG_CHECKING(-lrt for RT_PREEMPT and POSIX) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include - #include - #include - ]], - [[ - struct timespec t; - clock_gettime(CLOCK_MONOTONIC ,&t); - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t, NULL); - ]])], - [ - have_librt=yes - AC_MSG_RESULT(ok)], - [ - have_librt=no - AC_MSG_RESULT(failed) - ]) - LIBS=$LIBS_hold -fi - -AC_MSG_CHECKING(whether to build POSIX threads) -test "$with_posix" = check && with_posix=yes -test "$have_librt" = no && with_posix=no -AC_MSG_RESULT($with_posix) -if test "$with_posix" = yes; then - POSIX_THREADS_LDFLAGS="-lpthread -lrt $LIBCGROUP_LIBS" - POSIX_THREADS_RTFLAGS="$POSIX_THREADS_RTFLAGS -pthread $LIBCGROUP_CFLAGS" - BUILD_THREAD_FLAVORS="$BUILD_THREAD_FLAVORS posix" -fi - -AC_MSG_CHECKING(whether to build RT_PREEMPT threads) -test "$with_rt_preempt" = check && with_rt_preempt=yes -test "$have_librt" = no && with_rt_preempt=no -AC_MSG_RESULT($with_rt_preempt) -if test "$with_rt_preempt" = yes; then - RT_PREEMPT_THREADS_LDFLAGS="-lpthread -lrt $LIBCGROUP_LIBS" - RT_PREEMPT_THREADS_RTFLAGS="$RT_PREEMPT_THREADS_RTFLAGS -pthread" - RT_PREEMPT_THREADS_RTFLAGS="$RT_PREEMPT_THREADS_RTFLAGS $LIBCGROUP_CFLAGS" - BUILD_THREAD_FLAVORS="$BUILD_THREAD_FLAVORS rt-preempt" - with_userland_rt_threads=yes -fi - - -############################################################################## -# Xenomai flavor checks, both userland and kthreads - -if test "$with_xenomai" != no -o "$with_xenomai_kernel" != no; then +if test "$with_xenomai" != no; then # XENOMAI_THREADS_RTS: look for the xeno-config executable XENOMAI_THREADS_RTS='' if test "$xeno_config_from_cmdline" = yes; then @@ -1534,14 +900,10 @@ if test "$with_xenomai" != no -o "$with_xenomai_kernel" != no; then with_xenomai=no fi fi - if test -x "$XENOMAI_THREADS_RTS"; then - # found xeno-config; use same one for kernel threads for consistency - XENOMAI_KERNEL_THREADS_RTS="$XENOMAI_THREADS_RTS" - fi fi if test -n "$XENOMAI_THREADS_RTS"; then - # XENOMAI_THREADS_RTFLAGS: test runtime library & get flags + # XENOMAI_RTFLAGS: test runtime library & get flags LIBS_hold="$LIBS" CFLAGS_hold="$CFLAGS" CPPFLAGS_hold="$CPPFLAGS" @@ -1558,7 +920,7 @@ if test -n "$XENOMAI_THREADS_RTS"; then CPPFLAGS="$CPPFLAGS_hold" fi -if test "$with_xenomai" != no -o "$with_xenomai_kernel" != no; then +if test "$with_xenomai" != no; then flags="$($XENOMAI_THREADS_RTS --cflags)" # Xenomai docs recommend turning off CONFIG_CC_STACKPROTECTOR # on all arches but x86_64; this causes missing symbols without @@ -1566,8 +928,7 @@ if test "$with_xenomai" != no -o "$with_xenomai_kernel" != no; then if test "$host_cpu" != x86_64; then flags="$flags -fno-stack-protector" fi - XENOMAI_THREADS_RTFLAGS="$XENOMAI_THREADS_RTFLAGS $flags" - XENOMAI_KERNEL_THREADS_RTFLAGS="$XENOMAI_KERNEL_THREADS_RTFLAGS -g $flags" + XENOMAI_RTFLAGS="$flags" # xenomai kernel math options flags="-ffast-math -mhard-float" if test "$($XENOMAI_THREADS_RTS --arch)" = x86; then @@ -1578,152 +939,24 @@ if test "$with_xenomai" != no -o "$with_xenomai_kernel" != no; then # -mpreferred-stack-boundary=3 on x86_64 arch, so force it. flags="$flags -mpreferred-stack-boundary=4" fi - XENOMAI_KERNEL_THREADS_KERNEL_MATH_CFLAGS="$flags" # ldflags flags="$($XENOMAI_THREADS_RTS --ldflags)" AC_PRUNE_DEFAULT_LDFLAGS(flags) - XENOMAI_THREADS_LDFLAGS="$XENOMAI_THREADS_LDFLAGS $flags" - XENOMAI_KERNEL_THREADS_LDFLAGS="$XENOMAI_KERNEL_THREADS_LDFLAGS $flags" + XENOMAI_LDFLAGS+="$XENOMAI_THREADS_LDFLAGS $flags" fi AC_MSG_CHECKING(whether to build Xenomai userland threads) test "$with_xenomai" = check && with_xenomai=yes test -z "$XENOMAI_THREADS_RTS" && with_xenomai=no -if test $with_xenomai = yes; then - BUILD_THREAD_FLAVORS="$BUILD_THREAD_FLAVORS xenomai" - with_userland_rt_threads=yes -elif test "$xenomai_from_cmdline" = yes; then +if test $with_xenomai = no -a "$xenomai_from_cmdline" = yes; then AC_MSG_ERROR([Requested '--with-xenomai', but unable to configure]) fi AC_MSG_RESULT($with_xenomai) -AC_MSG_CHECKING(whether to build Xenomai kernel threads) -if test "$with_xenomai_kernel" = check; then - # xenomai-kernel threads are broken in many ways on ARM arch; see - # #63 - $TARGET_PLATFORM_PC && \ - with_xenomai_kernel=yes || \ - with_xenomai_kernel=no -fi -test -z "$xenomai_kernels" && with_xenomai_kernel=no -test -z "$XENOMAI_THREADS_RTS" && with_xenomai_kernel=no -if test $with_xenomai_kernel = yes; then - BUILD_THREAD_FLAVORS="$BUILD_THREAD_FLAVORS xenomai-kernel" -elif test "$xenomai_kernel_from_cmdline" = yes; then - AC_MSG_ERROR([Requested '--with-xenomai-kernel', but unable to configure]) -fi -AC_MSG_RESULT($with_xenomai_kernel) - - -############################################################################## -# RTAI flavor checks - -if test "$with_rtai_kernel" != no; then - # look for rtai-config path - RTAI_KERNEL_THREADS_RTS='' - if test "$rtai_config_from_cmdline" = yes; then - # user-supplied path - RTAI_KERNEL_THREADS_RTS=$with_rtai_config - else - # guess path from defaults - rtai_config_path='' - dirs="$(echo \ - /usr/realtime-`uname -r` /usr/realtime* /usr /usr/src/rtai*)" - for d in $dirs; do - rtai_config_path="$rtai_config_path:$d:$d/bin" - done - AC_PATH_PROGS([RTAI_KERNEL_THREADS_RTS],[rtai-config], - [],[$rtai_config_path]) - fi - # check rtai-config path - if test -n "$RTAI_KERNEL_THREADS_RTS"; then - # path found, so check its validity: --linux-dir should return - # a configured kernel source directory with .config file - AC_MSG_CHECKING([usability of RTAI utility, $RTAI_KERNEL_THREADS_RTS]) - if test -x $RTAI_KERNEL_THREADS_RTS -a \ - -f $($RTAI_KERNEL_THREADS_RTS -o --linux-dir 2>/dev/null)/.config - then - # ShabbyX-style `rtai-config` - RTAI_KERNEL_THREADS_RTS="$RTAI_KERNEL_THREADS_RTS -o" - AC_MSG_RESULT(yes) - elif test -x $RTAI_KERNEL_THREADS_RTS -a \ - -f $($RTAI_KERNEL_THREADS_RTS --linux-dir 2>/dev/null)/.config - then - AC_MSG_RESULT(yes) - else - RTAI_KERNEL_THREADS_RTS='' - AC_MSG_RESULT(no) - fi - fi - # deal with nothing found in the right way - if test -z "$RTAI_KERNEL_THREADS_RTS"; then - if test "$rtai_config_from_cmdline" = yes; then - # --with-rtai-config specified, but invalid path - AC_MSG_ERROR(--with-rtai-config: "$with_rtai_config": bad path) - elif test "$with_rtai_kernel" = yes; then - # --with-rtai-kernel specified but can't find rtai-config - AC_MSG_ERROR("rtai-config" not found; use --with-rtai-config") - else - with_rtai_kernel=no - fi - fi -fi - -# Generate RTFLAGS for RTAI -if test $with_rtai_kernel != no -a -n "$rtai_kernels"; then - - RTAI_KERNEL_THREADS_RTFLAGS="$($RTAI_KERNEL_THREADS_RTS --module-cflags) \ - -I$($RTAI_KERNEL_THREADS_RTS --prefix)/include" - RTAI_KERNEL_THREADS_LDFLAGS="$($RTAI_KERNEL_THREADS_RTS --lxrt-ldflags) \ - -llxrt -Wl,-rpath,$($RTAI_KERNEL_THREADS_RTS --library-dir)" - - if test "$host_cpu" = x86_64; then - flags="-msse -mpreferred-stack-boundary=4 -funsafe-math-optimizations" - else - flags="-fno-unsafe-math-optimizations" - fi - RTAI_KERNEL_THREADS_KERNEL_MATH_CFLAGS="$flags" - - RTAI_KERNEL_THREADS_RTDIR=$(readlink -f \ - $($RTAI_KERNEL_THREADS_RTS --module-dir)) -fi -AC_MSG_CHECKING(whether to build RTAI threads) -test -z "$RTAI_KERNEL_THREADS_RTS" && with_rtai_kernel=no -test -z "$rtai_kernels" && with_rtai_kernel=no - -# Check the RTAI Module.symvers file -if test $with_rtai_kernel != no; then - RTAI_KERNEL_THREADS_EXTRA_SYMBOLS=`$RTAI_KERNEL_THREADS_RTS \ - --module-dir`/Module.symvers - if ! test -f "${RTAI_KERNEL_THREADS_EXTRA_SYMBOLS}"; then - if test "$with_rtai_kernel" = check; then - with_rtai_kernel=no - else - AC_MSG_ERROR([RTAI build requested but no Module.symvers found]) - fi - fi -fi -test "$with_rtai_kernel" = check && with_rtai_kernel=yes -if test $with_rtai_kernel = yes; then - BUILD_THREAD_FLAVORS="$BUILD_THREAD_FLAVORS rtai-kernel" -fi -AC_MSG_RESULT($with_rtai_kernel) -if test $with_rtai_kernel = yes; then - AC_MSG_CHECKING(RTAI version) - if grep -q rt_free_timers $RTAI_KERNEL_THREADS_EXTRA_SYMBOLS; then - RTAI_VERSION=401 - AC_MSG_RESULT(4.1 or greater) - else - RTAI_VERSION=400 - AC_MSG_RESULT(4.0 or earlier) - fi -fi - ############################################################################## # Subsection 2.6 # # Hardware driver detection # -# - Configure usermode PCI drivers # # - Configure libudev # ############################################################################## @@ -1738,64 +971,9 @@ fi AC_MSG_RESULT($with_drivers) -AC_ARG_ENABLE(usermode-pci, - [AS_HELP_STRING([--enable-usermode-pci], - [Build PCI drivers with usermode PCI support])], - [with_usermode_pci=$enableval], - [with_usermode_pci=check]) -# record what was requested on the command line -if test $with_usermode_pci = yes; then - usermode_pci_requested_cmdline=yes -else - usermode_pci_requested_cmdline=no -fi -if test $with_drivers = yes -a $with_usermode_pci != no; then - usermode_pci_disabled_cmdline=no -else - usermode_pci_disabled_cmdline=yes -fi - -# test usability of libudev, needed by userland drivers -with_libudev=no -if test "$with_drivers" = "yes" -a $with_usermode_pci != no; then - PKG_CHECK_MODULES(LIBUDEV, libudev, with_libudev=yes, with_libudev=no) -fi +# test usability of libudev, needed by drivers +PKG_CHECK_MODULES(LIBUDEV, libudev, with_libudev=yes, with_libudev=no) -AC_MSG_CHECKING(whether to build usermode PCI hardware drivers) -if test "$usermode_pci_disabled_cmdline" = yes; then - # user explicitly disabled either userland drivers or all drivers - with_usermode_pci=no - AC_MSG_RESULT([disabled by user]) -elif test $with_drivers = no; then - with_usermode_pci=no - AC_MSG_RESULT([drivers disabled by user]) -elif test $TARGET_PLATFORM_PC = false; then - with_usermode_pci=no - AC_MSG_RESULT([unavailable for non-PC architecture]) -elif test "$with_usermode_pci" = check -a $with_userland_rt_threads = no; then - with_usermode_pci=no - AC_MSG_RESULT([default disabled for no userland RT threads]) -elif test $with_libudev = no; then - with_usermode_pci=no - AC_MSG_RESULT([no; depends on libudev]) -elif test "$with_usermode_pci" = check -a $with_userland_rt_threads = yes; then - with_usermode_pci=yes - AC_MSG_RESULT([default enabled for userland RT threads]) -else - # catchall - AC_MSG_RESULT($with_usermode_pci) -fi -# if --with-usermode-pci was specified on the cmdline but is -# unavailable, consider it an error -test $usermode_pci_requested_cmdline = yes -a $with_usermode_pci = no && \ - AC_MSG_ERROR([Usermode PCI drivers requested but unavailable]) -# if xenomai or rt-preempt will be built and userland drivers were -# not explicitly disabled but will not be built, issue a warning -test $with_usermode_pci = no \ - -a $usermode_pci_disabled_cmdline = no \ - -a $with_userland_rt_threads = yes && \ - $TARGET_PLATFORM_PC && \ - AC_MSG_WARN([Usermode PCI drivers will not be available]) ############################################################################## # Subsection 2.7 # @@ -1804,22 +982,11 @@ test $with_usermode_pci = no \ # - config.h macro definitions # ############################################################################## -# RTDIR: FIXME: needs maintenance (elimination) -# latencyplot only works with RTAI and needs RTDIR -AC_SUBST([RTDIR],$RTAI_KERNEL_THREADS_RTDIR) - - if test "$with_drivers" = yes; then AC_DEFINE(BUILD_DRIVERS, [], [build hardware drivers]) fi AC_SUBST(BUILD_DRIVERS,[$with_drivers]) -if test "$USE_SHMDRV" = yes; then - AC_DEFINE(USE_SHMDRV, [], [use shm driver module]) -fi -AC_SUBST(USE_SHMDRV) -AC_SUBST(SHMDRV_KERNEL_DIRS,[$shmdrv_kernels]) - AC_SUBST(BUILD_EXAMPLES) if test "$BUILD_EXAMPLES" = yes; then AC_DEFINE(BUILD_EXAMPLES, [], [build programming examples]) @@ -1841,6 +1008,9 @@ if test "$BUILD_NMLDEP" = yes; then AC_DEFINE(BUILD_NMLDEP, [], [build NML dependent parts]) fi +AC_SUBST([ZMQ_CFLAGS]) +AC_SUBST([ZMQ_LIBS]) + AC_SUBST([CZMQ_CFLAGS]) AC_SUBST([CZMQ_LIBS]) @@ -1868,6 +1038,7 @@ AC_SUBST([UUID_LIBS]) AC_SUBST([LIBCGROUP_CFLAGS]) AC_SUBST([LIBCGROUP_LIBS]) +AC_SUBST([USE_ZMQ]) AC_SUBST([USE_CZMQ]) AC_SUBST([USE_PROTOBUF]) AC_SUBST([USE_JANSSON]) @@ -1878,10 +1049,6 @@ AC_SUBST([USE_SSL]) AC_SUBST([USE_UUID]) AC_SUBST([USE_LIBCGROUP]) -if test "$with_usermode_pci" = yes; then - AC_DEFINE([USERMODE_PCI], [], [build PCI drivers with usermode PCI support]) -fi -AC_SUBST([USERMODE_PCI],[$with_usermode_pci]) AC_SUBST(LIBUDEV_CFLAGS) AC_SUBST(LIBUDEV_LIBS) AC_DEFINE(HAVE_LIBUDEV, [], [libudev installed and available]) @@ -1937,37 +1104,8 @@ AC_SUBST(TARGET_PLATFORM_ZEDBOARD,$target_platform_zedboard_val) ############################################################ # thread-specific -DDEFINE and Makefile.inc variables -# List of threads flavors -AC_SUBST([BUILD_THREAD_FLAVORS]) - - -# POSIX settings -if test "$with_posix" = yes; then - AC_DEFINE([HAVE_POSIX_THREADS],[],[Build POSIX threads]) -fi -AC_SUBST([HAVE_POSIX_THREADS],[$with_posix]) -AC_SUBST([POSIX_THREADS_FLAVOR_ID],_cfg_flavor_id(posix)) -AC_SUBST([POSIX_THREADS_BUILD_SYS],_cfg_flavor_build_sys(posix)) -AC_SUBST([POSIX_THREADS_SOURCE],[rt-preempt]) -AC_SUBST([POSIX_THREADS_RTFLAGS]) -AC_SUBST([POSIX_THREADS_LDFLAGS]) -AC_SUBST([POSIX_THREADS_RTDIR],[]) -AC_SUBST([POSIX_THREADS_RTS],[]) -AC_SUBST([POSIX_THREADS_EXTRA_KMODS],[]) - -# RT_PREEMPT settings -if test "$with_rt_preempt" = yes; then - AC_DEFINE([HAVE_RT_PREEMPT_THREADS],[],[Build RT_PREEMPT threads]) -fi -AC_SUBST([HAVE_RT_PREEMPT_THREADS],[$with_rt_preempt]) -AC_SUBST([RT_PREEMPT_THREADS_FLAVOR_ID],_cfg_flavor_id(rt-preempt)) -AC_SUBST([RT_PREEMPT_THREADS_BUILD_SYS],_cfg_flavor_build_sys(rt-preempt)) -AC_SUBST([RT_PREEMPT_THREADS_SOURCE],[rt-preempt]) -AC_SUBST([RT_PREEMPT_THREADS_RTFLAGS]) -AC_SUBST([RT_PREEMPT_THREADS_LDFLAGS]) -AC_SUBST([RT_PREEMPT_THREADS_RTDIR],[]) -AC_SUBST([RT_PREEMPT_THREADS_RTS],[]) -AC_SUBST([RT_PREEMPT_THREADS_EXTRA_KMODS],[]) +AC_SUBST([THREADS_RTFLAGS]) +AC_SUBST([THREADS_LDFLAGS]) # Xenomai general settings if test "$XENOMAI_V2" = true; then @@ -1981,59 +1119,9 @@ if test "$with_xenomai" = yes; then AC_DEFINE([HAVE_XENOMAI_THREADS],[],[Build Xenomai userland threads]) fi AC_SUBST([HAVE_XENOMAI_THREADS],[$with_xenomai]) -AC_SUBST([XENOMAI_THREADS_FLAVOR_ID],_cfg_flavor_id(xenomai)) -AC_SUBST([XENOMAI_THREADS_BUILD_SYS],_cfg_flavor_build_sys(xenomai)) -AC_SUBST([XENOMAI_THREADS_SOURCE],[xenomai]) -AC_SUBST([XENOMAI_THREADS_RTFLAGS]) -AC_SUBST([XENOMAI_THREADS_LDFLAGS]) AC_SUBST([XENOMAI_THREADS_RTS]) -AC_SUBST([XENOMAI_THREADS_RTDIR],[]) -AC_SUBST([XENOMAI_THREADS_EXTRA_KMODS],[]) -AC_SUBST([PRECISE_MULTILIB_BUG],[$PRECISE_MULTILIB_BUG]) - -# Xenomai kernel settings -if test "$with_xenomai_kernel" = yes; then - AC_DEFINE([HAVE_XENOMAI_KERNEL_THREADS],[],[Build Xenomai kernel threads]) -fi -AC_SUBST([HAVE_XENOMAI_KERNEL_THREADS],[$with_xenomai_kernel]) -AC_SUBST([XENOMAI_KERNEL_THREADS_FLAVOR_ID],_cfg_flavor_id(xenomai-kernel)) -AC_SUBST([XENOMAI_KERNEL_THREADS_BUILD_SYS], - _cfg_flavor_build_sys(xenomai-kernel)) -AC_SUBST([XENOMAI_KERNEL_THREADS_SOURCE],[xenomai-kernel]) -# force hard-float for kernel modules -AC_SUBST([XENOMAI_KERNEL_THREADS_RTFLAGS]) -AC_SUBST([XENOMAI_KERNEL_THREADS_LDFLAGS]) -AC_SUBST([XENOMAI_KERNEL_THREADS_RTS]) -AC_SUBST([XENOMAI_KERNEL_THREADS_KERNEL_DIRS],[$xenomai_kernels]) -AC_SUBST([XENOMAI_KERNEL_THREADS_EXTRA_SYMBOLS]) -# in-kernel math options -AC_SUBST([XENOMAI_KERNEL_THREADS_KERNEL_MATH_CFLAGS]) -AC_SUBST([XENOMAI_KERNEL_THREADS_RTDIR],[]) -AC_SUBST([XENOMAI_KERNEL_THREADS_EXTRA_KMODS], - "_cfg_flavor_extra_kmods(xenomai-kernel)") - -# RTAI settings -if test "$with_rtai_kernel" = yes; then - AC_DEFINE([HAVE_RTAI_KERNEL_THREADS],[],[Build RTAI threads]) -fi -AC_SUBST([HAVE_RTAI_KERNEL_THREADS],[$with_rtai_kernel]) -AC_SUBST([RTAI_KERNEL_THREADS_FLAVOR_ID],_cfg_flavor_id(rtai-kernel)) -AC_SUBST([RTAI_KERNEL_THREADS_BUILD_SYS],_cfg_flavor_build_sys(rtai-kernel)) -AC_SUBST([RTAI_KERNEL_THREADS_SOURCE],[rtai-kernel]) -AC_SUBST([RTAI_KERNEL_THREADS_RTFLAGS]) -AC_SUBST([RTAI_KERNEL_THREADS_LDFLAGS]) -AC_SUBST([RTAI_KERNEL_THREADS_RTS]) -AC_SUBST([RTAI_KERNEL_THREADS_KERNEL_DIRS],[$rtai_kernels]) -AC_SUBST([RTAI_KERNEL_THREADS_EXTRA_SYMBOLS]) -AC_SUBST([RTAI_KERNEL_THREADS_KERNEL_MATH_CFLAGS]) -# absolute path of rtai-config rtdir with symlinks dereferenced -AC_SUBST([RTAI_KERNEL_THREADS_RTDIR],[$RTAI_KERNEL_THREADS_RTDIR]) -AC_SUBST([RTAI_KERNEL_THREADS_EXTRA_KMODS], - "_cfg_flavor_extra_kmods(rtai-kernel)") -if test -n "$RTAI_VERSION"; then - AC_DEFINE_UNQUOTED([RTAI_VERSION],$RTAI_VERSION,"RTAI version") -fi - +AC_SUBST([XENOMAI_RTFLAGS]) +AC_SUBST([XENOMAI_LDFLAGS]) # while we are at it, drop a git scent mark GIT_VERSION=unknown @@ -2250,7 +1338,7 @@ if test "xyes" = "x$RUN_IN_PLACE"; then EMC2_PO_DIR=$EMC2_HOME/share/locale EMC2_HELP_DIR=$EMC2_HOME/help EMC2_RTLIB_DIR=$EMC2_HOME/rtlib -# LINUXCNC_CONFIG_PATH="~/machinekit/configs:$EMC2_HOME/configs" + EMC2_MODULES_DIR=$EMC2_RTLIB_DIR/modules EMC2_NCFILES_DIR=$EMC2_HOME/nc_files REALTIME=$EMC2_HOME/scripts/realtime EMC2_IMAGE_DIR=$EMC2_HOME @@ -2268,7 +1356,7 @@ else EMC2_PO_DIR=${prefix}/share/locale EMC2_HELP_DIR=${prefix}/share/doc/linuxcnc EMC2_RTLIB_DIR=${prefix}/lib/linuxcnc -# LINUXCNC_CONFIG_PATH="~/machinekit/configs:${sysconfdir}/linuxcnc/configs:$(fe "$datadir")/linuxcnc/examples/sample-configs" + EMC2_MODULES_DIR=$EMC2_RTLIB_DIR/modules EMC2_NCFILES_DIR=${prefix}/share/linuxcnc/ncfiles REALTIME=${bindir}/realtime EMC2_IMAGE_DIR=$(fe "$datadir")/linuxcnc @@ -2286,6 +1374,8 @@ AC_DEFINE_UNQUOTED([EMC2_HOME], "$EMC2_HOME", [Prefix or RIP directory]) AC_DEFINE_UNQUOTED([MACHINEKIT_INI], "$MACHINEKIT_INI", [path of global machinekit.ini file]) AC_DEFINE_UNQUOTED([EMC2_BIN_DIR], "$EMC2_BIN_DIR", [Directory for binaries]) AC_DEFINE_UNQUOTED([EMC2_RTLIB_DIR], "$EMC2_RTLIB_DIR", [Directory for ulapi shared objects]) +AC_DEFINE_UNQUOTED([EMC2_MODULES_DIR], "$EMC2_MODULES_DIR", + [Directory for rtapi shared objects]) AC_DEFINE_UNQUOTED([EMC2_PO_DIR], "$EMC2_PO_DIR", [Directory for po/mo translation files]) AC_DEFINE_UNQUOTED([EMC2_NCFILES_DIR], "$EMC2_NCFILES_DIR", [Directory for nc files]) AC_DEFINE_UNQUOTED([EMC2_IMAGE_DIR], "$EMC2_IMAGE_DIR", [Directory for images]) @@ -2299,6 +1389,7 @@ AC_SUBST([EMC2_TCL_DIR]) AC_SUBST([EMC2_TCL_LIB_DIR]) AC_SUBST([EMC2_HELP_DIR]) AC_SUBST([EMC2_RTLIB_DIR]) +AC_SUBST([EMC2_MODULES_DIR]) AC_SUBST([EMC2_LANG_DIR]) #AC_SUBST([LINUXCNC_CONFIG_PATH]) AC_SUBST([EMC2_NCFILES_DIR]) @@ -2402,27 +1493,6 @@ then AC_MSG_ERROR([awk not found]) fi -if test -n "${rtai_kernels}${xenomai_kernels}${shmdrv_kernels}"; then - # Kernel module tools only needed for kthreads - AC_PATH_PROG(INSMOD, insmod, "none", $SPATH) - if test $INSMOD = "none" - then - AC_MSG_ERROR([insmod not found]) - fi - - AC_PATH_PROG(RMMOD, rmmod, "none", $SPATH) - if test $RMMOD = "none" - then - AC_MSG_ERROR([rmmod not found]) - fi - - AC_PATH_PROG(LSMOD, lsmod, "none", $SPATH) - if test $LSMOD = "none" - then - AC_MSG_ERROR([lsmod not found]) - fi -fi - AC_PATH_PROG(PIDOF, pidof, "none", $SPATH) if test $PIDOF = "none" then @@ -2454,43 +1524,6 @@ fi # MANDB empty is handled in doc/Submakefile AC_PATH_PROG(MANDB, mandb, "") -AC_ARG_WITH(rmmod, - [ --with-rmmod= rmmod variant], - [ - case "$withval" in - "" | y | ye | yes) - AC_MSG_ERROR([You must supply an argument to --with-rmmod.]) - ;; - n | no | none) - RMMOD="" - ;; - *) - RMMOD="$withval" - esac - ], - [ - RMMOD="$EMC2_BIN_DIR/linuxcnc_module_helper remove" - ]) - -AC_ARG_WITH(insmod, - [ --with-insmod= insmod variant], - [ - case "$withval" in - "" | y | ye | yes) - AC_MSG_ERROR([You must supply an argument to --with-insmod.]) - ;; - n | no | none) - INSMOD="" - ;; - *) - INSMOD="$withval" - esac - ], - [ - INSMOD="$EMC2_BIN_DIR/linuxcnc_module_helper insert" - ]) - - ############################################################################## # Subsection 3.5 - check for programs needed to build documentation # # # @@ -2673,32 +1706,6 @@ AC_SUBST(BUILD_DOCS) # multiple places. Keep screwball constructs out of this, and it can # be used in both kernel space and user space. -dnl _cfg_thread_flavor_macros(): define thread flavor IDs -dnl and set RTAPI_, BUILD_SYS_ & THREADS_HEADERS macros -AC_DEFUN([_cfg_thread_flavor_macros],[dnl -m4_foreach([_cfg_flavor],[_cfg_all_flavors],[dnl -[#]define RTAPI_[]_cfg_flavor_upcase(_cfg_flavor)[]_ID dnl -_cfg_flavor_id(_cfg_flavor) -[#]define RTAPI_[]_cfg_flavor_upcase(_cfg_flavor)[]_NAME dnl -"_cfg_flavor" -]) -#if ! defined(THREAD_FLAVOR_ID) -// this isn't allowed when building RTAPI -#ifdef RTAPI -#error RTAPI defined but THREAD_FLAVOR_ID not defined -#endif -m4_foreach([_cfg_flavor],[_cfg_all_flavors],[dnl -[#]elif THREAD_FLAVOR_ID == RTAPI_[]_cfg_flavor_upcase(_cfg_flavor)_ID -[#] define RTAPI_[]_cfg_flavor_upcase(_cfg_flavor) -[#] define THREAD_FLAVOR_NAME "_cfg_flavor" -[#] define _cfg_flavor_BUILD_SYS(_cfg_flavor) -[#] define THREADS_HEADERS "_cfg_flavor_threads_headers(_cfg_flavor)" -])dnl -#else -#error unknown value for THREAD_FLAVOR_ID -#endif -]) - AH_TOP([/******************************************************************** * Description: config.h @@ -2747,23 +1754,12 @@ AH_TOP([/******************************************************************** // can be overridden by an option to rtapi_msgd #define HAL_STACKSIZE 32768 -// a pseudo-flavor id to indicate ulapi.so is not yet loaded -// not a build target, just a state indicator for ulapi_autoload.c -#define RTAPI_NOTLOADED_NAME "not-yet-loaded" -#define RTAPI_NOTLOADED_ID 99 - // format of zeroMQ IPC socket pathnames // pass: RUNDIR, rtapi_instance, service name, uuid // service name is: log, rtapi, halrcomp etc #define ZMQIPC_FORMAT "ipc://%s/%d.%s.%s" -] -// flavor IDs for the various threads systems -// and conditional to set thread system and build_sys macros -// alter these in configure.ac Subsection 2.0 -dnl this needs to be unquoted -_cfg_thread_flavor_macros -) +]) AH_VERBATIM([_GNU_SOURCE], [/* Enable GNU extensions on systems that have them. */ @@ -2806,24 +1802,6 @@ AH_BOTTOM(#endif AC_MSG_NOTICE([Building rtapi.ini generator script]) cp ../scripts/gen-rtapi.ini.sh.in.tmpl ../scripts/gen-rtapi.ini.sh.in -cat >> ../scripts/gen-rtapi.ini.sh.in <@ -# These values do not normally need to be changed. -rtapi_app=@EMC2_LIBEXEC_DIR@/rtapi_app_[]_cfg_flavor -RTS=@_cfg_flavor_upcase(_cfg_flavor)_THREADS_RTS@ -RTDIR=@_cfg_flavor_upcase(_cfg_flavor)_THREADS_RTDIR@ -MODULES=@_cfg_flavor_upcase(_cfg_flavor)_THREADS_EXTRA_KMODS@ -]) -EOF -EOFOUTER - ############################################################################## # Section 6 - Check for tcl/tk support # # # @@ -3130,20 +2108,11 @@ fi AC_SUBST([BUILD_PYTHON]) AC_SUBST([SITEPY]) -if test "$BUILD_EMCWEB" = yes; then - # these are needed for the emcweb interface only - AX_BOOST_SERIALIZATION() - AX_BOOST_THREAD() - AX_BOOST_SYSTEM() -fi - ############################################################################## # files that get created by ./configure # ############################################################################## AC_CONFIG_FILES([../scripts/gen-rtapi.ini.sh]) -AC_CONFIG_FILES([../scripts/check-build-vs-configure-sha], [chmod +x ../scripts/check-build-vs-configure-sha]) -#AC_CONFIG_FILES([../scripts/linuxcnc], [chmod +x ../scripts/linuxcnc]) AC_CONFIG_FILES([../scripts/halrun], [chmod +x ../scripts/halrun]) AC_CONFIG_FILES([../scripts/rip-environment], [chmod +x ../scripts/rip-environment]) AC_CONFIG_FILES([../scripts/haltcl], [chmod +x ../scripts/haltcl]) diff --git a/src/hal/accessor/hal_accessor-expanded-c.i b/src/hal/accessor/hal_accessor-expanded-c.i deleted file mode 100644 index bcf22fdc93..0000000000 --- a/src/hal/accessor/hal_accessor-expanded-c.i +++ /dev/null @@ -1,4160 +0,0 @@ -# 1 "hal/lib/hal_accessor.h" -# 1 "/home/mah/machinekit/src//" -# 1 "" -# 1 "" -# 1 "/usr/include/stdc-predef.h" 1 3 4 -# 1 "" 2 -# 1 "hal/lib/hal_accessor.h" - - -# 1 "./config.h" 1 -# 4 "hal/lib/hal_accessor.h" 2 -# 1 "rtapi/rtapi.h" 1 -# 84 "rtapi/rtapi.h" -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 1 3 4 -# 147 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 3 4 -typedef long int ptrdiff_t; -# 212 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 3 4 -typedef long unsigned int size_t; -# 324 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 3 4 -typedef int wchar_t; -# 422 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 3 4 -typedef struct { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long)))); - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double)))); -} max_align_t; -# 85 "rtapi/rtapi.h" 2 -# 1 "rtapi/rtapi_int.h" 1 -# 27 "rtapi/rtapi_int.h" -# 1 "/usr/include/x86_64-linux-gnu/asm/types.h" 1 3 4 - - - -# 1 "/usr/include/asm-generic/types.h" 1 3 4 - - - - - -# 1 "/usr/include/asm-generic/int-ll64.h" 1 3 4 -# 11 "/usr/include/asm-generic/int-ll64.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/asm/bitsperlong.h" 1 3 4 -# 10 "/usr/include/x86_64-linux-gnu/asm/bitsperlong.h" 3 4 -# 1 "/usr/include/asm-generic/bitsperlong.h" 1 3 4 -# 11 "/usr/include/x86_64-linux-gnu/asm/bitsperlong.h" 2 3 4 -# 12 "/usr/include/asm-generic/int-ll64.h" 2 3 4 - - - - - - - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - - -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -# 7 "/usr/include/asm-generic/types.h" 2 3 4 -# 5 "/usr/include/x86_64-linux-gnu/asm/types.h" 2 3 4 -# 28 "rtapi/rtapi_int.h" 2 - - -# 1 "/usr/local/include/ck_limits.h" 1 3 -# 44 "/usr/local/include/ck_limits.h" 3 -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 1 3 4 -# 34 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 3 4 -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/syslimits.h" 1 3 4 - - - - - - -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 1 3 4 -# 168 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 3 4 -# 1 "/usr/include/limits.h" 1 3 4 -# 25 "/usr/include/limits.h" 3 4 -# 1 "/usr/include/features.h" 1 3 4 -# 374 "/usr/include/features.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 -# 385 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 -# 386 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 -# 375 "/usr/include/features.h" 2 3 4 -# 398 "/usr/include/features.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 -# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 -# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 -# 399 "/usr/include/features.h" 2 3 4 -# 26 "/usr/include/limits.h" 2 3 4 -# 143 "/usr/include/limits.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 1 3 4 -# 160 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 1 3 4 -# 38 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 3 4 -# 1 "/usr/include/linux/limits.h" 1 3 4 -# 39 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 2 3 4 -# 161 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 2 3 4 -# 144 "/usr/include/limits.h" 2 3 4 - - - -# 1 "/usr/include/x86_64-linux-gnu/bits/posix2_lim.h" 1 3 4 -# 148 "/usr/include/limits.h" 2 3 4 - - - -# 1 "/usr/include/x86_64-linux-gnu/bits/xopen_lim.h" 1 3 4 -# 33 "/usr/include/x86_64-linux-gnu/bits/xopen_lim.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/stdio_lim.h" 1 3 4 -# 34 "/usr/include/x86_64-linux-gnu/bits/xopen_lim.h" 2 3 4 -# 152 "/usr/include/limits.h" 2 3 4 -# 169 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 2 3 4 -# 8 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/syslimits.h" 2 3 4 -# 35 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 2 3 4 -# 45 "/usr/local/include/ck_limits.h" 2 3 -# 31 "rtapi/rtapi_int.h" 2 -# 86 "rtapi/rtapi.h" 2 -# 97 "rtapi/rtapi.h" -# 1 "rtapi/rtapi_errno.h" 1 -# 19 "rtapi/rtapi_errno.h" -# 1 "/usr/include/errno.h" 1 3 4 -# 31 "/usr/include/errno.h" 3 4 - - - - -# 1 "/usr/include/x86_64-linux-gnu/bits/errno.h" 1 3 4 -# 24 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 -# 1 "/usr/include/linux/errno.h" 1 3 4 -# 1 "/usr/include/x86_64-linux-gnu/asm/errno.h" 1 3 4 -# 1 "/usr/include/asm-generic/errno.h" 1 3 4 - - - -# 1 "/usr/include/asm-generic/errno-base.h" 1 3 4 -# 5 "/usr/include/asm-generic/errno.h" 2 3 4 -# 1 "/usr/include/x86_64-linux-gnu/asm/errno.h" 2 3 4 -# 1 "/usr/include/linux/errno.h" 2 3 4 -# 25 "/usr/include/x86_64-linux-gnu/bits/errno.h" 2 3 4 -# 50 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 -extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); -# 36 "/usr/include/errno.h" 2 3 4 -# 54 "/usr/include/errno.h" 3 4 -extern char *program_invocation_name, *program_invocation_short_name; - - - - -# 68 "/usr/include/errno.h" 3 4 -typedef int error_t; -# 20 "rtapi/rtapi_errno.h" 2 -# 98 "rtapi/rtapi.h" 2 - - - - -# 1 "/usr/local/include/ck_pr.h" 1 3 -# 31 "/usr/local/include/ck_pr.h" 3 -# 1 "/usr/local/include/ck_cc.h" 1 3 -# 32 "/usr/local/include/ck_cc.h" 3 -# 1 "/usr/local/include/gcc/ck_cc.h" 1 3 -# 31 "/usr/local/include/gcc/ck_cc.h" 3 -# 1 "/usr/local/include/ck_md.h" 1 3 -# 32 "/usr/local/include/gcc/ck_cc.h" 2 3 -# 116 "/usr/local/include/gcc/ck_cc.h" 3 -__attribute__((unused)) static int -ck_cc_ffs(unsigned int x) -{ - - return __builtin_ffs(x); -} - -__attribute__((unused)) static int -ck_cc_clz(unsigned int x) -{ - - return __builtin_clz(x); -} - -__attribute__((unused)) static int -ck_cc_ctz(unsigned int x) -{ - - return __builtin_ctz(x); -} - -__attribute__((unused)) static int -ck_cc_popcount(unsigned int x) -{ - - return __builtin_popcount(x); -} -# 33 "/usr/local/include/ck_cc.h" 2 3 -# 32 "/usr/local/include/ck_pr.h" 2 3 -# 1 "/usr/local/include/ck_limits.h" 1 3 -# 44 "/usr/local/include/ck_limits.h" 3 -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/limits.h" 1 3 4 -# 45 "/usr/local/include/ck_limits.h" 2 3 -# 33 "/usr/local/include/ck_pr.h" 2 3 - -# 1 "/usr/local/include/ck_stdint.h" 1 3 -# 31 "/usr/local/include/ck_stdint.h" 3 -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 1 3 4 -# 9 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 3 4 -# 1 "/usr/include/stdint.h" 1 3 4 -# 26 "/usr/include/stdint.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/wchar.h" 1 3 4 -# 27 "/usr/include/stdint.h" 2 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 -# 28 "/usr/include/stdint.h" 2 3 4 -# 36 "/usr/include/stdint.h" 3 4 -typedef signed char int8_t; -typedef short int int16_t; -typedef int int32_t; - -typedef long int int64_t; - - - - - - - -typedef unsigned char uint8_t; -typedef unsigned short int uint16_t; - -typedef unsigned int uint32_t; - - - -typedef unsigned long int uint64_t; -# 65 "/usr/include/stdint.h" 3 4 -typedef signed char int_least8_t; -typedef short int int_least16_t; -typedef int int_least32_t; - -typedef long int int_least64_t; - - - - - - -typedef unsigned char uint_least8_t; -typedef unsigned short int uint_least16_t; -typedef unsigned int uint_least32_t; - -typedef unsigned long int uint_least64_t; -# 90 "/usr/include/stdint.h" 3 4 -typedef signed char int_fast8_t; - -typedef long int int_fast16_t; -typedef long int int_fast32_t; -typedef long int int_fast64_t; -# 103 "/usr/include/stdint.h" 3 4 -typedef unsigned char uint_fast8_t; - -typedef unsigned long int uint_fast16_t; -typedef unsigned long int uint_fast32_t; -typedef unsigned long int uint_fast64_t; -# 119 "/usr/include/stdint.h" 3 4 -typedef long int intptr_t; - - -typedef unsigned long int uintptr_t; -# 134 "/usr/include/stdint.h" 3 4 -typedef long int intmax_t; -typedef unsigned long int uintmax_t; -# 10 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 2 3 4 -# 32 "/usr/local/include/ck_stdint.h" 2 3 -# 35 "/usr/local/include/ck_pr.h" 2 3 -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdbool.h" 1 3 4 -# 36 "/usr/local/include/ck_pr.h" 2 3 - - - -# 1 "/usr/local/include/gcc/x86_64/ck_pr.h" 1 3 -# 36 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -# 1 "/usr/local/include/ck_stdint.h" 1 3 -# 37 "/usr/local/include/gcc/x86_64/ck_pr.h" 2 3 - - - - - - -# 1 "/usr/local/include/gcc/x86_64/ck_f_pr.h" 1 3 -# 44 "/usr/local/include/gcc/x86_64/ck_pr.h" 2 3 -# 65 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void -ck_pr_stall(void) -{ - __asm__ __volatile__("pause" ::: "memory"); - return; -} -# 79 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_fence_strict_atomic(void) -{ - __asm__ __volatile__("sfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_atomic_store(void) -{ - __asm__ __volatile__("sfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_atomic_load(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_store_atomic(void) -{ - __asm__ __volatile__("sfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_load_atomic(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_load(void) -{ - __asm__ __volatile__("lfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_load_store(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_store(void) -{ - __asm__ __volatile__("sfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_store_load(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_memory(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_release(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_acquire(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_lock(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -__attribute__((unused)) static void ck_pr_fence_strict_unlock(void) -{ - __asm__ __volatile__("mfence" ::: "memory"); -} -# 103 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void -ck_pr_rfo(const void *m) -{ - - __asm__ __volatile__("prefetchw (%0)" - : - : "r" (m) - : "memory"); - - return; -} -# 131 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void * ck_pr_fas_ptr(void *target, void * v) -{ - __asm__ __volatile__("xchgq" " %0, %1" : "+m" (*(char *)target), "+q" (v) : : "memory"); - return v; -} - - - -__attribute__((unused)) static double ck_pr_fas_double(double *target, double v) -{ - __asm__ __volatile__("xchgq" " %0, %1" : "+m" (*(double *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static char ck_pr_fas_char(char *target, char v) -{ - __asm__ __volatile__("xchgb" " %0, %1" : "+m" (*(char *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static unsigned int ck_pr_fas_uint(unsigned int *target, unsigned int v) -{ - __asm__ __volatile__("xchgl" " %0, %1" : "+m" (*(unsigned int *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static int ck_pr_fas_int(int *target, int v) -{ - __asm__ __volatile__("xchgl" " %0, %1" : "+m" (*(int *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static uint64_t ck_pr_fas_64(uint64_t *target, uint64_t v) -{ - __asm__ __volatile__("xchgq" " %0, %1" : "+m" (*(uint64_t *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static uint32_t ck_pr_fas_32(uint32_t *target, uint32_t v) -{ - __asm__ __volatile__("xchgl" " %0, %1" : "+m" (*(uint32_t *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static uint16_t ck_pr_fas_16(uint16_t *target, uint16_t v) -{ - __asm__ __volatile__("xchgw" " %0, %1" : "+m" (*(uint16_t *)target), "+q" (v) : : "memory"); - return v; -} -__attribute__((unused)) static uint8_t ck_pr_fas_8(uint8_t *target, uint8_t v) -{ - __asm__ __volatile__("xchgb" " %0, %1" : "+m" (*(uint8_t *)target), "+q" (v) : : "memory"); - return v; -} -# 162 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void * ck_pr_md_load_ptr(const void *target) -{ - void * r; - __asm__ __volatile__("movq" " %1, %0" : "=q" (r) : "m" (*(const char *)target) : "memory"); - return (r); -} - - - -__attribute__((unused)) static char ck_pr_md_load_char(const char *target) -{ - char r; - __asm__ __volatile__("movb" " %1, %0" : "=q" (r) : "m" (*(const char *)target) : "memory"); - return (r); -} -__attribute__((unused)) static unsigned int ck_pr_md_load_uint(const unsigned int *target) -{ - unsigned int r; - __asm__ __volatile__("movl" " %1, %0" : "=q" (r) : "m" (*(const unsigned int *)target) : "memory"); - return (r); -} -__attribute__((unused)) static int ck_pr_md_load_int(const int *target) -{ - int r; - __asm__ __volatile__("movl" " %1, %0" : "=q" (r) : "m" (*(const int *)target) : "memory"); - return (r); -} -__attribute__((unused)) static double ck_pr_md_load_double(const double *target) -{ - double r; - __asm__ __volatile__("movq" " %1, %0" : "=q" (r) : "m" (*(const double *)target) : "memory"); - return (r); -} -__attribute__((unused)) static uint64_t ck_pr_md_load_64(const uint64_t *target) -{ - uint64_t r; - __asm__ __volatile__("movq" " %1, %0" : "=q" (r) : "m" (*(const uint64_t *)target) : "memory"); - return (r); -} -__attribute__((unused)) static uint32_t ck_pr_md_load_32(const uint32_t *target) -{ - uint32_t r; - __asm__ __volatile__("movl" " %1, %0" : "=q" (r) : "m" (*(const uint32_t *)target) : "memory"); - return (r); -} -__attribute__((unused)) static uint16_t ck_pr_md_load_16(const uint16_t *target) -{ - uint16_t r; - __asm__ __volatile__("movw" " %1, %0" : "=q" (r) : "m" (*(const uint16_t *)target) : "memory"); - return (r); -} -__attribute__((unused)) static uint8_t ck_pr_md_load_8(const uint8_t *target) -{ - uint8_t r; - __asm__ __volatile__("movb" " %1, %0" : "=q" (r) : "m" (*(const uint8_t *)target) : "memory"); - return (r); -} - - - - -__attribute__((unused)) static void -ck_pr_load_64_2(const uint64_t target[2], uint64_t v[2]) -{ - __asm__ __volatile__("movq %%rdx, %%rcx;" - "movq %%rax, %%rbx;" - "lock " "cmpxchg16b %2;" - : "=a" (v[0]), - "=d" (v[1]) - : "m" (*(const uint64_t *)target) - : "rbx", "rcx", "memory", "cc"); - return; -} - -__attribute__((unused)) static void -ck_pr_load_ptr_2(const void *t, void *v) -{ - ck_pr_load_64_2(t, - v); - return; -} -# 208 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_md_load_char_16(const char t[2], char v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -__attribute__((unused)) static void ck_pr_md_load_int_4(const int t[2], int v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -__attribute__((unused)) static void ck_pr_md_load_uint_4(const unsigned int t[2], unsigned int v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -__attribute__((unused)) static void ck_pr_md_load_32_4(const uint32_t t[2], uint32_t v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -__attribute__((unused)) static void ck_pr_md_load_16_8(const uint16_t t[2], uint16_t v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -__attribute__((unused)) static void ck_pr_md_load_8_16(const uint8_t t[2], uint8_t v[2]) -{ - ck_pr_load_64_2((const uint64_t *)(const void *)t, (uint64_t *)(void *)v); - return; -} -# 242 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_md_store_ptr(void *target, const void * v) -{ - __asm__ __volatile__("movq" " %1, %0" : "=m" (*(char *)target) : "Z" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_double(double *target, double v) -{ - __asm__ __volatile__("movq" " %1, %0" : "=m" (*(double *)target) : "q" (v) : "memory"); - return; -} - - - -__attribute__((unused)) static void ck_pr_md_store_char(char *target, char v) -{ - __asm__ __volatile__("movb" " %1, %0" : "=m" (*(char *)target) : "e" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_int(int *target, int v) -{ - __asm__ __volatile__("movl" " %1, %0" : "=m" (*(int *)target) : "e" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_uint(unsigned int *target, unsigned int v) -{ - __asm__ __volatile__("movl" " %1, %0" : "=m" (*(unsigned int *)target) : "Z" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_64(uint64_t *target, uint64_t v) -{ - __asm__ __volatile__("movq" " %1, %0" : "=m" (*(uint64_t *)target) : "Z" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_32(uint32_t *target, uint32_t v) -{ - __asm__ __volatile__("movl" " %1, %0" : "=m" (*(uint32_t *)target) : "Z" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_16(uint16_t *target, uint16_t v) -{ - __asm__ __volatile__("movw" " %1, %0" : "=m" (*(uint16_t *)target) : "Z" "q" (v) : "memory"); - return; -} -__attribute__((unused)) static void ck_pr_md_store_8(uint8_t *target, uint8_t v) -{ - __asm__ __volatile__("movb" " %1, %0" : "=m" (*(uint8_t *)target) : "Z" "q" (v) : "memory"); - return; -} -# 274 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static uintptr_t ck_pr_faa_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "xaddq" " %1, %0" : "+m" (*(char *)target), "+q" (d) : : "memory", "cc"); - return (d); -} - - - -__attribute__((unused)) static char ck_pr_faa_char(char *target, char d) -{ - __asm__ __volatile__("lock " "xaddb" " %1, %0" : "+m" (*(char *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static unsigned int ck_pr_faa_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "xaddl" " %1, %0" : "+m" (*(unsigned int *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static int ck_pr_faa_int(int *target, int d) -{ - __asm__ __volatile__("lock " "xaddl" " %1, %0" : "+m" (*(int *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static uint64_t ck_pr_faa_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "xaddq" " %1, %0" : "+m" (*(uint64_t *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static uint32_t ck_pr_faa_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "xaddl" " %1, %0" : "+m" (*(uint32_t *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static uint16_t ck_pr_faa_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "xaddw" " %1, %0" : "+m" (*(uint16_t *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -__attribute__((unused)) static uint8_t ck_pr_faa_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "xaddb" " %1, %0" : "+m" (*(uint8_t *)target), "+q" (d) : : "memory", "cc"); - return (d); -} -# 332 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_inc_ptr(void *target) -{ - __asm__ __volatile__("lock " "inc" "q" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_ptr_zero(void *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "q" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_char(char *target) -{ - __asm__ __volatile__("lock " "inc" "b" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_char_zero(char *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "b" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_int(int *target) -{ - __asm__ __volatile__("lock " "inc" "l" " %0" : "+m" (*(int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_int_zero(int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "l" " %0; setz %1" : "+m" (*(int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_uint(unsigned int *target) -{ - __asm__ __volatile__("lock " "inc" "l" " %0" : "+m" (*(unsigned int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_uint_zero(unsigned int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "l" " %0; setz %1" : "+m" (*(unsigned int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_64(uint64_t *target) -{ - __asm__ __volatile__("lock " "inc" "q" " %0" : "+m" (*(uint64_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_64_zero(uint64_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "q" " %0; setz %1" : "+m" (*(uint64_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_32(uint32_t *target) -{ - __asm__ __volatile__("lock " "inc" "l" " %0" : "+m" (*(uint32_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_32_zero(uint32_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "l" " %0; setz %1" : "+m" (*(uint32_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_16(uint16_t *target) -{ - __asm__ __volatile__("lock " "inc" "w" " %0" : "+m" (*(uint16_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_16_zero(uint16_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "w" " %0; setz %1" : "+m" (*(uint16_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_8(uint8_t *target) -{ - __asm__ __volatile__("lock " "inc" "b" " %0" : "+m" (*(uint8_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_inc_8_zero(uint8_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "inc" "b" " %0; setz %1" : "+m" (*(uint8_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_ptr(void *target) -{ - __asm__ __volatile__("lock " "dec" "q" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_ptr_zero(void *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "q" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_char(char *target) -{ - __asm__ __volatile__("lock " "dec" "b" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_char_zero(char *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "b" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_int(int *target) -{ - __asm__ __volatile__("lock " "dec" "l" " %0" : "+m" (*(int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_int_zero(int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "l" " %0; setz %1" : "+m" (*(int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_uint(unsigned int *target) -{ - __asm__ __volatile__("lock " "dec" "l" " %0" : "+m" (*(unsigned int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_uint_zero(unsigned int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "l" " %0; setz %1" : "+m" (*(unsigned int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_64(uint64_t *target) -{ - __asm__ __volatile__("lock " "dec" "q" " %0" : "+m" (*(uint64_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_64_zero(uint64_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "q" " %0; setz %1" : "+m" (*(uint64_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_32(uint32_t *target) -{ - __asm__ __volatile__("lock " "dec" "l" " %0" : "+m" (*(uint32_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_32_zero(uint32_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "l" " %0; setz %1" : "+m" (*(uint32_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_16(uint16_t *target) -{ - __asm__ __volatile__("lock " "dec" "w" " %0" : "+m" (*(uint16_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_16_zero(uint16_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "w" " %0; setz %1" : "+m" (*(uint16_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_8(uint8_t *target) -{ - __asm__ __volatile__("lock " "dec" "b" " %0" : "+m" (*(uint8_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_dec_8_zero(uint8_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "dec" "b" " %0; setz %1" : "+m" (*(uint8_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_ptr(void *target) -{ - __asm__ __volatile__("lock " "neg" "q" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_ptr_zero(void *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "q" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_char(char *target) -{ - __asm__ __volatile__("lock " "neg" "b" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_char_zero(char *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "b" " %0; setz %1" : "+m" (*(char *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_int(int *target) -{ - __asm__ __volatile__("lock " "neg" "l" " %0" : "+m" (*(int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_int_zero(int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "l" " %0; setz %1" : "+m" (*(int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_uint(unsigned int *target) -{ - __asm__ __volatile__("lock " "neg" "l" " %0" : "+m" (*(unsigned int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_uint_zero(unsigned int *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "l" " %0; setz %1" : "+m" (*(unsigned int *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_64(uint64_t *target) -{ - __asm__ __volatile__("lock " "neg" "q" " %0" : "+m" (*(uint64_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_64_zero(uint64_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "q" " %0; setz %1" : "+m" (*(uint64_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_32(uint32_t *target) -{ - __asm__ __volatile__("lock " "neg" "l" " %0" : "+m" (*(uint32_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_32_zero(uint32_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "l" " %0; setz %1" : "+m" (*(uint32_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_16(uint16_t *target) -{ - __asm__ __volatile__("lock " "neg" "w" " %0" : "+m" (*(uint16_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_16_zero(uint16_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "w" " %0; setz %1" : "+m" (*(uint16_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_8(uint8_t *target) -{ - __asm__ __volatile__("lock " "neg" "b" " %0" : "+m" (*(uint8_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_neg_8_zero(uint8_t *target, _Bool *r) -{ - __asm__ __volatile__("lock " "neg" "b" " %0; setz %1" : "+m" (*(uint8_t *)target), "=m" (*r) : : "memory", "cc"); - return; -} - - - - -__attribute__((unused)) static void ck_pr_not_ptr(void *target) -{ - __asm__ __volatile__("lock " "not" "q" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_char(char *target) -{ - __asm__ __volatile__("lock " "not" "b" " %0" : "+m" (*(char *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_int(int *target) -{ - __asm__ __volatile__("lock " "not" "l" " %0" : "+m" (*(int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_uint(unsigned int *target) -{ - __asm__ __volatile__("lock " "not" "l" " %0" : "+m" (*(unsigned int *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_64(uint64_t *target) -{ - __asm__ __volatile__("lock " "not" "q" " %0" : "+m" (*(uint64_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_32(uint32_t *target) -{ - __asm__ __volatile__("lock " "not" "l" " %0" : "+m" (*(uint32_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_16(uint16_t *target) -{ - __asm__ __volatile__("lock " "not" "w" " %0" : "+m" (*(uint16_t *)target) : : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_not_8(uint8_t *target) -{ - __asm__ __volatile__("lock " "not" "b" " %0" : "+m" (*(uint8_t *)target) : : "memory", "cc"); - return; -} -# 373 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_add_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "add" "q" " %1, %0" : "+m" (*(char *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_char(char *target, char d) -{ - __asm__ __volatile__("lock " "add" "b" " %1, %0" : "+m" (*(char *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_int(int *target, int d) -{ - __asm__ __volatile__("lock " "add" "l" " %1, %0" : "+m" (*(int *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "add" "l" " %1, %0" : "+m" (*(unsigned int *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "add" "q" " %1, %0" : "+m" (*(uint64_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "add" "l" " %1, %0" : "+m" (*(uint32_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "add" "w" " %1, %0" : "+m" (*(uint16_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_add_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "add" "b" " %1, %0" : "+m" (*(uint8_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "sub" "q" " %1, %0" : "+m" (*(char *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_char(char *target, char d) -{ - __asm__ __volatile__("lock " "sub" "b" " %1, %0" : "+m" (*(char *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_int(int *target, int d) -{ - __asm__ __volatile__("lock " "sub" "l" " %1, %0" : "+m" (*(int *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "sub" "l" " %1, %0" : "+m" (*(unsigned int *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "sub" "q" " %1, %0" : "+m" (*(uint64_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "sub" "l" " %1, %0" : "+m" (*(uint32_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "sub" "w" " %1, %0" : "+m" (*(uint16_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_sub_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "sub" "b" " %1, %0" : "+m" (*(uint8_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "and" "q" " %1, %0" : "+m" (*(char *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_char(char *target, char d) -{ - __asm__ __volatile__("lock " "and" "b" " %1, %0" : "+m" (*(char *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_int(int *target, int d) -{ - __asm__ __volatile__("lock " "and" "l" " %1, %0" : "+m" (*(int *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "and" "l" " %1, %0" : "+m" (*(unsigned int *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "and" "q" " %1, %0" : "+m" (*(uint64_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "and" "l" " %1, %0" : "+m" (*(uint32_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "and" "w" " %1, %0" : "+m" (*(uint16_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_and_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "and" "b" " %1, %0" : "+m" (*(uint8_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "or" "q" " %1, %0" : "+m" (*(char *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_char(char *target, char d) -{ - __asm__ __volatile__("lock " "or" "b" " %1, %0" : "+m" (*(char *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_int(int *target, int d) -{ - __asm__ __volatile__("lock " "or" "l" " %1, %0" : "+m" (*(int *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "or" "l" " %1, %0" : "+m" (*(unsigned int *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "or" "q" " %1, %0" : "+m" (*(uint64_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "or" "l" " %1, %0" : "+m" (*(uint32_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "or" "w" " %1, %0" : "+m" (*(uint16_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_or_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "or" "b" " %1, %0" : "+m" (*(uint8_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_ptr(void *target, uintptr_t d) -{ - __asm__ __volatile__("lock " "xor" "q" " %1, %0" : "+m" (*(char *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_char(char *target, char d) -{ - __asm__ __volatile__("lock " "xor" "b" " %1, %0" : "+m" (*(char *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_int(int *target, int d) -{ - __asm__ __volatile__("lock " "xor" "l" " %1, %0" : "+m" (*(int *)target) : "e" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_uint(unsigned int *target, unsigned int d) -{ - __asm__ __volatile__("lock " "xor" "l" " %1, %0" : "+m" (*(unsigned int *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_64(uint64_t *target, uint64_t d) -{ - __asm__ __volatile__("lock " "xor" "q" " %1, %0" : "+m" (*(uint64_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_32(uint32_t *target, uint32_t d) -{ - __asm__ __volatile__("lock " "xor" "l" " %1, %0" : "+m" (*(uint32_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_16(uint16_t *target, uint16_t d) -{ - __asm__ __volatile__("lock " "xor" "w" " %1, %0" : "+m" (*(uint16_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -__attribute__((unused)) static void ck_pr_xor_8(uint8_t *target, uint8_t d) -{ - __asm__ __volatile__("lock " "xor" "b" " %1, %0" : "+m" (*(uint8_t *)target) : "Z" "q" (d) : "memory", "cc"); - return; -} -# 400 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static _Bool ck_pr_cas_ptr(void *target, void * compare, void * set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgq" " %2, %0; setz %1" : "+m" (*(char *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} - - - -__attribute__((unused)) static _Bool ck_pr_cas_char(char *target, char compare, char set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgb" " %2, %0; setz %1" : "+m" (*(char *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_int(int *target, int compare, int set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgl" " %2, %0; setz %1" : "+m" (*(int *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_uint(unsigned int *target, unsigned int compare, unsigned int set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgl" " %2, %0; setz %1" : "+m" (*(unsigned int *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_double(double *target, double compare, double set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgq" " %2, %0; setz %1" : "+m" (*(double *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_64(uint64_t *target, uint64_t compare, uint64_t set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgq" " %2, %0; setz %1" : "+m" (*(uint64_t *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_32(uint32_t *target, uint32_t compare, uint32_t set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgl" " %2, %0; setz %1" : "+m" (*(uint32_t *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_16(uint16_t *target, uint16_t compare, uint16_t set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgw" " %2, %0; setz %1" : "+m" (*(uint16_t *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_8(uint8_t *target, uint8_t compare, uint8_t set) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchgb" " %2, %0; setz %1" : "+m" (*(uint8_t *)target), "=a" (z) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -# 436 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static _Bool ck_pr_cas_ptr_value(void *target, void * compare, void * set, void *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "q" " %3, %0;" "mov %% " "rax" ", %2;" "setz %1;" : "+m" (*(char *)target), "=a" (z), "=m" (*(char *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} - - - - -__attribute__((unused)) static _Bool ck_pr_cas_char_value(char *target, char compare, char set, char *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "b" " %3, %0;" "mov %% " "al" ", %2;" "setz %1;" : "+m" (*(char *)target), "=a" (z), "=m" (*(char *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_int_value(int *target, int compare, int set, int *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "l" " %3, %0;" "mov %% " "eax" ", %2;" "setz %1;" : "+m" (*(int *)target), "=a" (z), "=m" (*(int *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_uint_value(unsigned int *target, unsigned int compare, unsigned int set, unsigned int *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "l" " %3, %0;" "mov %% " "eax" ", %2;" "setz %1;" : "+m" (*(unsigned int *)target), "=a" (z), "=m" (*(unsigned int *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_double_value(double *target, double compare, double set, double *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "q" " %3, %0;" "mov %% " "rax" ", %2;" "setz %1;" : "+m" (*(double *)target), "=a" (z), "=m" (*(double *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_64_value(uint64_t *target, uint64_t compare, uint64_t set, uint64_t *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "q" " %3, %0;" "mov %% " "rax" ", %2;" "setz %1;" : "+m" (*(uint64_t *)target), "=a" (z), "=m" (*(uint64_t *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_32_value(uint32_t *target, uint32_t compare, uint32_t set, uint32_t *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "l" " %3, %0;" "mov %% " "eax" ", %2;" "setz %1;" : "+m" (*(uint32_t *)target), "=a" (z), "=m" (*(uint32_t *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_16_value(uint16_t *target, uint16_t compare, uint16_t set, uint16_t *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "w" " %3, %0;" "mov %% " "ax" ", %2;" "setz %1;" : "+m" (*(uint16_t *)target), "=a" (z), "=m" (*(uint16_t *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} -__attribute__((unused)) static _Bool ck_pr_cas_8_value(uint8_t *target, uint8_t compare, uint8_t set, uint8_t *v) -{ - _Bool z; - __asm__ __volatile__("lock " "cmpxchg" "b" " %3, %0;" "mov %% " "al" ", %2;" "setz %1;" : "+m" (*(uint8_t *)target), "=a" (z), "=m" (*(uint8_t *)v) : "q" (set), "a" (compare) : "memory", "cc"); - return z; -} - - - - - - - -__attribute__((unused)) static _Bool -ck_pr_cas_64_2(uint64_t target[2], uint64_t compare[2], uint64_t set[2]) -{ - _Bool z; - - __asm__ __volatile__("movq 0(%4), %%rax;" - "movq 8(%4), %%rdx;" - "lock " "cmpxchg16b %0; setz %1" - : "+m" (*target), - "=q" (z) - : "b" (set[0]), - "c" (set[1]), - "q" (compare) - : "memory", "cc", "%rax", "%rdx"); - return z; -} - -__attribute__((unused)) static _Bool -ck_pr_cas_ptr_2(void *t, void *c, void *s) -{ - return ck_pr_cas_64_2(t, - c, - s); -} - -__attribute__((unused)) static _Bool -ck_pr_cas_64_2_value(uint64_t target[2], - uint64_t compare[2], - uint64_t set[2], - uint64_t v[2]) -{ - _Bool z; - - __asm__ __volatile__("lock " "cmpxchg16b %0;" - "setz %3" - : "+m" (*target), - "=a" (v[0]), - "=d" (v[1]), - "=q" (z) - : "a" (compare[0]), - "d" (compare[1]), - "b" (set[0]), - "c" (set[1]) - : "memory", "cc"); - return z; -} - -__attribute__((unused)) static _Bool -ck_pr_cas_ptr_2_value(void *t, void *c, void *s, void *v) -{ - return ck_pr_cas_64_2_value(t, - c, - s, - v); -} -# 529 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static _Bool ck_pr_cas_double_2(double t[2], double c[2], double s[2]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_double_2_value(double *t, double c[2], double s[2], double *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_char_16(char t[16], char c[16], char s[16]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_char_16_value(char *t, char c[16], char s[16], char *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_int_4(int t[4], int c[4], int s[4]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_int_4_value(int *t, int c[4], int s[4], int *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_uint_4(unsigned int t[4], unsigned int c[4], unsigned int s[4]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_uint_4_value(unsigned int *t, unsigned int c[4], unsigned int s[4], unsigned int *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_32_4(uint32_t t[4], uint32_t c[4], uint32_t s[4]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_32_4_value(uint32_t *t, uint32_t c[4], uint32_t s[4], uint32_t *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_16_8(uint16_t t[8], uint16_t c[8], uint16_t s[8]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_16_8_value(uint16_t *t, uint16_t c[8], uint16_t s[8], uint16_t *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -__attribute__((unused)) static _Bool ck_pr_cas_8_16(uint8_t t[16], uint8_t c[16], uint8_t s[16]) -{ - return ck_pr_cas_64_2((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s); -} -__attribute__((unused)) static _Bool ck_pr_cas_8_16_value(uint8_t *t, uint8_t c[16], uint8_t s[16], uint8_t *v) -{ - return ck_pr_cas_64_2_value((uint64_t *)(void *)t, (uint64_t *)(void *)c, (uint64_t *)(void *)s, (uint64_t *)(void *)v); -} -# 565 "/usr/local/include/gcc/x86_64/ck_pr.h" 3 -__attribute__((unused)) static _Bool ck_pr_btc_ptr(void *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "q %2, %0" "; setc %1" : "+m" (*(char *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btc_uint(unsigned int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "l %2, %0" "; setc %1" : "+m" (*(unsigned int *)target), "=q" (c) : "q" ((unsigned int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btc_int(int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "l %2, %0" "; setc %1" : "+m" (*(int *)target), "=q" (c) : "q" ((int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btc_64(uint64_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "q %2, %0" "; setc %1" : "+m" (*(uint64_t *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btc_32(uint32_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "l %2, %0" "; setc %1" : "+m" (*(uint32_t *)target), "=q" (c) : "q" ((uint32_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btc_16(uint16_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btc" "w %w2, %0" "; setc %1" : "+m" (*(uint16_t *)target), "=q" (c) : "q" ((uint16_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_ptr(void *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "q %2, %0" "; setc %1" : "+m" (*(char *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_uint(unsigned int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "l %2, %0" "; setc %1" : "+m" (*(unsigned int *)target), "=q" (c) : "q" ((unsigned int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_int(int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "l %2, %0" "; setc %1" : "+m" (*(int *)target), "=q" (c) : "q" ((int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_64(uint64_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "q %2, %0" "; setc %1" : "+m" (*(uint64_t *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_32(uint32_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "l %2, %0" "; setc %1" : "+m" (*(uint32_t *)target), "=q" (c) : "q" ((uint32_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_bts_16(uint16_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "bts" "w %w2, %0" "; setc %1" : "+m" (*(uint16_t *)target), "=q" (c) : "q" ((uint16_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_ptr(void *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "q %2, %0" "; setc %1" : "+m" (*(char *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_uint(unsigned int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "l %2, %0" "; setc %1" : "+m" (*(unsigned int *)target), "=q" (c) : "q" ((unsigned int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_int(int *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "l %2, %0" "; setc %1" : "+m" (*(int *)target), "=q" (c) : "q" ((int)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_64(uint64_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "q %2, %0" "; setc %1" : "+m" (*(uint64_t *)target), "=q" (c) : "q" ((uint64_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_32(uint32_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "l %2, %0" "; setc %1" : "+m" (*(uint32_t *)target), "=q" (c) : "q" ((uint32_t)b) : "memory", "cc"); - return c; -} -__attribute__((unused)) static _Bool ck_pr_btr_16(uint16_t *target, unsigned int b) -{ - _Bool c; - __asm__ __volatile__("lock " "btr" "w %w2, %0" "; setc %1" : "+m" (*(uint16_t *)target), "=q" (c) : "q" ((uint16_t)b) : "memory", "cc"); - return c; -} -# 40 "/usr/local/include/ck_pr.h" 2 3 -# 56 "/usr/local/include/ck_pr.h" 3 -# 1 "/usr/local/include/gcc/ck_pr.h" 1 3 -# 36 "/usr/local/include/gcc/ck_pr.h" 3 -__attribute__((unused)) static void -ck_pr_barrier(void) -{ - - __asm__ __volatile__("" ::: "memory"); - return; -} -# 57 "/usr/local/include/ck_pr.h" 2 3 -# 78 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_fence_load_depends(void) -{ - ck_pr_barrier(); - return; -} -# 128 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_fence_atomic(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_atomic_load(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_atomic_store(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_store_atomic(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_load_atomic(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_load_store(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_store_load(void) -{ - ck_pr_fence_strict_store_load(); - return; -} -__attribute__((unused)) static void ck_pr_fence_load(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_store(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_memory(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_acquire(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_release(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_lock(void) -{ - ck_pr_barrier(); - return; -} -__attribute__((unused)) static void ck_pr_fence_unlock(void) -{ - ck_pr_barrier(); - return; -} -# 277 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_add_double(double *target, double value) -{ - double previous; - double punt; - punt = ck_pr_md_load_double(target); - previous = (double)punt; - while (ck_pr_cas_double_value(target, (double)previous, (double)(previous + value), &previous) == 0) ck_pr_stall(); - return; -} - - - - -__attribute__((unused)) static void ck_pr_sub_double(double *target, double value) -{ - double previous; - double punt; - punt = ck_pr_md_load_double(target); - previous = (double)punt; - while (ck_pr_cas_double_value(target, (double)previous, (double)(previous - value), &previous) == 0) ck_pr_stall(); - return; -} -# 677 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_inc_double(double *target) -{ - ck_pr_add_double(target, (double)1); - return; -} - - - - -__attribute__((unused)) static void ck_pr_dec_double(double *target) -{ - ck_pr_sub_double(target, (double)1); - return; -} -# 916 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static void ck_pr_neg_double(double *target) -{ - double previous; - double punt; - punt = (double)ck_pr_md_load_double(target); - previous = (double)punt; - while (ck_pr_cas_double_value(target, (double)previous, (double)(- previous), &previous) == 0) ck_pr_stall(); - return; -} -# 1107 "/usr/local/include/ck_pr.h" 3 -__attribute__((unused)) static double ck_pr_faa_double(double *target, double delta) -{ - double previous; - double punt; - punt = (double)ck_pr_md_load_double(target); - previous = (double)punt; - while (ck_pr_cas_double_value(target, (double)previous, (double)(previous + delta), &previous) == 0) ck_pr_stall(); - return ((double)previous); -} -# 103 "rtapi/rtapi.h" 2 - - - - - - - - - -# 1 "rtapi/rtapi_global.h" 1 -# 64 "rtapi/rtapi_global.h" -# 1 "rtapi/rtapi_shmkeys.h" 1 -# 65 "rtapi/rtapi_global.h" 2 -# 1 "rtapi/rtapi_bitops.h" 1 -# 48 "rtapi/rtapi_bitops.h" -typedef unsigned long rtapi_atomic_type; -# 75 "rtapi/rtapi_bitops.h" -static inline int rtapi_test_and_set_bit(int nr, rtapi_atomic_type *bitmap) -{ - return (__atomic_fetch_or(bitmap + ((nr) / (8 * sizeof(rtapi_atomic_type))), - (1UL << ((nr) % (8 * sizeof(rtapi_atomic_type)))), - 5) - & (1UL << ((nr) % (8 * sizeof(rtapi_atomic_type))))) != 0; -} - -static inline rtapi_atomic_type rtapi_test_and_clear_bit(int nr, rtapi_atomic_type * bitmap) -{ - return (__atomic_fetch_and(bitmap + ((nr) / (8 * sizeof(rtapi_atomic_type))), - ~(1UL << ((nr) % (8 * sizeof(rtapi_atomic_type)))), - 5) - & (1UL << ((nr) % (8 * sizeof(rtapi_atomic_type))))) != 0; -} - -static inline void rtapi_set_bit(int nr, rtapi_atomic_type * bitmap) -{ - __atomic_or_fetch(bitmap + ((nr) / (8 * sizeof(rtapi_atomic_type))), - (1UL << ((nr) % (8 * sizeof(rtapi_atomic_type)))), - 5); -} - -static inline void rtapi_clear_bit(int nr, rtapi_atomic_type * bitmap) -{ - __atomic_and_fetch(bitmap + ((nr) / (8 * sizeof(rtapi_atomic_type))), - ~(1UL << ((nr) % (8 * sizeof(rtapi_atomic_type)))), - 5); -} - -static inline rtapi_atomic_type rtapi_test_bit(int nr, rtapi_atomic_type * const bitmap) -{ - return (__atomic_fetch_or(bitmap + ((nr) / (8 * sizeof(rtapi_atomic_type))), - 0, - 5) - & (1UL << ((nr) % (8 * sizeof(rtapi_atomic_type))))) != 0; -} - -static inline rtapi_atomic_type rtapi_add_and_fetch(int delta, - rtapi_atomic_type * const value) -{ - return __atomic_add_fetch (value, delta, 5); -} - -static inline rtapi_atomic_type rtapi_subtract_and_fetch(int delta, - rtapi_atomic_type * const value) -{ - return __atomic_sub_fetch (value, delta, 5); -} -# 66 "rtapi/rtapi_global.h" 2 -# 1 "rtapi/rtapi_exception.h" 1 -# 22 "rtapi/rtapi_exception.h" -typedef void * exc_register_t; - - - - -typedef enum { - RTAPI_EXCEPTION_NONE=0, - - - RTAI_RTE_TMROVRN, - - RTAI_RTE_UNBLKD, - RTAI_RTE_UNCLASSIFIED, - RTAI_TRAP, - - - XK_TRAP, - XK_TRAP_BUG, - XK_ETIMEDOUT, - - XK_EWOULDBLOCK, - XK_EINTR, - XK_EPERM, - XK_UNDOCUMENTED, - - - XU_SIGXCPU, - XU_SIGXCPU_BUG, - XU_ETIMEDOUT, - XU_EWOULDBLOCK, - XU_EINTR, - XU_EPERM, - XU_UNDOCUMENTED, - - - RTP_DEADLINE_MISSED, - - RTAPI_EXCEPTION_LAST, - -} rtapi_exception_t; -# 74 "rtapi/rtapi_exception.h" -typedef struct { - - int trap_errors; - - - - int modeswitches; - int ctxswitches; - int pagefaults; - long long exectime; - unsigned status; - - - - int wait_errors; - int total_overruns; - - - - -} xenomai_stats_t; - -typedef struct { - int wait_errors; -} rtai_stats_t; - -typedef struct { - - int wait_errors; - - - long utime_sec; - long utime_usec; - - long stime_sec; - long stime_usec; - - long ru_minflt; - long ru_majflt; - long ru_nsignals; - long ru_nivcsw; - - long startup_ru_minflt; - long startup_ru_majflt; - long startup_ru_nivcsw; - -} rtprempt_stats_t; - - - -typedef struct { - - int num_updates; - - - - - - - int api_errors; - int other_errors; - - - union { - xenomai_stats_t xeno; - rtai_stats_t rtai; - rtprempt_stats_t rtpreempt; - } flavor; -} rtapi_threadstatus_t; - - - - -typedef struct { - - unsigned event; - unsigned domid; - exc_register_t ip; - exc_register_t sp; - int pid; - int errcode; - - - unsigned long overruns; - - - void *siginfo; - -} xenomai_exception_t; - -typedef struct { - - unsigned vector; - int signo; - exc_register_t ip; - -} rtai_exception_t; - -typedef struct { - - - void *siginfo; -} rtpreempt_exception_t; - - - - -typedef struct { - int task_id; - int error_code; - - - union { - - xenomai_exception_t xeno; - - rtai_exception_t rtai; - - - rtpreempt_exception_t rtpreempt; - } flavor; -} rtapi_exception_detail_t; -# 206 "rtapi/rtapi_exception.h" -typedef int (*rtapi_exception_handler_t) (rtapi_exception_t type, - - - rtapi_exception_detail_t *, - rtapi_threadstatus_t *); -# 67 "rtapi/rtapi_global.h" 2 -# 1 "rtapi/ring.h" 1 -# 65 "rtapi/ring.h" -# 1 "rtapi/rtapi_mbarrier.h" 1 -# 66 "rtapi/ring.h" 2 -# 1 "rtapi/rtapi_string.h" 1 -# 39 "rtapi/rtapi_string.h" -# 1 "/usr/include/string.h" 1 3 4 -# 27 "/usr/include/string.h" 3 4 - - - - - -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 1 3 4 -# 33 "/usr/include/string.h" 2 3 4 -# 44 "/usr/include/string.h" 3 4 - - -extern void *memcpy (void *__restrict __dest, const void *__restrict __src, - size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern void *memmove (void *__dest, const void *__src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - - - - -extern void *memccpy (void *__restrict __dest, const void *__restrict __src, - int __c, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - - - -extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); - - -extern int memcmp (const void *__s1, const void *__s2, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); -# 96 "/usr/include/string.h" 3 4 -extern void *memchr (const void *__s, int __c, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - -# 110 "/usr/include/string.h" 3 4 -extern void *rawmemchr (const void *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); -# 121 "/usr/include/string.h" 3 4 -extern void *memrchr (const void *__s, int __c, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - - - - - -extern char *strcpy (char *__restrict __dest, const char *__restrict __src) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - -extern char *strncpy (char *__restrict __dest, - const char *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern char *strcat (char *__restrict __dest, const char *__restrict __src) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - -extern char *strncat (char *__restrict __dest, const char *__restrict __src, - size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern int strcmp (const char *__s1, const char *__s2) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - -extern int strncmp (const char *__s1, const char *__s2, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern int strcoll (const char *__s1, const char *__s2) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - -extern size_t strxfrm (char *__restrict __dest, - const char *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); - - - - - - -# 1 "/usr/include/xlocale.h" 1 3 4 -# 27 "/usr/include/xlocale.h" 3 4 -typedef struct __locale_struct { - - struct __locale_data *__locales[13]; - - - const unsigned short int *__ctype_b; - const int *__ctype_tolower; - const int *__ctype_toupper; - - - const char *__names[13]; -} *__locale_t; - - -typedef __locale_t locale_t; -# 164 "/usr/include/string.h" 2 3 4 - - -extern int strcoll_l (const char *__s1, const char *__s2, __locale_t __l) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3))); - -extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n, - __locale_t __l) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4))); - - - - - -extern char *strdup (const char *__s) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); - - - - - - -extern char *strndup (const char *__string, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); -# 211 "/usr/include/string.h" 3 4 - -# 236 "/usr/include/string.h" 3 4 -extern char *strchr (const char *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); -# 263 "/usr/include/string.h" 3 4 -extern char *strrchr (const char *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - -# 277 "/usr/include/string.h" 3 4 -extern char *strchrnul (const char *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - - - - - -extern size_t strcspn (const char *__s, const char *__reject) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern size_t strspn (const char *__s, const char *__accept) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); -# 315 "/usr/include/string.h" 3 4 -extern char *strpbrk (const char *__s, const char *__accept) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); -# 342 "/usr/include/string.h" 3 4 -extern char *strstr (const char *__haystack, const char *__needle) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - - - -extern char *strtok (char *__restrict __s, const char *__restrict __delim) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))); - - - - -extern char *__strtok_r (char *__restrict __s, - const char *__restrict __delim, - char **__restrict __save_ptr) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 3))); - -extern char *strtok_r (char *__restrict __s, const char *__restrict __delim, - char **__restrict __save_ptr) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 3))); -# 373 "/usr/include/string.h" 3 4 -extern char *strcasestr (const char *__haystack, const char *__needle) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - - - - - - -extern void *memmem (const void *__haystack, size_t __haystacklen, - const void *__needle, size_t __needlelen) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 3))); - - - -extern void *__mempcpy (void *__restrict __dest, - const void *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern void *mempcpy (void *__restrict __dest, - const void *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - - - -extern size_t strlen (const char *__s) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - - - - -extern size_t strnlen (const char *__string, size_t __maxlen) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - - - - -extern char *strerror (int __errnum) __attribute__ ((__nothrow__ , __leaf__)); - -# 438 "/usr/include/string.h" 3 4 -extern char *strerror_r (int __errnum, char *__buf, size_t __buflen) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))) ; - - - - - -extern char *strerror_l (int __errnum, __locale_t __l) __attribute__ ((__nothrow__ , __leaf__)); - - - - - -extern void __bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); - - - -extern void bcopy (const void *__src, void *__dest, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern void bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); - - -extern int bcmp (const void *__s1, const void *__s2, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); -# 489 "/usr/include/string.h" 3 4 -extern char *index (const char *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); -# 517 "/usr/include/string.h" 3 4 -extern char *rindex (const char *__s, int __c) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); - - - - -extern int ffs (int __i) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); - - - - -extern int ffsl (long int __l) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); -__extension__ extern int ffsll (long long int __ll) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)); - - - -extern int strcasecmp (const char *__s1, const char *__s2) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern int strncasecmp (const char *__s1, const char *__s2, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - - - - -extern int strcasecmp_l (const char *__s1, const char *__s2, - __locale_t __loc) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3))); - -extern int strncasecmp_l (const char *__s1, const char *__s2, - size_t __n, __locale_t __loc) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 4))); - - - - - -extern char *strsep (char **__restrict __stringp, - const char *__restrict __delim) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - - -extern char *strsignal (int __sig) __attribute__ ((__nothrow__ , __leaf__)); - - -extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern char *stpcpy (char *__restrict __dest, const char *__restrict __src) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - -extern char *__stpncpy (char *__restrict __dest, - const char *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); -extern char *stpncpy (char *__restrict __dest, - const char *__restrict __src, size_t __n) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); - - - - -extern int strverscmp (const char *__s1, const char *__s2) -__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); - - -extern char *strfry (char *__string) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); - - -extern void *memfrob (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -# 604 "/usr/include/string.h" 3 4 -extern char *basename (const char *__filename) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))); -# 644 "/usr/include/string.h" 3 4 - -# 40 "rtapi/rtapi_string.h" 2 -# 67 "rtapi/ring.h" 2 - - - - - - - -typedef __s32 ring_size_t; - -typedef struct { - size_t tail __attribute__((aligned(16))); - __u8 scratchpad_buf[0]; -} ringtrailer_t; - - - - - - - -typedef enum { - RINGTYPE_RECORD = 0, - RINGTYPE_MULTIPART = (1UL << (0)), - RINGTYPE_STREAM = (1UL << (1)), - RINGTYPE_ANY = ((1UL << (0))|(1UL << (1))), - RINGTYPE_MASK = ((1UL << (0))|(1UL << (1))) -} ring_type_t; - - - -typedef enum { - USE_RMUTEX = (1UL << (2)), - USE_WMUTEX = (1UL << (3)), - ALLOC_HALMEM = (1UL << (4)), -} ring_mode_flags_t; - -typedef struct { - __u8 type : 2; - __u8 use_rmutex : 1; - __u8 use_wmutex : 1; - - - - - - - __u8 alloc_halmem : 1; - - __u32 userflags : 27; - - __s32 refcount; - __s32 reader, writer; - __s32 reader_instance, writer_instance; - rtapi_atomic_type rmutex, wmutex; - size_t trailer_size; - size_t size_mask; - size_t size; - size_t head __attribute__((aligned(16))); - __u64 generation; - __u8 buf[0]; -} ringheader_t; -# 137 "rtapi/ring.h" -typedef struct { - __s32 magic; - ringheader_t *header; - ringtrailer_t *trailer; - __u8 *buf; - void *scratchpad; -} ringbuffer_t; - -static inline int ringbuffer_attached(ringbuffer_t *rb) -{ - return (rb->magic == 0x74737769); -} - - -typedef struct { - const ringbuffer_t *ring; - __u64 generation; - size_t offset; -} ringiter_t; - -typedef struct { - const void *rv_base; - size_t rv_len; - __u32 rv_flags; -} ringvec_t; -# 171 "rtapi/ring.h" -static inline ring_size_t size_aligned(const ring_size_t x) -{ - return x + (-x & (8 - 1)); -} - - - -static unsigned inline next_power_of_two(unsigned v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -static inline size_t ring_storage_alloc(int flags, size_t size) -{ - if ((flags & RINGTYPE_MASK) == RINGTYPE_STREAM) { - - return next_power_of_two(size); - } else { - - - return size_aligned(size); - } -} - -static inline size_t ring_trailer_alloc(size_t sp_size) -{ - return size_aligned(sizeof(ringtrailer_t) + sp_size); -} - - - -static inline size_t ring_memsize(int flags, size_t size, size_t sp_size) -{ - return sizeof(ringheader_t) + - ring_storage_alloc(flags, size) + - ring_trailer_alloc(sp_size); -} - -static inline int ring_refcount(ringheader_t *ringheader) -{ - return ringheader->refcount; -} - -static inline ringtrailer_t *_trailer_from_header(const ringheader_t *ringheader) -{ - return (ringtrailer_t *) ((char *)ringheader->buf + ringheader->size); -} - -static inline size_t ring_scratchpad_size(ringbuffer_t *ring) -{ - return ring->header->trailer_size - sizeof(ringtrailer_t); -} - - - - -static inline void ringheader_init(ringheader_t *ringheader, int flags, - size_t size, size_t sp_size) -{ - ringtrailer_t *t; - - - - - - - ringheader->size = ring_storage_alloc(flags,size); - ringheader->trailer_size = ring_trailer_alloc(sp_size); - - - ringheader->rmutex = ringheader->wmutex = 0; - ringheader->reader = ringheader->writer = 0; - ringheader->reader_instance = ringheader->writer_instance = 0; - ringheader->head = 0; - t = _trailer_from_header(ringheader); - t->tail = 0; - ringheader->type = (flags & RINGTYPE_MASK); - - - if (flags & RINGTYPE_STREAM) { - ringheader->size_mask = ringheader->size -1; - } else { - ringheader->generation = 0; - } - ringheader->refcount = 1; -} - - - - - -static inline void ringbuffer_init(ringheader_t *ringheader, ringbuffer_t *ring) -{ - - ring->header = ringheader; - ring->trailer = _trailer_from_header(ringheader); - ring->buf = &ringheader->buf[0]; - - - - if (ring_scratchpad_size(ring)) - ring->scratchpad = ring->trailer->scratchpad_buf; - else - ring->scratchpad = ((void *)0); - ring->magic = 0x74737769; -} -# 300 "rtapi/ring.h" -static inline ring_size_t * _size_at(const ringbuffer_t *ring, const size_t off) -{ - return (ring_size_t *) (ring->buf + off); -} - - - -static inline size_t record_usage(const size_t record_size) -{ - return size_aligned(record_size + sizeof(ring_size_t)); -} -# 337 "rtapi/ring.h" -static inline int record_write_begin(ringbuffer_t *ring, void ** data, size_t sz) -{ - size_t free; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - size_t a = size_aligned(sz + sizeof(ring_size_t)); - - - if (a > h->size) - return 34; - - free = (h->size + h->head - t->tail - 1) % h->size + 1; - - - - if (free <= a) return 11; - - - if (t->tail + a > h->size) { - - - if (h->head <= a) - - return 11; - - - *data = _size_at(ring, 0) + 1; - return 0; - } - - *data = _size_at(ring, t->tail) + 1; - return 0; -} -# 378 "rtapi/ring.h" -static inline int record_write_end(ringbuffer_t *ring, void * data, size_t sz) -{ - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - size_t a = size_aligned(sz + sizeof(ring_size_t)); - - - if (data == _size_at(ring, 0) + 1) { - - - *_size_at(ring, t->tail) = -1; - t->tail = 0; - } - - *_size_at(ring, t->tail) = sz; - - - - - __sync_synchronize(); - - t->tail = (t->tail + a) % h->size; - - return 0; -} -# 414 "rtapi/ring.h" -static inline int record_write(ringbuffer_t *ring, void * data, size_t sz) -{ - void * ptr; - int r = record_write_begin(ring, &ptr, sz); - if (r) return r; - memmove(ptr, data, sz); - return record_write_end(ring, ptr, sz); -} - - - - - - -static inline int _ring_read_at(const ringbuffer_t *ring, size_t offset, - const void **data, size_t *size) -{ - ring_size_t *sz; - ringtrailer_t *t = ring->trailer; - - if (offset == t->tail) - - return 11; - - - __sync_synchronize(); - - sz = _size_at(ring, offset); - if (*sz < 0) - - return _ring_read_at(ring, 0, data, size); - - - *size = *sz; - *data = sz + 1; - return 0; -} -# 463 "rtapi/ring.h" -static inline int record_read(const ringbuffer_t *ring, const void **data, size_t *size) -{ - return _ring_read_at(ring, ring->header->head, data, size); -} - - - - - - -static inline const void *record_next(ringbuffer_t *ring) -{ - const void *data; - size_t size; - if (record_read(ring, &data, &size)) return 0; - return data; -} -# 488 "rtapi/ring.h" -static inline ring_size_t record_next_size(ringbuffer_t *ring) -{ - const void *data; - size_t size; - if (record_read(ring, &data, &size)) return -1; - return size; -} -# 507 "rtapi/ring.h" -static inline size_t record_write_space(const ringheader_t *h) -{ - int avail = 0; - ringtrailer_t *t = _trailer_from_header(h); - - if (t->tail < h->head) - avail = h->head - t->tail; - else - avail = (((h->head) > (h->size - t->tail))?(h->head):(h->size - t->tail)); - return (((0) > (avail - (2 * 8)))?(0):(avail - (2 * 8))); -} -# 529 "rtapi/ring.h" -static inline size_t record_space(size_t element) -{ - return size_aligned(element + sizeof(ring_size_t)); -} - - - -static inline ring_size_t _ring_shift_offset(const ringbuffer_t *ring, size_t offset) -{ - ring_size_t size; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - if (h->head == t->tail) - return -1; - - - - - __sync_synchronize(); - - size = *_size_at(ring, offset); - if (size < 0) - return _ring_shift_offset(ring, 0); - size = size_aligned(size + sizeof(ring_size_t)); - return (offset + size) % h->size; -} -# 578 "rtapi/ring.h" -static inline int record_shift(ringbuffer_t *ring) -{ - ring_size_t off = _ring_shift_offset(ring, ring->header->head); - if (off < 0) return 11; - ring->header->generation++; - ring->header->head = off; - return 0; -} - - - - - -static inline int record_flush(ringbuffer_t *ring) -{ - int count = 0; - - while (!record_shift(ring)) - count++; - return count; -} -# 629 "rtapi/ring.h" -static inline int record_iter_init(const ringbuffer_t *ring, - ringiter_t *iter) -{ - iter->ring = ring; - iter->generation = ring->header->generation; - iter->offset = ring->header->head; - if (ring->header->generation != iter->generation) - return 11; - return 0; -} - -static inline int record_iter_invalid(const ringiter_t *iter) -{ - if (iter->ring->header->generation > iter->generation) - return 22; - return 0; -} - -static inline int record_iter_shift(ringiter_t *iter) -{ - ring_size_t off; - - if (record_iter_invalid(iter)) return 22; - off = _ring_shift_offset(iter->ring, iter->offset); - if (off < 0) return 11; - iter->generation++; - iter->offset = off; - return 0; -} - -static inline int record_iter_read(const ringiter_t *iter, - const void **data, size_t *size) -{ - if (record_iter_invalid(iter)) return 22; - - - return _ring_read_at(iter->ring, iter->offset, data, size); -} - - - -static inline int ring_isstream(ringbuffer_t *ring) -{ - return (ring->header->type == RINGTYPE_STREAM); -} - -static inline int ring_ismultipart(ringbuffer_t *ring) -{ - return (ring->header->type == RINGTYPE_MULTIPART); -} - - -static inline int ring_use_wmutex(ringbuffer_t *ring) -{ - return ring->header->use_wmutex ; -} - -static inline int ring_use_rmutex(ringbuffer_t *ring) -{ - return ring->header->use_rmutex; -} -# 789 "rtapi/ring.h" -static inline size_t stream_get_read_vector(const ringbuffer_t *ring, - ringvec_t *vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w, r; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - w = t->tail; - r = h->head; - - if (w > r) { - free_cnt = w - r; - } else { - free_cnt = (w - r + h->size) & h->size_mask; - } - cnt2 = r + free_cnt; - if (cnt2 > h->size) { - - - vec[0].rv_base = (void *) &(ring->buf[r]); - vec[0].rv_len = h->size - r; - vec[1].rv_base = (void *) ring->buf; - vec[1].rv_len = cnt2 & h->size_mask; - - } else { - - vec[0].rv_base = (void *) &(ring->buf[r]); - vec[0].rv_len = free_cnt; - vec[1].rv_len = 0; - vec[1].rv_base = ((void *)0); - } - return vec[0].rv_len + vec[1].rv_len; -} - - - - - - -static inline void stream_get_write_vector(const ringbuffer_t *ring, - ringvec_t *vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w, r; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - w = t->tail; - r = h->head; - - if (w > r) { - free_cnt = ((r - w + h->size) & h->size_mask) - 1; - } else if (w < r) { - free_cnt = (r - w) - 1; - } else { - free_cnt = h->size - 1; - } - cnt2 = w + free_cnt; - if (cnt2 > h->size) { - - - vec[0].rv_base = (void *) &(ring->buf[w]); - vec[0].rv_len = h->size - w; - vec[1].rv_base = (void *) ring->buf; - vec[1].rv_len = cnt2 & h->size_mask; - } else { - vec[0].rv_base = (void *) &(ring->buf[w]); - vec[0].rv_len = free_cnt; - vec[1].rv_len = 0; - } - if (free_cnt) - __sync_synchronize(); -} - - - - - - -static inline size_t stream_read_space(const ringheader_t *h) -{ - size_t w, r; - ringtrailer_t *t = _trailer_from_header(h); - - w = t->tail; - r = h->head; - if (w > r) { - return w - r; - } else { - return (w - r + h->size) & h->size_mask; - } -} - - - - -static inline size_t stream_read(ringbuffer_t *ring, char *dest, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - ringheader_t *h = ring->header; - - if ((free_cnt = stream_read_space (h)) == 0) { - return 0; - } - to_read = cnt > free_cnt ? free_cnt : cnt; - cnt2 = h->head + to_read; - if (cnt2 > h->size) { - n1 = h->size - h->head; - n2 = cnt2 & h->size_mask; - } else { - n1 = to_read; - n2 = 0; - } - memcpy (dest, &(ring->buf[h->head]), n1); - h->head = (h->head + n1) & h->size_mask; - - if (n2) { - memcpy (dest + n1, &(ring->buf[h->head]), n2); - h->head = (h->head + n2) & h->size_mask; - } - return to_read; -} - - - - - - -static inline size_t stream_peek(ringbuffer_t *ring, char *dest, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - size_t tmp_head; - ringheader_t *h = ring->header; - - tmp_head = h->head; - if ((free_cnt = stream_read_space (h)) == 0) { - return 0; - } - to_read = cnt > free_cnt ? free_cnt : cnt; - cnt2 = tmp_head + to_read; - if (cnt2 > h->size) { - n1 = h->size - tmp_head; - n2 = cnt2 & h->size_mask; - } else { - n1 = to_read; - n2 = 0; - } - memcpy (dest, &(ring->buf[tmp_head]), n1); - tmp_head = (tmp_head + n1) & h->size_mask; - - if (n2) { - memcpy (dest + n1, &(ring->buf[tmp_head]), n2); - } - return to_read; -} - - - -static inline void stream_read_advance(ringbuffer_t *ring, size_t cnt) -{ - size_t tmp; - ringheader_t *h = ring->header; - - - - - - __sync_synchronize(); - tmp = (h->head + cnt) & h->size_mask; - h->head = tmp; -} - - - - - - -static inline size_t stream_flush(ringbuffer_t *ring) -{ - size_t left = stream_read_space(ring->header); - if (left > 0) - stream_read_advance(ring, left); - return left; -} - - - - - -static inline size_t stream_write_space(const ringheader_t *h) -{ - size_t w, r; - ringtrailer_t *t = _trailer_from_header(h); - - w = t->tail; - r = h->head; - if (w > r) { - return ((r - w + h->size) & h->size_mask) - 1; - } else if (w < r) { - return (r - w) - 1; - } else { - return h->size - 1; - } -} - - - - -static inline size_t stream_write(ringbuffer_t *ring, const char *src, - size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_write; - size_t n1, n2; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - if ((free_cnt = stream_write_space (h)) == 0) { - return 0; - } - to_write = cnt > free_cnt ? free_cnt : cnt; - cnt2 = t->tail + to_write; - if (cnt2 > h->size) { - n1 = h->size - t->tail; - n2 = cnt2 & h->size_mask; - } else { - n1 = to_write; - n2 = 0; - } - memcpy (&(ring->buf[t->tail]), src, n1); - t->tail = (t->tail + n1) & h->size_mask; - if (n2) { - memcpy (&(ring->buf[t->tail]), src + n1, n2); - t->tail = (t->tail + n2) & h->size_mask; - } - return to_write; -} - - -static inline void stream_write_advance(ringbuffer_t *ring, size_t cnt) -{ - size_t tmp; - ringheader_t *h = ring->header; - ringtrailer_t *t = ring->trailer; - - - - - __sync_synchronize(); - tmp = (t->tail + cnt) & h->size_mask; - t->tail = tmp; -} -# 68 "rtapi/rtapi_global.h" 2 -# 1 "rtapi/rtapi_heap.h" 1 -# 14 "rtapi/rtapi_heap.h" - - - -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdarg.h" 1 3 4 -# 40 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdarg.h" 3 4 -typedef __builtin_va_list __gnuc_va_list; -# 98 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdarg.h" 3 4 -typedef __gnuc_va_list va_list; -# 18 "rtapi/rtapi_heap.h" 2 - - - - - - - -struct rtapi_heap; -struct rtapi_heap_stat { - size_t arena_size; - size_t total_avail; - size_t fragments; - size_t largest; - size_t requested; - size_t allocated; - size_t freed; -}; - -void *_rtapi_malloc_aligned(struct rtapi_heap *h, size_t nbytes, size_t align); -void *_rtapi_malloc(struct rtapi_heap *h, size_t nbytes); -void *_rtapi_calloc(struct rtapi_heap *h, size_t n, size_t size); -void *_rtapi_realloc(struct rtapi_heap *h, void *p, size_t size); -void _rtapi_free(struct rtapi_heap *h, void *p); -size_t _rtapi_allocsize(struct rtapi_heap *h, const void *ap); -int _rtapi_heap_init(struct rtapi_heap *h, const char *name); - - -int _rtapi_heap_addmem(struct rtapi_heap *h, void *space, size_t size); - -int _rtapi_heap_setflags(struct rtapi_heap *heap, int flags); -size_t _rtapi_heap_status(struct rtapi_heap *h, struct rtapi_heap_stat *hs); - - -typedef void (*chunk_t)(size_t size, void *chunk, void *user); -size_t _rtapi_heap_walk_freelist(struct rtapi_heap *h, chunk_t cb, void *user); - - -# 69 "rtapi/rtapi_global.h" 2 -# 1 "rtapi/rtapi_heap_private.h" 1 - - - -# 1 "rtapi/rtapi.h" 1 -# 5 "rtapi/rtapi_heap_private.h" 2 -# 28 "rtapi/rtapi_heap_private.h" -typedef struct rtapi_malloc_align { - double _align[1]; -} rtapi_malloc_align_t; - - - - - -typedef struct rtapi_malloc_tag { - uint32_t size : 24; - uint32_t attr : 8; -} rtapi_malloc_tag_t; - -union rtapi_malloc_header { - struct hdr { - uint32_t next; - rtapi_malloc_tag_t tag; - } s; - rtapi_malloc_align_t align; -}; - -typedef union rtapi_malloc_header rtapi_malloc_hdr_t; - -struct rtapi_heap { - rtapi_malloc_hdr_t base; - size_t free_p; - size_t arena_size; - rtapi_atomic_type mutex; - int flags; - size_t requested; - size_t allocated; - int freed; - char name[16]; -}; - -static inline void *heap_ptr(struct rtapi_heap *base, size_t offset) -{ - return ((unsigned char *)base + offset); -} - -static inline size_t heap_off(struct rtapi_heap *base, void *p) -{ - return ((unsigned char *)p - (unsigned char *)base); -} -# 70 "rtapi/rtapi_global.h" 2 - - - - - - -typedef struct { - unsigned magic; - int layout_version; - unsigned long mutex; - - size_t global_segment_size; - - - - int instance_id; - int rtapi_thread_flavor; - - - int rt_msg_level; - int user_msg_level; - rtapi_atomic_type next_handle; - int hal_size; - int hal_thread_stack_size; - - - - - - int hal_descriptor_alignment; - - - - - int hal_heap_flags; - - - - - unsigned char service_uuid[16]; - - int rtapi_app_pid; - int rtapi_msgd_pid; - - - rtapi_threadstatus_t thread_status[64 + 1]; - - - int error_ring_full; - int error_ring_locked; - - - - - int rtapi_messages_ptr; - - - struct rtapi_heap heap; - - - unsigned char arena[0] __attribute__((aligned((64)))); - -} global_data_t; - -extern global_data_t *global_data; -# 113 "rtapi/rtapi.h" 2 -# 1 "rtapi/rtapi_heap.h" 1 -# 114 "rtapi/rtapi.h" 2 -# 1 "rtapi/rtapi_exception.h" 1 -# 115 "rtapi/rtapi.h" 2 - - - - - -# 137 "rtapi/rtapi.h" -static inline int is_aligned(const void *pointer, size_t byte_count) -{ - return (uintptr_t)pointer % byte_count == 0; -} -# 151 "rtapi/rtapi.h" -typedef __s32 shmoff_t; - - - -static inline void *shm_ptr(const void *base, const shmoff_t offset) -{ - return ((char *)base + offset); -} -static inline shmoff_t shm_off(const void *base, const void *p) -{ - return ((char *)p - (char *)base); -} -# 181 "rtapi/rtapi.h" -typedef int (*rtapi_init_t)(const char *); - - -extern int _rtapi_init(const char *modname); -# 196 "rtapi/rtapi.h" -typedef int (*rtapi_exit_t)(int); - - -extern int _rtapi_exit(int module_id); - - - - -typedef int (*rtapi_next_handle_t)(void); - - -extern int _rtapi_next_handle(void); - - - - - -typedef void * (*rtapi_malloc_t)(struct rtapi_heap *h, size_t nbytes); - - - -typedef void * (*rtapi_malloc_aligned_t)(struct rtapi_heap *h, - size_t nbytes, - size_t align); - - - -typedef void * (*rtapi_calloc_t)(struct rtapi_heap *h, size_t n, size_t size); - - - -typedef void * (*rtapi_realloc_t)(struct rtapi_heap *h, void *p, size_t size); - - - -typedef void (*rtapi_free_t)(struct rtapi_heap *h, void *p); - - - -typedef size_t (*rtapi_allocsize_t)(struct rtapi_heap *h, const void *p); - - - -typedef int (*rtapi_heap_init_t)(struct rtapi_heap *h, const char *name); - - - - -typedef int (*rtapi_heap_addmem_t)(struct rtapi_heap *h, void *space, size_t size); - - - -typedef size_t (*rtapi_heap_status_t)(struct rtapi_heap *h, struct rtapi_heap_stat *hs); - - - -typedef int (*rtapi_heap_setflags_t)(struct rtapi_heap *h, int flags); - - - -typedef size_t (*rtapi_heap_walk_freelist_t)(struct rtapi_heap *h, - chunk_t cb, void *user); -# 279 "rtapi/rtapi.h" -int rtapi_argvize(int avsize, char **av, char *s); -# 290 "rtapi/rtapi.h" -extern int rtapi_snprintf(char *buf, unsigned long int size, - const char *fmt, ...) -__attribute__((format(printf,3,4))); -# 303 "rtapi/rtapi.h" -extern int rtapi_vsnprintf(char *buf, unsigned long size, - const char *fmt, va_list ap); -# 319 "rtapi/rtapi.h" -extern void rtapi_print(const char *fmt, ...) -__attribute__((format(printf,1,2))); - - - - - - -typedef enum { - RTAPI_MSG_NONE = 0, - RTAPI_MSG_ERR, - RTAPI_MSG_WARN, - RTAPI_MSG_INFO, - RTAPI_MSG_DBG, - RTAPI_MSG_ALL -} msg_level_t; - -extern void rtapi_print_msg(int level, const char *fmt, ...) -__attribute__((format(printf,2,3))); - - -void rtapi_print_loc(const int level, - const char *func, - const int line, - const char *topic, - const char *fmt, ...) -__attribute__((format(printf,5,6))); - - -const char *rtapi_last_msg(void); -# 417 "rtapi/rtapi.h" -extern int rtapi_set_msg_level(int level); - - -extern int rtapi_get_msg_level(void); -# 431 "rtapi/rtapi.h" -typedef void(*rtapi_msg_handler_t)(msg_level_t level, const char *fmt, - va_list ap); - - -typedef void (*rtapi_set_msg_handler_t)(rtapi_msg_handler_t); - -extern void rtapi_set_msg_handler(rtapi_msg_handler_t handler); - -typedef rtapi_msg_handler_t (*rtapi_get_msg_handler_t)(void); - -extern rtapi_msg_handler_t rtapi_get_msg_handler(void); - -extern int rtapi_set_logtag(const char *fmt, ...); -extern const char *rtapi_get_logtag(void); - -typedef enum { - MSG_KERNEL = 0, - MSG_RTUSER = 1, - MSG_ULAPI = 2, -} msg_origin_t; - - - -int vs_ringlogfv(const msg_level_t level, - const int pid, - const msg_origin_t origin, - const char *tag, - const char *format, - va_list ap); - - - -typedef struct { - msg_origin_t origin; - int pid; - int level; - char tag[16]; - char buf[0]; -} rtapi_msgheader_t; -# 480 "rtapi/rtapi.h" -# 1 "/usr/include/sched.h" 1 3 4 -# 25 "/usr/include/sched.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4 -# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 -# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 - - -typedef unsigned char __u_char; -typedef unsigned short int __u_short; -typedef unsigned int __u_int; -typedef unsigned long int __u_long; - - -typedef signed char __int8_t; -typedef unsigned char __uint8_t; -typedef signed short int __int16_t; -typedef unsigned short int __uint16_t; -typedef signed int __int32_t; -typedef unsigned int __uint32_t; - -typedef signed long int __int64_t; -typedef unsigned long int __uint64_t; - - - - - - - -typedef long int __quad_t; -typedef unsigned long int __u_quad_t; -# 121 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 -# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4 -# 122 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 - - -typedef unsigned long int __dev_t; -typedef unsigned int __uid_t; -typedef unsigned int __gid_t; -typedef unsigned long int __ino_t; -typedef unsigned long int __ino64_t; -typedef unsigned int __mode_t; -typedef unsigned long int __nlink_t; -typedef long int __off_t; -typedef long int __off64_t; -typedef int __pid_t; -typedef struct { - int __val[2]; -} __fsid_t; -typedef long int __clock_t; -typedef unsigned long int __rlim_t; -typedef unsigned long int __rlim64_t; -typedef unsigned int __id_t; -typedef long int __time_t; -typedef unsigned int __useconds_t; -typedef long int __suseconds_t; - -typedef int __daddr_t; -typedef int __key_t; - - -typedef int __clockid_t; - - -typedef void * __timer_t; - - -typedef long int __blksize_t; - - - - -typedef long int __blkcnt_t; -typedef long int __blkcnt64_t; - - -typedef unsigned long int __fsblkcnt_t; -typedef unsigned long int __fsblkcnt64_t; - - -typedef unsigned long int __fsfilcnt_t; -typedef unsigned long int __fsfilcnt64_t; - - -typedef long int __fsword_t; - -typedef long int __ssize_t; - - -typedef long int __syscall_slong_t; - -typedef unsigned long int __syscall_ulong_t; - - - -typedef __off64_t __loff_t; -typedef __quad_t *__qaddr_t; -typedef char *__caddr_t; - - -typedef long int __intptr_t; - - -typedef unsigned int __socklen_t; -# 26 "/usr/include/sched.h" 2 3 4 - - -# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h" 1 3 4 -# 29 "/usr/include/sched.h" 2 3 4 - - - -# 1 "/usr/include/time.h" 1 3 4 -# 73 "/usr/include/time.h" 3 4 - - -typedef __time_t time_t; - - - -# 120 "/usr/include/time.h" 3 4 -struct timespec { - __time_t tv_sec; - __syscall_slong_t tv_nsec; -}; -# 33 "/usr/include/sched.h" 2 3 4 - - -typedef __pid_t pid_t; - - - - - -# 1 "/usr/include/x86_64-linux-gnu/bits/sched.h" 1 3 4 -# 72 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 -struct sched_param { - int __sched_priority; -}; - - - - - -extern int clone (int (*__fn) (void *__arg), void *__child_stack, - int __flags, void *__arg, ...) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int unshare (int __flags) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_getcpu (void) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int setns (int __fd, int __nstype) __attribute__ ((__nothrow__ , __leaf__)); - - - - - - - - - - - -struct __sched_param { - int __sched_priority; -}; -# 118 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 -typedef unsigned long int __cpu_mask; - - - - - - -typedef struct { - __cpu_mask __bits[1024 / (8 * sizeof (__cpu_mask))]; -} cpu_set_t; -# 201 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 - - -extern int __sched_cpucount (size_t __setsize, const cpu_set_t *__setp) -__attribute__ ((__nothrow__ , __leaf__)); -extern cpu_set_t *__sched_cpualloc (size_t __count) __attribute__ ((__nothrow__ , __leaf__)) ; -extern void __sched_cpufree (cpu_set_t *__set) __attribute__ ((__nothrow__ , __leaf__)); - - -# 42 "/usr/include/sched.h" 2 3 4 - - - - - - - -extern int sched_setparam (__pid_t __pid, const struct sched_param *__param) -__attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_getparam (__pid_t __pid, struct sched_param *__param) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_setscheduler (__pid_t __pid, int __policy, - const struct sched_param *__param) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_getscheduler (__pid_t __pid) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_yield (void) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_get_priority_max (int __algorithm) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_get_priority_min (int __algorithm) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __attribute__ ((__nothrow__ , __leaf__)); -# 116 "/usr/include/sched.h" 3 4 -extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize, - const cpu_set_t *__cpuset) __attribute__ ((__nothrow__ , __leaf__)); - - -extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize, - cpu_set_t *__cpuset) __attribute__ ((__nothrow__ , __leaf__)); - - - -# 481 "rtapi/rtapi.h" 2 -# 498 "rtapi/rtapi.h" -static __inline__ void rtapi_mutex_give(unsigned long *mutex) -{ - rtapi_test_and_clear_bit(0, mutex); -} -# 510 "rtapi/rtapi.h" -static __inline__ int rtapi_mutex_try(unsigned long *mutex) -{ - return rtapi_test_and_set_bit(0, mutex); -} - - - - - - -static __inline__ void rtapi_mutex_get(unsigned long *mutex) -{ - while (rtapi_test_and_set_bit(0, mutex)) { - - - - sched_yield(); - - } -} - - -struct _mutex_cleanup { - int cond; - rtapi_atomic_type *m; -}; - - -static inline void _autorelease_mutex_if(struct _mutex_cleanup *c) -{ - if (c->cond) - rtapi_mutex_give(c->m); -} -# 651 "rtapi/rtapi.h" -typedef long long int (*rtapi_get_time_t)(void); - - -extern long long int _rtapi_get_time(void); -# 681 "rtapi/rtapi.h" -typedef long long int (*rtapi_get_clocks_t)(void); - - -extern long long int _rtapi_get_clocks(void); -# 723 "rtapi/rtapi.h" -typedef void (*taskcode_t) (void*); - -typedef enum { - TF_NONRT = (1UL << (0)), - TF_NOWAIT = (1UL << (1)), - -} rtapi_thread_flags_t; - - -typedef struct { - taskcode_t taskcode; - void *arg; - int prio; - int owner; - unsigned long int stacksize; - int uses_fp; - char *name; - int cpu_id; - rtapi_thread_flags_t flags; -} rtapi_task_args_t; - - -typedef int (*rtapi_prio_highest_lowest_t)(void); - - -extern int _rtapi_prio_highest(void); - - -extern int _rtapi_prio_lowest(void); - -typedef int (*rtapi_prio_next_higher_lower_t)(int); - - -extern int _rtapi_prio_next_higher(int prio); - - -extern int _rtapi_prio_next_lower(int prio); -# 904 "rtapi/rtapi.h" -typedef int (*rtapi_shmem_new_t)(int, int, unsigned long int); - - -extern int _rtapi_shmem_new(int key, int module_id, - unsigned long int size); - - - - -typedef int (*rtapi_shmem_new_inst_t)(int, int, int, unsigned long int); - - -extern int _rtapi_shmem_new_inst(int key, int instance, int module_id, - unsigned long int size); - - - - - - -typedef int (*rtapi_shmem_delete_t)(int, int); - - -extern int _rtapi_shmem_delete(int shmem_id, int module_id); - -typedef int (*rtapi_shmem_delete_inst_t)(int, int, int); - - -extern int _rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id); -# 941 "rtapi/rtapi.h" -typedef int (*rtapi_shmem_getptr_t)(int, void **, unsigned long int *); - - -extern int _rtapi_shmem_getptr(int shmem_id, void **ptr, unsigned long int *size); - -typedef int (*rtapi_shmem_getptr_inst_t)(int, int, void **, unsigned long int *); - - -extern int _rtapi_shmem_getptr_inst(int shmem_id, int instance, void **ptr, unsigned long int *size); - - - - - - -typedef int (*rtapi_shmem_exists_t)(int); - - -extern int _rtapi_shmem_exists(int key); -# 972 "rtapi/rtapi.h" -typedef rtapi_exception_handler_t (*rtapi_set_exception_t) (rtapi_exception_handler_t); - - -extern rtapi_exception_handler_t _rtapi_set_exception(rtapi_exception_handler_t h); -# 984 "rtapi/rtapi.h" -# 1 "rtapi/rtapi_io.h" 1 -# 39 "rtapi/rtapi_io.h" -# 1 "/usr/include/x86_64-linux-gnu/sys/io.h" 1 3 4 -# 23 "/usr/include/x86_64-linux-gnu/sys/io.h" 3 4 - -# 32 "/usr/include/x86_64-linux-gnu/sys/io.h" 3 4 -extern int ioperm (unsigned long int __from, unsigned long int __num, - int __turn_on) __attribute__ ((__nothrow__ , __leaf__)); - - - - -extern int iopl (int __level) __attribute__ ((__nothrow__ , __leaf__)); - - - -static __inline unsigned char -inb (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned char -inb_p (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw (unsigned short int __port) -{ - unsigned short _v; - - __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw_p (unsigned short int __port) -{ - unsigned short int _v; - - __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl (unsigned short int __port) -{ - unsigned int _v; - - __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl_p (unsigned short int __port) -{ - unsigned int _v; - __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline void -outb (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outb_p (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outw (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1": :"a" (__value), "Nd" (__port)); - -} - -static __inline void -outw_p (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outl (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outl_p (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -insb (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insb":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insw (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insw":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insl (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insl":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsb (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsw (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsl (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - - - - -# 40 "rtapi/rtapi_io.h" 2 -# 49 "rtapi/rtapi_io.h" -static inline void rtapi_outb(unsigned char byte, unsigned int port) -{ - outb(byte,port); -} - - - - - - -static inline unsigned char rtapi_inb(unsigned int port) -{ - return inb(port); -} - - - - - -static inline void rtapi_outw(unsigned short word, unsigned int port) -{ - outw(word,port); -}; - - - - - -static inline unsigned short rtapi_inw(unsigned int port) -{ - return inw(port); -} -# 985 "rtapi/rtapi.h" 2 -# 1034 "rtapi/rtapi.h" -typedef int (*rtapi_dummy_t)(void); - -typedef struct { - const char *git_version; - const char *thread_flavor_name; - int thread_flavor_id; - unsigned long thread_flavor_flags; - - - rtapi_init_t rtapi_init; - rtapi_exit_t rtapi_exit; - rtapi_next_handle_t rtapi_next_handle; - - - - - - - rtapi_dummy_t rtapi_clock_set_period; - rtapi_dummy_t rtapi_delay; - rtapi_dummy_t rtapi_delay_max; - - rtapi_get_time_t rtapi_get_time; - rtapi_get_clocks_t rtapi_get_clocks; - - rtapi_prio_highest_lowest_t rtapi_prio_highest; - rtapi_prio_highest_lowest_t rtapi_prio_lowest; - rtapi_prio_next_higher_lower_t rtapi_prio_next_higher; - rtapi_prio_next_higher_lower_t rtapi_prio_next_lower; -# 1073 "rtapi/rtapi.h" - rtapi_dummy_t rtapi_task_new; - rtapi_dummy_t rtapi_task_delete; - rtapi_dummy_t rtapi_task_start; - rtapi_dummy_t rtapi_wait; - rtapi_dummy_t rtapi_task_resume; - rtapi_dummy_t rtapi_task_pause; - rtapi_dummy_t rtapi_task_self; - - - rtapi_shmem_new_t rtapi_shmem_new; - rtapi_shmem_new_inst_t rtapi_shmem_new_inst; - rtapi_shmem_delete_t rtapi_shmem_delete; - rtapi_shmem_delete_inst_t rtapi_shmem_delete_inst; - rtapi_shmem_getptr_t rtapi_shmem_getptr; - rtapi_shmem_getptr_inst_t rtapi_shmem_getptr_inst; - rtapi_shmem_exists_t rtapi_shmem_exists; - - - - - rtapi_dummy_t rtapi_set_exception; - - - - - rtapi_dummy_t rtapi_task_update_stats; - - rtapi_malloc_t rtapi_malloc; - rtapi_malloc_aligned_t rtapi_malloc_aligned; - rtapi_calloc_t rtapi_calloc; - rtapi_realloc_t rtapi_realloc; - rtapi_free_t rtapi_free; - rtapi_allocsize_t rtapi_allocsize; - rtapi_heap_init_t rtapi_heap_init; - rtapi_heap_addmem_t rtapi_heap_addmem; - rtapi_heap_status_t rtapi_heap_status; - rtapi_heap_setflags_t rtapi_heap_setflags; - rtapi_heap_walk_freelist_t rtapi_heap_walk_freelist; - -} rtapi_switch_t; - - - -extern rtapi_switch_t *rtapi_switch; - - - - - -typedef rtapi_switch_t *(*rtapi_get_handle_t)(void); -extern rtapi_switch_t *rtapi_get_handle(void); -# 1132 "rtapi/rtapi.h" -extern void rtapi_autorelease_mutex(void *variable); - - - -extern int rtapi_instance; -# 1145 "rtapi/rtapi.h" -typedef int (*ulapi_main_t)(int, int, global_data_t *); -typedef int (*ulapi_exit_t)(int); -extern int ulapi_main(int instance, int flavor, global_data_t *global); -extern int ulapi_exit(int instance); - - -extern void ulapi_cleanup(void); - - - -extern void ulapi_kernel_compat_check(rtapi_switch_t *rtapi_switch, - char *ulapi_lib); -extern int ulapi_loaded(void); -# 1357 "rtapi/rtapi.h" - -# 5 "hal/lib/hal_accessor.h" 2 - - -# 17 "hal/lib/hal_accessor.h" -static inline void *hal_ptr(const shmoff_t offset) -{ - return ((char *)hal_shmem_base + offset); -} -static inline shmoff_t hal_off(const void *p) -{ - return ((char *)p - (char *)hal_shmem_base); -} -static inline shmoff_t hal_off_safe(const void *p) -{ - if (p == ((void *)0)) return 0; - return ((char *)p - (char *)hal_shmem_base); -} -# 57 "hal/lib/hal_accessor.h" -static inline const hal_bit_t set_bit_pin(bit_pin_ptr p, const hal_bit_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._bp); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - __atomic_store(&u->_b, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_s32_t set_s32_pin(s32_pin_ptr p, const hal_s32_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._sp); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - __atomic_store(&u->_s, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_u32_t set_u32_pin(u32_pin_ptr p, const hal_u32_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._up); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - __atomic_store(&u->_u, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_float_t set_float_pin(float_pin_ptr p, const hal_float_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._fp); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - __atomic_store(&u->_f, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return value; -} -# 79 "hal/lib/hal_accessor.h" -static inline const hal_bit_t get_bit_pin(const bit_pin_ptr p) -{ - const hal_pin_t *pin = (const hal_pin_t *)hal_ptr(p._bp); - const hal_data_u *u = (const hal_data_u *)hal_ptr(pin->data_ptr); - if (__builtin_expect(!!(hh_get_rmb(&pin->hdr)), 0)) __sync_synchronize(); - hal_bit_t rvalue ; - __atomic_load(&u->_b, &rvalue , 5); - return rvalue ; -} -static inline const hal_s32_t get_s32_pin(const s32_pin_ptr p) -{ - const hal_pin_t *pin = (const hal_pin_t *)hal_ptr(p._sp); - const hal_data_u *u = (const hal_data_u *)hal_ptr(pin->data_ptr); - if (__builtin_expect(!!(hh_get_rmb(&pin->hdr)), 0)) __sync_synchronize(); - hal_s32_t rvalue ; - __atomic_load(&u->_s, &rvalue , 5); - return rvalue ; -} -static inline const hal_u32_t get_u32_pin(const u32_pin_ptr p) -{ - const hal_pin_t *pin = (const hal_pin_t *)hal_ptr(p._up); - const hal_data_u *u = (const hal_data_u *)hal_ptr(pin->data_ptr); - if (__builtin_expect(!!(hh_get_rmb(&pin->hdr)), 0)) __sync_synchronize(); - hal_u32_t rvalue ; - __atomic_load(&u->_u, &rvalue , 5); - return rvalue ; -} -static inline const hal_float_t get_float_pin(const float_pin_ptr p) -{ - const hal_pin_t *pin = (const hal_pin_t *)hal_ptr(p._fp); - const hal_data_u *u = (const hal_data_u *)hal_ptr(pin->data_ptr); - if (__builtin_expect(!!(hh_get_rmb(&pin->hdr)), 0)) __sync_synchronize(); - hal_float_t rvalue ; - __atomic_load(&u->_f, &rvalue , 5); - return rvalue ; -} -# 101 "hal/lib/hal_accessor.h" -static inline const hal_s32_t incr_s32_pin(s32_pin_ptr p, const hal_s32_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._sp); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - hal_s32_t rvalue = __atomic_add_fetch(&u->_s, (value), 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return rvalue; -} -static inline const hal_u32_t incr_u32_pin(u32_pin_ptr p, const hal_u32_t value) -{ - hal_pin_t *pin = (hal_pin_t *)hal_ptr(p._up); - hal_data_u *u = (hal_data_u *)hal_ptr(pin->data_ptr); - hal_u32_t rvalue = __atomic_add_fetch(&u->_u, (value), 5); - if (__builtin_expect(!!(hh_get_wmb(&pin->hdr)), 0)) __sync_synchronize(); - return rvalue; -} -# 121 "hal/lib/hal_accessor.h" -static inline const hal_bit_t get_bit_sig(const bit_sig_ptr p) -{ - const hal_sig_t *sig = (const hal_sig_t *)hal_ptr(p._bs); - if (__builtin_expect(!!(hh_get_rmb(&sig->hdr)), 0)) __sync_synchronize(); - hal_bit_t rvalue ; - __atomic_load(&sig->value._b, &rvalue , 5); - return rvalue ; -} -static inline const hal_s32_t get_s32_sig(const s32_sig_ptr p) -{ - const hal_sig_t *sig = (const hal_sig_t *)hal_ptr(p._ss); - if (__builtin_expect(!!(hh_get_rmb(&sig->hdr)), 0)) __sync_synchronize(); - hal_s32_t rvalue ; - __atomic_load(&sig->value._s, &rvalue , 5); - return rvalue ; -} -static inline const hal_u32_t get_u32_sig(const u32_sig_ptr p) -{ - const hal_sig_t *sig = (const hal_sig_t *)hal_ptr(p._us); - if (__builtin_expect(!!(hh_get_rmb(&sig->hdr)), 0)) __sync_synchronize(); - hal_u32_t rvalue ; - __atomic_load(&sig->value._u, &rvalue , 5); - return rvalue ; -} -static inline const hal_float_t get_float_sig(const float_sig_ptr p) -{ - const hal_sig_t *sig = (const hal_sig_t *)hal_ptr(p._fs); - if (__builtin_expect(!!(hh_get_rmb(&sig->hdr)), 0)) __sync_synchronize(); - hal_float_t rvalue ; - __atomic_load(&sig->value._f, &rvalue , 5); - return rvalue ; -} -# 143 "hal/lib/hal_accessor.h" -static inline const hal_bit_t set_bit_sig(bit_sig_ptr s, const hal_bit_t value) -{ - hal_sig_t *sig = (hal_sig_t *)hal_ptr(s._bs); - __atomic_store(&sig->value._b, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&sig->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_s32_t set_s32_sig(s32_sig_ptr s, const hal_s32_t value) -{ - hal_sig_t *sig = (hal_sig_t *)hal_ptr(s._ss); - __atomic_store(&sig->value._s, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&sig->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_u32_t set_u32_sig(u32_sig_ptr s, const hal_u32_t value) -{ - hal_sig_t *sig = (hal_sig_t *)hal_ptr(s._us); - __atomic_store(&sig->value._u, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&sig->hdr)), 0)) __sync_synchronize(); - return value; -} -static inline const hal_float_t set_float_sig(float_sig_ptr s, const hal_float_t value) -{ - hal_sig_t *sig = (hal_sig_t *)hal_ptr(s._fs); - __atomic_store(&sig->value._f, &value, 5); - if (__builtin_expect(!!(hh_get_wmb(&sig->hdr)), 0)) __sync_synchronize(); - return value; -} - - - - -static inline _Bool bit_pin_null(const bit_pin_ptr b) -{ - return b._bp == 0; -} -static inline _Bool s32_pin_null(const s32_pin_ptr b) -{ - return b._sp == 0; -} -static inline _Bool u32_pin_null(const u32_pin_ptr b) -{ - return b._up == 0; -} -static inline _Bool float_pin_null(const float_pin_ptr b) -{ - return b._fp == 0; -} -static inline _Bool bit_sig_null(const bit_sig_ptr s) -{ - return s._bs == 0; -} -static inline _Bool s32_sig_null(const s32_sig_ptr s) -{ - return s._ss == 0; -} -static inline _Bool u32_sig_null(const u32_sig_ptr s) -{ - return s._us == 0; -} -static inline _Bool float_sig_null(const float_sig_ptr s) -{ - return s._fs == 0; -} - - - -const char *hals_type(const hal_type_t type); - -const char *hals_pindir(const hal_pin_dir_t dir); - - -bit_pin_ptr halx_pin_bit_newf(const hal_pin_dir_t dir, - const int owner_id, - const char *fmt, ...) -__attribute__((format(printf,3,4))); - -float_pin_ptr halx_pin_float_newf(const hal_pin_dir_t dir, - const int owner_id, - const char *fmt, ...) -__attribute__((format(printf,3,4))); - -u32_pin_ptr halx_pin_u32_newf(const hal_pin_dir_t dir, - const int owner_id, - const char *fmt, ...) -__attribute__((format(printf,3,4))); - -s32_pin_ptr halx_pin_s32_newf(const hal_pin_dir_t dir, - const int owner_id, - const char *fmt, ...) -__attribute__((format(printf,3,4))); -# 216 "hal/lib/hal_accessor.h" diff --git a/src/hal/components/Submakefile b/src/hal/components/Submakefile index 0b778a5a0a..2050c11271 100644 --- a/src/hal/components/Submakefile +++ b/src/hal/components/Submakefile @@ -1,17 +1,8 @@ HALCOMP_SUBMAKEFILE= hal/components/Submakefile # for debugging this file - to prevent recompilation of # everything under the sun with every small change -HALCOMP_SUBMAKEFILE= hal/components/Submakefile -# for debugging this file - to prevent recompilation of -# everything under the sun with every small change #HALCOMP_SUBMAKEFILE= -ifeq ($(BUILD_KBUILD),yes) -COMPS := $(patsubst $(BASEPWD)/%,%,$(wildcard \ - $(BASEPWD)/hal/components/*.comp $(BASEPWD)/hal/drivers/*.comp \ - $(BASEPWD)/machinetalk/msgcomponents/*.comp)) -include $(patsubst %.comp, $(BASEPWD)/halcomp-srcs/%.mak, $(COMPS)) -else COMPS := $(sort $(wildcard hal/components/*.comp)) USER_COMP_COMPS := $(sort $(wildcard hal/user_comps/*.comp)) @@ -32,6 +23,8 @@ DRIVER_COMPS := $(patsubst %,hal/drivers/%, \ mesa_uart.comp \ $(if $(TARGET_PLATFORM_PC), \ pcl720.comp \ + ) \ + $(ifeq $(HAS_SYS_IO),yes \ serport.comp \ ) \ ) @@ -46,18 +39,10 @@ ifeq ($(BUILD_DOCS),yes) .PHONY: docpages endif -ifeq ($(TRIVIAL_BUILD)+$(BUILD_THREAD_MODULES),no+yes) --include $(patsubst %.comp, $(BASEPWD)/halcomp-srcs/%.mak,\ - $(COMPS) $(DRIVER_COMPS) $(MSG_COMPS)) -endif # TRIVIAL_BUILD == no -endif # KERNELRELEASE != '' - -ifeq ($(BUILD_THREAD_MODULES),yes) obj-m += $(patsubst hal/drivers/%.comp, %.o, \ $(patsubst hal/components/%.comp, %.o, \ $(patsubst machinetalk/msgcomponents/%.comp, %.o, \ $(COMPS) $(DRIVER_COMPS) $(MSG_COMPS)))) -endif $(COMP_DOCPAGES): ../man/man9/%.asciidoc: hal/components/%.comp ../bin/comp $(ECHO) Making comp docpage $(notdir $@) @@ -92,56 +77,49 @@ $(MSG_COMP_DOCPAGES): ../man/man9/%.asciidoc: \ --frontmatter="edit-branch: $(EDIT_BRANCH)" \ -o $@ $< -ifeq ($(BUILD_ALL_FLAVORS),yes) -# .c and .mak files are identical for all flavors -# -# in the top-level make, build them once in a common location -halcomp-srcs/%.c: %.comp ../bin/comp +# Build .c sources +objects/%.c: %.comp ../bin/comp $(ECHO) "Preprocessing $(notdir $<)" @mkdir -p $(dir $@) $(Q)../bin/comp --require-license -o $@ $< -halcomp-srcs/%.mak: %.comp $(HALCOMP_SUBMAKEFILE) - $(ECHO) "Generating comp build rules for $(notdir $<)" - @mkdir -p $(dir $@) - $(Q)echo "$(notdir $*)-objs := halcomp-srcs/$*.o" > $@.tmp - $(Q)echo "\$$(RTLIBDIR)/$(notdir $*)\$$(MODULE_EXT): \\" >> $@.tmp - $(Q)echo " \$$(OBJDIR)/halcomp-srcs/$*.o" >> $@.tmp - $(Q)mv -f $@.tmp $@ - -# Generate .c and .mak files before the modules target -modules: $(patsubst %.comp, halcomp-srcs/%.c, \ - $(COMPS) $(DRIVER_COMPS) $(MSG_COMPS)) -modules: $(patsubst %.comp, halcomp-srcs/%.mak, \ - $(COMPS) $(DRIVER_COMPS) $(MSG_COMPS)) -endif # BUILD_ALL_FLAVORS == yes - -# ifeq ($(BUILD_THREAD_MODULES),yes) -# # to build flavors separately, source files need to be linked -# # are these still neededby kthreads build? -# # are they used at all? -# HALCOMP_DIR_STAMPS := \ -# halcomp-srcs/hal/components/.dir-stamp \ -# halcomp-srcs/hal/drivers/.dir-stamp -# $(HALCOMP_DIR_STAMPS): -# @mkdir -p $(dir $@) && touch $@ - -# ifeq ($(BUILD_KBUILD),no) -# # do we still need this? These don't seem to be usedin userland threads -# $(OBJDIR)/halcomp-srcs/hal/%.c: halcomp-srcs/hal/%.c \ -# $(patsubst %,$(OBJDIR)/%,$(HALCOMP_DIR_STAMPS)) -# cp $< $@ -# else -# #do we need this? This shouldbe taken care of by the wholesale copy operation -# halcomp-srcs/hal/%.c: $(BASEPWD)/halcomp-srcs/hal/%.c $(HALCOMP_DIR_STAMPS) -# cp $< $@ -# endif -# endif +# Generate rules for building component.so files from component.comp files +# +# example: $$(call comp_build_rules,hal/components,hal/components/logic.comp) +# produces rules: +# logic-objs := objects/hal/components/logic.o +# ../rtlib/modules/remote.so: \ +# objects/modules/objects/machinetalk/msgcomponents/remote.o +# +define comp_build_rules +$$(patsubst $$(dir $(1))%.comp,%-objs,$(1)) := \ + $$(patsubst %.comp,objects/%.o,$(1)) +$$(patsubst $(dir $(1))%.comp,$(RTLIBDIR)/%.so,$(1)): \ + $(OBJDIR)/objects/$$(patsubst %.comp,%.o,$(1)) + +endef +# +# For hal/components/*.comp: +$(eval $(foreach comp,$(COMPS),$(call comp_build_rules,$(comp)))) +# +# For hal/drivers/*.comp: +$(eval $(foreach comp,$(DRIVER_COMPS),$(call comp_build_rules,$(comp)))) +# +# For machinetalk/msgcomponents/*.comp: +$(eval $(foreach comp,$(MSG_COMPS),$(call comp_build_rules,$(comp)))) + + +#$$(info $(call comp_build_rules,machinetalk/msgcomponents/remote.comp)) +#$$(info $(patsubst $(dir machinetalk/msgcomponents/remote.comp)%.comp,%-objs,machinetalk/msgcomponents/remote.comp) := $(patsubst %.comp,objects/%.o,machinetalk/msgcomponents/remote.comp)) +#$$(info $(patsubst machinetalk/msgcomponents/%.comp,../rtlib/modules/%.so,machinetalk/msgcomponents/remote.comp): objects/modules/objects/$(patsubst %.comp,%.o,machinetalk/msgcomponents/remote.comp)) HALSTREAMERSRCS := hal/components/streamer_usr.c USERSRCS += $(HALSTREAMERSRCS) -../bin/halstreamer: $(call TOOBJS, $(HALSTREAMERSRCS)) ../lib/liblinuxcnchal.so.0 +../bin/halstreamer: \ + $(call TOOBJS, $(HALSTREAMERSRCS)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ TARGETS += ../bin/halstreamer @@ -149,14 +127,35 @@ TARGETS += ../bin/halstreamer HALSAMPLERSRCS := hal/components/sampler_usr.c USERSRCS += $(HALSAMPLERSRCS) -../bin/halsampler: $(call TOOBJS, $(HALSAMPLERSRCS)) ../lib/liblinuxcnchal.so.0 +../bin/halsampler: \ + $(call TOOBJS, $(HALSAMPLERSRCS)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ TARGETS += ../bin/halsampler -# build instructions for the delayline module -obj-m += delayline.o -# the list of parts -delayline-objs := hal/components/delayline.o $(MATHSTUB) - -$(RTLIBDIR)/delayline$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(delayline-objs)) +# C-language components + +#$$(eval $(call c_comp_build_rules,hal/components/boss_plc.o)) +$(eval $(call c_comp_build_rules,hal/components/encoder.o)) +$(eval $(call c_comp_build_rules,hal/components/encoderv2.o)) +$(eval $(call c_comp_build_rules,hal/components/counter.o)) +$(eval $(call c_comp_build_rules,hal/components/encoder_ratio.o)) +$(eval $(call c_comp_build_rules,hal/components/encoder_ratiov2.o)) +$(eval $(call c_comp_build_rules,hal/components/stepgen.o)) +$(eval $(call c_comp_build_rules,hal/components/stepgenv2.o)) +$(eval $(call c_comp_build_rules,hal/components/lcd.o)) +$(eval $(call c_comp_build_rules,hal/components/matrix_kb.o)) +$(eval $(call c_comp_build_rules,hal/components/mux_generic.o)) +$(eval $(call c_comp_build_rules,hal/components/pwmgen.o)) +$(eval $(call c_comp_build_rules,hal/components/pwmgenv2.o)) +$(eval $(call c_comp_build_rules,hal/components/siggen.o)) +$(eval $(call c_comp_build_rules,hal/components/threads.o)) +#$$(eval $(call c_comp_build_rules,hal/components/supply.o)) +$(eval $(call c_comp_build_rules,hal/components/sim_encoder.o)) +#$$(eval $(call c_comp_build_rules,hal/components/watchdog.o)) +#$$(eval $(call c_comp_build_rules,hal/components/modmath.o)) +$(eval $(call c_comp_build_rules,hal/components/streamer.o)) +$(eval $(call c_comp_build_rules,hal/components/sampler.o)) +$(eval $(call c_comp_build_rules,hal/components/delayline.o)) diff --git a/src/hal/components/hal_pru.c b/src/hal/components/hal_pru.c index ef67b8809f..fa34dcab1b 100644 --- a/src/hal/components/hal_pru.c +++ b/src/hal/components/hal_pru.c @@ -8,10 +8,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_compat.h" /* RTAPI support functions */ #include "rtapi_app.h" /* RTAPI realtime module decls */ @@ -110,7 +106,7 @@ static int comp_id; /* component ID */ static const char *modname = MODNAME; // if filename doesnt exist, prefix this path: -char *fw_path = "/lib/firmware/pru/"; +char *fw_path = "/lib/firmware/pru/"; // shared with PRU static unsigned long *pru_data_ram; // points to PRU data RAM @@ -335,7 +331,7 @@ static int setup_pru(int pru, char *filename, int disabled) // default the .bin filename if not given if (!strlen(filename)){ - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "%s: no filename given - default to %s\n", modname, DEFAULT_CODE); filename = DEFAULT_CODE; @@ -346,7 +342,7 @@ static int setup_pru(int pru, char *filename, int disabled) if (!((stat(pru_binpath, &statb) == 0) && S_ISREG(statb.st_mode))) { - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "%s: filename %s does not exist.\n", modname, pru_binpath); // filename not found, prefix fw_path & try that: strcpy(pru_binpath, fw_path); diff --git a/src/hal/components/hal_prudebug.c b/src/hal/components/hal_prudebug.c index fffa4b6a29..1c6b9345ef 100644 --- a/src/hal/components/hal_prudebug.c +++ b/src/hal/components/hal_prudebug.c @@ -8,10 +8,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - // try to make sense of IEP and ECAP counters // not part of debugging #define EXPLORE_COUNTERS 1 diff --git a/src/hal/components/mux_generic.c b/src/hal/components/mux_generic.c index 5a31ac2d77..01bd406d65 100644 --- a/src/hal/components/mux_generic.c +++ b/src/hal/components/mux_generic.c @@ -23,10 +23,8 @@ #include "hal.h" #include "hal_priv.h" -#if defined(BUILD_SYS_USER_DSO) #include #include -#endif /* module information */ MODULE_AUTHOR("Andy Pugh"); diff --git a/src/hal/components/pepper.c b/src/hal/components/pepper.c index 22bfdc23ce..70fe9de71e 100644 --- a/src/hal/components/pepper.c +++ b/src/hal/components/pepper.c @@ -6,7 +6,7 @@ * * Author: Bas Laarhoven * License: GPL Version 2 -* +* * Copyright (c) 2014 All rights reserved. * * Last change: 16-04-2014 sjl - created. @@ -93,10 +93,6 @@ MODULE_DESCRIPTION("Pepper Board Configuration Component for EMC HAL"); MODULE_LICENSE("GPL"); -#if !defined( BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - /*********************************************************************** * STRUCTURES AND GLOBAL VARIABLES * ************************************************************************/ @@ -276,11 +272,11 @@ static void pepper_update( void *arg, long period) * Simple, two state implementation (00 & 11). */ if (*(pepper->io_ena_in) == 0) { - spindle_mosi = + spindle_mosi = enable_sck = 0; state = 0; } else { - spindle_mosi = + spindle_mosi = enable_sck = *(pepper->stepper_ena_in[ 0]) || *(pepper->stepper_ena_in[ 1]) || @@ -412,7 +408,7 @@ static int pepper_export( hal_pepper_t* addr, const char* prefix) { int retval; int i; - + retval = hal_pin_bit_newf( HAL_IN, &(addr->io_ena_in), comp_id, "%s.io-ena.in", prefix); if (retval != 0) { return retval; diff --git a/src/hal/components/rtfault.comp b/src/hal/components/rtfault.comp index 5272e76d0f..95fcd2022e 100644 --- a/src/hal/components/rtfault.comp +++ b/src/hal/components/rtfault.comp @@ -11,10 +11,8 @@ license "GPL"; ;; #include "rtapi.h" -#if defined(BUILD_SYS_USER_DSO) #include #include -#endif #include static bool previous_fault; static int n; @@ -23,9 +21,8 @@ FUNCTION(_) { if (previous_fault ^ fault) { n = count; } - previous_fault = fault; + previous_fault = fault; if (n) { -#if defined(BUILD_SYS_USER_DSO) // printf() eventually calls write(), which will cause // a Xenomai domain switch @@ -33,12 +30,5 @@ FUNCTION(_) { if (delay) nanosleep(&nap, NULL); printf("fault # %d\n", n--); -#else - do { - rtapi_delay(delay * 1000 * 1000); - n--; - } while (n > 0); - rtapi_print_msg(RTAPI_MSG_ERR, "RT delay ..\n"); -#endif } } diff --git a/src/hal/components/rtmon.comp b/src/hal/components/rtmon.comp index c53c6fa668..dcf65f075d 100644 --- a/src/hal/components/rtmon.comp +++ b/src/hal/components/rtmon.comp @@ -62,7 +62,7 @@ license "GPL"; // in a non-thread function to wiggle and read pins static struct __comp_state *this; -static int rtmon_exception_handler(rtapi_exception_t type, +static int rtmon_exception_handler(int type, rtapi_exception_detail_t *detail, rtapi_threadstatus_t *threadstatus) diff --git a/src/hal/cython/machinekit/compat.pxd b/src/hal/cython/machinekit/compat.pxd index 9053213fe5..be4ac685f5 100644 --- a/src/hal/cython/machinekit/compat.pxd +++ b/src/hal/cython/machinekit/compat.pxd @@ -4,38 +4,4 @@ cdef extern from "rtapi_bitops.h": int RTAPI_BIT(int b) cdef extern from "rtapi_compat.h": - cdef int FLAVOR_DOES_IO - cdef int FLAVOR_KERNEL_BUILD - cdef int FLAVOR_RTAPI_DATA_IN_SHM - cdef int POSIX_FLAVOR_FLAGS - cdef int RTPREEMPT_FLAVOR_FLAGS - cdef int RTAI_KERNEL_FLAVOR_FLAGS - cdef int XENOMAI_KERNEL_FLAVOR_FLAGS - cdef int XENOMAI_FLAVOR_FLAGS - - ctypedef struct flavor_t: - const char *name - const char *mod_ext - const char *so_ext - const char *build_sys - int flavor_id - unsigned long flags - - int c_is_module_loaded "is_module_loaded" (const char *module) - int c_load_module "load_module" (const char *module, const char *modargs) - int c_run_module_helper "run_module_helper" (const char *format) - - int c_kernel_is_xenomai "kernel_is_xenomai" () - int c_kernel_is_rtai "kernel_is_rtai" () - int c_kernel_is_rtpreempt "kernel_is_rtpreempt" () - - int c_xenomai_gid "xenomai_gid" () - int c_user_in_xenomai_group "user_in_xenomai_group" () - int c_kernel_instance_id "kernel_instance_id" () - - flavor_t flavors[] - flavor_t *c_flavor_byname "flavor_byname" (const char *flavorname) - flavor_t *c_flavor_byid "flavor_byid" (int flavor_id) - flavor_t *c_default_flavor "default_flavor"() - int c_module_path "module_path" (char *result, const char *basename) int c_get_rtapi_config "get_rtapi_config" (char *result, const char *param, int n) diff --git a/src/hal/cython/machinekit/compat.pyx b/src/hal/cython/machinekit/compat.pyx index 595b902d6a..116680690b 100644 --- a/src/hal/cython/machinekit/compat.pyx +++ b/src/hal/cython/machinekit/compat.pyx @@ -4,84 +4,6 @@ from .compat cimport * from os import strerror -cdef Flavor_Init(flavor_t *f): - result = Flavor() - result._f = f - return result - -cdef class Flavor: - cdef flavor_t *_f - - property name: - def __get__(self): return self._f.name - - property mod_ext: - def __get__(self): return self._f.mod_ext - - property so_ext: - def __get__(self): return self._f.so_ext - - property build_sys: - def __get__(self): return self._f.build_sys - - property flavorid: - def __get__(self): return self._f.flavor_id - - property flags: - def __get__(self): return self._f.flags - -def is_module_loaded(m): - return c_is_module_loaded(m) - -def kernel_is_xenomai(): - return bool(c_kernel_is_xenomai()) - -def kernel_is_rtai(): - return bool(c_kernel_is_rtai()) - -def kernel_is_rtpreempt(): - return bool(c_kernel_is_rtpreempt()) - -def xenomai_gid(): - return c_xenomai_gid() - -def user_in_xenomai_group(): - return bool(c_user_in_xenomai_group()) - -def kernel_instance_id(): - return c_kernel_instance_id() - -def flavor_byname(name): - cdef flavor_t *f = c_flavor_byname(name) - if f == NULL: - raise RuntimeError("flavor_byname: no such flavor: %s" % name) - return Flavor_Init(f) - -def flavor_byid(id): - cdef flavor_t *f = c_flavor_byid(id) - if f == NULL: - raise RuntimeError("flavor_byid: no such flavor: %d" % id) - return Flavor_Init(f) - - -def default_flavor(): - cdef flavor_t *f = c_default_flavor() - if f == NULL: - raise RuntimeError("BUG: flavor() failed") - return Flavor_Init(f) - -def run_module_helper(name): - rc = c_run_module_helper(name) - if rc: - raise RuntimeError("module_helper(%s) failed: %d %s " % (name, rc, strerror(rc))) - -def module_path(basename): - cdef char result[1024] - rc = c_module_path(result, basename) - if rc: - raise RuntimeError("modpath(%s) failed: %d %s " % (basename, rc, strerror(-rc))) - return str(result) - def get_rtapi_config(param): cdef char result[1024] rc = c_get_rtapi_config(result, param, 1024) diff --git a/src/hal/cython/machinekit/global_data.pxd b/src/hal/cython/machinekit/global_data.pxd index b586727533..b8439937f9 100644 --- a/src/hal/cython/machinekit/global_data.pxd +++ b/src/hal/cython/machinekit/global_data.pxd @@ -6,7 +6,6 @@ cdef extern from "rtapi.h": int instance_id char *instance_name - int rtapi_thread_flavor int rt_msg_level int user_msg_level diff --git a/src/hal/drivers/Submakefile b/src/hal/drivers/Submakefile index 3e7dbd0056..3ee089c799 100644 --- a/src/hal/drivers/Submakefile +++ b/src/hal/drivers/Submakefile @@ -5,8 +5,137 @@ INCLUDES += hal/drivers $(Q)cp $^ $@ # build instructions for the hal_p260c module -obj-m += hal_p260c.o -# the list of parts -hal_p260c-objs := hal/drivers/hal_p260c.o $(MATHSTUB) +$(eval $(call c_comp_build_rules,hal/drivers/hal_p260c.o)) -$(RTLIBDIR)/hal_p260c$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_p260c-objs)) +# C-language components +ifeq ($(BUILD_DRIVERS),yes) +ifeq ($(HAS_SYS_IO),yes) +$(eval $(call c_comp_build_rules,hal/drivers/hal_parport.o)) +$(eval $(call c_comp_build_rules,hal/drivers/pci_8255.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_tiro.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_stg.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_ax5214h.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_speaker.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_skeleton.o)) +endif +$(eval $(call c_comp_build_rules,hal/drivers/hal_vti.o)) +#$$(eval $(call c_comp_build_rules,hal/drivers/hal_evoreg.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_motenc.o)) + +ifdef TARGET_PLATFORM_RASPBERRY +$(eval $(call c_comp_build_rules,hal/drivers/hal_gpio.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_spi.o)) +endif + +ifdef TARGET_PLATFORM_SOCFPGA +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_soc_ol.o)) +endif + +ifdef TARGET_PLATFORM_BEAGLEBONE +$(eval $(call c_comp_build_rules,hal/drivers/hal_bb_gpio/hal_bb_gpio.o)) +$(eval $(call c_comp_build_rules,hal/components/pepper.o)) +# Silence warning in GCC 4.4 +$(OBJDIR)/hal/components/pepper.o: EXTRA_CFLAGS += -Wno-packed-bitfield-compat + +$(eval $(call c_comp_build_rules,hal/drivers/hal_arm335xQEP.o)) +endif + +ifdef TARGET_PLATFORM_H3 +$(eval $(call c_comp_build_rules,hal/drivers/hal_gpio_h3.o)) +endif + +ifdef TARGET_PLATFORM_CHIP +$(eval $(call c_comp_build_rules,hal/drivers/hal_chip_gpio.o)) +endif + +ifdef TARGET_PLATFORM_ZEDBOARD +$(eval $(call c_comp_build_rules,hal/drivers/hal_zed_gpio.o)) +$(eval $(call c_comp_build_rules,hal/drivers/hal_zed_can.o)) +endif + +# hal_pru_generic driver +ifdef TARGET_PLATFORM_BEAGLEBONE +$(eval $(call c_comp_build_rules, \ + hal/drivers/hal_pru_generic/hal_pru_generic.o, \ + hal/drivers/hal_pru_generic/pwmgen.o \ + hal/drivers/hal_pru_generic/stepgen.o \ + hal/drivers/hal_pru_generic/encoder.o \ + hal/support/pru/prussdrv.o \ + $(LIBPTHREAD) \ + )) +endif + +# these won't compile as-is with userland threading +###################################################### +#$$(eval $(call c_comp_build_rules,hal/drivers/hal_m5i20.o)) +#$$(eval $(call c_comp_build_rules,hal/drivers/hal_ppmc.o)) +#$$(eval $(call c_comp_build_rules,hal/drivers/opto_ac5.o)) +#$$(eval $(call c_comp_build_rules,hal/drivers/hal_gm.o)) +#endif +#################################################### + +BUILD_HOSTMOT2=yes + +ifeq ($(BUILD_HOSTMOT2),yes) +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_eth.o)) +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hostmot2.o,\ + hal/drivers/mesa-hostmot2/backported-strings.o \ + hal/drivers/mesa-hostmot2/dbspi.o \ + hal/drivers/mesa-hostmot2/ioport.o \ + hal/drivers/mesa-hostmot2/encoder.o \ + hal/drivers/mesa-hostmot2/abs_encoder.o\ + hal/drivers/mesa-hostmot2/resolver.o \ + hal/drivers/mesa-hostmot2/pwmgen.o \ + hal/drivers/mesa-hostmot2/tp_pwmgen.o \ + hal/drivers/mesa-hostmot2/sserial.o \ + hal/drivers/mesa-hostmot2/stepgen.o \ + hal/drivers/mesa-hostmot2/bspi.o \ + hal/drivers/mesa-hostmot2/uart.o \ + hal/drivers/mesa-hostmot2/pktuart.o \ + hal/drivers/mesa-hostmot2/watchdog.o \ + hal/drivers/mesa-hostmot2/pins.o \ + hal/drivers/mesa-hostmot2/dpll.o \ + hal/drivers/mesa-hostmot2/irq.o \ + hal/drivers/mesa-hostmot2/led.o \ + hal/drivers/mesa-hostmot2/fwid.o \ + hal/drivers/mesa-hostmot2/tram.o \ + hal/drivers/mesa-hostmot2/raw.o \ + hal/drivers/mesa-hostmot2/nano_soc_adc.o \ + hal/drivers/mesa-hostmot2/capsense.o \ + hal/drivers/mesa-hostmot2/bitfile.o \ + rtapi/userpci/device.o \ + rtapi/userpci/firmware.o \ + rtapi/userpci/string.o \ +)) + +ifeq ($(HAS_SYS_IO),yes) +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_7i43.o,\ + hal/drivers/mesa-hostmot2/hm2_7i43.o \ + hal/drivers/mesa-hostmot2/bitfile.o \ +)) + +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_7i90.o, \ + hal/drivers/mesa-hostmot2/bitfile.o \ +)) + +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_pci.o, \ + hal/drivers/mesa-hostmot2/bitfile.o \ +)) +endif +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_test.o, \ + hal/drivers/mesa-hostmot2/bitfile.o \ +)) +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/setsserial.o, \ + rtapi/userpci/device.o \ + rtapi/userpci/firmware.o \ + rtapi/userpci/string.o \ +)) +ifeq ($(HAS_SYS_IO),yes) +$(eval $(call c_comp_build_rules,hal/drivers/mesa-hostmot2/hm2_pci.o, \ + hal/drivers/mesa-hostmot2/bitfile.o \ +)) +endif +endif # BUILD_HOSTMOT2 + +$(eval $(call c_comp_build_rules,hal/drivers/probe_parport.o)) +endif diff --git a/src/hal/drivers/hal_arm335xQEP.c b/src/hal/drivers/hal_arm335xQEP.c index 4482239540..f555ce2b8b 100644 --- a/src/hal/drivers/hal_arm335xQEP.c +++ b/src/hal/drivers/hal_arm335xQEP.c @@ -64,10 +64,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - /* Module information */ #define MODNAME "hal_arm335xQEP" MODULE_AUTHOR("Russell Gower"); @@ -525,4 +521,3 @@ static int export_encoder(eqep_t *eqep) return 0; } - diff --git a/src/hal/drivers/hal_ax5214h.c b/src/hal/drivers/hal_ax5214h.c index 7cd59af392..7329065bac 100644 --- a/src/hal/drivers/hal_ax5214h.c +++ b/src/hal/drivers/hal_ax5214h.c @@ -1,37 +1,37 @@ /******************************************************************** * Description: AX5214H.c -* This file, 'AX5214H.c', is a HAL component that -* provides a driver for the Axiom Measurement & Control +* This file, 'AX5214H.c', is a HAL component that +* provides a driver for the Axiom Measurement & Control * AX5241H 48 channel digital I/O board. * * Author: John Kasunich * License: GPL Version 2 -* +* * Copyright (c) 2005 All rights reserved. * -* Last change: +* Last change: ********************************************************************/ /** This file, 'AX5214H.c', is a HAL component that provides a driver for the Axiom Measurement & Control AX5241H 48 channel digital I/O board. - The configuration is determined by a config string passed to + The configuration is determined by a config string passed to insmod when loading the module. The format consists of a base address, followed by a eight character string that sets the - direction of each group of pins, repeated for each card (if + direction of each group of pins, repeated for each card (if more than one card is used). Each character of the direction string is either "I" or "O". The first character sets the - direction of port A on channel 1 (Port 1A), the next sets + direction of port A on channel 1 (Port 1A), the next sets port B on channel 1 (port 1B), the next sets the low nibble - of port C on channel 1 (port 1CL), and the fourth sets the + of port C on channel 1 (port 1CL), and the fourth sets the high nibble of port C on channel 1 (port 1CH). The next four - characters do the same thing for channel 2 (ports 2A, 2B, + characters do the same thing for channel 2 (ports 2A, 2B, 2CL, and 2CH). example: insmod AX5214.o cfg="0x220 IIIOIIOO" - - The example above is for one card, with its base address - set to hex 220, and with 36 channels of input (Ports 1A, + + The example above is for one card, with its base address + set to hex 220, and with 36 channels of input (Ports 1A, 1B, 1CL, 2A, and 2B) and 12 channels of output (Ports 1CH, 2CL, and 2CH). @@ -44,16 +44,16 @@ 'ax5214..in-' and 'ax5214..in--not'. - is the board number, starting from zero. + is the board number, starting from zero. is the pin number, from 0 to 47. - + Note that the driver assumes active LOW signals. This is so that modules such as OPTO-22 will work correctly - (TRUE means output ON, or input energized). If the + (TRUE means output ON, or input energized). If the signals are being used directly without buffering or isolation the inversion needs to be accounted for. - The driver exports two HAL functions for each board, + The driver exports two HAL functions for each board, 'ax5214..read' and 'ax5214..write'. */ @@ -92,13 +92,8 @@ #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ #include "hal.h" /* HAL public API decls */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ -#ifdef BUILD_SYS_USER_DSO -#include -#else -#include -#endif +#include "rtapi_io.h" /* module information */ MODULE_AUTHOR("John Kasunich"); @@ -264,7 +259,7 @@ void rtapi_app_exit(void) { int n; board_t *board; - + for ( n = 0 ; n < num_boards ; n++ ) { board = &(board_array[n]); /* reset all outputs to high/off */ @@ -306,13 +301,13 @@ static void split_input(unsigned char data, io_pin_t *dest, int num) mask <<= 1; dest++; } -} +} static void read_board(void *arg, long period) { board_t *board; unsigned char indata; - + board = arg; if ( (board->dir_bits & 0x01) == 0 ) { indata = rtapi_inb(board->base_addr+0); @@ -586,7 +581,7 @@ static int export_board(int boardnum, board_t * board) } board->port1config = config; config = 0x80; - + dir = board->dir_bits & 0x10; retval += export_port ( boardnum, 24, &(board->port_2A[0]), 8, dir ); if ( dir == 0 ) { @@ -608,7 +603,7 @@ static int export_board(int boardnum, board_t * board) config |= 0x08; } board->port2config = config; - /* initialize hardware - all outputs high + /* initialize hardware - all outputs high (since outputs are active low) */ outb(board->port1config, board->base_addr+3); outb(0xff, board->base_addr+0); diff --git a/src/hal/drivers/hal_chip_gpio.c b/src/hal/drivers/hal_chip_gpio.c index 1d5da377f0..277bbc0bf8 100644 --- a/src/hal/drivers/hal_chip_gpio.c +++ b/src/hal/drivers/hal_chip_gpio.c @@ -23,9 +23,6 @@ #include "chip/libsoc_mmap_gpio.h" -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif #if !defined(TARGET_PLATFORM_CHIP) #error "This driver is for the BeagleBone platform only" #endif diff --git a/src/hal/drivers/hal_gpio.c b/src/hal/drivers/hal_gpio.c index 699517fa03..20495c1479 100644 --- a/src/hal/drivers/hal_gpio.c +++ b/src/hal/drivers/hal_gpio.c @@ -9,7 +9,7 @@ * some code taken from the bcm2835 library by:: * * Author: Mike McCauley (mikem@open.com.au) -* Copyright (C) 2011 Mike McCauley +* Copyright (C) 2011 Mike McCauley * see http://www.open.com.au/mikem/bcm2835/ * Copyright (c) 2012 Ben Croston - cpuinfo.* * @@ -18,7 +18,7 @@ s********************************************************************/ #include "rtapi.h" /* RTAPI realtime OS API */ -#include "rtapi_bitops.h" +#include "rtapi_bitops.h" #include "rtapi_app.h" /* RTAPI realtime module decls */ /* this also includes config.h */ #include "hal.h" /* HAL public API decls */ @@ -30,9 +30,6 @@ s********************************************************************/ #define BCM2709_PERI_BASE 0x3F000000 #define BCM2709_GPIO_BASE (BCM2709_PERI_BASE + 0x200000) -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif #if !defined(TARGET_PLATFORM_RASPBERRY) #error "This driver is for the Raspberry and Raspberry2 platforms only" #endif @@ -182,7 +179,7 @@ static int setup_gpiomem_access(void) static int setup_gpio_access(int rev, int ncores) { - // open /dev/mem + // open /dev/mem if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { rtapi_print_msg(RTAPI_MSG_ERR,"HAL_GPIO: can't open /dev/mem: %d - %s", errno, strerror(errno)); @@ -198,7 +195,7 @@ static int setup_gpio_access(int rev, int ncores) if (gpio == MAP_FAILED) { rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_GPIO: mmap failed: %d - %s\n", + "HAL_GPIO: mmap failed: %d - %s\n", errno, strerror(errno)); return -1;; } @@ -229,7 +226,7 @@ int rtapi_app_main(void) char *endptr; if ((rev = get_rpi_revision()) < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "unrecognized Raspberry revision, see /proc/cpuinfo\n"); return -EINVAL; } @@ -284,7 +281,7 @@ int rtapi_app_main(void) } dir_map = strtoul(dir, &endptr,0); if (*endptr) { - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "HAL_GPIO: dir=%s - trailing garbage: '%s'\n", dir, endptr); return -1; @@ -296,7 +293,7 @@ int rtapi_app_main(void) } exclude_map = strtoul(exclude, &endptr,0); if (*endptr) { - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "HAL_GPIO: exclude=%s - trailing garbage: '%s'\n", exclude, endptr); return -1; @@ -332,7 +329,7 @@ int rtapi_app_main(void) } if (retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_GPIO: ERROR: pin %d export failed with err=%i\n", + "HAL_GPIO: ERROR: pin %d export failed with err=%i\n", n,retval); hal_exit(comp_id); return -1; @@ -375,10 +372,10 @@ static void write_port(void *arg, long period) int n; for (n = 0; n < npins; n++) { - if (exclude_map & RTAPI_BIT(n)) + if (exclude_map & RTAPI_BIT(n)) continue; if (dir_map & RTAPI_BIT(n)) { - if (*(port_data[n])) { + if (*(port_data[n])) { bcm2835_gpio_set(gpios[n]); } else { bcm2835_gpio_clr(gpios[n]); diff --git a/src/hal/drivers/hal_motenc.c b/src/hal/drivers/hal_motenc.c index b77528e37d..11004e7b7d 100644 --- a/src/hal/drivers/hal_motenc.c +++ b/src/hal/drivers/hal_motenc.c @@ -126,9 +126,7 @@ #include "rtapi.h" // RTAPI realtime OS API. #include "rtapi_app.h" // RTAPI realtime module decls. -#if defined(BUILD_SYS_USER_DSO) #include "rtapi_pci.h" -#endif #include "hal.h" // HAL public API decls. #include "motenc.h" // Hardware dependent defines. @@ -210,9 +208,7 @@ typedef struct { typedef struct { // Private data. -#if defined(BUILD_SYS_USER_DSO) struct rtapi_pcidev *pDev; -#endif MotencRegMap *pCard; int boardType; char *pTypeName; @@ -279,11 +275,7 @@ int rtapi_app_main(void) { int i, j; -#if defined(BUILD_SYS_USER_DSO) struct rtapi_pcidev *pDev = NULL; -#else - struct pci_dev *pDev = NULL; -#endif MotencRegMap *pCard = NULL; Device *pDevice; @@ -301,11 +293,7 @@ rtapi_app_main(void) i = 0; // Find a MOTENC card. -#if defined(BUILD_SYS_USER_DSO) while((i < MAX_DEVICES) && ((pDev = rtapi_pci_get_device(MOTENC_VENDOR_ID, MOTENC_DEVICE_ID, pDev)) != NULL)){ -#else - while((i < MAX_DEVICES) && ((pDev = pci_get_device(MOTENC_VENDOR_ID, MOTENC_DEVICE_ID, pDev)) != NULL)){ -#endif // Allocate memory for device object. pDevice = hal_malloc(sizeof(Device)); @@ -314,22 +302,14 @@ rtapi_app_main(void) hal_exit(driver.componentId); return(-ENOMEM); } -#if defined(BUILD_SYS_USER_DSO) pDevice->pDev = pDev; -#endif // Save pointer to device object. driver.deviceTable[i++] = pDevice; - + // Map card into memory. -#if defined(BUILD_SYS_USER_DSO) pCard = (MotencRegMap *)rtapi_pci_ioremap(pDev, 2, sizeof(MotencRegMap)); rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card detected\n"); rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card address @ %p, Len = %d\n", pCard, (int)sizeof(MotencRegMap)); -#else - pCard = (MotencRegMap *)ioremap_nocache(pci_resource_start(pDev, 2), pci_resource_len(pDev, 2)); - rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card detected in slot %2x\n", PCI_SLOT(pDev->devfn)); - rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card address @ %p, Len = %d\n", pCard, (int)pci_resource_len(pDev, 2)); -#endif // Initialize device. Device_Init(pDevice, pCard); rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card is %s, ID: %d\n", pDevice->pTypeName, pDevice->boardID); @@ -338,7 +318,7 @@ rtapi_app_main(void) hal_exit(driver.componentId); return(-ENODEV); } - + if ( driver.idPresent[pDevice->boardID] != 0 ) { // duplicate ID... a strict driver would bail out, but @@ -356,7 +336,7 @@ rtapi_app_main(void) rtapi_print_msg(RTAPI_MSG_WARN, "MOTENC: WARNING, duplicate ID, remapped to %d\n", j); } driver.idPresent[pDevice->boardID] = 1; - + // Export pins, parameters, and functions. if(Device_ExportPinsParametersFunctions(pDevice, driver.componentId)){ hal_exit(driver.componentId); @@ -394,15 +374,11 @@ rtapi_app_exit(void) for(j = 0; j < MOTENC_NUM_DAC_CHANNELS; j++){ pDevice->pCard->dac[j] = MOTENC_DAC_COUNT_ZERO; } - + // Unmap card. -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_iounmap(pDevice->pDev, (void *)(pDevice->pCard)); // Unregister the device rtapi_pci_put_device(pDevice->pDev); -#else - iounmap((void *)(pDevice->pCard)); -#endif // TODO: Free device object when HAL supports free. // hal_free(pDevice); } @@ -450,7 +426,7 @@ Device_Init(Device *this, MotencRegMap *pCard) // Extract board id from first FPGA. The user sets this via jumpers on the card. status = pCard->fpga[0].statusControl; this->boardID = (status & MOTENC_STATUS_BOARD_ID) >> MOTENC_STATUS_BOARD_ID_SHFT; - + // Initialize hardware. for(i = 0; i < this->numFpga; i++){ pCard->fpga[i].digitalIo = MOTENC_DIGITAL_OUT; @@ -481,7 +457,7 @@ Device_ExportPinsParametersFunctions(Device *this, int componentId) rtapi_set_msg_level(RTAPI_MSG_WARN); boardId = this->boardID; - + // Export encoders. error = Device_ExportEncoderPinsParametersFunctions(this, componentId, boardId); @@ -901,7 +877,7 @@ Device_AdcRead(void *arg, long period) pCard->adcDataCommand = MOTENC_ADC_COMMAND_CHN_0_1_2_3; pCard->adcStartConversion = 1; break; - + // Wait for first conversion, start conversion on second 4 channels. case 1: if(Device_AdcRead4(this, 0)){ diff --git a/src/hal/drivers/hal_p260c.c b/src/hal/drivers/hal_p260c.c index 0ea9adb964..76086f2be7 100644 --- a/src/hal/drivers/hal_p260c.c +++ b/src/hal/drivers/hal_p260c.c @@ -26,10 +26,6 @@ #include #include -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #define MODNAME "hal_p260c" /* module information */ @@ -94,7 +90,7 @@ static char *tty_debug; RTAPI_MP_STRING( tty_debug, "Serial port name, /dev/ttyUSB1"); #endif -static int comp_id; +static int comp_id; unsigned long runtime; unsigned long threadtime; @@ -106,7 +102,7 @@ typedef struct _mod_status { hal_s32_t *maxwritetime; hal_s32_t *writecnt; // s32 count of write calls - + hal_bit_t *comm_error; // Currently some board has a communication error hal_bit_t *permanent_error; // Permanent error triggered by comm_error ( Must be reset ) hal_bit_t *reset_permanent; // Input bit to reset permanent error @@ -150,7 +146,7 @@ void write_gpio( int gpio, int on ) {} void configure_output( int gpio ) {} #endif -int rtapi_app_main(void) +int rtapi_app_main(void) { int i, j, retval; char *data, *token; @@ -158,7 +154,7 @@ int rtapi_app_main(void) comp_id = hal_init(modname); - if(comp_id < 0) + if(comp_id < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: hal_init() failed\n", modname); return -1; @@ -187,7 +183,7 @@ int rtapi_app_main(void) if ( addrs != NULL ) { data = addrs; - while((token = strtok(data, ",")) != NULL) + while((token = strtok(data, ",")) != NULL) { int add = strtol(token, NULL, 16); @@ -244,7 +240,7 @@ int rtapi_app_main(void) for (j=0;jmaxreadtime), comp_id, "%s.sys_max_read", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin maxreadtime could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_pin_s32_newf(HAL_IN, &(mstat->maxwritetime), comp_id, "%s.sys_max_write", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin maxwritetime could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_pin_s32_newf(HAL_IN, &(mstat->writecnt), comp_id, "%s.sys_writecnt", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin writecnt could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_pin_bit_newf(HAL_OUT, &(mstat->comm_error), comp_id, "%s.rx_comm_error", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin comm_error could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_pin_bit_newf(HAL_OUT, &(mstat->permanent_error), comp_id, "%s.rx_perm_error", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin permanent_error could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_pin_bit_newf(HAL_IN, &(mstat->reset_permanent), comp_id, "%s.rx_reset_error", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin reset_permanent could not export pin, err: %d\n", modname, retval); hal_exit(comp_id); @@ -345,35 +341,35 @@ int rtapi_app_main(void) // Parameters retval = hal_param_s32_newf(HAL_RW, &(mstat->clear_comm_count), comp_id, "%s.clear_comm_count", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param clear_comm_count could not create, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_param_s32_newf(HAL_RW, &(mstat->set_perm_count), comp_id, "%s.set_perm_count", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param set_perm_count could not create, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_param_s32_newf(HAL_RW, &(mstat->min_tx_boards), comp_id, "%s.minimum_tx", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param minimum_tx could not create, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_param_s32_newf(HAL_RW, &(mstat->max_rx_wait), comp_id, "%s.max_rx_wait", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param minimum_tx could not create, err: %d\n", modname, retval); hal_exit(comp_id); return -1; } retval = hal_param_bit_newf(HAL_RW, &(mstat->debug_on_error), comp_id, "%s.debug_on_error", modname ); - if(retval < 0) + if(retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param debug_on_error could not create, err: %d\n", modname, retval); hal_exit(comp_id); @@ -438,7 +434,7 @@ static int openserial(char *devicename, int baud) options = oldterminfo; rtapi_print_msg(RTAPI_MSG_INFO, "termios\niflag = %08X\noflag = %08X\ncflag = %08X\nlflag = %08X\n", options.c_iflag, options.c_oflag, options.c_cflag, options.c_lflag ); - + // Ignore input break // Check parity options.c_iflag = IGNBRK; @@ -649,7 +645,7 @@ static u8 validate_input_buffer( u8 *input_data, u16 *bits ) // // Count RX valids. // gets called once per cycle for each board. -// +// static int read_counts( int board ) { int ret = 0; @@ -806,7 +802,7 @@ static void read_all_data() // reset timeout t0 = rtapi_get_time(); - + // Check max time between reads if ( last_readtime && *(mstat->maxreadtime) < (t0-last_readtime) ) { @@ -1015,4 +1011,3 @@ static void serial_port_task( void *arg, long period ) runtime = t1 - t0; } - diff --git a/src/hal/drivers/hal_parport.c b/src/hal/drivers/hal_parport.c index bc12949252..dc91cc2587 100644 --- a/src/hal/drivers/hal_parport.c +++ b/src/hal/drivers/hal_parport.c @@ -1,14 +1,14 @@ /******************************************************************** * Description: hal_parport.c -* This file, 'hal_parport.c', is a HAL component that +* This file, 'hal_parport.c', is a HAL component that * provides a driver for the standard PC parallel port. * * Author: John Kasunich * License: GPL Version 2 -* +* * Copyright (c) 2003 All rights reserved. * -* Last change: +* Last change: ********************************************************************/ /** This file, 'hal_parport.c', is a HAL component that provides a @@ -99,13 +99,11 @@ #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_ctype.h" /* isspace() */ #include "rtapi_app.h" /* RTAPI realtime module decls */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ +#include "rtapi_io.h" #include "hal.h" /* HAL public API decls */ -#ifdef BUILD_SYS_USER_DSO /* userland builds */ # include -#endif #include "hal_parport.h" @@ -127,7 +125,7 @@ RTAPI_MP_STRING(cfg, "config string"); typedef struct { unsigned short base_addr; /* base I/O address (0x378, etc.) */ unsigned char data_dir; /* non-zero if pins 2-9 are input */ - unsigned char use_control_in; /* non-zero if pins 1, 4, 16, 17 are input */ + unsigned char use_control_in; /* non-zero if pins 1, 4, 16, 17 are input */ hal_bit_t *status_in[10]; /* ptrs for in pins 15, 13, 12, 10, 11 */ hal_bit_t *data_in[16]; /* ptrs for input pins 2 - 9 */ hal_bit_t *data_out[8]; /* ptrs for output pins 2 - 9 */ @@ -206,7 +204,7 @@ int rtapi_app_main(void) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) &&0//FIXME - // this calculation fits in a 32-bit unsigned + // this calculation fits in a 32-bit unsigned // as long as CPUs are under about 6GHz ns2tsc_factor = (cpu_khz << 6) / 15625ul; #else @@ -221,7 +219,7 @@ int rtapi_app_main(void) rtapi_print ( "config string '%s'\n", cfg ); /* as a RT module, we don't get a nice argc/argv command line, we only get a single string... so we need to tokenize it ourselves */ - /* in addition, it seems that insmod under kernel 2.6 will truncate + /* in addition, it seems that insmod under kernel 2.6 will truncate a string parameter at the first whitespace. So we allow '_' as an alternate token separator. */ cp = cfg; @@ -383,7 +381,7 @@ static void reset_port(void *arg, long period) { parport_t *port = arg; long long deadline, reset_time_tsc; unsigned char outdata = (port->outdata&~port->reset_mask) ^ port->reset_val; - + if(port->reset_time > period/4) port->reset_time = period/4; reset_time_tsc = ns2tsc(port->reset_time); @@ -544,7 +542,7 @@ static int pins_and_params(char *argv[]) if (argv[n] != 0) { /* is the next token 'in' or 'out' ? */ if ((argv[n][0] == 'i') || (argv[n][0] == 'I')) { - /* we aren't picky, anything starting with 'i' means 'in' ;-) + /* we aren't picky, anything starting with 'i' means 'in' ;-) */ data_dir[num_ports] = 1; use_control_in[num_ports] = 0; @@ -556,7 +554,7 @@ static int pins_and_params(char *argv[]) n++; } else if ((argv[n][0] == 'x') || (argv[n][0] == 'X')) { /* experimental: some parports support a bidirectional - * control port. Enable this with pins 2-9 in output mode, + * control port. Enable this with pins 2-9 in output mode, * which gives a very nice 8 outs and 9 ins. */ data_dir[num_ports] = 0; use_control_in[num_ports] = 1; @@ -702,11 +700,11 @@ static int export_port(int portnum, parport_t * port) port->data_out, port->data_inv, port->data_reset, 6); retval += export_output_pin(portnum, 9, port->data_out, port->data_inv, port->data_reset, 7); - retval += hal_param_u32_newf(HAL_RW, &port->reset_time, comp_id, + retval += hal_param_u32_newf(HAL_RW, &port->reset_time, comp_id, "parport.%d.reset-time", portnum); - retval += hal_param_u32_newf(HAL_RW, &port->debug1, comp_id, + retval += hal_param_u32_newf(HAL_RW, &port->debug1, comp_id, "parport.%d.debug1", portnum); - retval += hal_param_u32_newf(HAL_RW, &port->debug2, comp_id, + retval += hal_param_u32_newf(HAL_RW, &port->debug2, comp_id, "parport.%d.debug2", portnum); port->write_time = 0; } diff --git a/src/hal/drivers/hal_pru_generic/Submakefile b/src/hal/drivers/hal_pru_generic/Submakefile index ae91111af9..dc620e9a1f 100644 --- a/src/hal/drivers/hal_pru_generic/Submakefile +++ b/src/hal/drivers/hal_pru_generic/Submakefile @@ -1,13 +1,6 @@ ifdef TARGET_PLATFORM_BEAGLEBONE -# These are actually the same location but the package -# build needs to set a path relative to the Makefile, -# from whence it will be copied to debian/tmp -ifeq ($(RUN_IN_PLACE),yes) -PRUBINDIR := $(EMC2_HOME)/rtlib/prubin -else PRUBINDIR := ../rtlib/prubin -endif # support for ARM335x PRU (Programmable Realtime Unit) components and SUPPORT_DIR := hal/support @@ -22,7 +15,7 @@ PRU_FILES := $(wildcard $(PRU_SRC_DIR)/*.p) PRU_BIN := $(patsubst %,$(PRUBINDIR)/%.bin,$(PRU_MAINS)) PRU_DBG := $(patsubst %,$(PRUBINDIR)/%.dbg,$(PRU_MAINS)) -modules : $(PRU_BIN) $(PRU_DBG) +modules : $(PRU_BIN) $(PRU_DBG) # .bin output, create listing PASM_BINFLAGS := -b -L -d @@ -30,7 +23,7 @@ PASM_BINFLAGS := -b -L -d # conversion rule for the above # assemble .p into .bin object files -$(PRUBINDIR)/%.bin $(PRUBINDIR)/%.dbg: $(PASM) +$(PRUBINDIR)/%.bin $(PRUBINDIR)/%.dbg: $(PASM) PRU_DEPS := $(patsubst %,objects/%,$(patsubst %,$(PRU_SRC_DIR)/%.d,$(PRU_MAINS))) @@ -44,13 +37,28 @@ $(PRU_DEPS): objects/%.d : %.p objects/%.bin objects/%.dbg : %.p objects/%.d $(PASM) $(Q)mkdir -p $(PRUBINDIR) - $(ECHO) Assembling PRU code $@ + $(ECHO) Assembling PRU code $@ $(Q)$(PASM) $(PASM_BINFLAGS) $< $(basename $@) $(PRU_BIN): $(PRUBINDIR)/%.bin : objects/$(PRU_SRC_DIR)/%.bin cp -f $^ $@ + $(Q)mkdir -p $(RTLIBDIR) + ln -sf ../prubin/$(notdir $@) $(RTLIBDIR)/$(notdir $@) $(PRU_DBG): $(PRUBINDIR)/%.dbg : objects/$(PRU_SRC_DIR)/%.dbg cp -f $^ $@ + $(Q)mkdir -p $(RTLIBDIR) + ln -sf ../prubin/$(notdir $@) $(RTLIBDIR)/$(notdir $@) + +install_prubin: + $(DIR) $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/prubin +# # Copy .bin and .dbg files to the rtlib/prubin directory + $(FILE) $(PRUBINDIR)/*.bin $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/prubin + $(FILE) $(PRUBINDIR)/*.dbg $(DESTDIR)$(EMC2_RTLIB_BASE_DIR)/prubin +# # Copy .bin and .dbg symlinks to the rtlib/modules directory + $(DIR) $(DESTDIR)$(EMC2_RTLIB_DIR) + cp -a $(RTLIBDIR)/*.bin $(RTLIBDIR)/*.dbg $(DESTDIR)$(EMC2_RTLIB_DIR) + +install: install_prubin endif diff --git a/src/hal/drivers/hal_pru_generic/encoder.c b/src/hal/drivers/hal_pru_generic/encoder.c index b8434e7350..d3094d7403 100644 --- a/src/hal/drivers/hal_pru_generic/encoder.c +++ b/src/hal/drivers/hal_pru_generic/encoder.c @@ -52,10 +52,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #include "rtapi.h" #include "rtapi_app.h" #include "rtapi_string.h" @@ -83,84 +79,84 @@ const PRU_encoder_LUT_t Counter_LUT = { { // New New Old Old -// Quadrature B A | B A B A +// Quadrature B A | B A B A // x4 Mode ==================== - 1, // 0 0 | 0 0 0 0 - 0, // 0 - | 0 0 0 1 - 2, // - 0 | 0 0 1 0 - 1, // - - | 0 0 1 1 - 2, // 0 + | 0 1 0 0 - 1, // 0 1 | 0 1 0 1 - 1, // - + | 0 1 1 0 - 0, // - 1 | 0 1 1 1 - 0, // + 0 | 1 0 0 0 - 1, // + - | 1 0 0 1 - 1, // 1 0 | 1 0 1 0 - 2, // 1 - | 1 0 1 1 - 1, // + + | 1 1 0 0 - 2, // + 1 | 1 1 0 1 - 0, // 1 + | 1 1 1 0 - 1, // 1 1 | 1 1 1 1 + 1, // 0 0 | 0 0 0 0 + 0, // 0 - | 0 0 0 1 + 2, // - 0 | 0 0 1 0 + 1, // - - | 0 0 1 1 + 2, // 0 + | 0 1 0 0 + 1, // 0 1 | 0 1 0 1 + 1, // - + | 0 1 1 0 + 0, // - 1 | 0 1 1 1 + 0, // + 0 | 1 0 0 0 + 1, // + - | 1 0 0 1 + 1, // 1 0 | 1 0 1 0 + 2, // 1 - | 1 0 1 1 + 1, // + + | 1 1 0 0 + 2, // + 1 | 1 1 0 1 + 0, // 1 + | 1 1 1 0 + 1, // 1 1 | 1 1 1 1 // New New Old Old -// Up/Down B A | B A B A +// Up/Down B A | B A B A // Mode ==================== - 1, // 0 0 | 0 0 0 0 - 1, // 0 - | 0 0 0 1 - 1, // - 0 | 0 0 1 0 - 1, // - - | 0 0 1 1 - 0, // 0 + | 0 1 0 0 - 1, // 0 1 | 0 1 0 1 - 2, // - + | 0 1 1 0 - 1, // - 1 | 0 1 1 1 - 1, // + 0 | 1 0 0 0 - 1, // + - | 1 0 0 1 - 1, // 1 0 | 1 0 1 0 - 1, // 1 - | 1 0 1 1 - 0, // + + | 1 1 0 0 - 1, // + 1 | 1 1 0 1 - 2, // 1 + | 1 1 1 0 - 1, // 1 1 | 1 1 1 1 + 1, // 0 0 | 0 0 0 0 + 1, // 0 - | 0 0 0 1 + 1, // - 0 | 0 0 1 0 + 1, // - - | 0 0 1 1 + 0, // 0 + | 0 1 0 0 + 1, // 0 1 | 0 1 0 1 + 2, // - + | 0 1 1 0 + 1, // - 1 | 0 1 1 1 + 1, // + 0 | 1 0 0 0 + 1, // + - | 1 0 0 1 + 1, // 1 0 | 1 0 1 0 + 1, // 1 - | 1 0 1 1 + 0, // + + | 1 1 0 0 + 1, // + 1 | 1 1 0 1 + 2, // 1 + | 1 1 1 0 + 1, // 1 1 | 1 1 1 1 // New New Old Old -// Counter B A | B A B A +// Counter B A | B A B A // Mode ==================== - 1, // 0 0 | 0 0 0 0 - 1, // 0 - | 0 0 0 1 - 1, // - 0 | 0 0 1 0 - 1, // - - | 0 0 1 1 - 2, // 0 + | 0 1 0 0 - 1, // 0 1 | 0 1 0 1 - 2, // - + | 0 1 1 0 - 1, // - 1 | 0 1 1 1 - 1, // + 0 | 1 0 0 0 - 1, // + - | 1 0 0 1 - 1, // 1 0 | 1 0 1 0 - 1, // 1 - | 1 0 1 1 - 2, // + + | 1 1 0 0 - 1, // + 1 | 1 1 0 1 - 2, // 1 + | 1 1 1 0 - 1, // 1 1 | 1 1 1 1 + 1, // 0 0 | 0 0 0 0 + 1, // 0 - | 0 0 0 1 + 1, // - 0 | 0 0 1 0 + 1, // - - | 0 0 1 1 + 2, // 0 + | 0 1 0 0 + 1, // 0 1 | 0 1 0 1 + 2, // - + | 0 1 1 0 + 1, // - 1 | 0 1 1 1 + 1, // + 0 | 1 0 0 0 + 1, // + - | 1 0 0 1 + 1, // 1 0 | 1 0 1 0 + 1, // 1 - | 1 0 1 1 + 2, // + + | 1 1 0 0 + 1, // + 1 | 1 1 0 1 + 2, // 1 + | 1 1 1 0 + 1, // 1 1 | 1 1 1 1 // New New Old Old -// Quadrature B A | B A B A +// Quadrature B A | B A B A // x1 Mode ==================== - 1, // 0 0 | 0 0 0 0 - 1, // 0 - | 0 0 0 1 - 1, // - 0 | 0 0 1 0 - 1, // - - | 0 0 1 1 - 2, // 0 + | 0 1 0 0 - 1, // 0 1 | 0 1 0 1 - 1, // - + | 0 1 1 0 - 1, // - 1 | 0 1 1 1 - 1, // + 0 | 1 0 0 0 - 1, // + - | 1 0 0 1 - 1, // 1 0 | 1 0 1 0 - 1, // 1 - | 1 0 1 1 - 1, // + + | 1 1 0 0 - 1, // + 1 | 1 1 0 1 - 0, // 1 + | 1 1 1 0 - 1 // 1 1 | 1 1 1 1 + 1, // 0 0 | 0 0 0 0 + 1, // 0 - | 0 0 0 1 + 1, // - 0 | 0 0 1 0 + 1, // - - | 0 0 1 1 + 2, // 0 + | 0 1 0 0 + 1, // 0 1 | 0 1 0 1 + 1, // - + | 0 1 1 0 + 1, // - 1 | 0 1 1 1 + 1, // + 0 | 1 0 0 0 + 1, // + - | 1 0 0 1 + 1, // 1 0 | 1 0 1 0 + 1, // 1 - | 1 0 1 1 + 1, // + + | 1 1 0 0 + 1, // + 1 | 1 1 0 1 + 0, // 1 + | 1 1 1 0 + 1 // 1 1 | 1 1 1 1 } }; static u64 timebase; /* master timestamp */ diff --git a/src/hal/drivers/hal_pru_generic/hal_pru_generic.c b/src/hal/drivers/hal_pru_generic/hal_pru_generic.c index 480a78eea1..62dbce1b6d 100644 --- a/src/hal/drivers/hal_pru_generic/hal_pru_generic.c +++ b/src/hal/drivers/hal_pru_generic/hal_pru_generic.c @@ -60,10 +60,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #include RTAPI_INC_LIST_H #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ @@ -107,7 +103,7 @@ MODULE_LICENSE("GPL"); // Default pin to use for PRU modules...use a pin that does not leave the PRU #define PRU_DEFAULT_PIN 17 -// Start out with default pulse length/width and setup/hold delays of 1 mS (1000000 nS) +// Start out with default pulse length/width and setup/hold delays of 1 mS (1000000 nS) #define DEFAULT_DELAY 1000000 #define f_period_s ((double)(l_period_ns * 1e-9)) @@ -153,7 +149,7 @@ static int comp_id; /* component ID */ static const char *modname = "hal_pru_generic"; // if filename doesnt exist, prefix this path: -char *fw_path = "/lib/firmware/pru/"; +char *fw_path = "/lib/firmware/pru/"; // shared with PRU static unsigned long *pru_data_ram; // points to PRU data RAM @@ -383,7 +379,7 @@ int assure_module_loaded(const char *module) } int pru_init(int pru, char *filename, int disabled, hal_pru_generic_t *hpg) { - + int i; int retval; @@ -445,7 +441,7 @@ rtapi_print_msg(RTAPI_MSG_DBG, "PRU data ram mapped\n"); } int setup_pru(int pru, char *filename, int disabled, hal_pru_generic_t *hpg) { - + int retval; if (event > -1) { @@ -461,7 +457,7 @@ int setup_pru(int pru, char *filename, int disabled, hal_pru_generic_t *hpg) { // default the .bin filename if not given if (!strlen(filename)) filename = DEFAULT_CODE; - + strcpy(pru_binpath, filename); struct stat statb; @@ -605,7 +601,7 @@ int fixup_pin(u32 hal_pin) { break; default: ret = 0; - } + } if (ret == 0) HPG_ERR("Unknown pin: %d\n",(int)hal_pin); @@ -618,4 +614,3 @@ int fixup_pin(u32 hal_pin) { return ret; } - diff --git a/src/hal/drivers/hal_pru_generic/pwmgen.c b/src/hal/drivers/hal_pru_generic/pwmgen.c index d8c5f5c2fa..4b29fe685d 100644 --- a/src/hal/drivers/hal_pru_generic/pwmgen.c +++ b/src/hal/drivers/hal_pru_generic/pwmgen.c @@ -58,10 +58,6 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #include "rtapi.h" #include "rtapi_app.h" #include "rtapi_string.h" @@ -170,7 +166,7 @@ rtapi_print_msg(RTAPI_MSG_DBG, "hpg_pwm_init\n"); pru_task_add(hpg, &(hpg->pwmgen.instance[i].task)); - if ((r = export_pwmgen(hpg,i)) != 0){ + if ((r = export_pwmgen(hpg,i)) != 0){ HPG_ERR("ERROR: failed to export pwmgen %i: %i\n",i,r); return -1; } diff --git a/src/hal/drivers/hal_pru_generic/stepgen.c b/src/hal/drivers/hal_pru_generic/stepgen.c index 5e6b974cdc..88798af332 100644 --- a/src/hal/drivers/hal_pru_generic/stepgen.c +++ b/src/hal/drivers/hal_pru_generic/stepgen.c @@ -58,17 +58,13 @@ #error "This driver is for the beaglebone platform only" #endif -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - // #include RTAPI_INC_LIST_H // #include "rtapi.h" /* RTAPI realtime OS API */ // #include "rtapi_app.h" /* RTAPI realtime module decls */ // #include "rtapi_math.h" // #include "hal.h" /* HAL public API decls */ // #include -// +// // #include // #include // #include @@ -87,16 +83,16 @@ #define f_period_s ((double)(l_period_ns * 1e-9)) -// Start out with default pulse length/width and setup/hold delays of 1 mS (1000000 nS) +// Start out with default pulse length/width and setup/hold delays of 1 mS (1000000 nS) #define DEFAULT_DELAY 1000000 /*********************************************************************** * REALTIME FUNCTIONS * ************************************************************************/ -// +// // read accumulator to figure out where the stepper has gotten to -// +// void hpg_stepgen_read(hal_pru_generic_t *hpg, long l_period_ns) { // Read data from the PRU here... @@ -366,7 +362,7 @@ static void update_stepgen(hal_pru_generic_t *hpg, long l_period_ns, int i) { steps_per_sec_cmd = new_vel * *(s->hal.pin.position_scale); s->pru.rate = steps_per_sec_cmd * (double)0x08000000 * (double) hpg->config.pru_period * 1e-9; - + // clip rate just to be safe...should be limited by code above if ((s->pru.rate < 0x80000000) && (s->pru.rate > 0x03FFFFFF)) { s->pru.rate = 0x03FFFFFF; @@ -615,7 +611,7 @@ rtapi_print_msg(RTAPI_MSG_DBG, "hpg_stepgen_init\n"); hpg->stepgen.instance[i].pru.task.hdr.mode = eMODE_STEP_DIR; pru_task_add(hpg, &(hpg->stepgen.instance[i].task)); - if ((r = export_stepgen(hpg,i)) != 0){ + if ((r = export_stepgen(hpg,i)) != 0){ rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: failed to export stepgen %i: %i\n", hpg->config.name,i,r); return -1; diff --git a/src/hal/drivers/hal_skeleton.c b/src/hal/drivers/hal_skeleton.c index 9b3b66753a..2049b40106 100644 --- a/src/hal/drivers/hal_skeleton.c +++ b/src/hal/drivers/hal_skeleton.c @@ -77,7 +77,7 @@ #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ +#include "rtapi_io.h" #include "hal.h" /* HAL public API decls */ diff --git a/src/hal/drivers/hal_speaker.c b/src/hal/drivers/hal_speaker.c index cb89f10599..b9eb7c6155 100644 --- a/src/hal/drivers/hal_speaker.c +++ b/src/hal/drivers/hal_speaker.c @@ -62,8 +62,8 @@ #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ +#include "rtapi_io.h" #include "hal.h" /* HAL public API decls */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ /* module information */ MODULE_AUTHOR("Jeff Epler"); diff --git a/src/hal/drivers/hal_spi.c b/src/hal/drivers/hal_spi.c index 6aa8866637..08b271f911 100644 --- a/src/hal/drivers/hal_spi.c +++ b/src/hal/drivers/hal_spi.c @@ -31,10 +31,6 @@ #include "cpuinfo.c" -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #if !defined(TARGET_PLATFORM_RASPBERRY) #error "This driver is for the Raspberry Pi platform only" #endif @@ -640,4 +636,4 @@ FILE *fp; procCount = 2; } return procCount; -} \ No newline at end of file +} diff --git a/src/hal/drivers/hal_stg.c b/src/hal/drivers/hal_stg.c index 3e4d040e0c..d71703db63 100644 --- a/src/hal/drivers/hal_stg.c +++ b/src/hal/drivers/hal_stg.c @@ -4,94 +4,94 @@ * * Author: Alex Joni * License: GPL Version 2 -* +* * Copyright (c) 2004 All rights reserved. * see below for aditional notes * -* Last change: +* Last change: ********************************************************************/ /** This is the driver for Servo-To-Go Model I & II board. The board includes 8 channels of quadrature encoder input, 8 channels of analog input and output, 32 bits digital I/O, and an interval timer with interrupt. - + Installation of the driver only realtime: - + insmod hal_stg num_chan=8 dio="IIOO" - autodetects the address or - + insmod hal_stg base=0x200 num_chan=8 dio="IIOO" - + Check your Hardware manual for your base address. - The digital inputs/outputs configuration is determined by a - config string passed to insmod when loading the module. + The digital inputs/outputs configuration is determined by a + config string passed to insmod when loading the module. The format consists by a four character string that sets the direction of each group of pins. Each character of the direction string is either "I" or "O". The first character sets the - direction of port A (Port A - DIO.0-7), the next sets - port B (Port B - DIO.8-15), the next sets port C (Port C - DIO.16-23), + direction of port A (Port A - DIO.0-7), the next sets + port B (Port B - DIO.8-15), the next sets port C (Port C - DIO.16-23), and the fourth sets port D (Port D - DIO.24-31). - + The following items are exported to the HAL. - + Encoders: Parameters: float stg..position-scale (counts per unit) - + Pins: s32 stg..counts float stg..position /todo bit stg..index-enable /todo bit stg..enc-reset-count - + Functions: void stg..capture_position - - + + DACs: Parameters: float stg..dac-offset float stg..dac-gain - + Pins: float stg..dac-value - + Functions: void stg..dac-write - - + + ADC: Parameters: float stg..adc-offset float stg..adc-gain - + Pins: float stg..adc-value - + Functions: void stg..adc-read - - + + Digital In: Pins: bit stg.in- bit stg.in--not - + Functions: void stg.digital-in-read - - + + Digital Out: Parameters: bit stg.out--invert - + Pins: bit stg.out- - + Functions: void stg.digital-out-write @@ -105,7 +105,7 @@ */ -/* Based on STGMEMBS.CPP from the Servo To Go Windows drivers +/* Based on STGMEMBS.CPP from the Servo To Go Windows drivers - Copyright (c) 1996 Servo To Go Inc and released under GPL Version 2 */ /* Also relates to the EMC1 code (very similar to STGMEMBS.CPP) work done by Fred Proctor, Will Shackleford */ @@ -136,14 +136,11 @@ */ #include "config.h" -#ifdef BUILD_SYS_KBUILD -#include -#endif #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ +#include "rtapi_io.h" #include "hal.h" /* HAL public API decls */ #include "hal_stg.h" /* STG related defines */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ /* module information */ MODULE_AUTHOR("Alex Joni"); @@ -197,7 +194,7 @@ typedef struct { /* dio data */ io_pin port[4][8]; /* holds 4 ports each 8 pins, either input or output */ unsigned char dir_bits; /* remembers config (which port is input which is output) */ - + unsigned char model; } stg_struct; @@ -339,7 +336,7 @@ int rtapi_app_main(void) /* we now should have directions figured out, next is exporting the pins based on that */ mask = 0x01; for ( m = 0 ; m < 4 ; m++ ) { - + /* port, direction, driver */ export_pins(m, (dir_bits & mask), stg_driver); @@ -349,7 +346,7 @@ int rtapi_app_main(void) stg_driver->dir_bits = dir_bits; /* remember direction of each port, will be used in the write / read functions */ stg_dio_init(); - + /* export all the variables for each counter, dac */ for (n = 0; n < num_chan; n++) { /* export all vars */ @@ -381,7 +378,7 @@ int rtapi_app_main(void) /* init counter chip */ stg_counter_init(n); - + retval = export_dac(n, stg_driver); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, @@ -408,13 +405,13 @@ int rtapi_app_main(void) *(stg_driver->adc_value[n]) = 0; stg_driver->adc_offset[n] = 0.0; stg_driver->adc_gain[n] = 1.0; - + stg_driver->adc_current_chan = -1; /* notify that no conversion has been started yet */ /* init adc chip */ stg_adc_init(n); } - + /* export functions */ retval = hal_export_funct("stg.capture-position", stg_counter_capture, stg_driver, 1, 0, comp_id); @@ -516,18 +513,18 @@ static void stg_counter_capture(void *arg, long period) /* * STG Model 1, stg1 */ - for( n = 0; n < num_chan; n++ ) + for( n = 0; n < num_chan; n++ ) { /* reset and then select current axes pair to be reset by index * Because they index polarity is configurable for the stg2 card be select * even for the odd axes */ stg1_select_index_axis(arg, n); - if (stg1_get_index_pulse_latch(arg, n)) + if (stg1_get_index_pulse_latch(arg, n)) { *(stg->index_latch[n]) = 1; - if ( *(stg->index_enable[n]) == 1 ) + if ( *(stg->index_enable[n]) == 1 ) { // read the value without latching, latching was done on index // remember this as an offset, it will be substracted from nominal @@ -543,8 +540,8 @@ static void stg_counter_capture(void *arg, long period) */ } else { /* NOP, no action needed, since the selection of an index pair is just valid until the next - * pair is selected */ - } + * pair is selected */ + } } else { *(stg->index_latch[n]) = 0; } @@ -557,7 +554,7 @@ static void stg_counter_capture(void *arg, long period) */ // Set IDLEN - for( mask = 0, n = 0; n < num_chan; n++ ) + for( mask = 0, n = 0; n < num_chan; n++ ) { if( *(stg->index_enable[n]) == 1 ) { @@ -565,19 +562,19 @@ static void stg_counter_capture(void *arg, long period) } } stg2_select_index_axes( arg, mask ); - + // Read all latches index_pulse_latches = stg2_get_all_index_pulse_latches( arg ); // set or reset index_latch // index-enable reset if needed - for( n = 0; n < num_chan; n++ ) + for( n = 0; n < num_chan; n++ ) { if( index_pulse_latches & (1<index_latch[n]) = 1; - if ( *(stg->index_enable[n]) == 1 ) + if ( *(stg->index_enable[n]) == 1 ) { // read the value without latching, latching was done on index // remember this as an offset, it will be substracted from nominal @@ -600,17 +597,17 @@ static void stg_counter_capture(void *arg, long period) } // Reset all latches stg2_reset_all_index_latches( arg ); - + } else { // NOP, only models stg1 and stg2, thus should never be reached */ } - for (n = 0; n < num_chan; n++) + for (n = 0; n < num_chan; n++) { /* capture raw counts to latches */ stg_counter_latch(n); /* read raw count, and substract the offset (determined by indexed homing) */ - *(stg->count[n]) = stg_counter_read(n) - stg->offset[n]; + *(stg->count[n]) = stg_counter_read(n) - stg->offset[n]; /* make sure scale isn't zero or tiny to avoid divide error */ if (stg->pos_scale[n] < 0.0) { if (stg->pos_scale[n] > -EPSILON) @@ -626,9 +623,9 @@ static void stg_counter_capture(void *arg, long period) return; } -/* stg_debug_print - * run this function from a very slow, - * e.g. 1sec thread and it will give some information +/* stg_debug_print + * run this function from a very slow, + * e.g. 1sec thread and it will give some information */ /* static void stg_debug_print( void *arg, long period ) @@ -647,27 +644,18 @@ static void stg_debug_print( void *arg, long period ) msg = rtapi_get_msg_level(); rtapi_set_msg_level( STG_MSG_LEVEL ); - if( stg->model == 1 ) + if( stg->model == 1 ) { -//#ifndef BUILD_SYS_KBUILD intc_reg = rtapi_inb(base + INTC); -//#else - intc_reg = inb(base + INTC); -//#endif - rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: IXS1 is %s\n", counter, ( intc_reg & IXS1 ) ? "TRUE" : "FALSE" ); + rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: IXS1 is %s\n", counter, ( intc_reg & IXS1 ) ? "TRUE" : "FALSE" ); rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: IXS0 is %s\n", counter, ( intc_reg & IXS0 ) ? "TRUE" : "FALSE" ); rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: IXLVL is active %s\n", counter, ( intc_reg & IXLVL ) ? "TRUE" : "FALSE" ); - } else if (stg->model == 2 ) + } else if (stg->model == 2 ) { -// #ifndef BUILD_SYS_KBUILD idlen_reg = rtapi_inb( base + IDLEN ); seldi_reg = rtapi_inb( base + SELDI ); -// #else - idlen_reg = inb( base + IDLEN ); - seldi_reg = inb( base + SELDI ); -// #endif - + rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: IDLEN is 0x%02x\n", counter, idlen_reg ); rtapi_print_msg(RTAPI_MSG_DBG, "STG: %04d: SELDI is 0x%02x\n", counter, seldi_reg ); @@ -687,7 +675,7 @@ static void stg_debug_print( void *arg, long period ) /* stg_dacs_write() - writes all dac's to the board - calls stg_dac_write() */ static void stg_dacs_write(void *arg, long period) -{ +{ stg_struct *stg; double volts; short ncounts, i; @@ -703,8 +691,8 @@ static void stg_dacs_write(void *arg, long period) volts = 10.0; /* compute the value for the DAC, the extra - in there is STG specific */ ncounts = (short) ((((-10.0 - volts) * 0x1FFF) / 20.0) - 1 ); - /* write it to the card */ - stg_dac_write(i, ncounts); + /* write it to the card */ + stg_dac_write(i, ncounts); } return; } @@ -725,14 +713,14 @@ static void stg_dacs_write(void *arg, long period) - and at the end of the function the new conversion is started, so that the data will be available at the next run. This way 8 periods are needed to read 8 ADC's. It is possible to set the board - to do faster conversions (AZ bit on INTC off), but that would make it less + to do faster conversions (AZ bit on INTC off), but that would make it less reliable (autozero takes care of temp. errors).*/ /*! \todo STG_ADC_Improvement (if any user requests it). Another improvement might be to let the user chose what channels he would like for ADC (having only 2 channels might speed things up considerably). */ static void stg_adcs_read(void *arg, long period) -{ +{ stg_struct *stg; double volts; short ncounts; @@ -740,7 +728,7 @@ static void stg_adcs_read(void *arg, long period) stg = arg; i = stg->adc_current_chan; - if ((i >= 0) && (i < num_chan)) { + if ((i >= 0) && (i < num_chan)) { /* we should have the conversion done for adc_num_chan */ ncounts = stg_adc_read(stg,i); volts = ncounts * 10.0 / 4096; @@ -748,7 +736,7 @@ static void stg_adcs_read(void *arg, long period) } /* if adc_num_chan < 0, it's the first time this routine runs thus we don't have any ready data, we simply start the next conversion */ - if (stg->adc_current_chan++ >= num_chan) + if (stg->adc_current_chan++ >= num_chan) stg->adc_current_chan=0; //increase the channel, and roll back to 0 after all chans are done /* select the current channel with the mux, and start the conversion */ @@ -781,7 +769,7 @@ static void split_input(unsigned char data, io_pin *dest, int num) dest++; } return; -} +} // helper function to extract the data out of HAL and place it into a char // written by JMK @@ -816,65 +804,33 @@ static void stg_di_read(void *arg, long period) //reads digital inputs from the stg_struct *stg; unsigned char val; stg=arg; - + if ( (stg->dir_bits & 0x01) == 0) { // if port A is set as input, read the bits if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + DIO_A); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + DIO_A); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + PORT_A); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + PORT_A); -#endif /* BUILD_SYS_KBUILD */ split_input(val, &(stg->port[0][0]), 8); } if ( (stg->dir_bits & 0x02) == 0) { // if port B is set as input, read the bits if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + DIO_B); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + DIO_B); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + PORT_B); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + PORT_B); -#endif /* BUILD_SYS_KBUILD */ split_input(val, &(stg->port[1][0]), 8); } if ( (stg->dir_bits & 0x04) == 0) { // if port C is set as input, read the bits if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + DIO_C); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + DIO_C); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + PORT_C); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + PORT_C); -#endif /* BUILD_SYS_KBUILD */ split_input(val, &(stg->port[2][0]), 8); } if ( (stg->dir_bits & 0x08) == 0) { // if port D is set as input, read the bits if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + DIO_D); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + DIO_D); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD val = rtapi_inb(base + PORT_D); -#else /* BUILD_SYS_KBUILD */ - val = inb(base + PORT_D); -#endif /* BUILD_SYS_KBUILD */ split_input(val, &(stg->port[3][0]), 8); } } @@ -888,62 +844,30 @@ static void stg_do_write(void *arg, long period) //writes digital outputs to the if ( (stg->dir_bits & 0x01) != 0) { // if port A is set as output, write the bits val = build_output(&(stg->port[0][0]), 8); if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + DIO_A); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + DIO_A); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + PORT_A); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + PORT_A); -#endif /* BUILD_SYS_KBUILD */ } if ( (stg->dir_bits & 0x02) != 0) { // if port B is set as output, write the bits val = build_output(&(stg->port[1][0]), 8); if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + DIO_B); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + DIO_B); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + PORT_B); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + PORT_B); -#endif /* BUILD_SYS_KBUILD */ } if ( (stg->dir_bits & 0x04) != 0) { // if port C is set as output, write the bits val = build_output(&(stg->port[2][0]), 8); if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + DIO_C); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + DIO_C); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + PORT_C); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + PORT_C); -#endif /* BUILD_SYS_KBUILD */ } if ( (stg->dir_bits & 0x08) != 0) { // if port D is set as output, write the bits val = build_output(&(stg->port[3][0]), 8); if (stg->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + DIO_D); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + DIO_D); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD rtapi_outb(val, base + PORT_D); -#else /* BUILD_SYS_KBUILD */ - outb(val, base + PORT_D); -#endif /* BUILD_SYS_KBUILD */ } } @@ -959,40 +883,24 @@ static void stg_do_write(void *arg, long period) //writes digital outputs to the /* stg_counter_init() - Initializes the channel - + works the same for both cards (STG & STG2) */ static int stg_counter_init(int ch) { /* Set Counter Command Register - Master Control, Master Reset (MRST), */ /* and Reset address pointer (RADR). */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x23, CTRL(ch)); -#else /* BUILD_SYS_KBUILD */ - outb(0x23, CTRL(ch)); -#endif /* BUILD_SYS_KBUILD */ /* Set Counter Command Register - Input Control, OL Load (P3), */ /* and Enable Inputs A and B (INA/B). */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x68, CTRL(ch)); -#else /* BUILD_SYS_KBUILD */ - outb(0x68, CTRL(ch)); -#endif /* BUILD_SYS_KBUILD */ /* Set Counter Command Register - Output Control */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x80, CTRL(ch)); -#else /* BUILD_SYS_KBUILD */ - outb(0x80, CTRL(ch)); -#endif /* BUILD_SYS_KBUILD */ /* Set Counter Command Register - Quadrature */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0xC3, CTRL(ch)); -#else /* BUILD_SYS_KBUILD */ - outb(0xC3, CTRL(ch)); -#endif /* BUILD_SYS_KBUILD */ return 0; } @@ -1004,10 +912,10 @@ static int stg_counter_init(int ch) static int stg_dac_init(int ch) { int i; - + /* set all DAC's to 0 on startup */ for (i=0; i < num_chan; i++) { - stg_dac_write(i, 0x1000); //by Xuecheng, 0x1000 coresponds to 0V + stg_dac_write(i, 0x1000); //by Xuecheng, 0x1000 coresponds to 0V } return 0; } @@ -1022,11 +930,7 @@ static int stg_adc_init(int ch) /* not much to setup for the ADC's */ /* only select the mode of operation we will work with AutoZero */ if (stg_driver->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x0f, base + MIO_2); // the second 82C55 is already configured (by running stg_dio_init) -#else /* BUILD_SYS_KBUILD */ - outb(0x0f, base + MIO_2); // the second 82C55 is already configured (by running stg_dio_init) -#endif /* BUILD_SYS_KBUILD */ // we only set bit 8 (AZ) to 1 to enable it return 0; } @@ -1047,105 +951,55 @@ static int stg_dio_init(void) control |= 0x02; if ( (stg_driver->dir_bits & 0x04) == 0) // if port C is set as input, set bits accordingly control |= 0x09; - + if (stg_driver->model == 1) { // write the computed control to MIO_1 -#ifndef BUILD_SYS_KBUILD rtapi_outb(control, base+MIO_1); -#else /* BUILD_SYS_KBUILD */ - outb(control, base+MIO_1); -#endif /* BUILD_SYS_KBUILD */ } else { //model STG2 // write port A,B,C direction to ABC_DIR -#ifndef BUILD_SYS_KBUILD rtapi_outb(control, base+ABC_DIR); -#else /* BUILD_SYS_KBUILD */ - outb(control, base+ABC_DIR); -#endif /* BUILD_SYS_KBUILD */ } - -#ifndef BUILD_SYS_KBUILD + tempINTC = rtapi_inb(base + INTC); -#else /* BUILD_SYS_KBUILD */ - tempINTC = inb(base + INTC); -#endif /* BUILD_SYS_KBUILD */ - + if (stg_driver->model == 1) { // next compute the directions for port D, located on the second 82C55 control = 0x82; - + if ( (stg_driver->dir_bits & 0x08) == 0)// if port D is set as input, set bits accordingly control = 0x92; -#ifndef BUILD_SYS_KBUILD tempIMR = rtapi_inb(base + IMR); // get the current interrupt mask -#else /* BUILD_SYS_KBUILD */ - tempIMR = inb(base + IMR); // get the current interrupt mask -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(0xff, base + OCW1); //mask off all interrupts -#else /* BUILD_SYS_KBUILD */ - outb(0xff, base + OCW1); //mask off all interrupts -#endif /* BUILD_SYS_KBUILD */ - + // write the computed control to MIO_2 -#ifndef BUILD_SYS_KBUILD rtapi_outb(control, base+MIO_2); -#else /* BUILD_SYS_KBUILD */ - outb(control, base+MIO_2); -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(tempINTC, base + INTC); //restore interrupt control reg. -#else /* BUILD_SYS_KBUILD */ - outb(tempINTC, base + INTC); //restore interrupt control reg. -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(tempIMR, base+ OCW1); //restore int mask -#else /* BUILD_SYS_KBUILD */ - outb(tempIMR, base+ OCW1); //restore int mask -#endif /* BUILD_SYS_KBUILD */ } else { //model STG2 - + // save contents of CNTRL0, it will get reinitialized -#ifndef BUILD_SYS_KBUILD tempCtrl0 = rtapi_inb(base+CNTRL0); tempCtrl1 = rtapi_inb(base+CNTRL1); -#else /* BUILD_SYS_KBUILD */ - tempCtrl0 = inb(base+CNTRL0); - tempCtrl1 = inb(base+CNTRL1); -#endif /* BUILD_SYS_KBUILD */ - + // CNTRL0 output, BRDTST input, D output control = 0x82; if ( (stg_driver->dir_bits & 0x08) == 0)// if port D is set as input, set bits accordingly control = 0x8b; - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(0xff, base + CNTRL1); // disable interrupts -#else /* BUILD_SYS_KBUILD */ - outb(0xff, base + CNTRL1); // disable interrupts -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(control, base + D_DIR); // set port D direction, also resets CNTRL0 -#else /* BUILD_SYS_KBUILD */ - outb(control, base + D_DIR); // set port D direction, also resets CNTRL0 -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(tempCtrl0, base + CNTRL0); rtapi_outb( (tempCtrl1 & 0x0f) | 0xf0, base + CNTRL1); -#else /* BUILD_SYS_KBUILD */ - outb(tempCtrl0, base + CNTRL0); - outb( (tempCtrl1 & 0x0f) | 0xf0, base + CNTRL1); -#endif /* BUILD_SYS_KBUILD */ } - + return 0; } @@ -1155,13 +1009,9 @@ static int stg_dio_init(void) * these do the actual data exchange with the board * ************************************************************************/ -static void stg_counter_latch(int i) +static void stg_counter_latch(int i) { -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x03, CTRL(i)); -#else /* BUILD_SYS_KBUILD */ - outb(0x03, CTRL(i)); -#endif /* BUILD_SYS_KBUILD */ } @@ -1183,15 +1033,9 @@ static long stg_counter_read(int i) } byte; } pos; -#ifndef BUILD_SYS_KBUILD pos.byte.b0 = rtapi_inb(DATA(i)); pos.byte.b1 = rtapi_inb(DATA(i)); pos.byte.b2 = rtapi_inb(DATA(i)); -#else /* BUILD_SYS_KBUILD */ - pos.byte.b0 = inb(DATA(i)); - pos.byte.b1 = inb(DATA(i)); - pos.byte.b2 = inb(DATA(i)); -#endif /* BUILD_SYS_KBUILD */ if (pos.byte.b2 < 0) { pos.byte.b3 = -1; } else { @@ -1207,11 +1051,11 @@ static void stg1_select_index_axis(void *arg, unsigned int channel) unsigned char byPol = 1; if (stg->model == 1) - { + { /* * Set polarity to low active if that is requested */ - if( *(stg->index_polarity[channel]) == 0 ) + if( *(stg->index_polarity[channel]) == 0 ) { byPol = 0; } @@ -1219,28 +1063,20 @@ static void stg1_select_index_axis(void *arg, unsigned int channel) /* Stg manual p. 21: "The bits are level triggered and cannot be reset if they are active" * So it is save to reset them and only those which are really active will remain */ stg1_reset_index_latch(arg, channel); - + // routine for Model 1 // initialize stuff to poll index pulse byAxis = channel; - + byAxis &= 0x6; // ignore low bit, we check 2 axes at a time byAxis <<= 3; // shift into position for IXS1, IXS0 -#ifndef BUILD_SYS_KBUILD byIntc = rtapi_inb(base + INTC); // get a copy of INTC, we'll change -#else /* BUILD_SYS_KBUILD */ - byIntc = inb(base + INTC); // get a copy of INTC, we'll change -#endif /* BUILD_SYS_KBUILD */ // some bits in it, not all byIntc &= ~(IXLVL | IXS1 | IXS0); // zero bits for axis and polarity byIntc |= byAxis; // put axes address in INTC if (byPol != 0) // is index pulse active high? byIntc |= IXLVL; -#ifndef BUILD_SYS_KBUILD rtapi_outb(byIntc, base + INTC); -#else /* BUILD_SYS_KBUILD */ - outb(byIntc, base + INTC); -#endif /* BUILD_SYS_KBUILD */ } } @@ -1250,11 +1086,7 @@ static void stg2_select_index_axes( void *arg, unsigned char mask ) * writing 0 to the corresponding bit disables the index pulse * writing 1 enables it */ -#ifndef BUILD_SYS_KBUILD rtapi_outb( mask, base + IDLEN ); -#else /* BUILD_SYS_KBUILD */ - outb( mask, base + IDLEN ); -#endif /* BUILD_SYS_KBUILD */ return; } @@ -1266,13 +1098,8 @@ static void stg1_reset_index_latch(void *arg, unsigned int channel) if (stg->model == 1) { // routine for Model 1 -#ifndef BUILD_SYS_KBUILD rtapi_inb(base + ODDRST); //reset index pulse latch for ODD axis rtapi_inb(base + BRDTST); //reset index pulse latch for EVEN axis -#else /* BUILD_SYS_KBUILD */ - inb(base + ODDRST); //reset index pulse latch for ODD axis - inb(base + BRDTST); //reset index pulse latch for EVEN axis -#endif /* BUILD_SYS_KBUILD */ } return; } @@ -1282,29 +1109,20 @@ static void stg2_reset_all_index_latches( void *arg ) stg_struct *stg = arg; if( stg->model == 2 ) { - /* - * stg2 manual p.22, - * writing 0 to IDL resets the index latch, + /* + * stg2 manual p.22, + * writing 0 to IDL resets the index latch, * writing 1 has no effect */ -#ifndef BUILD_SYS_KBUILD rtapi_outb( 0x00, base + IDL); -#else /* BUILD_SYS_KBUILD */ - outb( 0x00, base + IDL); -#endif /* BUILD_SYS_KBUILD */ } return; } unsigned char stg1_get_current_IRR(void) { -#ifndef BUILD_SYS_KBUILD rtapi_outb(base + OCW3, 0x0a); // IRR on next read return rtapi_inb(base + IRR); -#else /* BUILD_SYS_KBUILD */ - outb(base + OCW3, 0x0a); // IRR on next read - return inb(base + IRR); -#endif /* BUILD_SYS_KBUILD */ } static unsigned short stg1_get_index_pulse_latch(void *arg, unsigned int chan) @@ -1333,28 +1151,20 @@ static unsigned char stg2_get_all_index_pulse_latches( void *arg ) unsigned char indexRegister = 0; if( stg-> model == 2 ) -#ifndef BUILD_SYS_KBUILD indexRegister = rtapi_inb( base + IDL ); -#else /* BUILD_SYS_KBUILD */ - indexRegister = inb( base + IDL ); -#endif /* BUILD_SYS_KBUILD */ return indexRegister; } /* stg_dac_write() - writes a dac channel - + works the same for both cards (STG & STG2) */ static int stg_dac_write(int ch, short value) -{ +{ /* write the DAC */ -#ifndef BUILD_SYS_KBUILD rtapi_outw(value, base + DAC_0 + (ch << 1)); -#else /* BUILD_SYS_KBUILD */ - outw(value, base + DAC_0 + (ch << 1)); -#endif /* BUILD_SYS_KBUILD */ return 0; } @@ -1367,70 +1177,36 @@ int stg_adc_start(void *arg, unsigned short wAxis) unsigned char tempCtrl0; stg = arg; - + if (stg->model == 1) { /* do a dummy read from the ADC, just to set the input multiplexer to the right channel */ -#ifndef BUILD_SYS_KBUILD rtapi_inw(base + ADC_0 + (wAxis << 1)); -#else /* BUILD_SYS_KBUILD */ - inw(base + ADC_0 + (wAxis << 1)); -#endif /* BUILD_SYS_KBUILD */ /* wait 4 uS for settling time on the multiplexer and ADC. You probably shouldn't really have a delay in a driver */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); -#else /* BUILD_SYS_KBUILD */ - outb(0, 0x80); - outb(0, 0x80); - outb(0, 0x80); - outb(0, 0x80); -#endif /* BUILD_SYS_KBUILD */ /* now start conversion */ -#ifndef BUILD_SYS_KBUILD rtapi_outw(0, base + ADC_0 + (wAxis << 1)); -#else /* BUILD_SYS_KBUILD */ - outw(0, base + ADC_0 + (wAxis << 1)); -#endif /* BUILD_SYS_KBUILD */ } else { //model STG2 -#ifndef BUILD_SYS_KBUILD tempCtrl0 = rtapi_inb(base+CNTRL0) & 0x07; // save IRQ -#else /* BUILD_SYS_KBUILD */ - tempCtrl0 = inb(base+CNTRL0) & 0x07; // save IRQ -#endif /* BUILD_SYS_KBUILD */ tempCtrl0 |= (wAxis << 4) | 0x88; //autozero & cal cycle -#ifndef BUILD_SYS_KBUILD rtapi_outb(tempCtrl0, base + CNTRL0); // select channel -#else /* BUILD_SYS_KBUILD */ - outb(tempCtrl0, base + CNTRL0); // select channel -#endif /* BUILD_SYS_KBUILD */ /* wait 4 uS for settling time on the multiplexer and ADC. You probably shouldn't really have a delay in a driver */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); rtapi_outb(0, 0x80); -#else /* BUILD_SYS_KBUILD */ - outb(0, 0x80); - outb(0, 0x80); - outb(0, 0x80); - outb(0, 0x80); -#endif /* BUILD_SYS_KBUILD */ - + /* now start conversion */ -#ifndef BUILD_SYS_KBUILD rtapi_outw(0, base + ADC_0); -#else /* BUILD_SYS_KBUILD */ - outw(0, base + ADC_0); -#endif /* BUILD_SYS_KBUILD */ } return 0; }; @@ -1443,9 +1219,9 @@ static short stg_adc_read(void *arg, int axis) stg = arg; /* - there must have been a delay between stg_adc_start() and - stg_adc_read(), of 19 usec if autozeroing (we are), 4 usecs - otherwise. In code that calls this, make sure you split these + there must have been a delay between stg_adc_start() and + stg_adc_read(), of 19 usec if autozeroing (we are), 4 usecs + otherwise. In code that calls this, make sure you split these calls up with some intervening code */ @@ -1457,32 +1233,16 @@ static short stg_adc_read(void *arg, int axis) Register) of Interrupt Controller. Don't wait forever though bail out eventually. */ -#ifndef BUILD_SYS_KBUILD for (j = 0; !(rtapi_inb(base + IRR) & 0x08) && (j < 1000); j++); -#else /* BUILD_SYS_KBUILD */ - for (j = 0; !(inb(base + IRR) & 0x08) && (j < 1000); j++); -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD + j = rtapi_inw(base + ADC_0 + (axis << 1)); -#else /* BUILD_SYS_KBUILD */ - j = inw(base + ADC_0 + (axis << 1)); -#endif /* BUILD_SYS_KBUILD */ } else { //model 2 -#ifndef BUILD_SYS_KBUILD for (j = 0; (rtapi_inb(base + BRDTST) & 0x08) && (j < 1000); j++); -#else /* BUILD_SYS_KBUILD */ - for (j = 0; (inb(base + BRDTST) & 0x08) && (j < 1000); j++); -#endif /* BUILD_SYS_KBUILD */ - -#ifndef BUILD_SYS_KBUILD - j = rtapi_inw(base + ADC_0 + (axis << 1)); -#else /* BUILD_SYS_KBUILD */ - j = inw(base + ADC_0 + (axis << 1)); -#endif /* BUILD_SYS_KBUILD */ - + + j = rtapi_inw(base + ADC_0 + (axis << 1)); + } @@ -1502,12 +1262,12 @@ static short stg_adc_read(void *arg, int axis) static int stg_set_interrupt(short interrupt) { unsigned char tempINTC; - + if (stg_driver->model == 1) tempINTC=0x80; else tempINTC=0x88;//also CAL low, don|t want ADC to calibrate - + switch (interrupt) { case 3: break; case 5: tempINTC |= 4;break; @@ -1518,19 +1278,11 @@ static int stg_set_interrupt(short interrupt) case 12: tempINTC |= 3;break; case 15: tempINTC |= 1;break; default: tempINTC |= 4;break; - } + } if (stg_driver->model == 1) -#ifndef BUILD_SYS_KBUILD rtapi_outb(tempINTC, base + INTC); -#else /* BUILD_SYS_KBUILD */ - outb(tempINTC, base + INTC); -#endif /* BUILD_SYS_KBUILD */ else -#ifndef BUILD_SYS_KBUILD rtapi_outb(tempINTC, base + CNTRL0); -#else /* BUILD_SYS_KBUILD */ - outb(tempINTC, base + CNTRL0); -#endif /* BUILD_SYS_KBUILD */ return 0; } @@ -1549,11 +1301,11 @@ static int stg_init_card() */ if ( (model != 0) && (base != 0) ) { - stg_driver->model = model; + stg_driver->model = model; } else { base = stg_autodetect(); } - + /* * Now check if the settings for a card a ok */ @@ -1568,54 +1320,32 @@ static int stg_init_card() * STG1 */ // initialize INTC as output -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x92, base + MIO_2); -#else /* BUILD_SYS_KBUILD */ - outb(0x92, base + MIO_2); -#endif /* BUILD_SYS_KBUILD */ - + stg_set_interrupt(5); // initialize it to smthg, we won't use it anyways - -#ifndef BUILD_SYS_KBUILD + rtapi_outb(0x1a, base + ICW1); // initialize the 82C59 as single chip (STG docs say so:) rtapi_outb(0x00, base + ICW2); // ICW2 not used, must init it to 0 rtapi_outb(0xff, base + OCW1); // mask off all interrupts -#else /* BUILD_SYS_KBUILD */ - outb(0x1a, base + ICW1); // initialize the 82C59 as single chip (STG docs say so:) - outb(0x00, base + ICW2); // ICW2 not used, must init it to 0 - outb(0xff, base + OCW1); // mask off all interrupts -#endif /* BUILD_SYS_KBUILD */ rtapi_print_msg(RTAPI_MSG_INFO, "STG: Initialised stg%1d card at address %x\n", stg_driver->model, base); - } else if (stg_driver->model == 2 ) { + } else if (stg_driver->model == 2 ) { /* * STG2 */ -#ifndef BUILD_SYS_KBUILD rtapi_outb(0x8b, base + D_DIR); // initialize CONTRL0 output, BRDTST input -#else /* BUILD_SYS_KBUILD */ - outb(0x8b, base + D_DIR); // initialize CONTRL0 output, BRDTST input -#endif /* BUILD_SYS_KBUILD */ - + /* stg2 manual, p.21 * writing 0 to the corresponding bit disables the index pulse * writing 1 enables it */ -#ifndef BUILD_SYS_KBUILD rtapi_outb( 0x00, base + IDLEN ); -#else /* BUILD_SYS_KBUILD */ - outb( 0x00, base + IDLEN ); -#endif /* BUILD_SYS_KBUILD */ /* stg2 manual, p.21 * writing 0 to the corresponding bit selects the index pulse to latch the counter * writing 1 to the corresponding bit selects EXLATCH to latch the counter */ -#ifndef BUILD_SYS_KBUILD rtapi_outb( 0x00, base + SELDI ); -#else /* BUILD_SYS_KBUILD */ - outb( 0x00, base + SELDI ); -#endif /* BUILD_SYS_KBUILD */ stg_set_interrupt(5); // initialize it to something, we won't use it anyways rtapi_print_msg(RTAPI_MSG_INFO, @@ -1624,7 +1354,7 @@ static int stg_init_card() rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: The model stg%1d is not correct\n", stg_driver->model ); return -ENODEV; } - + /* restore saved message level */ rtapi_set_msg_level(msg); @@ -1649,18 +1379,10 @@ unsigned short stg_autodetect() address = i * 0x20 + 0x200; /* does jumper = i? */ -#ifndef BUILD_SYS_KBUILD //if ((rtapi_inb(address + BRDTST) & 0x0f) == i) { // by Xuecheng, not necessary -#else /* BUILD_SYS_KBUILD */ - //if ((inb(address + BRDTST) & 0x0f) == i) { // by Xuecheng, not necessary -#endif /* BUILD_SYS_KBUILD */ k = 0; // var for getting the serial for (j = 0; j < 8; j++) { -#ifndef BUILD_SYS_KBUILD ofs = (rtapi_inb(address + BRDTST) >> 4); -#else /* BUILD_SYS_KBUILD */ - ofs = (inb(address + BRDTST) >> 4); -#endif /* BUILD_SYS_KBUILD */ if (ofs & 8) { /* is SER set? */ ofs = ofs & 7; /* mask for Q2,Q1,Q0 */ @@ -1749,15 +1471,15 @@ static int export_counter(int num, stg_struct *addr) /* - * The index polarity is configurable for the stg1 cards only, + * The index polarity is configurable for the stg1 cards only, * but not for the stg2 cards */ - if( addr->model == 1 ) + if( addr->model == 1 ) { /* export read only HAL pin for index pulse polarity */ retval = hal_pin_bit_newf(HAL_IN, &addr->index_polarity[num], comp_id, "stg.%d.index-polarity", num); - if (retval != 0) + if (retval != 0) { return retval; } @@ -1905,7 +1627,7 @@ static int export_output_pin(int pinnum, io_pin * pin) * This function exports a lot of stuff, which results in a lot of * logging if msg_level is at INFO or ALL. So we save the current value * of msg_level and restore it later. If you actually need to log this - * function's actions, change the second line below + * function's actions, change the second line below */ msg = rtapi_get_msg_level(); rtapi_set_msg_level( STG_MSG_LEVEL ); diff --git a/src/hal/drivers/hal_tiro.c b/src/hal/drivers/hal_tiro.c index 1897648d3f..1bed05bc4f 100644 --- a/src/hal/drivers/hal_tiro.c +++ b/src/hal/drivers/hal_tiro.c @@ -60,8 +60,8 @@ #include "config.h" #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ +#include "rtapi_io.h" #include "hal.h" /* HAL public API decls */ -#include "rtapi_io.h" /* rtapi_outb() rtapi_inb() */ /* module information */ MODULE_AUTHOR("Alex Joni"); diff --git a/src/hal/drivers/hal_vti.c b/src/hal/drivers/hal_vti.c index c3254e2f11..73ac53bb47 100644 --- a/src/hal/drivers/hal_vti.c +++ b/src/hal/drivers/hal_vti.c @@ -35,9 +35,9 @@ config string passed to insmod when loading the module. The format consists of a character string that sets the direction of each group of pins. Each character or character pair - of the direction string is one of "I", "O", "ii", "io", "oi" or "oo". - The individual and character pair formats may be used interchangably in - the same string, however the lower case format must always appear in + of the direction string is one of "I", "O", "ii", "io", "oi" or "oo". + The individual and character pair formats may be used interchangably in + the same string, however the lower case format must always appear in pairs. The representatiom of each character or character pair is as follows: I: 8 (0..7) Inputs @@ -153,9 +153,6 @@ */ #include "config.h" -#if !defined(BUILD_SYS_USER_DSO) -#include -#endif #include "rtapi.h" /* RTAPI realtime OS API */ #include "rtapi_app.h" /* RTAPI realtime module decls */ #include @@ -211,13 +208,8 @@ typedef struct { } vti_struct; static vti_struct *vti_driver; -#if defined(BUILD_SYS_USER_DSO) #include "rtapi_pci.h" static struct rtapi_pcidev *dev = NULL; -#else -struct pci_dev *dev = NULL; -struct pci_access *device; -#endif volatile struct encoder *encoder = NULL; volatile struct timer *timer = NULL; volatile struct dac *dac = NULL; @@ -283,7 +275,7 @@ static void vti_do_write(void *arg, long period); //writes digital outputs to th int rtapi_app_main(void) { int retval; - + /* test for number of channels */ if ((num_chan <= 0) || (num_chan > MAX_CHAN)) { rtapi_print_msg(RTAPI_MSG_ERR, @@ -322,9 +314,7 @@ int rtapi_app_main(void) diocount = vti_parse_dio(); if (diocount == -1) { -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: bad config info for port.\n"); return -1; @@ -335,9 +325,7 @@ int rtapi_app_main(void) /* init counter chip */ if (vti_counter_init(num_chan) == -1) { -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: bad config info counter.\n"); return -1; @@ -355,9 +343,7 @@ int rtapi_app_main(void) if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.counter-capture funct export failed\n"); -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); return -1; } @@ -369,9 +355,7 @@ int rtapi_app_main(void) if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.write-dacs funct export failed\n"); -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); return -1; } @@ -382,9 +366,7 @@ int rtapi_app_main(void) if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.read-adcs funct export failed\n"); -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); return -1; } @@ -395,9 +377,7 @@ int rtapi_app_main(void) if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.di-read funct export failed\n"); -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); return -1; } @@ -410,9 +390,7 @@ int rtapi_app_main(void) if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.do-write funct export failed\n"); -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); return -1; } @@ -470,13 +448,11 @@ static int vti_parse_dio(void) void rtapi_app_exit(void) { -#if defined(BUILD_SYS_USER_DSO) rtapi_pci_iounmap(dev, (void __iomem *)encoder); rtapi_pci_iounmap(dev, (void __iomem *)dac); rtapi_pci_iounmap(dev, (void __iomem *)timer); rtapi_pci_iounmap(dev, (void __iomem *)ip); rtapi_pci_put_device(dev); -#endif hal_exit(comp_id); } @@ -488,7 +464,7 @@ static void vti_counter_capture(void *arg, long period) { vti_struct *vti; int i; - + vti = arg; for (i = 0; i < num_chan; i++) { /* capture raw counts to latches */ @@ -520,7 +496,7 @@ static void vti_dacs_write(void *arg, long period) (*(vti->dac_value[i]) - vti->dac_offset[i]) * vti->dac_gain[i]; /* compute the value for the DAC, the extra - in there is vti specific */ ncounts = ((volts / 10) * 0x7fff) + 0x8000; - + /* write it to the card */ vti_dac_write(i, ncounts); } @@ -528,7 +504,7 @@ static void vti_dacs_write(void *arg, long period) /* The VTI board has no ADCs. Procedure is retained only as a stub, should it be called from elsewhere in the application. */ - + static void vti_adcs_read(void *arg, long period) { return; @@ -599,7 +575,7 @@ static void vti_di_read(void *arg, long period) //reads digital inputs from the split_input(latchedVal, &(vti->port[0][0]), 4); if (vti->dir_bits[1] == 0) split_input(latchedVal, &(vti->port[0][4]), 4); - + /* Get Extended I/O inputs */ if (diocount <= 8) return; // No extended I/O enabled for (i = 1; i < (diocount / 8); i++) { @@ -615,17 +591,17 @@ static void vti_do_write(void *arg, long period) //writes digital outputs to the { vti_struct *vti; int i; - + vti = arg; /* Write ENCDAC onboard outputs */ if (diocount == 0) return; // No DIO encoder->DIO = build_output(&(vti->port[0][0]), 8); if (diocount <= 8) return; // No extended I/O - + /* Write Extended I/O outputs */ for (i = 1; i < diocount / 8; i++) { - dac->DIO[i - 1] = build_output(&(vti->port[i][0]), 8); - } + dac->DIO[i - 1] = build_output(&(vti->port[i][0]), 8); + } } @@ -673,7 +649,7 @@ static int vti_counter_init(int counters) static int vti_dac_init(int channels) { int retval, i; - + encoder->DAC = DAC_IND_MODE; // Enable DACs for output indpendent of watchdog for (i = 0; i < channels; i++) { retval = export_dac(i, vti_driver); @@ -704,7 +680,7 @@ static int vti_dio_init(int nibbles) { unsigned int mask; int i; - + /* we will select the directions of each port */ /* First initialize the 8 on board I/O points */ if (diocount == 0) return 0; // No DIO @@ -755,34 +731,34 @@ static long vti_counter_read(int axis) Longword EncData; static long int lastCount; // static unsigned short lastdac; - + if ((axis >= MAX_CHANS) || (axis < 0)) { return 0x80000000; // Return encoder error value } lastCount = enc_counts[axis]; status = encoder->Status; // latch status from vti board count = encoder->Counter[axis]; // latch count from vti board - + EncData.Long = (long int)enc_counts[axis]; if (status & (1 << axis)) { if (status & (1 << (axis + 4))) { - EncData.Word[1] += 1; + EncData.Word[1] += 1; } else { - EncData.Word[1] -= 1; + EncData.Word[1] -= 1; } } - - + + EncData.Word[0] = count; -// Filter out spurious roll overs / roll unders - if ((EncData.Long - lastCount) > 0x7fff) +// Filter out spurious roll overs / roll unders + if ((EncData.Long - lastCount) > 0x7fff) EncData.Word[1] -= 1; - else + else if ((lastCount - EncData.Long) > 0x7fff) EncData.Word[1] += 1; enc_counts[axis] = EncData.Long; - + return EncData.Long; } @@ -800,7 +776,7 @@ static int vti_dac_write(int axis, short value) junk = dac->mode; // Read from mode to trigger update dac immediately junk++; // Silence compiler '-Wunused-value' warnings dac->dac[axis] = value; // Write dac value - + return 0; } @@ -829,23 +805,10 @@ static int vti_init_card() { int retval=vti_autodetect(); if (retval == 0) { -#if defined(BUILD_SYS_USER_DSO) encoder = (volatile struct encoder *) rtapi_pci_ioremap(dev, 2, sizeof(encoder)); dac = (volatile struct dac *) rtapi_pci_ioremap(dev, 4, sizeof(dac)); timer = (volatile struct timer *) rtapi_pci_ioremap(dev, 3, sizeof(timer)); ip = (volatile struct ip *) rtapi_pci_ioremap(dev, 5, sizeof(ip)); -#else - encoder = (volatile struct encoder *) - ioremap(pci_resource_start(dev, 2), sizeof(encoder)); - dac = - (volatile struct dac *) ioremap(pci_resource_start(dev, - 4), sizeof(dac)); - timer = - (volatile struct timer *) ioremap(pci_resource_start(dev, - 3), sizeof(timer)); - ip = (volatile struct ip *) ioremap(pci_resource_start(dev, 5), - sizeof(ip)); -#endif } else { return (retval); } @@ -866,19 +829,11 @@ static int vti_init_card() /* scans possible addresses for vti cards */ static int vti_autodetect() { -#if defined(BUILD_SYS_USER_DSO) dev = rtapi_pci_get_device(VENDOR, DEVICE, NULL); if (dev) { rtapi_pci_put_device(dev); rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Card detected in slot"); -#else - dev = pci_get_device(VENDOR, DEVICE, dev); - if (dev) { - pci_dev_put(dev); - rtapi_print_msg(RTAPI_MSG_INFO, - "VTI: Card detected in slot: %2x\n", PCI_SLOT(dev->devfn)); -#endif return (0); } else { rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Exiting with auto detect failed\n"); diff --git a/src/hal/drivers/hal_zed_can.c b/src/hal/drivers/hal_zed_can.c index 492c3bdcee..712c86b4e9 100644 --- a/src/hal/drivers/hal_zed_can.c +++ b/src/hal/drivers/hal_zed_can.c @@ -21,34 +21,34 @@ using CAN8 interface board. \details - The number FOC axis controlled is determined by the insmod command - line parameter 'FOC_axis' passed from .hal configuration file. - It accepts a comma separated (no spaces) list of up to 8 numbers - indicating the CAN address of the FOC channel. + The number FOC axis controlled is determined by the insmod command + line parameter 'FOC_axis' passed from .hal configuration file. + It accepts a comma separated (no spaces) list of up to 8 numbers + indicating the CAN address of the FOC channel. \note actually the FOC axis are configured all with address 3 each - axis on a single CAN line in order to stress the system with maximum + axis on a single CAN line in order to stress the system with maximum CAN load. - - A second command line parameter "ctrl_type", selects between position + + A second command line parameter "ctrl_type", selects between position csp, traj-generator, velocity, current, torque control modes - - in order to adapt to different mechanical setup/encoder type the following + + in order to adapt to different mechanical setup/encoder type the following parameters are needed: PPR: pulses per revolution (for 2FOC is always 65536 all encoders are expanded to 16bit) - Screw_ratio: lead screw ratio (mm/turns) such as 5mm/turn - Screw gear: number of teeths of screw pulley - Motor gear: number of teeths of motor pulley + Screw_ratio: lead screw ratio (mm/turns) such as 5mm/turn + Screw gear: number of teeths of screw pulley + Motor gear: number of teeths of motor pulley To use this driver the 2FOC boards must be configured for speed control - and CAN address 3 connecting each axis on a different CAN8 line in a + and CAN address 3 connecting each axis on a different CAN8 line in a point2point configuration. - 2FOC periodic message is configured for: + 2FOC periodic message is configured for: - position(32bit) - velocity(16bit) - Iq(16bit) \par How to compile. - In order to compile, this driver should be placed in the + In order to compile, this driver should be placed in the /machinekit/src/hal/drivers/ directory in the the Makefile in the /machinekit/src directory add the following: ifeq ($(TARGET_PLATFORM), zedboard) @@ -57,9 +57,9 @@ endif in the '# Subdirectory: hal/drivers' section - and add + and add ifeq ($(TARGET_PLATFORM),zedboard) - $(RTLIBDIR)/hal_zedcan$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_zedcan-objs)) + $(RTLIBDIR)/hal_zedcan.so: $(addprefix $(OBJDIR)/,$(hal_zedcan-objs)) endif in the '# build kernel RTAPI modules' section @@ -77,13 +77,10 @@ */ #include "rtapi.h" // rtapi_print_msg() -#include "rtapi_bitops.h" // RTAPI_BIT(n) -#include "rtapi_app.h" // +#include "rtapi_bitops.h" // RTAPI_BIT(n) +#include "rtapi_app.h" // #include "hal.h" -#if !defined(BUILD_SYS_USER_DSO) - #error "This driver is for usermode threads only" -#endif #if !defined(TARGET_PLATFORM_ZEDBOARD) #error "This driver is for the Zedboard platform only" #endif @@ -115,7 +112,7 @@ MODULE_AUTHOR("Claudio Lorini"); MODULE_DESCRIPTION("Driver CAN for Zedboard 2FOC board"); MODULE_LICENSE("GPL"); -// Miscellaneous peripheral +// Miscellaneous peripheral #define PMODA_OUTREG 0x04 #define PMODB_INREG 0x08 #define RESET_CAN_REG 0x00 @@ -164,7 +161,7 @@ typedef struct { // used for debug pourpouses hal_float_t dbg; - + } FOC_data_t; /** \brief Array of FOC_data structs in shared memory, 1 per configured axis */ @@ -212,11 +209,11 @@ bool FOCAxisIsOperationEnable[MAX_FOC_CHAN]={false}; \pre */ static void send_setpoint(void *arg, long period) { - int nbytes; + int nbytes; int n; __s16 setpoint; FOC_data_t *foctxdata = NULL; - + // point to first axis data foctxdata = arg; @@ -225,7 +222,7 @@ static void send_setpoint(void *arg, long period) // giva a fake feedback to machinekit // *(foctxdata->feedback) = *(foctxdata->setpoint); - + // procede to periodic CAN data exchange only if FOC in 'enable operation' if( false != FOCAxisIsOperationEnable[n] ) { @@ -255,26 +252,26 @@ static void send_setpoint(void *arg, long period) \brief Parse incoming CAN messages \params rxframe: incoming message n: CAN channel - FOC_data_t: FOC data image to fill + FOC_data_t: FOC data image to fill \return 0 everything OK -1 */ int ParseMessage(struct can_frame *rxframe, int n, FOC_data_t *focrxdata) { // parse packet type, mask away CAN address switch( ( rxframe->can_id & 0xFFFFFF) ) { - + case 0xFFFF81: - { + { // 0x81FFFF81, here it is a periodic! grab first (4 bytes) data (position). __s32 *pos = NULL; // FOC position feedback is 65536 postions per turn // for a direct drive screw with 1mm x turn 65536.0; // for a direct drive screw with 5mm x turn 65536.0/5.0; - // for 46:22 pulleys and 5mm x turn 65535/(5*46/22) + // for 46:22 pulleys and 5mm x turn 65535/(5*46/22) pos = (__s32*) rxframe->data; - // *(focrxdata->feedback) = (float) *pos / (65536.0/5.0); - *(focrxdata->feedback) = (float) *pos / ( (float)PPR[n] / ( (float)Screw_ratio[n]*((float)Motor_gear[n]/Screw_gear[n]))); + // *(focrxdata->feedback) = (float) *pos / (65536.0/5.0); + *(focrxdata->feedback) = (float) *pos / ( (float)PPR[n] / ( (float)Screw_ratio[n]*((float)Motor_gear[n]/Screw_gear[n]))); } break; @@ -282,7 +279,7 @@ int ParseMessage(struct can_frame *rxframe, int n, FOC_data_t *focrxdata) { // 0x81FFFF82, here it is a status/error packet. hal_u32_t *stat = NULL, *err = NULL; - + stat = (hal_u32_t*) rxframe->data; err = (hal_u32_t*) (rxframe->data+4); *(focrxdata->focstatus) = (hal_u32_t) *stat; @@ -295,8 +292,8 @@ int ParseMessage(struct can_frame *rxframe, int n, FOC_data_t *focrxdata) break; case 0xFFFFFF: - // 0x8xFFFFFF: ok, this is a command NACK, something serious has happened, - // like an set-point overrange or such... + // 0x8xFFFFFF: ok, this is a command NACK, something serious has happened, + // like an set-point overrange or such... // \todo try to mend it. rtapi_print_msg(RTAPI_MSG_ERR,"HAL_ZED_CAN: Error: NACK (0x%X) from CAN%d",rxframe->can_id, n); // hal_exit(comp_id); @@ -336,7 +333,7 @@ WR(map_MiscAddress + PMODA_OUTREG, rmw); // procede to periodic CAN data exchange only if FOC in 'enable operation' if( false != FOCAxisIsOperationEnable[n] ) { - // parse all messages (eventually) in the rx queue + // parse all messages (eventually) in the rx queue do { // read data (hopefully not-blocking) nbytes = read (sock[n], &rxframe[n], sizeof (struct can_frame)); @@ -359,9 +356,9 @@ WR(map_MiscAddress + PMODA_OUTREG, rmw); /** \brief Setup CAN communication with 2FOC board - \details - \pre - \return + \details + \pre + \return 0: everything ok. ....: failed to initialize communication */ static int setup_CAN(int n) @@ -388,13 +385,13 @@ static int setup_CAN(int n) /** \todo error mamagement a palla */ // - rtapi_snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "can%d",n); + rtapi_snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "can%d",n); // ioctl (sock[n], SIOCGIFINDEX, &ifr); // addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; - + rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: %s at index %d\n", ifr.ifr_name, ifr.ifr_ifindex); // Bind the socket @@ -410,16 +407,16 @@ static int setup_CAN(int n) hal_exit(comp_id); return -1; } - + /* sets the socket read timout to zero */ memset((char*)&tv,0,sizeof(tv)); if(-1 == setsockopt(sock[n], SOL_SOCKET, SO_RCVTIMEO,(char *)&tv,sizeof(tv))) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: Error: cannot set socket RX timeout"); hal_exit(comp_id); return -1; - } + } - // make the socket read non-blocking + // make the socket read non-blocking if(0 != fcntl(sock[n], F_SETFL, fcntl(sock[n], F_GETFL, 0) | O_NONBLOCK)) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: Error: cannot set socket in non-blocking mode"); hal_exit(comp_id); @@ -440,7 +437,7 @@ static int setup_CAN(int n) /** \brief Determine Zynq revision \details Parse data in /proc/cpuinfo for 'Revision' - \return + \return -1: unable to parse /proc/cpuinfo -1: unable to parse a version number nnnn: the one and only revision */ @@ -451,14 +448,14 @@ static int zynq_revision() // parse /proc/cpuinfo for the line: Revision char *rev_line = "Revision"; FILE *f = fopen(path,"r"); - + if (!f) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: can't open %s: %d - %s\n", path, errno, strerror(errno)); hal_exit(comp_id); return -1; } - + while (fgets(line, sizeof(line), f)) { if (!strncmp(line, rev_line, strlen(rev_line))) { s = strchr(line, ':'); @@ -473,16 +470,16 @@ static int zynq_revision() } /** - \brief Parse the control type configuration passed to the module + \brief Parse the control type configuration passed to the module \details Valid configurations are: 'c' for CSP, Contimuous Setpoint Position 'j' for TRAJGEN, Position control with trajectory generator - 'v' for VELOCITY, Velocity control - 'i' for CURRENT, Current (torque) control + 'v' for VELOCITY, Velocity control + 'i' for CURRENT, Current (torque) control 't' for TORQUE, Torque control with sensor feedback - \todo all. - \return - MODE: detected mode + \todo all. + \return + MODE: detected mode INVALID: mode not set or invalid */ static CONTROL parse_ctrl_type(const char *ctrl) { @@ -499,24 +496,24 @@ static CONTROL parse_ctrl_type(const char *ctrl) /** \brief Determine Zedboard FPGA HW revision - \details The FPGA can contain different resources, a version register determine + \details The FPGA can contain different resources, a version register determine the available resources - \todo Do register read for FPGA versioning - \return + \todo Do register read for FPGA versioning + \return 01: the one and only revision */ static int zb_revision() { return 01; } -/** - \brief Export pins for component(s) - \param - num: component number - addr: pointer to array of the num^th FOC channel data +/** + \brief Export pins for component(s) + \param + num: component number + addr: pointer to array of the num^th FOC channel data */ static int exportFOCaxis(int num, FOC_data_t * addr) -{ +{ int retval = 0; // @@ -528,8 +525,8 @@ static int exportFOCaxis(int num, FOC_data_t * addr) rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: ERROR: pin setpoint export failed with err=%d", retval); hal_exit(comp_id); return -1; - } - // make available position feedback in hal + } + // make available position feedback in hal if ( (retval = hal_pin_float_newf(HAL_OUT, &(addr->feedback), comp_id, "hal_zed_can.%d.feedback", num) ) < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: ERROR: pin feedback export failed with err=%d", retval); hal_exit(comp_id); @@ -548,7 +545,7 @@ static int exportFOCaxis(int num, FOC_data_t * addr) hal_exit(comp_id); return -1; } - // instantiate parameter + // instantiate parameter retval = hal_pin_u32_newf(HAL_OUT, &(addr->focstatus), comp_id, "hal_zed_can.%d.status", num); // check for failed debug space mapping if(retval != 0) { @@ -556,7 +553,7 @@ static int exportFOCaxis(int num, FOC_data_t * addr) hal_exit(comp_id); return -1; } - // instantiate parameter + // instantiate parameter retval = hal_pin_u32_newf(HAL_OUT, &(addr->focerror), comp_id, "hal_zed_can.%d.error", num); // check for failed debug space mapping if(retval != 0) { @@ -571,8 +568,8 @@ static int exportFOCaxis(int num, FOC_data_t * addr) } /** - \brief do a programmable delay in a barbarous way... - \details + \brief do a programmable delay in a barbarous way... + \details \params delaycycle: delay expiration value */ void dodelay(unsigned long delaycycles) { @@ -585,16 +582,16 @@ void dodelay(unsigned long delaycycles) /** \brief Make sure the periodic communication with 2FOC board is on - \details - \pre - \return + \details + \pre + \return 0: everything ok. ....: failed to initialize periodic communication */ int setup_2FOC_periodic() { int nbytes; int n; - // \todo use the global variable for status/error + // \todo use the global variable for status/error FOC_data_t *focrxdata = NULL; // zero contents of databuffers @@ -643,12 +640,12 @@ int setup_2FOC_periodic() rtapi_print_msg(RTAPI_MSG_ERR,"HAL_ZED_CAN: Unable to send 'enable operation' command to axis %d",n); hal_exit(comp_id); exit(-1); - } + } dodelay(20000); } rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: ShutDown,SwitchOn, EnableOperation sent to all channels."); - + // \todo Check anything possible before waiting for alignment // - errors of any kind // - board switched on and operationenabled @@ -660,7 +657,7 @@ int setup_2FOC_periodic() // wait for completion of the rotor alignment (flag in status message) for (n = 0; n < num_chan; n++) { int nbytes=0; - + do { // read CAN packet nbytes = read (sock[n], &rxframe[n], sizeof (struct can_frame)); @@ -671,9 +668,9 @@ int setup_2FOC_periodic() } } } - // rotor alignment completed + // rotor alignment completed while ( 0 == (*(focrxdata->focstatus) & 0x00020000 ) ); - + // \todo Check anything possible before living control to machinekit: // - errors of any kind // - correct configuration (speed loop) @@ -698,23 +695,23 @@ int rtapi_app_main(void) { // zynq and FPGA code revision int rev, zrev, n; - // save messaging level + // save messaging level static int msg_level; int retval = 0; - - int fdmisc; - // save message level on entering + int fdmisc; + + // save message level on entering msg_level = rtapi_get_msg_level(); - + /* setup messaging level in: RTAPI_MSG_NONE, RTAPI_MSG_ERR, RTAPI_MSG_WARN, RTAPI_MSG_INFO, RTAPI_MSG_DBG, RTAPI_MSG_ALL */ rtapi_set_msg_level(RTAPI_MSG_ALL); - // check Zynq revision + // check Zynq revision if ((zrev = zynq_revision()) < 0) { - // unable to determine zynq revision + // unable to determine zynq revision rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: ERROR: unable to determine zynq revision"); hal_exit(comp_id); return -1; @@ -722,9 +719,9 @@ int rtapi_app_main(void) // notify zynq revision rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: Zynq Revision %d \n", zrev); - // check Zedboard FPGA hardware revision + // check Zedboard FPGA hardware revision rev = zb_revision(); - + // do revision specific configuration switch (rev) { case 01: @@ -748,9 +745,9 @@ int rtapi_app_main(void) printf("Map Misc peripheral: virtual 0x%x real 0x%x \n", map_MiscAddress, MISC_ADDR); // parse module parameters in order to find the number - // of configured FOC channels and their CAN address/configuration + // of configured FOC channels and their CAN address/configuration for(n = 0; n < MAX_FOC_CHAN && FOC_axis[n] != -1 ; n++) { - // check for a valid CAN address + // check for a valid CAN address if( (FOC_axis[n] <= 0) || ( FOC_axis[n] > 15) ) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_CAN: ERROR: bad CAN address '%i', axis %i", FOC_axis[n], n); hal_exit(comp_id); @@ -763,9 +760,9 @@ int rtapi_app_main(void) hal_exit(comp_id); return -1; } - // found a correctly configured channel + // found a correctly configured channel num_chan++; - // notify + // notify rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: FOC axis %d with CAN address %d.",n, FOC_axis[n] ); rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: Motor gear %d, Screw gear %d, Screw ratio %d Encoder PPR %d.", Screw_gear[n], Motor_gear[n], Screw_ratio[n], PPR[n]); } @@ -774,7 +771,7 @@ int rtapi_app_main(void) hal_exit(comp_id); return -1; } - + // allocate shared memory for FOC_data of each axis FOC_data_array = hal_malloc(num_chan * sizeof(FOC_data_t)); if ( 0 == FOC_data_array ) { @@ -839,16 +836,16 @@ int rtapi_app_main(void) return 0; } -/** - \brief Exit component closing communication with EMS +/** + \brief Exit component closing communication with EMS \pre */ void rtapi_app_exit(void) -{ +{ int n; // notify clean termination rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_CAN: component terminated successfully \n"); - + // close CAN sockets for(n = 0; n < num_chan ; n++) { close(sock[n]); @@ -856,4 +853,3 @@ void rtapi_app_exit(void) hal_exit(comp_id); } - diff --git a/src/hal/drivers/hal_zed_gpio.c b/src/hal/drivers/hal_zed_gpio.c index b3954b8d23..99634f6ece 100644 --- a/src/hal/drivers/hal_zed_gpio.c +++ b/src/hal/drivers/hal_zed_gpio.c @@ -18,17 +18,17 @@ \details This driver profides a series of digital IO connected to the PMods connectors JA1, JB1, JC1, JD1, JE1 and Vita connector. - + In order to mantain rt performances the access to the peripheral is done as a memory access to the xilinx-gpio peripheral. - Details of the pheripheral registers structure can be found in the + Details of the pheripheral registers structure can be found in the following document: ug585-Zynq-7000-TRM.pdf (pag.381, pag.1348) \par IO connection table: Pin assignment with CAN8 board (Vita) 55,56,57,58,59,60,61,62 - Led CAN (out) - 63,64,65,66,67,68,69,70 - DIP Switch 1 (in) + 63,64,65,66,67,68,69,70 - DIP Switch 1 (in) 71,72,73,74,75,76,77,78 - J8 Outputs (out) 79,80,81,82,83,84,85 - J6 Inputs (in) 86,87,88,89,90,91,92 - J7 Inputs (in) @@ -38,67 +38,67 @@ \version 00 \date 07.02.2014 compiled from source tree and loaded successfully \version 01 - \date 12.02.2014 Inputs working at last! + \date 12.02.2014 Inputs working at last! \version 02 \date 20.03.2015 Moved to a true rt implementation \version 03 \note \bug - \warning + \warning \todo - \pre - \param + \pre + \param \return */ /** -\brief Zynq gpio peripheral register mapping from ug585-Zynq-7000-TRM.pdf +\brief Zynq gpio peripheral register mapping from ug585-Zynq-7000-TRM.pdf */ /** \brief gpio peripheral base address */ -#define GPIO_BASE 0xE000A000 +#define GPIO_BASE 0xE000A000 -/** \breief This registers enables software to change the value being output. +/** \breief This registers enables software to change the value being output. Only data values with a corresponding deasserted mask bit will be changed. 0: pin value is updated 1: pin is masked */ -#define MASK_DATA_0_LSW 0x00000000 -#define MASK_DATA_0_MSW 0x00000004 -#define MASK_DATA_1_LSW 0x00000008 -#define MASK_DATA_1_MSW 0x0000000C -#define MASK_DATA_2_LSW 0x00000010 -#define MASK_DATA_2_MSW 0x00000014 -#define MASK_DATA_3_LSW 0x00000018 -#define MASK_DATA_3_MSW 0x0000001C - -/** \breief This register controls the value being output when the GPIO -signal is configured as an output. All 32bits of this register are written +#define MASK_DATA_0_LSW 0x00000000 +#define MASK_DATA_0_MSW 0x00000004 +#define MASK_DATA_1_LSW 0x00000008 +#define MASK_DATA_1_MSW 0x0000000C +#define MASK_DATA_2_LSW 0x00000010 +#define MASK_DATA_2_MSW 0x00000014 +#define MASK_DATA_3_LSW 0x00000018 +#define MASK_DATA_3_MSW 0x0000001C + +/** \breief This register controls the value being output when the GPIO +signal is configured as an output. All 32bits of this register are written at one time. */ #define DATA_0 0x00000040 #define DATA_1 0x00000044 #define DATA_2 0x00000048 #define DATA_3 0x0000004C -/** \breief This register enables software to observe the value on the device pin. -If the GPIO signal is configured as an output, then this would normally reflect +/** \breief This register enables software to observe the value on the device pin. +If the GPIO signal is configured as an output, then this would normally reflect the value being driven on the output. Writes to this register are ignored.*/ #define DATA_0_RO 0x00000060 // 00..31 [8:7] cannot be used as inputs, will always return 0 when read. -#define DATA_1_RO 0x00000064 // 32..53 +#define DATA_1_RO 0x00000064 // 32..53 #define DATA_2_RO 0x00000068 // 54..85 #define DATA_3_RO 0x0000006C // 86..117 -/** \breief This register controls whether the IO pin is acting as an input -or an output. Since the input logic is always enabled, this effectively +/** \breief This register controls whether the IO pin is acting as an input +or an output. Since the input logic is always enabled, this effectively enables/disables the output driver. 0: input 1: output */ -#define DIRM_0 0x00000204 -#define DIRM_1 0x00000244 +#define DIRM_0 0x00000204 +#define DIRM_1 0x00000244 #define DIRM_2 0x00000284 #define DIRM_3 0x000002C4 -/** \breief When the IO is configured as an output, this controls whether +/** \breief When the IO is configured as an output, this controls whether the output is enabled or not. When the output is disabled, the pin is tri-stated. 0: disabled 1: enabled */ @@ -107,40 +107,40 @@ the output is enabled or not. When the output is disabled, the pin is tri-stated #define OEN_2 0x00000288 #define OEN_3 0x000002C8 -/** \breief This register shows which bits are currently masked and which -are un-masked/enabled. This register is read only, so masks cannot be +/** \breief This register shows which bits are currently masked and which +are un-masked/enabled. This register is read only, so masks cannot be changed here. 0: interrupt source enabled 1: interrupt source masked */ -#define INT_MASK_0 0x0000020C -#define INT_MASK_1 0x0000024C +#define INT_MASK_0 0x0000020C +#define INT_MASK_1 0x0000024C #define INT_MASK_2 0x0000028C -#define INT_MASK_3 0x000002CC +#define INT_MASK_3 0x000002CC -/** \breief This register is used to enable or unmask a GPIO input for -use as an interrupt source.Writing a 1 to any bit of this register enables/unmasks +/** \breief This register is used to enable or unmask a GPIO input for +use as an interrupt source.Writing a 1 to any bit of this register enables/unmasks that signal for interrupts. */ -#define INT_EN_0 0x00000210 +#define INT_EN_0 0x00000210 #define INT_EN_1 0x00000250 #define INT_EN_2 0x00000290 -#define INT_EN_3 0x000002D0 +#define INT_EN_3 0x000002D0 -/** \breief This register is used to disable or mask a GPIO input for use -as an interrupt source. Writing a 1 to any bit of this register disables/masks +/** \breief This register is used to disable or mask a GPIO input for use +as an interrupt source. Writing a 1 to any bit of this register disables/masks that signal for interrupts. */ -#define INT_DIS_0 0x00000214 +#define INT_DIS_0 0x00000214 #define INT_DIS_1 0x00000254 #define INT_DIS_2 0x00000294 #define INT_DIS_3 0x000002D4 -/** \breief This registers shows if an interrupt event has occurred or not. +/** \breief This registers shows if an interrupt event has occurred or not. Writing a 1 to a bit in this register clears the interrupt status for that bit. */ #define INT_STAT_0 0x00000218 #define INT_STAT_1 0x00000258 #define INT_STAT_2 0x00000298 #define INT_STAT_3 0x000002D8 -/** \breief This register controls whether the interrupt is edge sensitive +/** \breief This register controls whether the interrupt is edge sensitive or level sensitive. 0: level-sensitive 1: edge-sensitive */ @@ -149,21 +149,21 @@ or level sensitive. #define INT_TYPE_2 0x0000029C #define INT_TYPE_3 0x000002DC -/** \breief This register controls whether the interrupt is active-low or +/** \breief This register controls whether the interrupt is active-low or active high (or falling-edge sensitive or rising-edge sensitive). 0: active low or falling edge 1: active high or rising edge */ -#define INT_POLARITY_0 0x00000220 +#define INT_POLARITY_0 0x00000220 #define INT_POLARITY_1 0x00000260 #define INT_POLARITY_2 0x000002A0 -#define INT_POLARITY_3 0x000002E0 +#define INT_POLARITY_3 0x000002E0 -/** \breief If INT_TYPE is set to edge sensitive, then this register enables an -interrupt event on both rising and falling edges. This register is ignored if +/** \breief If INT_TYPE is set to edge sensitive, then this register enables an +interrupt event on both rising and falling edges. This register is ignored if INT_TYPE is set to level sensitive. 0: trigger on single edge, using configured interrupt polarity 1: trigger on both edges */ -#define INT_ANY_0 0x00000224 +#define INT_ANY_0 0x00000224 #define INT_ANY_1 0x00000264 #define INT_ANY_2 0x000002A4 #define INT_ANY_3 0x000002E4 @@ -177,9 +177,6 @@ INT_TYPE is set to level sensitive. #include "rtapi_app.h" #include "hal.h" -#if !defined(BUILD_SYS_USER_DSO) - #error "This driver is for usermode threads only" -#endif #if !defined(TARGET_PLATFORM_ZEDBOARD) #error "This driver is for the Zedboard platform only" #endif @@ -218,7 +215,7 @@ static void write_port(void *arg, long period) // J8 Outputs from 71 to 78 are on DATA_2 reg. for (n = 0; n < ngpo; n++) { - if (0 == *(oport_data[n])) { + if (0 == *(oport_data[n])) { RTAPI_BIT_CLEAR(RDATA_2, n+17); } else { @@ -246,13 +243,13 @@ static void read_port(void *arg, long period) \brief configrure GPIOs \pre ngpio must be initialized first*/ static void setup_gpio_access() -{ +{ // set DATA_2 as 8 outputs J8 + 8 out LED *((unsigned *)(base + DIRM_2)) = 0x01FE01FE; - // enable output drivers + // enable output drivers *((unsigned *)(base + OEN_2)) = 0x01FE01FE; - // enable update outputs + // enable update outputs *((unsigned *)(base + MASK_DATA_2_LSW)) = 0x0; *((unsigned *)(base + MASK_DATA_2_MSW)) = 0x0; } @@ -260,7 +257,7 @@ static void setup_gpio_access() /** \brief Determine Zynq revision \details Parse data in /proc/cpuinfo for 'Revision' - \return + \return -1: unable to parse /proc/cpuinfo -1: unable to parse a version number nnnn: the one and only revision */ @@ -271,13 +268,13 @@ static int zynq_revision() // parse /proc/cpuinfo for the line: Revision char *rev_line = "Revision"; FILE *f = fopen(path,"r"); - + if (!f) { rtapi_print_msg(RTAPI_MSG_ERR, "HAL_ZED_GPIO: can't open %s: %d - %s\n", path, errno, strerror(errno)); return -1; } - + while (fgets(line, sizeof(line), f)) { if (!strncmp(line, rev_line, strlen(rev_line))) { s = strchr(line, ':'); @@ -293,10 +290,10 @@ static int zynq_revision() /** \brief Determine Zedboard FPGA HW revision - \details The FPGA can contain different resources, a version register determine + \details The FPGA can contain different resources, a version register determine the available resources - \todo Do register read for FPGA versioning - \return + \todo Do register read for FPGA versioning + \return 01: the one and only revision */ static int zb_revision() { @@ -322,20 +319,20 @@ int rtapi_app_main(void) RTAPI_MSG_WARN, RTAPI_MSG_INFO, RTAPI_MSG_DBG, - RTAPI_MSG_ALL + RTAPI_MSG_ALL rtapi_set_msg_level(RTAPI_MSG_ALL); */ - // check Zynq revision + // check Zynq revision if ((zrev = zynq_revision()) < 0) { - // unable to determine zynq revision + // unable to determine zynq revision return -1; } // notify zynq revision rtapi_print_msg(RTAPI_MSG_INFO, "HAL_ZED_GPIO: Zynq Revision %d \n", zrev); - // check Zedboard FPGA hardware revision + // check Zedboard FPGA hardware revision rev = zb_revision(); - + // do revision specific configuration switch (rev) { case 01: @@ -357,7 +354,7 @@ int rtapi_app_main(void) return -1; } - // mmap the device into memory + // mmap the device into memory { unsigned page_addr, page_offset; unsigned page_size=sysconf(_SC_PAGESIZE); @@ -432,10 +429,10 @@ int rtapi_app_main(void) return 0; } -/** +/** \brief Exit component */ void rtapi_app_exit(void) -{ +{ //close /dev/mem close(fd); @@ -444,5 +441,3 @@ void rtapi_app_exit(void) hal_exit(comp_id); } - - diff --git a/src/hal/drivers/mesa-hostmot2/bspi.c b/src/hal/drivers/mesa-hostmot2/bspi.c index 64e4768c24..7f0240c742 100644 --- a/src/hal/drivers/mesa-hostmot2/bspi.c +++ b/src/hal/drivers/mesa-hostmot2/bspi.c @@ -364,3 +364,6 @@ void hm2_bspi_cleanup(hostmot2_t *hm2) void hm2_bspi_write(hostmot2_t *hm2) { } + + + diff --git a/src/hal/drivers/mesa-hostmot2/dbspi.c b/src/hal/drivers/mesa-hostmot2/dbspi.c index 26816b5ff6..dabf886c86 100644 --- a/src/hal/drivers/mesa-hostmot2/dbspi.c +++ b/src/hal/drivers/mesa-hostmot2/dbspi.c @@ -364,3 +364,6 @@ void hm2_dbspi_cleanup(hostmot2_t *hm2) void hm2_dbspi_write(hostmot2_t *hm2) { } + + + diff --git a/src/hal/drivers/mesa-hostmot2/hm2_7i43.c b/src/hal/drivers/mesa-hostmot2/hm2_7i43.c index 8571f721b6..a9ad527413 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_7i43.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_7i43.c @@ -19,10 +19,6 @@ #include "config_module.h" -#if defined(BUILD_SYS_KBUILD) -#include -#endif - #include "rtapi.h" #include "rtapi_app.h" #include "rtapi_math.h" @@ -69,9 +65,9 @@ static hm2_7i43_t board[HM2_7I43_MAX_BOARDS]; static int num_boards; -// +// // EPP I/O code -// +// static inline void hm2_7i43_epp_addr8(u8 addr, hm2_7i43_t *board) { outb(addr, board->port.base + HM2_7I43_EPP_ADDRESS_OFFSET); @@ -193,7 +189,7 @@ static void hm2_7i43_nanosleep(unsigned long int nanoseconds) { -// +// // these are the low-level i/o functions exported to the hostmot2 driver // @@ -350,7 +346,7 @@ int hm2_7i43_reset(hm2_lowlevel_io_t *this) { hm2_7i43_epp_write(0x5A, board); - // + // // this code resets the FPGA *only* if the CPLD is in charge of the // parallel port // @@ -417,7 +413,7 @@ static int hm2_7i43_setup(void) { // // claim the I/O regions for the parport - // + // r = hal_parport_get(comp_id, &board[i].port, ioaddr[i], ioaddr_hi[i], PARPORT_MODE_EPP); @@ -525,4 +521,3 @@ void rtapi_app_exit(void) { hal_exit(comp_id); LL_PRINT("driver unloaded\n"); } - diff --git a/src/hal/drivers/mesa-hostmot2/hm2_eth.c b/src/hal/drivers/mesa-hostmot2/hm2_eth.c index 8f03e00e3e..eba269c69b 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_eth.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_eth.c @@ -34,7 +34,7 @@ #include #include #include -#include + #include #include #include diff --git a/src/hal/drivers/mesa-hostmot2/hm2_pci.c b/src/hal/drivers/mesa-hostmot2/hm2_pci.c index 8544ec7dfd..db198276aa 100755 --- a/src/hal/drivers/mesa-hostmot2/hm2_pci.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_pci.c @@ -20,13 +20,9 @@ #include "config.h" -#if defined(USERMODE_PCI) && defined(BUILD_SYS_USER_DSO) #include #include #include -#else -#include -#endif #include "rtapi.h" #include "rtapi_app.h" @@ -207,7 +203,7 @@ MODULE_DEVICE_TABLE(pci, hm2_pci_tbl); -// +// // these are the "low-level I/O" functions exported up // @@ -452,7 +448,7 @@ static int hm2_plx9054_reset(hm2_lowlevel_io_t *this) { -// +// // misc internal functions // @@ -839,4 +835,3 @@ void rtapi_app_exit(void) { LL_PRINT("driver unloaded\n"); hal_exit(comp_id); } - diff --git a/src/hal/drivers/mesa-hostmot2/hm2_soc_ol.c b/src/hal/drivers/mesa-hostmot2/hm2_soc_ol.c index b8f4785819..7b3533aac5 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_soc_ol.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_soc_ol.c @@ -91,10 +91,6 @@ see configs/hm2-soc-stepper/irqtest.hal for a usage example /* #error "This driver is for the socfpga platform only" */ /* #endif */ -#if !defined(BUILD_SYS_USER_DSO) -#error "This driver is for usermode threads only" -#endif - #include "rtapi.h" #include "rtapi_app.h" #include "rtapi_string.h" @@ -518,7 +514,7 @@ static int instantiate(const int argc, char* const *argv) void *blob = NULL; LL_PRINT("loading Mesa AnyIO HostMot2 socfpga overlay driver version " HM2_SOCFPGA_VERSION "\n"); - + if(debug){ for(x = 0; x < argc; x++){ LL_DBG("argv[%d] = %s\n", x, argv[x]); @@ -533,20 +529,20 @@ static int instantiate(const int argc, char* const *argv) int inst_id = hal_inst_create(name, comp_id, sizeof(hm2_soc_t), (void **)&brd); if (inst_id < 0) return -1; - + /******************************************************************************** // Initialise and fill inst array values first // // Then zero or void instparam values or they will be passed to next instance // If they are boolean, just zeroing to the default is sufficient // - // If they are a value within a value range, you should void it to -1, + // If they are a value within a value range, you should void it to -1, // so that the instantiation code can insert the default value if it finds -1 // - // Alternatively it could flag an error if it means at least one previous + // Alternatively it could flag an error if it means at least one previous // instance exists and this value cannot be valid ( see num ) **********************************************************************************/ - + brd->name = name; brd->config = NULL; brd->descriptor = NULL; @@ -577,13 +573,13 @@ static int instantiate(const int argc, char* const *argv) LL_ERR("num set to -1 by previous instance. Set a valid board number"); return -1; } - else + else brd->num = num; // void parameters no_init_llio = 0; num = -1; debug = 0; - + // read a custom fwid message if given if (brd->descriptor != NULL) { struct stat st; diff --git a/src/hal/drivers/mesa-hostmot2/hm2_test.c b/src/hal/drivers/mesa-hostmot2/hm2_test.c index ccb61b7485..dfae7550d9 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_test.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_test.c @@ -27,13 +27,11 @@ #include "config.h" -#if defined(USERMODE_PCI) && defined(BUILD_SYS_USER_DSO) +#ifdef SYS_IO_DEFINED #include +#endif #include #include -#else -#include -#endif #include "rtapi.h" #include "rtapi_app.h" @@ -79,7 +77,7 @@ static void set32(hm2_test_t *me, u16 addr, u32 val) { } -// +// // these are the "low-level I/O" functions exported up // @@ -131,18 +129,18 @@ int rtapi_app_main(void) { switch (test_pattern) { - // + // // this one has nothing - // + // case 0: { break; } - // + // // this one has a good IO Cookie, but that's it - // + // case 1: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -150,10 +148,10 @@ int rtapi_app_main(void) { } - // + // // this one has a good IO Cookie and Config Name // the idrom offset is 0, and there's nothing there - // + // case 2: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -169,10 +167,10 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's an invalid IDROM type there - // + // case 3: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -195,11 +193,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // but the portwidth is 0 - // + // case 4: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -217,11 +215,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // but the portwidth is 29 which is bogus - // + // case 5: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -243,11 +241,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth - // + // case 6: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -269,11 +267,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth, but problematic IOPorts and IOWidth - // + // case 7: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -301,11 +299,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth, but IOPorts doesnt match what the llio said - // + // case 8: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -331,12 +329,12 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth, IOPorts, and IOWidth // but the clocks are bad - // + // case 9: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -363,12 +361,12 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth, IOPorts, and IOWidth // but the clocks are bad - // + // case 10: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -396,11 +394,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good PortWidth, IOPorts, IOWidth, and clocks - // + // // The problem with this register file is that the Pin Descriptor // array contains no valid PDs, though the IDROM advertised 144 pins. // @@ -535,11 +533,11 @@ int rtapi_app_main(void) { } - // + // // good IO Cookie, Config Name, and IDROM Type // the IDROM offset is the usual, 0x400, and there's a good IDROM type there // good but unusual (non-24) PortWidth - // + // case 14: { set32(me, HM2_ADDR_IOCOOKIE, HM2_IOCOOKIE); @@ -606,4 +604,3 @@ void rtapi_app_exit(void) { LL_PRINT("driver unloaded\n"); hal_exit(comp_id); } - diff --git a/src/hal/drivers/mesa-hostmot2/hostmot2.c b/src/hal/drivers/mesa-hostmot2/hostmot2.c index c0c9b71c62..ce6724ee31 100755 --- a/src/hal/drivers/mesa-hostmot2/hostmot2.c +++ b/src/hal/drivers/mesa-hostmot2/hostmot2.c @@ -181,8 +181,7 @@ const char *hm2_hz_to_mhz(u32 freq_hz) { freq_mhz = freq_hz / (1000*1000); freq_mhz_fractional = (freq_hz / 1000) % 1000; - r = rtapi_snprintf( - mhz_str, sizeof(mhz_str), "%d.%03d", freq_mhz, freq_mhz_fractional); + r = rtapi_snprintf(mhz_str, sizeof(mhz_str), "%d.%03d", freq_mhz, freq_mhz_fractional); if (r >= sizeof(mhz_str)) { HM2_ERR_NO_LL("too many MHz!\n"); return "(unpresentable)"; diff --git a/src/hal/drivers/probe_parport.c b/src/hal/drivers/probe_parport.c index 0d674c8b58..02a301c99e 100644 --- a/src/hal/drivers/probe_parport.c +++ b/src/hal/drivers/probe_parport.c @@ -1,6 +1,6 @@ /******************************************************************** * Description: probe_parport.c -* This file, 'probe_parport.c', is a HAL component that +* This file, 'probe_parport.c', is a HAL component that * does "PNP" probing for the standard PC parallel port. * If your parallel port does not work with emc2, it may if you * load this driver before you load hal_parport, e.g.: @@ -14,14 +14,14 @@ * * Author: Jeff Epler * License: GPL Version 2 -* +* * Copyright (c) 2006 All rights reserved. * -* Last change: +* Last change: ********************************************************************/ /* Low-level parallel-port routines for 8255-based PC-style hardware. - * + * * Authors: Phil Blundell * Tim Waugh * Jose Renau @@ -33,7 +33,7 @@ * Cleaned up include files - Russell King * DMA support - Bert De Jonghe * Many ECP bugs fixed. Fred Barnes & Jamie Lokier, 1999 - * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G. + * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G. * Various hacks, Fred Barnes, 04/2001 * Updated probing logic - Adam Belay */ @@ -45,8 +45,6 @@ static int comp_id; -#if defined(BUILD_SYS_USER_DSO) - int rtapi_app_main(void) { comp_id = hal_init("probe_parport"); if (comp_id < 0) { @@ -61,105 +59,3 @@ int rtapi_app_main(void) { void rtapi_app_exit(void) { hal_exit(comp_id); } - -#else - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -MODULE_AUTHOR("Jeff Epler"); -MODULE_DESCRIPTION("Parallel Port PNP driver for EMC HAL"); -MODULE_LICENSE("GPL"); - -static int pnp_registered_parport = 0; - -static const struct pnp_device_id probe_parport_pnp_tbl[] = { - /* Standard LPT Printer Port */ - {.id = "PNP0400", .driver_data = 0}, - /* ECP Printer Port */ - {.id = "PNP0401", .driver_data = 0}, - { } -}; - -MODULE_DEVICE_TABLE(pnp,probe_parport_pnp_tbl); - -static int probe_parport_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) -{ - unsigned long io_lo, io_hi; - - if (pnp_port_valid(dev,0) && - !(pnp_port_flags(dev,0) & IORESOURCE_DISABLED)) { - io_lo = pnp_port_start(dev,0); - } else - return -EINVAL; - - if (pnp_port_valid(dev,1) && - !(pnp_port_flags(dev,1) & IORESOURCE_DISABLED)) { - io_hi = pnp_port_start(dev,1); - } else - io_hi = 0; - - rtapi_print_msg(RTAPI_MSG_INFO, "parport: PnPBIOS parport detected, io_lo=%lx io_hi=%lx\n", - io_lo, io_hi); - - pnp_set_drvdata(dev,NULL); - return 0; -} - -static void probe_parport_pnp_remove(struct pnp_dev *dev) -{ -} - -/* we only need the pnp layer to activate the device, at least for now */ -static struct pnp_driver probe_parport_pnp_driver = { - .name = "probe_parport", - .id_table = probe_parport_pnp_tbl, - .probe = probe_parport_pnp_probe, - .remove = probe_parport_pnp_remove, -}; - - -int rtapi_app_main(void) { - int r; - - comp_id = hal_init("probe_parport"); - if (comp_id < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, "PROBE_PARPORT: ERROR: hal_init() failed\n"); - return -1; - } - - - r = pnp_register_driver (&probe_parport_pnp_driver); - if (r >= 0) { - pnp_registered_parport = 1; - } else { - rtapi_print_msg(RTAPI_MSG_WARN, "PROBE_PARPORT: no PnPBIOS parports were detected (%d)\n", r); - } - - hal_ready(comp_id); - return 0; -} - -void rtapi_app_exit(void) { - if (pnp_registered_parport) - pnp_unregister_driver (&probe_parport_pnp_driver); - hal_exit(comp_id); -} - -#endif diff --git a/src/hal/i_components/Submakefile b/src/hal/i_components/Submakefile index 8fd9acf142..6fec737248 100644 --- a/src/hal/i_components/Submakefile +++ b/src/hal/i_components/Submakefile @@ -14,11 +14,6 @@ CONVERTERS := \ conv_u64_float.icomp conv_u64_bit.icomp conv_u64_s64.icomp \ conv_s64_u64.icomp conv_u64_u32.icomp conv_s64_s32.icomp conv_s64_u32.icomp -ifeq ($(BUILD_KBUILD),yes) -ICOMPS := $(patsubst $(BASEPWD)/%,%,$(wildcard \ - $(BASEPWD)/$(HALICOMPDIR)/*.icomp )) -include $(patsubst %.icomp, $(BASEPWD)/halcomp-srcs/%.mak, $(ICOMPS)) -else ICOMPS := $(sort $(wildcard $(HALICOMPDIR)/*.icomp) \ $(addprefix hal/i_components/, $(CONVERTERS))) @@ -32,17 +27,9 @@ ifeq ($(BUILD_DOCS),yes) .PHONY: i_docpages endif -ifeq ($(TRIVIAL_BUILD)+$(BUILD_THREAD_MODULES),no+yes) --include $(patsubst %.icomp, $(BASEPWD)/halcomp-srcs/%.mak,\ - $(ICOMPS)) -endif # TRIVIAL_BUILD == no -endif - -ifeq ($(BUILD_THREAD_MODULES),yes) obj-m += \ $(patsubst hal/i_components/%.icomp, %.o, $(ICOMPS)) -endif ICOMP_DOCPAGES := $(patsubst $(HALICOMPDIR)/%.icomp, ../man/man9/%.asciidoc, \ $(ICOMPS)) @@ -55,29 +42,25 @@ $(ICOMP_DOCPAGES): ../man/man9/%.asciidoc: $(HALICOMPDIR)/%.icomp ../bin/instcom --frontmatter="edit-branch: $(EDIT_BRANCH)" \ -o $@ $< -ifeq ($(BUILD_ALL_FLAVORS),yes) -# .c and .mak files are identical for all flavors -# -# in the top-level make, build them once in a common location -halcomp-srcs/%.c: %.icomp ../bin/instcomp +# build them once in a common location +objects/%.c: %.icomp ../bin/instcomp $(ECHO) "Preprocessing $(notdir $<)" @mkdir -p $(dir $@) $(Q)../bin/instcomp --require-license -o $@ $< -halcomp-srcs/%.mak: %.icomp $(HALICOMP_SUBMAKEFILE) - $(ECHO) "Generating icomp build rules for $(notdir $<)" - @mkdir -p $(dir $@) - $(Q)echo "$(notdir $*)-objs := halcomp-srcs/$*.o" > $@.tmp - $(Q)echo "\$$(RTLIBDIR)/$(notdir $*)\$$(MODULE_EXT): \\" >> $@.tmp - $(Q)echo " \$$(OBJDIR)/halcomp-srcs/$*.o" >> $@.tmp - $(Q)mv -f $@.tmp $@ - -# Generate .c and .mak files before the modules target -modules: $(patsubst %.icomp, halcomp-srcs/%.c, \ - $(ICOMPS) ) -modules: $(patsubst %.icomp, halcomp-srcs/%.mak, \ - $(ICOMPS)) -endif # BUILD_ALL_FLAVORS == yes +# Generate rules for building i_component.so files +# abs_s32-objs := objects/hal/i_components/abs_s32.o +# $(RTLIBDIR)/abs_s32.so: $(OBJDIR)/objects/hal/i_components/abs_s32.o +# +# example: $$(call icomp_build_rules hal/i_components/abs_s32.comp) +define icomp_build_rules +$$(patsubst $(HALICOMPDIR)/%.icomp,%-objs,$(1)) := \ + objects/$$(patsubst %.icomp,%.o,$(1)) +$$(patsubst $(HALICOMPDIR)/%.icomp,$(RTLIBDIR)/%.so,$(1)): \ + $(OBJDIR)/objects/$$(patsubst %.icomp,%.o,$(1)) + +endef +$(eval $(foreach icomp,$(ICOMPS),$(call icomp_build_rules,$(icomp)))) # Regenerate conv_*.icomp when below rules are touched $(addprefix hal/i_components/, $(CONVERTERS)): hal/i_components/Submakefile diff --git a/src/hal/jplanner/jplan.c b/src/hal/jplanner/jplan.c index 11c552edb3..8a3690727f 100644 --- a/src/hal/jplanner/jplan.c +++ b/src/hal/jplanner/jplan.c @@ -228,7 +228,7 @@ static int instantiate_jplan(const int argc, const char **argv) hal_pin_float_newf(HAL_OUT, &(jp->curr_pos), inst_id, "%s.%d.curr-pos", name, i) || hal_pin_float_newf(HAL_OUT, &(jp->curr_vel), inst_id, "%s.%d.curr-vel", name, i) || hal_pin_float_newf(HAL_IN, &(jp->home_pos), inst_id, "%s.%d.home-pos", name, i) || - hal_pin_bit_newf(HAL_IN, &(jp->home_set), inst_id, "%s.%d.home-set", name, i)) + hal_pin_bit_newf(HAL_IN, &(jp->home_set), inst_id, "%s.%d.home-set", name, i)) return -1; hal_pin_dir_t dir = queued ? HAL_OUT : HAL_IN; diff --git a/src/hal/lib/Submakefile b/src/hal/lib/Submakefile index d9d7456f97..555b102531 100644 --- a/src/hal/lib/Submakefile +++ b/src/hal/lib/Submakefile @@ -8,6 +8,7 @@ LIBS := ../lib $(ECHO) Copying header file $@ $(Q)cp $< $@ + # link in basic nanonpb support routines HALLIBSRCS := $(HALLIBDIR)/hal_lib.c \ $(HALLIBDIR)/hal_group.c \ @@ -15,7 +16,6 @@ HALLIBSRCS := $(HALLIBDIR)/hal_lib.c \ $(HALLIBDIR)/hal_rcomp.c \ $(HALLIBDIR)/hal_vtable.c \ $(HALLIBDIR)/hal_funct.c \ - $(HALLIBDIR)/hal_procfs.c \ $(HALLIBDIR)/hal_thread.c \ $(HALLIBDIR)/hal_param.c \ $(HALLIBDIR)/hal_signal.c \ @@ -27,14 +27,13 @@ HALLIBSRCS := $(HALLIBDIR)/hal_lib.c \ $(HALLIBDIR)/hal_object.c \ $(HALLIBDIR)/hal_object_selectors.c \ $(HALLIBDIR)/hal_accessor.c \ - $(HALLIBDIR)/hal_iring.c \ - rtapi/rtapi_heap.c + $(HALLIBDIR)/hal_iring.c # protobuf support functions which depend on HAL - on RT host only HALLIBMTALK_SRCS := $(addprefix $(HALLIBDIR)/, \ halpb.cc) -HALLIBMTALK_CXXFLAGS := -DULAPI $(PROTOBUF_CFLAGS) $(CZMQ_CFLAGS) +HALLIBMTALK_CXXFLAGS := $(PROTOBUF_CFLAGS) $(CZMQ_CFLAGS) HALLIBMTALK_LDFLAGS := $(PROTOBUF_LIBS) $(CZMQ_LIBS) $(call TOOBJSDEPS, $(HALLIBMTALK_SRCS)) : EXTRAFLAGS=-fPIC $(HALLIBMTALK_CXXFLAGS) @@ -42,7 +41,7 @@ $(call TOOBJSDEPS, $(HALLIBMTALK_SRCS)) : EXTRAFLAGS=-fPIC $(HALLIBMTALK_CXXFLAG # ULAPI: all thread-specific code now comes in through the ulapi library # (liblinuxcnculapi.so) which autoloads the proper ulapi on demand -$(call TOOBJSDEPS, $(HALLIBSRCS)): EXTRAFLAGS += $(THREADS_RTFLAGS) -fPIC +$(call TOOBJSDEPS, $(HALLIBSRCS)): EXTRAFLAGS += -fPIC # Add to list of sources to compile -DULAPI -> # objects/{$(HALLIBDIR)/hal_lib.o} @@ -55,20 +54,24 @@ HALLIB := ../lib/liblinuxcnchal.so # for now, link in ulapi plus any referenced objs directly # cause: http://fedoraproject.org/wiki/UnderstandingDSOLinkChange +# might seem like strange place to create modules dir, +# but hallib is one of the first to be built, so ensures +# it exists with symlinks, before module build + $(HALLIB).0: \ $(call TOOBJS, $(HALLIBSRCS)) \ - $(call TOOBJS, $(ULAPI_AUTOLOAD_SRCS)) \ $(call TOOBJS, $(SHMDRVAPISRCS)) \ $(call TOOBJS, $(HALLIBMTALK_SRCS)) \ $(call TOOBJS, $(LIBINISRCS)) \ - $(call TOOBJS, machinetalk/lib/syslog_async.c) \ + $(ULAPI_LIB).0 \ $(LIBS)/libmachinetalk-pb2++.so $(ECHO) Creating shared library $(notdir $@) @mkdir -p ../lib + @mkdir -p ../rtlib/modules @rm -f $@ $(Q)$(CC) $(LDFLAGS) -Wl,-rpath,$(EMC2_RTLIB_DIR) \ -Wl,-soname,$(notdir $@) -shared \ - -o $@ $^ -lstdc++ -ldl -lrt $(PROTOBUF_LIBS) $(PROTOCXXLIB) $(CZMQ_LIBS) $(RT_LDFLAGS) + -o $@ $^ -lstdc++ -ldl -lrt $(PROTOBUF_LIBS) $(PROTOCXXLIB) $(CZMQ_LIBS) HALMODULESRCS := $(HALLIBDIR)/halmodule.cc PYSRCS += $(HALMODULESRCS) @@ -83,13 +86,12 @@ PYTARGETS += $(HALMODULE) obj-m += hal_lib.o -hal_lib-objs := hal/lib/hal_lib.o $(MATHSTUB) +hal_lib-objs := hal/lib/hal_lib.o hal_lib-objs += hal/lib/hal_group.o hal_lib-objs += hal/lib/hal_ring.o hal_lib-objs += hal/lib/hal_rcomp.o hal_lib-objs += hal/lib/hal_vtable.o hal_lib-objs += hal/lib/hal_funct.o -hal_lib-objs += hal/lib/hal_procfs.o hal_lib-objs += hal/lib/hal_thread.o hal_lib-objs += hal/lib/hal_signal.o hal_lib-objs += hal/lib/hal_pin.o @@ -103,4 +105,4 @@ hal_lib-objs += hal/lib/hal_object_selectors.o hal_lib-objs += hal/lib/hal_accessor.o hal_lib-objs += hal/lib/hal_iring.o -$(RTLIBDIR)/hal_lib$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_lib-objs)) +$(RTLIBDIR)/hal_lib.so: $(addprefix $(OBJDIR)/,$(hal_lib-objs)) diff --git a/src/hal/lib/config_module.h b/src/hal/lib/config_module.h index e2915405fd..22058c1468 100644 --- a/src/hal/lib/config_module.h +++ b/src/hal/lib/config_module.h @@ -65,8 +65,6 @@ place of something like */ -#ifdef BUILD_SYS_USER_DSO - /* Usermode PCI builds */ #define RTAPI_INC_CTYPE_H @@ -77,18 +75,4 @@ #define RTAPI_INC_SLAB_H "userpci/slab.h" #define RTAPI_INC_STRING_H "userpci/string.h" -#else - -/* Linux kernel module builds */ - -#define RTAPI_INC_CTYPE_H "linux/ctype.h" -#define RTAPI_INC_DEVICE_H "linux/device.h" -#define RTAPI_INC_FIRMWARE_H "linux/firmware.h" -#define RTAPI_INC_GFP_H "linux/gfp.h" -#define RTAPI_INC_LIST_H "linux/list.h" -#define RTAPI_INC_SLAB_H "linux/slab.h" -#define RTAPI_INC_STRING_H "linux/string.h" - -#endif /* BUILD_SYS_USER_DSO */ - #endif /* CONFIG_MODULE_H */ diff --git a/src/hal/lib/hal_comp.c b/src/hal/lib/hal_comp.c index 3c5c190423..d9e92ba2e6 100644 --- a/src/hal/lib/hal_comp.c +++ b/src/hal/lib/hal_comp.c @@ -10,12 +10,10 @@ #include /* pid_t */ #include /* getpid() */ #endif -#if defined(BUILD_SYS_USER_DSO) || (defined(RTAPI) && !defined(BUILD_SYS_KBUILD)) #include #ifndef abs int abs(int x) { if(x < 0) return -x; else return x; } #endif -#endif hal_comp_t *halpr_alloc_comp_struct(void); @@ -76,10 +74,6 @@ hal_comp_t *halg_xinitfv(const int use_hal_mutex, rtapi_set_logtag("hal_lib"); int comp_id, retval; - // sanity: these must have been inited before by the - // respective rtapi.so/.ko module - PCHECK_NULL(rtapi_switch); - if ((dtor != NULL) && (ctor == NULL)) { HALFAIL_NULL(EINVAL,"component '%s': NULL constructor doesnt make" " sense with non-NULL destructor", name); @@ -160,12 +154,6 @@ hal_comp_t *halg_xinitfv(const int use_hal_mutex, HALFAIL_NULL(retval, "could not init HAL shared memory rc=%d", retval); } - retval = hal_proc_init(); - if (retval) { - rtapi_exit(lib_module_id); - lib_module_id = -1; - HALFAIL_NULL(retval, "could not init /proc files"); - } #endif // record hal_lib comp_id lib_module_id = comp_id; diff --git a/src/hal/lib/hal_group.c b/src/hal/lib/hal_group.c index 0719632b79..9bd1be7787 100644 --- a/src/hal/lib/hal_group.c +++ b/src/hal/lib/hal_group.c @@ -412,4 +412,3 @@ void free_group_struct(hal_group_t * group) halg_foreach(0, &args, yield_free); halg_free_object(false, (hal_object_ptr)group); } - diff --git a/src/hal/lib/hal_internal.h b/src/hal/lib/hal_internal.h index 58a1b1ff87..82a6c050b0 100644 --- a/src/hal/lib/hal_internal.h +++ b/src/hal/lib/hal_internal.h @@ -55,9 +55,6 @@ int free_ring_struct(hal_ring_t *hrptr); void free_group_struct(hal_group_t * group); int pin_by_signal_callback(hal_object_ptr o, foreach_args_t *args); -void hal_proc_clean(void); -int hal_proc_init(void); - void free_thread_struct(hal_thread_t * thread); extern int lib_module_id; extern int lib_mem_id; diff --git a/src/hal/lib/hal_lib.c b/src/hal/lib/hal_lib.c index 58c0c914dc..6363a4c3c4 100644 --- a/src/hal/lib/hal_lib.c +++ b/src/hal/lib/hal_lib.c @@ -65,6 +65,7 @@ #include "hal_iring.h" #include "rtapi_string.h" +#include "rtapi_flavor.h" // flavor_descriptor #ifdef RTAPI #include "rtapi_app.h" /* module information */ @@ -114,17 +115,11 @@ int lib_mem_id = -1; /* RTAPI shmem ID for library module */ // to run before any HAL/RTAPI activity starts, and until after it ends. // RTAPI cannot execute without the global segment existing and attached. -// depending on ULAP/ vs RTAPI and thread system (userland vs kthreads) -// the way how -// pointer to the global data segment, initialized by calling the -// the ulapi.so ulapi_main() method (ULAPI) or by external reference -// to the instance module (kernel modes) +// The pointer to the global data segment is initialized by calling +// rtapi_module_init() -// defined(BUILD_SYS_KBUILD) && defined(RTAPI) -// defined & attached in, and exported from rtapi_module.c - -// defined(BUILD_SYS_USER_DSO) && defined(RTAPI) +// defined(RTAPI) // defined & attached in, and exported from rtapi_main.c /*********************************************************************** @@ -144,7 +139,6 @@ int lib_mem_id = -1; /* RTAPI shmem ID for library module */ grabbed the hal_data mutex. */ - /*********************************************************************** * PUBLIC (API) FUNCTION CODE * ************************************************************************/ @@ -185,11 +179,9 @@ unsigned char hal_get_lock() int rtapi_app_main(void) { - rtapi_switch = rtapi_get_handle(); - // sanity: these must have been inited before by the // respective rtapi.so/.ko module - CHECK_NULL(rtapi_switch); + HAL_ASSERT(flavor_is_configured()); CHECK_NULL(global_data); HALDBG("initializing RT hal_lib support"); @@ -203,7 +195,6 @@ int rtapi_app_main(void) void rtapi_app_exit(void) { HALDBG("removing RT hal_lib support"); - hal_proc_clean(); halg_exit_thread(1, NULL); // this halg_exit() will unload hal_lib and detach the HAL shm segment // to avoid the chicken-and-egg problem of locking hal_data, and @@ -235,9 +226,6 @@ static void __attribute__ ((destructor)) ulapi_hal_lib_cleanup(void) HALDBG("lib_module_id=%d", lib_module_id); if (lib_module_id > -1) hal_exit(lib_module_id); - - // shut down ULAPI - ulapi_cleanup(); } #endif @@ -448,13 +436,13 @@ EXPORT_SYMBOL(hal_shmem_base); // ------------ private API: ------------ // found in their respective source files: -EXPORT_SYMBOL(halpr_find_comp_by_name); -EXPORT_SYMBOL(halpr_find_pin_by_name); -EXPORT_SYMBOL(halpr_find_sig_by_name); -EXPORT_SYMBOL(halpr_find_param_by_name); -EXPORT_SYMBOL(halpr_find_thread_by_name); -EXPORT_SYMBOL(halpr_find_funct_by_name); -EXPORT_SYMBOL(halpr_find_inst_by_name); +EXPORT_SYMBOL(halpr_find_comp_by_name); +EXPORT_SYMBOL(halpr_find_pin_by_name); +EXPORT_SYMBOL(halpr_find_sig_by_name); +EXPORT_SYMBOL(halpr_find_param_by_name); +EXPORT_SYMBOL(halpr_find_thread_by_name); +EXPORT_SYMBOL(halpr_find_funct_by_name); +EXPORT_SYMBOL(halpr_find_inst_by_name); EXPORT_SYMBOL(hal_data); // hal_comp.c: diff --git a/src/hal/lib/hal_logging.h b/src/hal/lib/hal_logging.h index cc2de6cc5b..16413c0fbb 100644 --- a/src/hal/lib/hal_logging.h +++ b/src/hal/lib/hal_logging.h @@ -2,6 +2,7 @@ #define HAL_LOGGING_H #include +#include RTAPI_BEGIN_DECLS void hal_print_loc(const int level, diff --git a/src/hal/lib/hal_parport.h b/src/hal/lib/hal_parport.h index 9791ddf3de..8288e54ce3 100644 --- a/src/hal/lib/hal_parport.h +++ b/src/hal/lib/hal_parport.h @@ -30,8 +30,6 @@ typedef struct hal_parport_t } hal_parport_t; -#if defined(BUILD_SYS_USER_DSO) - #include #include #include @@ -224,177 +222,4 @@ static inline void hal_parport_set_datadir(hal_parport_t *port, int enable_input -#else /***** REALTIME HYPERVISOR *****/ - -static int -hal_parport_get(int comp_id, hal_parport_t *port, - unsigned short base, unsigned short base_hi, unsigned int modes) -{ - int retval = 0; - struct parport *linux_port = 0; - memset(port, 0, sizeof(hal_parport_t)); - - // I/O addresses 1..16 are assumed to be linux parport numbers - if(base < 16) { - linux_port = parport_find_number(base); - if(!linux_port) - { - rtapi_print_msg(RTAPI_MSG_ERR, - "PARPORT: ERROR: linux parport %d not found\n", - base); - return -ENODEV; - } - } else { - linux_port = parport_find_base(base); - } - - if(linux_port) - { - if((modes & linux_port->modes) != modes) - { - rtapi_print_msg(RTAPI_MSG_WARN, - "PARPORT: linux parport %s does not support mode %x.\n" - "PARPORT: continuing anyway.\n", - linux_port->name, modes); - } - rtapi_print_msg(RTAPI_MSG_INFO, - "PARPORT: Using Linux parport %s at ioaddr=0x%lx:0x%lx\n", - linux_port->name, linux_port->base, linux_port->base_hi); - port->linux_dev = parport_register_device(linux_port, - hal_comp_name(comp_id), NULL, NULL, NULL, 0, NULL); - - if(!port->linux_dev) - { - parport_put_port(linux_port); - rtapi_print_msg(RTAPI_MSG_ERR, - "PARPORT: ERROR: port %s register failed\n", linux_port->name); - return -EIO; - } - - retval = parport_claim(port->linux_dev); - if(retval < 0) - { - parport_put_port(linux_port); - parport_unregister_device(port->linux_dev); - rtapi_print_msg(RTAPI_MSG_ERR, - "PARPORT: ERROR: port %s claim failed\n", linux_port->name); - return retval; - } - - port->base = linux_port->base; - if(linux_port->base_hi > 0) { - port->base_hi = linux_port->base_hi; - } else if(base_hi != (unsigned short)-1) { - if(base_hi == 0) base_hi = port->base + 0x400; - rtapi_print_msg(RTAPI_MSG_DBG, - "PARPORT: DEBUG: linux reports no ioaddr_hi, using 0x%x", - base_hi); - port->region_hi = - rtapi_request_region(base_hi, 3, hal_comp_name(comp_id)); - if(port->region_hi) { - rtapi_print_msg(RTAPI_MSG_DBG, - "PARPORT: DEBUG: got requested region starting at 0x%x", - base_hi); - port->base_hi = base_hi; - } else { - rtapi_print_msg(RTAPI_MSG_DBG, - "PARPORT: DEBUG: did not get requested region starting at 0x%x", - base_hi); - } - } - parport_put_port(linux_port); - } else { - if(base_hi == 0) base_hi = base + 0x400; - - port->base = base; - rtapi_print_msg(RTAPI_MSG_INFO, - "Using direct parport at ioaddr=0x%x:0x%x\n", base, base_hi); - - // SPP access needs only 3 bytes, but EPP needs 8. Allocating 8 - // is likely to always be OK, and it simplifies things (since the - // exact allocation size is also needed at deallocation). - port->region = rtapi_request_region(base, 8, hal_comp_name(comp_id)); - if(!port->region) - { - rtapi_print_msg(RTAPI_MSG_ERR, - "PARPORT: ERROR: request_region(0x%x) failed\n", base); - return -EBUSY; - } - - if(base_hi != (unsigned short)-1) - { - port->base_hi = base_hi; - port->region_hi = - rtapi_request_region(base_hi, 3, hal_comp_name(comp_id)); - if(!port->region_hi) - { - rtapi_print_msg(RTAPI_MSG_ERR, - "PARPORT: ERROR: request_region(0x%x) failed\n", base_hi); - rtapi_release_region(port->base, 8); - return -EBUSY; - } - } - } - return 0; -} - -void hal_parport_release(hal_parport_t *port) -{ - if(port->linux_dev) - { - rtapi_print_msg(RTAPI_MSG_INFO, - "PARPORT: Releasing Linux parport at ioaddr=0x%lx:0x%lx\n", - port->linux_dev->port->base, port->linux_dev->port->base_hi); - parport_release(port->linux_dev); - parport_unregister_device(port->linux_dev); - } - if(port->region) { - rtapi_print_msg(RTAPI_MSG_INFO, - "PARPORT: Releasing I/O region ioaddr=0x%x\n", port->base); - rtapi_release_region(port->base, 8); - } - if(port->region_hi) { - rtapi_print_msg(RTAPI_MSG_INFO, - "PARPORT: Releasing high I/O region ioaddr=0x%x\n", - port->base_hi); - rtapi_release_region(port->base_hi, 3); - } - memset(port, 0, sizeof(hal_parport_t)); -} - -static inline unsigned char hal_parport_read_status(hal_parport_t *port) -{ - return rtapi_inb(port->base + 1); -} - -static inline unsigned char hal_parport_read_data(hal_parport_t *port) -{ - return rtapi_inb(port->base + 0); -} - -static inline void hal_parport_write_data(hal_parport_t *port, unsigned char x) -{ - rtapi_outb(x, port->base + 0); -} - -static inline unsigned char hal_parport_read_control(hal_parport_t *port) -{ - return rtapi_inb(port->base + 2); -} - -static inline void hal_parport_write_control(hal_parport_t *port, unsigned char x) -{ - rtapi_outb(x, port->base + 2); -} - -static inline void hal_parport_set_datadir(hal_parport_t *port, int enable_inputs) -{ - if (enable_inputs) - hal_parport_write_control(port, hal_parport_read_control(port) | 0x20); - else - hal_parport_write_control(port, hal_parport_read_control(port) & ~0x20); -} - -#endif /* BUILD_SYS_USER_DSO */ - #endif diff --git a/src/hal/lib/hal_priv.h b/src/hal/lib/hal_priv.h index 05d228fa1c..f6c902d0a8 100644 --- a/src/hal/lib/hal_priv.h +++ b/src/hal/lib/hal_priv.h @@ -100,17 +100,7 @@ #include #endif - -#if defined(BUILD_SYS_USER_DSO) -#include -#else // kernel thread styles -#if defined(RTAPI) -#include -#else // ULAPI #include -#include /* remote comp timestamps */ -#endif -#endif RTAPI_BEGIN_DECLS diff --git a/src/hal/lib/hal_procfs.c b/src/hal/lib/hal_procfs.c deleted file mode 100644 index 7aadaf67c6..0000000000 --- a/src/hal/lib/hal_procfs.c +++ /dev/null @@ -1,158 +0,0 @@ -// HAL procfs API - kernel threads only - -#include "config.h" -#include "rtapi.h" /* RTAPI realtime OS API */ -#include "hal.h" /* HAL public API decls */ -#include "hal_priv.h" /* HAL private decls */ - -// maximum argc passed to hal_call_userfunct() -#define MAX_ARGV 50 - -#if defined(BUILD_SYS_USER_DSO) -#undef CONFIG_PROC_FS -#endif - -#ifdef CONFIG_PROC_FS -#include -#include -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -#else -// proc_dir_entry is private in Linux 3.10+, so re-define it here -struct proc_dir_entry { - unsigned int low_ino; - umode_t mode; - nlink_t nlink; - kuid_t uid; - kgid_t gid; - loff_t size; - const struct inode_operations *proc_iops; - const struct file_operations *proc_fops; - struct proc_dir_entry *next, *parent, *subdir; - void *data; - atomic_t count; /* use count */ - atomic_t in_use; /* number of callers into module in progress; */ - /* negative -> it's going away RSN */ - struct completion *pde_unload_completion; - struct list_head pde_openers; /* who did ->open, but not ->release */ - spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ - u8 namelen; - char name[]; -}; -#endif - -extern struct proc_dir_entry *rtapi_dir; -static struct proc_dir_entry *hal_dir = 0; -static struct proc_dir_entry *hal_rtapicmd = 0; - -// simple interface to hal_create_thread()/hal_thread_delete() -// through /proc/rtapi/hal/rtapicmd (kernel threadstyles only) -// -// to start a thread, write 'newthread' ' -// example: -// echo newthread servo-thread 1000000 1 -1 >/proc/rtapi/hal/rtapicmd -// -// to delete a thread, write 'delthread ' -// echo delthread servo-thread >/proc/rtapi/hal/rtapicmd -// -// HAL return values are reflected in the return value to write() -// -// NB: this should be move to an iocontrol, procfs doesnt cut it -static ssize_t proc_write_rtapicmd(struct file *file, - const char __user *buffer, size_t count, loff_t *data) -{ - char cmd[20], name[HAL_NAME_LEN + 1]; - unsigned long period; - int fp, cpu, retval; - - if (!strncmp(buffer,"newthread", 9)) { - if ((retval = sscanf(buffer, "%s %s %lu %d %d", - cmd, name, &period, &fp, &cpu)) != 5) { - HALFAIL_RC(EINVAL, - "newthread: expecting 5 items" - " (s:cmd s:name d:period d:fp d:cpu), got %d", - retval); - } - if ((period > 0) && - (strlen(name) > 0)) { - retval = hal_create_thread(name, period, fp, cpu); - if (retval < 0) { - HALFAIL_RC(EINVAL, "newthread: could not create thread '%s' - error %d", - name, retval); - return retval; - } else { - HALINFO("newthread: created %ld uS thread '%s' fp=%d cpu=%d", - period / 1000, name, fp, cpu); - } - } - } else if (!strncmp(buffer, "delthread", 9)) { - if ((retval = sscanf(buffer, "%s %s", cmd, name)) != 2) { - HALFAIL_RC(EINVAL, - "delthread: expecting 2 items: 'delthread '"); - } - if ((retval = hal_thread_delete(name))) { - HALFAIL_RC(EINVAL, "delthread '%s' error %d", name, retval); - } - HALINFO("delthread - thread '%s' deleted", name); - } else { - // rtapi_argvize modifies its third argument in-place - char rwbuf[1024]; - strncpy(rwbuf, buffer, sizeof(rwbuf)); - - char *argv[MAX_ARGV]; - int argc = rtapi_argvize(MAX_ARGV, argv, rwbuf); - if (argc > 1) { - if (!strncmp(argv[0],"call", 4)) { - int uret = 0, retval; - retval = hal_call_usrfunct(argv[1], - argc-2, - (const char**)&argv[2], - &uret); - if (retval) - return retval; // library return code - // retvall == 0: uret signifies userfunct return value - return uret; - } - } - HALFAIL_RC(EINVAL, "unrecognized rtapicmd: '%s'", cmd); - } - return count; -} - -void hal_proc_clean(void) { - if(hal_rtapicmd) - remove_proc_entry("rtapicmd", hal_dir); - if(hal_dir) - remove_proc_entry("hal", rtapi_dir); - hal_dir = hal_rtapicmd = 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static const struct file_operations proc_file_fops = { - .write = proc_write_rtapicmd, -}; -#endif - -int hal_proc_init(void) { - if(!rtapi_dir) return 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - hal_dir = create_proc_entry("hal", S_IFDIR, rtapi_dir); - if(!hal_dir) { hal_proc_clean(); return -1; } - hal_rtapicmd = create_proc_entry("rtapicmd", 0666, hal_dir); - if(!hal_rtapicmd) { hal_proc_clean(); return -1; } - hal_rtapicmd->data = NULL; - hal_rtapicmd->read_proc = NULL; - hal_rtapicmd->write_proc = proc_write_rtapicmd; -#else - hal_dir = proc_create("hal", S_IFDIR, rtapi_dir, NULL); - if(!hal_dir) { hal_proc_clean(); return -1; } - hal_rtapicmd = proc_create("rtapicmd", 0666, hal_dir, &proc_file_fops); - if(!hal_rtapicmd) { hal_proc_clean(); return -1; } -#endif - return 0; -} -#else -void hal_proc_clean(void) {} -int hal_proc_init(void) { return 0; } -#endif diff --git a/src/hal/lib/halmodule.cc b/src/hal/lib/halmodule.cc index 93ede2df5d..735c03546f 100644 --- a/src/hal/lib/halmodule.cc +++ b/src/hal/lib/halmodule.cc @@ -25,6 +25,7 @@ using namespace std; #include "rtapi.h" #include "hal.h" #include "hal_priv.h" +#include "rtapi_compat.h" #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) typedef int Py_ssize_t; @@ -1166,18 +1167,6 @@ void init_hal(void) { PyModule_AddIntConstant(m, "HAL_OUT", HAL_OUT); PyModule_AddIntConstant(m, "HAL_IO", HAL_IO); -#if defined(RTAPI_POSIX) - PyModule_AddIntConstant(m, "is_sim", 1); - PyModule_AddIntConstant(m, "is_rt", 0); -#else - PyModule_AddIntConstant(m, "is_sim", 0); - PyModule_AddIntConstant(m, "is_rt", 1); -#endif - -#ifdef RTAPI_KERNEL_VERSION - PyModule_AddStringConstant(m, "kernel_version", RTAPI_KERNEL_VERSION); -#endif - PyRun_SimpleString( "(lambda s=__import__('signal'):" "s.signal(s.SIGTERM, s.default_int_handler))()"); diff --git a/src/hal/simdrivers/Submakefile b/src/hal/simdrivers/Submakefile index ea26311fc6..8e80c01066 100644 --- a/src/hal/simdrivers/Submakefile +++ b/src/hal/simdrivers/Submakefile @@ -1,21 +1,9 @@ -ifeq ($(BUILD_SYS),sim) -UPARPORT_SRCS := $(addprefix hal/simdrivers/, \ - uparport.c) - -UPARPORT_LIBS := -UPARPORT_FLAGS := -DSIM -DSIMULATOR -DRTAPI -UULAPI -D__MODULE__ -Drealtime - -USERSRCS += $(UPARPORT_SRCS) -TARGETS += ../rtlib/hal_parport.so -endif - $(call TOOBJSDEPS, $(UPARPORT_SRCS)) : EXTRAFLAGS=-fPIC $(UPARPORT_FLAGS) ../rtlib/hal_parport.so: $(call TOOBJS, $(UPARPORT_SRCS)) $(UPARPORT_LIBS) $(ECHO) Linking $(notdir $@) - mkdir -p ../rtlib + mkdir -p ../rtlib/modules @rm -f $@ $(CC) -g $(LDFLAGS) -Wl,-soname,$(notdir $@) \ -shared -o $@ $^ $(UPARPORT_LIBS) - diff --git a/src/hal/support/Submakefile b/src/hal/support/Submakefile index 37be468bf0..5c7590db27 100644 --- a/src/hal/support/Submakefile +++ b/src/hal/support/Submakefile @@ -81,5 +81,8 @@ USERSRCS += $(PRUSSDRV_SRCS) # $(ECHO) Assembling PRU code $@ # $(Q)$(PASM) $(PASM_BINFLAGS) $^ $(basename $@) +# C components +$(eval $(call c_comp_build_rules,hal/components/hal_pru.o, $(LIBPTHREAD))) +$(eval $(call c_comp_build_rules,hal/components/hal_prudebug.o, $(LIBPTHREAD))) endif diff --git a/src/hal/user_comps/Submakefile b/src/hal/user_comps/Submakefile index c04574cbd6..c007d896c3 100644 --- a/src/hal/user_comps/Submakefile +++ b/src/hal/user_comps/Submakefile @@ -20,7 +20,12 @@ PYTARGETS += $(patsubst %, ../bin/%, $(USER_COMP_PY)) # USER_COMP_COMPS is defined in hal/components/Submakefile USER_COMP_BINS := $(patsubst hal/user_comps/%.comp, ../bin/%, $(USER_COMP_COMPS)) -../bin/%: hal/user_comps/%.comp ../bin/comp ../lib/liblinuxcnchal.so.0 ../lib/librtapi_math.so.0 +../bin/%: \ + hal/user_comps/%.comp \ + ../bin/comp \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ + ../lib/librtapi_math.so.0 $(ECHO) "Preprocessing usercomp $(notdir $<)" @mkdir -p objects/hal/user_comps $(Q)../bin/comp -o $(patsubst hal/user_comps/%.comp, objects/hal/user_comps/%.c, $<) $< @@ -28,6 +33,7 @@ USER_COMP_BINS := $(patsubst hal/user_comps/%.comp, ../bin/%, $(USER_COMP_COMPS) $(Q)$(CC) -DULAPI $(INCLUDE) -o $@ $(LDFLAGS) \ $(patsubst hal/user_comps/%.comp, objects/hal/user_comps/%.c, $<) \ ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ ../lib/librtapi_math.so.0 TARGETS += $(USER_COMP_BINS) @@ -40,7 +46,10 @@ USERSRCS += $(MODBUSSRCS) $(call TOOBJSDEPS, $(MODBUSSRCS)) : EXTRAFLAGS += $(MODBUSCCFLAGS) -../bin/gs2_vfd: $(call TOOBJS, $(MODBUSSRCS)) ../lib/liblinuxcnchal.so.0 +../bin/gs2_vfd: \ + $(call TOOBJS, $(MODBUSSRCS)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) -o $@ $^ $(LDFLAGS) $(MODBUSLDFLAGS) TARGETS += ../bin/gs2_vfd @@ -49,7 +58,10 @@ endif # HAVE_LIBMODBUS ifeq ($(HIDRAW_H_USABLE),yes) SHUTTLEXPRESS_SRC = hal/user_comps/shuttlexpress.c USERSRCS += $(SHUTTLEXPRESS_SRC) -../bin/shuttlexpress: $(call TOOBJS, $(SHUTTLEXPRESS_SRC)) ../lib/liblinuxcnchal.so.0 +../bin/shuttlexpress: \ + $(call TOOBJS, $(SHUTTLEXPRESS_SRC)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ TARGETS += ../bin/shuttlexpress @@ -60,7 +72,12 @@ ifdef HAVE_LIBUSB10 XHC_HB04_SRC = hal/user_comps/xhc-hb04.cc USERSRCS += $(XHC_HB04_SRC) $(call TOOBJSDEPS, $(XHC_HB04_SRC)) : EXTRAFLAGS += $(LIBUSB10_CFLAGS) -../bin/xhc-hb04: $(call TOOBJS, $(XHC_HB04_SRC)) ../lib/liblinuxcnchal.so.0 ../lib/liblinuxcncini.so.0 ../lib/librtapi_math.so.0 +../bin/xhc-hb04: \ + $(call TOOBJS, $(XHC_HB04_SRC)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ + ../lib/liblinuxcncini.so.0 \ + ../lib/librtapi_math.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ -lstdc++ $(LIBUSB10_LIBS) TARGETS += ../bin/xhc-hb04 diff --git a/src/hal/user_icomps/Submakefile b/src/hal/user_icomps/Submakefile index d07801fb20..b9900830a0 100644 --- a/src/hal/user_icomps/Submakefile +++ b/src/hal/user_icomps/Submakefile @@ -5,8 +5,4 @@ HALUSERICOMPDIR= hal/user_icomps HALUSERICOMP_SUBMAKEFILE= $(HALUSERICOMPDIR)/Submakefile -obj-m += watch.o -# the list of parts -watch-objs := $(HALUSERICOMPDIR)/watch.o - -$(RTLIBDIR)/watch$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(watch-objs)) \ No newline at end of file +$(eval $(call c_comp_build_rules,$(HALUSERICOMPDIR)/watch.o)) diff --git a/src/hal/userfunct-example/Submakefile b/src/hal/userfunct-example/Submakefile index 572e8b8b88..718d7d3592 100644 --- a/src/hal/userfunct-example/Submakefile +++ b/src/hal/userfunct-example/Submakefile @@ -1,15 +1,3 @@ USERFUNCTEXAMPLE_DIR := hal/userfunct-example -INCLUDES += $(USERFUNCTEXAMPLE_DIR) -../include/%.h: ./$(USERFUNCTEXAMPLE_DIR)/%.h - cp $^ $@ - -# obj-m += ufdemo.o -# vtexport-objs := \ -# $(USERFUNCTEXAMPLE_DIR)/ufdemo.o - - -# ifneq "$(filter normal user-dso,$(BUILD_SYS))" "" -# $(RTLIBDIR)/ufdemo$(MODULE_EXT): \ -# $(addprefix $(OBJDIR)/,$(ufdemo-objs)) -# endif +$(eval $(call c_comp_build_rules,$(USERFUNCTEXAMPLE_DIR)/ufdemo.o)) diff --git a/src/hal/utils/Submakefile b/src/hal/utils/Submakefile index f1e68bfda0..6aaa464977 100644 --- a/src/hal/utils/Submakefile +++ b/src/hal/utils/Submakefile @@ -12,6 +12,7 @@ $(call TOOBJSDEPS, hal/utils/halsh.c) : EXTRAFLAGS += $(TCL_CFLAGS) ../tcl/hal.so: $(call TOOBJS, $(HALSHSRCS)) \ ../lib/liblinuxcncini.so.0 \ ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ ../lib/libmachinetalk-pb2++.so.0 \ ../lib/libmtalk.so.0 \ ../lib/librtapi_math.so.0 @@ -25,6 +26,7 @@ $(call TOOBJSDEPS, $(HALCMDCCSRCS)) : EXTRAFLAGS = \ ../bin/halcmd: $(call TOOBJS, $(HALCMDSRCS)) $(call TOOBJS, $(HALCMDCCSRCS)) \ ../lib/liblinuxcncini.so.0 \ ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ ../lib/libmachinetalk-pb2++.so.0 \ ../lib/libmtalk.so.0 \ ../lib/librtapi_math.so.0 @@ -51,7 +53,10 @@ HALMETERSRCS := \ USERSRCS += $(HALMETERSRCS) -../bin/halmeter: $(call TOOBJS, $(HALMETERSRCS)) ../lib/liblinuxcnchal.so.0 +../bin/halmeter: \ + $(call TOOBJS, $(HALMETERSRCS)) \ + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(GTK_LIBS) TARGETS += ../bin/halmeter @@ -68,8 +73,9 @@ HALSCOPESRCS := \ USERSRCS += $(HALSCOPESRCS) ../bin/halscope: $(call TOOBJS, $(HALSCOPESRCS)) \ - ../lib/liblinuxcnchal.so.0 \ - ../lib/librtapi_math.so.0 + ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ + ../lib/librtapi_math.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(GTK_LIBS) TARGETS += ../bin/halscope @@ -87,7 +93,8 @@ $(call TOOBJSDEPS, $(HALGTKSRCS)) : EXTRAFLAGS = $(GTK_CFLAGS) $(call TOOBJS, $(HALGTKSRCS)): Makefile.inc endif -ifeq ($(USERMODE_PCI),yes) +ifeq ($(BUILD_DRIVERS),yes) +ifeq ($(HAS_SYS_IO),yes) # normal #PCI_DEBUG_FLAGS = # debug build for now @@ -111,6 +118,7 @@ USERSRCS += $(PCIREADSRCS) $(Q)$(CC) $(LDFLAGS) -o $@ $^ TARGETS += ../libexec/pci_read +endif endif ../bin/comp ../bin/instcomp: ../bin/%: objects/hal/utils/%.py @@ -124,3 +132,6 @@ objects/%.py: %.g @mkdir -p $(dir $@) $(ECHO) Parsing python $< $(Q)$(YAPPS2) $< $@ + +# C language components +$(eval $(call c_comp_build_rules,hal/utils/scope_rt.o)) diff --git a/src/hal/utils/comp.g b/src/hal/utils/comp.g index 8cad9ae538..62153c0359 100644 --- a/src/hal/utils/comp.g +++ b/src/hal/utils/comp.g @@ -654,7 +654,7 @@ def build_usr(tempdir, filename, mode, origfilename): makefile = os.path.join(tempdir, "Makefile") f = open(makefile, "w") f.write("%s: %s\n" % (binname, filename)) - f.write("\t$(CC) $(EXTRA_CFLAGS) -URTAPI -U__MODULE__ -DULAPI -Os %s -o $@ $< -Wl,-rpath,$(LIBDIR) -L$(LIBDIR) -llinuxcnchal %s\n" % ( + f.write("\t$(CC) $(EXTRA_CFLAGS) -URTAPI -U__MODULE__ -DULAPI -Os %s -o $@ $< -Wl,-rpath,$(LIBDIR) -L$(LIBDIR) -llinuxcnchal -llinuxcnculapi %s\n" % ( options.get("extra_compile_args", ""), options.get("extra_link_args", ""))) f.write("include %s\n" % find_modinc()) @@ -678,6 +678,7 @@ def build_rt(tempdir, filename, mode, origfilename): f.write("include %s\n" % find_modinc()) f.write("EXTRA_CFLAGS += -I%s\n" % os.path.abspath(os.path.dirname(origfilename))) f.write("EXTRA_CFLAGS += -I%s\n" % os.path.abspath('.')) + f.write("EXTRA_CFLAGS += -DRTAPI -L$(LIBDIR) -llinuxcnchal") f.close() if mode == INSTALL: target = "modules install" diff --git a/src/hal/utils/hal_comp.c b/src/hal/utils/hal_comp.c index 4f95c4ae62..912c635936 100644 --- a/src/hal/utils/hal_comp.c +++ b/src/hal/utils/hal_comp.c @@ -71,7 +71,7 @@ hal_comp_t *halg_xinitfv(const int use_hal_mutex, // sanity: these must have been inited before by the // respective rtapi.so/.ko module - PCHECK_NULL(rtapi_switch); + HAL_ASSERT(flavor_is_configured()); if ((dtor != NULL) && (ctor == NULL)) { HALFAIL_NULL(EINVAL,"component '%s': NULL constructor doesnt make" @@ -153,12 +153,6 @@ hal_comp_t *halg_xinitfv(const int use_hal_mutex, HALFAIL_NULL(retval, "could not init HAL shared memory rc=%d", retval); } - retval = hal_proc_init(); - if (retval) { - rtapi_exit(lib_module_id); - lib_module_id = -1; - HALFAIL_NULL(retval, "could not init /proc files"); - } #endif // record hal_lib comp_id lib_module_id = comp_id; diff --git a/src/hal/utils/halcmd.c b/src/hal/utils/halcmd.c index 6bf9d82172..d1f342eb66 100644 --- a/src/hal/utils/halcmd.c +++ b/src/hal/utils/halcmd.c @@ -91,7 +91,6 @@ int scriptmode = 0; /* used to make output "script friendly" (suppress headers) int prompt_mode = 0; /* when getting input from stdin, print a prompt */ int echo_mode = 0; char comp_name[HAL_NAME_LEN+1]; /* name for this instance of halcmd */ -flavor_ptr current_flavor; int autoload = 1; // on newinst, if comp not loaded, loadrt it static void quit(int); @@ -166,7 +165,6 @@ int halcmd_startup(int quiet, char *uri, const char *svc_uuid) { return -EINVAL; } hal_ready(comp_id); - current_flavor = flavor_byid(global_data->rtapi_thread_flavor); return 0; } diff --git a/src/hal/utils/halcmd.h b/src/hal/utils/halcmd.h index c9fc1f05bf..9decca205d 100644 --- a/src/hal/utils/halcmd.h +++ b/src/hal/utils/halcmd.h @@ -95,6 +95,4 @@ extern FILE *halcmd_inifile; #define MAX_CMD_LEN 1024 #define MAX_EXPECTED_SIGS 999 -extern flavor_ptr current_flavor; // reference to current flavor descriptor - #endif diff --git a/src/hal/utils/halcmd_commands.c b/src/hal/utils/halcmd_commands.c index 60b767c337..9fe623cb97 100644 --- a/src/hal/utils/halcmd_commands.c +++ b/src/hal/utils/halcmd_commands.c @@ -50,6 +50,7 @@ #include "halcmd_commands.h" #include "halcmd_rtapiapp.h" #include "rtapi_hexdump.h" +#include "rtapi_flavor.h" // flavor_descriptor #include <../include/machinetalk/protobuf/types.npb.h> @@ -2473,69 +2474,10 @@ static int print_heap(char **patterns) static void print_thread_stats(hal_thread_t *tptr) { - int flavor = global_data->rtapi_thread_flavor; - rtapi_threadstatus_t *ts = - &global_data->thread_status[tptr->task_id]; - halcmd_output("\nLowlevel thread statistics for '%s':\n\n", ho_name(tptr)); - // generic statistics counters - halcmd_output(" updates=%d\t", ts->num_updates); - if (ts->num_updates) { - halcmd_output("api_err=%d\t", ts->api_errors); - halcmd_output("other_err=%d\n", ts->api_errors); - } - - // flavor-specific statistics counters - switch (flavor) { - case RTAPI_XENOMAI_ID: // xenomai-user - case RTAPI_XENOMAI_KERNEL_ID: - - halcmd_output(" wait_errors=%d\t", - ts->flavor.xeno.wait_errors); - halcmd_output("overruns=%d\t", - ts->flavor.xeno.total_overruns); - halcmd_output("modeswitches=%d\t", - ts->flavor.xeno.modeswitches); - halcmd_output("contextswitches=%d\n", - ts->flavor.xeno.ctxswitches); - halcmd_output(" pagefaults=%d\t", - ts->flavor.xeno.pagefaults); - halcmd_output("exectime=%llduS\t", - ts->flavor.xeno.exectime/1000); - halcmd_output("status=0x%x\n", - ts->flavor.xeno.status); - break; - - case RTAPI_POSIX_ID: - case RTAPI_RT_PREEMPT_ID: - halcmd_output(" wait_errors=%d\t", - ts->flavor.rtpreempt.wait_errors); - halcmd_output("usercpu=%lduS\t", - ts->flavor.rtpreempt.utime_sec * 1000000 + - ts->flavor.rtpreempt.utime_usec); - halcmd_output("syscpu=%lduS\t", - ts->flavor.rtpreempt.stime_sec * 1000000 + - ts->flavor.rtpreempt.stime_usec); - halcmd_output("nsigs=%ld\n", - ts->flavor.rtpreempt.ru_nsignals); - halcmd_output(" ivcsw=%ld\t", - ts->flavor.rtpreempt.ru_nivcsw - - ts->flavor.rtpreempt.startup_ru_nivcsw); - halcmd_output(" minflt=%ld\t", - ts->flavor.rtpreempt.ru_minflt - - ts->flavor.rtpreempt.startup_ru_minflt); - halcmd_output(" majflt=%ld\n", - ts->flavor.rtpreempt.ru_majflt - - ts->flavor.rtpreempt.startup_ru_majflt); - break; - - default: - halcmd_error("halcmd: thread flavor %d stats not implemented\n", - flavor); - } - halcmd_output("\n"); + flavor_task_print_thread_stats_hook(NULL, tptr->task_id); } static int print_thread_entry(hal_object_ptr o, foreach_args_t *args) @@ -2588,7 +2530,7 @@ static int print_thread_entry(hal_object_ptr o, foreach_args_t *args) if (scriptmode != 0) { halcmd_output("\n"); } else { - // if a thread name was given, print the flavor specific stats + // if a thread name was given, print its stats if (named) print_thread_stats(tptr); } @@ -2600,7 +2542,7 @@ static void print_thread_info(char **patterns) { if (scriptmode == 0) { halcmd_output("Realtime Threads (flavor: %s, currently %s) :\n", - current_flavor->name, + flavor_name(NULL), (hal_data->threads_running > 0) ? "running" : "stopped"); halcmd_output(" Period FP CPU Name " "Time Max-Time util max jitter-95%% flags\n"); @@ -4414,7 +4356,7 @@ int do_newthread_cmd(char *name, char *args[]) continue; } if (sscanf(s, "cgname=%s", cgname) == 1) - continue; + continue; char *cp = s; per = strtol(s, &cp, 0); if ((*cp != '\0') && (!isspace(*cp))) { diff --git a/src/hal/utils/halcmd_completion.c b/src/hal/utils/halcmd_completion.c index 5640c6b8a8..a12364cdb6 100644 --- a/src/hal/utils/halcmd_completion.c +++ b/src/hal/utils/halcmd_completion.c @@ -560,8 +560,6 @@ static char *loadusr_generator(const char *text, int state) { return NULL; } -extern flavor_ptr current_flavor; // reference to current flavor descriptor - static char *loadrt_generator(const char *text, int state) { static int len; static DIR *d; @@ -571,8 +569,6 @@ static char *loadrt_generator(const char *text, int state) { if (get_rtapi_config(rtlibdir,"RTLIB_DIR",PATH_MAX) != 0) return NULL; - strcat(rtlibdir,"/"); - strcat(rtlibdir, current_flavor->name); strcat(rtlibdir,"/"); if(!state) { @@ -582,13 +578,11 @@ static char *loadrt_generator(const char *text, int state) { while(d && (ent = readdir(d))) { char *result; - if(!strstr(ent->d_name, default_flavor()->mod_ext)) continue; - if(startswith(ent->d_name, "rtapi.")) continue; + if(!strstr(ent->d_name, ".so")) continue; if(startswith(ent->d_name, "hal_lib.")) continue; if(strncmp(text, ent->d_name, len) != 0) continue; result = strdup(ent->d_name); - result[strlen(result) - \ - strlen(default_flavor()->mod_ext)] = 0; + result[strlen(result) - strlen(".so")] = 0; return result; } if (d != NULL) { diff --git a/src/hal/utils/halrmt.c b/src/hal/utils/halrmt.c deleted file mode 100644 index 418ba85ec9..0000000000 --- a/src/hal/utils/halrmt.c +++ /dev/null @@ -1,3579 +0,0 @@ -/******************************************************************** -* Description: halrmt.cc -* Simple telnet interface to EMC2 HAL commands (halcmd) -* -* Derived from work by jmkasunich -* -* Other contributers: -* Alex Joni -* -* Author: Eric H. Johnson -* License: GPL Version 2 -* System: Linux -* -* Copyright (c) 2006-2008 All rights reserved. -* -* Last change: -********************************************************************/ - -/******************************************************************* - Using halrmt: - - halrmt {-- --port --name --connectpw - --enablepw --sessions -ini} - - With -- --port Waits for socket connections (Telnet) on specified socket, without port - uses default port 5006. (note: linuxcncrsh uses 5007 as default) - With -- --name Sets the server name to specified name for Hello. - With -- --connectpw Sets the connection password to 'password'. Default EMC - With -- --enablepw Sets the enable password to 'password'. Default EMCTOO - With -- --sessions Sets the maximum number of simultaneous connextions - to max sessions. Default is no limit (-1). - With -- -ini , uses inifile instead of emc.ini. - - There are six commands supported, Where the commands set and get contain HAL - specific sub-commands based on the commands supported by halcmd. Commands and - most parameters are not case sensitive. The exceptions are passwords, - file paths and text strings. - - The supported commands are as follows: - - ==> HELLO <== - - Hello - If a valid password was entered the server will respond with - - HELLO ACK - - Where server name and server version are looked up from the implementation. - if an invalid password or any other syntax error occurs then the server - responds with: - - HELLO NAK - - ==> Get <== - - The get command includes one of the hal sub-commands, described below and - zero or more additional parameters. - - ==> Set <== - - The set command inclides one of the hal sub-commands, described below and - one or more additional parameters. - - ==> Quit <== - - The quit command disconnects the associated socket connection. - - ==> Shutdown <== - - The shutdown command tells EMC to shutdown before quitting the connection. This - command may only be issued if the Hello has been successfully negotiated and the - connection has control of the CNC (see enable sub-command below). This command - has no parameters. - - ==> Help <== - - The help command will return help information in text format over the telnet - connection. If no parameters are specified, it will itemize the available commands. - If a command is specified, it will provide usage information for the specified - command. Help will respond regardless of whether a "Hello" has been - successsfully negotiated. - - - HAL sub-commands: - - echo on | off - With get will return the current echo state, with set, sets the echo - state. When echo is on, all commands will be echoed upon receipt. This - state is local to each connection. - - verbose on | off - With get will return the current verbose state, with set, sets the - verbose state. When in verbose mode is on, all set commands return - positive acknowledgement in the form SET ACK. In addition, - text error messages will be issued when in verbose mode. This state - is local to each connection. - - enable | off - With get will return On or Off to indicate whether the current connection - is enabled to perform control functions. With set and a valid password, - the current connection is enabled for control functions. "OFF" may not - be used as a password and disables control functions for this connection. - - config [TBD] - - comm_mode ascii | binary - With get, will return the current communications mode. With set, will - set the communications mode to the specified mode. The binary protocol - is TBD. - - comm_prot - With get, returns the current protocol version used by the server, - with set, sets the server to use the specified protocol version, - provided it is lower than or equal to the highest version number - supported by the server implementation. - - Comps [] - - Get only, returns all components beginning with the specified substring. - If no substring is specified then it returns all components. - - Pins [] - - Get only, returns all information about all pins beginning with the - specified substring. If no substring is specified then it returns all pins. - - PinVals [] - - Get only, returns only value information about all pins beginning with the - specified substring. If no substring is specified then it returns all pins. - - Signals [] - - Get only, returns all information about all signals beginning with the - specified substring. If no substring is specified then it returns all signals. - - SigVals [] - - Get only, returns only value information about all signals beginning with the - specified substring. If no substring is specified then it returns all pins. - - Params [] - - Get only, returns all information about all parameters beginning with the - specified substring. If no substring is specified then it returns all - parameters. - - ParamVals [] - - Get only, returns only value information about all parameters beginning with the - specified substring. If no substring is specified then it returns all pins - parameters. - - Functs [] - - Get only, returns all information about all functions beginning with the - specified substring. If no substring is specified then it returns all - functions. - - Threads - - Get only, returns all information about all functions. - - Comp - - Get only, returns the component matching the specified name. - - Pin - - Get only, returns all information about the pin matching the specified - name. - - PinVal - - Get only, returns the value of the pin matching the specified name. - - Sig - - Get only, returns all information about the pin matching the specified - name. - - SigVal - - Get only, returns just the value of the signal matching the specified - name. - - Param - - Get only, returns all information about the parameter matching the - specified name. - - ParamVal - - Get only, returns just the value of the parameter matching the specified - name. - - Funct - - Get only, returns all information about the parameter matching the - specified name. - - Thread - - Get only, returns all information about the thread matching the - specified name. - - LoadRt - - Set only, loads the real time executable specified by name. - - Unload - - Set only, unloads the executable specified by name. - - LoadUsr - - Set only, loads the user executable specified by name. - - Linkps - - Set only, links the specified pin to the specified signal. - - Linksp - - Set only, links the specified signal to the specified pin. - - Linkpp - - Set only, links the pin specified by pin 1 with the pin specified by pin 2. - - Net - - Set only, nets the specified net list. - - Unlinkp - - Set only, unlinks the specified pins - - Lock - - Unlock - - NewSig - - Set only, creates the signal specified by name and of type specified by type. - - DelSig - - Set only, deletes the signal specified by name. - - SetP - - Set only, sets the parameter specified by name to the value specified by value. - - SetS - - Set only, sets the signal specified by name to the value specified by value. - - AddF [] - - Set only, adds the function specified by name, to the thread specified by - thread, with the optional parameters specified by parameters. - - DelF - - Set only, deletes the function specified by name. - - Save - - Start - - Stop - -****************************************************************************/ - -#include "config.h" - -#define _REENTRANT - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rtapi_math.h" -#include -#include -#include -#include -#include -#include -#include - -#include "rtapi.h" /* RTAPI realtime OS API */ -#include "hal.h" /* HAL public API decls */ -#include "hal_priv.h" /* private HAL decls */ -/* non-EMC related uses of halrmt may want to avoid libnml dependency */ -#ifndef NO_INI -#include "inifile.h" /* iniFind() from libnml */ -#endif - -/*********************************************************************** -* LOCAL FUNCTION DECLARATIONS * -************************************************************************/ - -/* These functions are used internally by this file. The code is at - the end of the file. */ - -#define MAX_TOK 20 -#define MAX_CMD_LEN 1024 -#define MAX_EXPECTED_SIGS 999 - -static int release_HAL_mutex(void); -static int do_help_cmd(char *command); -static int unloadrt_comp(char *mod_name); -static const char *data_type(int type); -static const char *pin_data_dir(int dir); -static const char *param_data_dir(int dir); -static const char *data_arrow1(int dir); -static const char *data_arrow2(int dir); -static char *data_value(int type, void *valptr); -static char *data_value2(int type, void *valptr); -static void save_comps(FILE *dst); -static void save_signals(FILE *dst); -static void save_links(FILE *dst, int arrows); -static void save_nets(FILE *dst, int arrows); -static void save_params(FILE *dst); -static void save_threads(FILE *dst); -static void print_help_general(int showR); - -/*********************************************************************** -* GLOBAL VARIABLES * -************************************************************************/ - -int comp_id = -1; /* -1 means hal_init() not called yet */ -int hal_flag = 0; /* used to indicate that halrmt might have the - hal mutex, so the sig handler can't just - exit, instead it must set 'done' */ -int done = 0; /* used to break out of processing loop */ -int linenumber=0; /* used to print linenumber on errors */ -int scriptmode = 0; /* used to make output "script friendly" (suppress headers) */ -int prompt_mode = 0; /* when getting input from stdin, print a prompt */ -char comp_name[HAL_NAME_LEN+1]; /* name for this instance of halrmt */ - -char pwd[16] = "EMC\0"; // Connect password -char enablePWD[16] = "EMCTOO\0"; // Enable password -char serverName[24] = "EMCNETSVR\0"; // Server name written in hello response -int sessions = 0; // Number of open sessions -int maxSessions = -1; // Maximum number of sessions to allow - -typedef struct { - int cliSock; - char hostName[80]; - char version[8]; - int linked; - int echo; - int verbose; - int enabled; - int commMode; - int commProt; - char inBuf[256]; - char outBuf[4096]; - char progName[256];} connectionRecType; - - -int port = 5006; -char errorStr[256]; - -int server_sockfd, client_sockfd; -socklen_t server_len, client_len; -struct sockaddr_in server_address; -struct sockaddr_in client_address; -int useSockets = 1; -int tokenIdx; -const char *delims = " \n\r\0"; -int connCount = -1; -int enabledConn = -1; - -typedef enum { - cmdHello, cmdSet, cmdGet, cmdQuit, cmdShutdown, cmdHelp, cmdUnknown} commandTokenType; - -typedef enum { - hcEcho, hcVerbose, hcEnable, hcConfig, hcCommMode, hcCommProt, - hcComps, hcPins, hcPinVals, hcSigs, hcSigVals, hcParams, hcParamVals, hcFuncts, hcThreads, - hcComp, hcPin, hcPinVal, hcSig, hcSigVal, hcParam, hcParamVal, hcFunct, hcThread, - hcLoadRt, hcUnload, hcLoadUsr, hcLinkps, hcLinksp, hcLinkpp, hcNet, hcUnlinkp, - hcLock, hcUnlock, hcNewSig, hcDelSig, hcSetP, hcSetS, hcAddF, hcDelF, - hcSave, hcStart, hcStop, hcUnknown - } halCommandType; - -typedef enum { - rtNoError, rtHandledNoError, rtStandardError, rtCustomError, rtCustomHandledError - } cmdResponseType; - -struct option longopts[] = { - {"port", 1, NULL, 'p'}, - {"name", 1, NULL, 'n'}, - {"sessions", 1, NULL, 's'}, - {"connectpw", 1, NULL, 'w'}, - {"enablepw", 1, NULL, 'e'}, - {0,0,0,0} -}; - -const char *commands[] = {"HELLO", "SET", "GET", "QUIT", "SHUTDOWN", "HELP", ""}; -const char *halCommands[] = { - "ECHO", "VERBOSE", "ENABLE", "CONFIG", "COMM_MODE", "COMM_PROT", - "COMPS", "PINS", "PINVALS", "SIGNALS", "SIGVALS", "PARAMS", "PARAMVALS", "FUNCTS", "THREADS", - "COMP", "PIN", "PINVAL", "SIGNAL", "SIGVAL", "PARAM", "PARAMVAL", "FUNCT", "THREAD", - "LOADRT", "UNLOAD", "LOADUSR", "LINKPS", "LINKSP", "LINKPP", "NET", "UNLINKP", - "LOCK", "UNLOCK", "NEWSIG", "DELSIG", "SETP", "SETS", "ADDF", "DELF", - "SAVE", "START", "STOP", ""}; - -#ifndef NO_INI - FILE *inifile = NULL; -#endif - - -/* signal handler */ -static void quit(int sig) -{ - if ( hal_flag ) { - /* this process might have the hal mutex, so just set the - 'done' flag and return, exit after mutex work finishes */ - done = 1; - } else { - /* don't have to worry about the mutex, but if we just - return, we might return into the fgets() and wait - all day instead of exiting. So we exit from here. */ - if ( comp_id > 0 ) { - hal_exit(comp_id); - } - _exit(1); - } -} - -static void strupr(char *s) -{ - int i; - - for (i = 0; i < (int)strlen(s); i++) - if (s[i] > 96 && s[i] <= 'z') - s[i] -= 32; -} - -static int initSockets() -{ - int optval = 1; - - server_sockfd = socket(AF_INET, SOCK_STREAM, 0); - setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(port); - server_len = sizeof(server_address); - bind(server_sockfd, (struct sockaddr *)&server_address, server_len); - listen(server_sockfd, 5); - signal(SIGCHLD, SIG_IGN); - return 0; -} - -static int sockWrite(connectionRecType *context) -{ - int ret; - strcat(context->outBuf, "\r\n"); - ret = write(context->cliSock, context->outBuf, strlen(context->outBuf)); - //FIXME return error based on ret, probably return (ret >= 0); - return 0; -} - -static void sockWriteError(const char *nakStr, connectionRecType *context) -{ - if (context->verbose == 1) - sprintf(context->outBuf, "%s %s", nakStr, errorStr); - else - sprintf(context->outBuf, "%s", nakStr); - sockWrite(context); -} - -pid_t hal_systemv_nowait(char *const argv[], connectionRecType *context) { - pid_t pid; - int n; - const char *nakStr = "SET LOADRT NAK"; - - /* now we need to fork, and then exec .... */ - /* disconnect from the HAL shmem area before forking */ - hal_exit(comp_id); - comp_id = 0; - /* now the fork() */ - pid = fork(); - if ( pid < 0 ) { - /* fork failed */ -// halcmd_error("fork() failed\n"); - /* reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - if (comp_id < 0) { - fprintf(stderr, "halcmd: hal_init() failed after fork: %d\n", - comp_id ); - exit(-1); - } - hal_ready(comp_id); - return -1; - } - if ( pid == 0 ) { - /* child process */ - /* print debugging info if "very verbose" (-V) */ - for(n=0; argv[n] != NULL; n++) { - rtapi_print_msg(RTAPI_MSG_DBG, "%s ", argv[n] ); - } - if (n == 0) { - snprintf(errorStr, sizeof(errorStr), "hal_systemv_nowait: empty argv array passed in\n"); - sockWriteError(nakStr, context); - exit(1); - } - rtapi_print_msg(RTAPI_MSG_DBG, "\n" ); - /* call execv() to invoke command */ - execvp(argv[0], argv); - /* should never get here */ -// halcmd_error("execv(%s) failed\n", argv[0] ); - sprintf(errorStr, "execv(%s) failed", argv[0]); - sockWriteError(nakStr, context); - exit(1); - } - /* parent process */ - /* reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - - return pid; -} - -int hal_systemv(char *const argv[], connectionRecType *context) { - pid_t pid; - int status; - int retval; - const char *nakStr = "SET LOADRT NAK"; - - /* do the fork */ - pid = hal_systemv_nowait(argv, context); - /* this is the parent process, wait for child to end */ - retval = waitpid ( pid, &status, 0 ); - retval = 0; - if (comp_id < 0) { - fprintf(stderr, "halcmd: hal_init() failed after systemv: %d\n", comp_id ); - exit(-1); - } - hal_ready(comp_id); - /* check result of waitpid() */ - if ( retval < 0 ) { -// halcmd_error("waitpid(%d) failed: %s\n", pid, strerror(errno) ); - sprintf(errorStr, "waitpid(%d) failed: %s", pid, strerror(errno)); - sockWriteError(nakStr, context); - return -1; - } - if ( WIFEXITED(status) == 0 ) { -// halcmd_error("child did not exit normally\n"); - sprintf(errorStr, "child did not exit normally"); - sockWriteError(nakStr, context); - return -1; - } - retval = WEXITSTATUS(status); - if ( retval != 0 ) { -// halcmd_error("exit value: %d\n", retval ); - sprintf(errorStr, "exit value: %d", retval); - sockWriteError(nakStr, context); - return -1; - } - return 0; -} - - -/*********************************************************************** -* LOCAL FUNCTION DEFINITIONS * -************************************************************************/ - -/* release_HAL_mutex() unconditionally releases the hal_mutex - very useful after a program segfaults while holding the mutex -*/ -static int release_HAL_mutex(void) -{ - int comp_id, mem_id, retval; - void *mem; - hal_data_t *hal_data; - - /* do RTAPI init */ - comp_id = rtapi_init("hal_unlocker"); - if (comp_id < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, "ERROR: rtapi init failed\n"); - return -EINVAL; - } - /* get HAL shared memory block from RTAPI */ - mem_id = rtapi_shmem_new(HAL_KEY, comp_id, global_data->hal_size); - if (mem_id < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ERROR: could not open shared memory\n"); - rtapi_exit(comp_id); - return -EINVAL; - } - /* get address of shared memory area */ - retval = rtapi_shmem_getptr(mem_id, &mem, 0); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ERROR: could not access shared memory\n"); - rtapi_exit(comp_id); - return -EINVAL; - } - /* set up internal pointers to shared mem and data structure */ - hal_data = (hal_data_t *) mem; - /* release mutex */ - rtapi_mutex_give(&(hal_data->mutex)); - /* release RTAPI resources */ - rtapi_shmem_delete(mem_id, comp_id); - rtapi_exit(comp_id); - /* done */ - return 0; - -} - -static int doLock(char *command, connectionRecType *context) -{ - int retval=0; - const char *nakStr = "SET LOCK NAK"; - - /* if command is blank, want to lock everything */ - if (*command == '\0') - retval = hal_set_lock(HAL_LOCK_ALL); - else - if (strcmp(command, "none") == 0) - retval = hal_set_lock(HAL_LOCK_NONE); - else - if (strcmp(command, "tune") == 0) - retval = hal_set_lock(HAL_LOCK_LOAD & HAL_LOCK_CONFIG); - else - if (strcmp(command, "all") == 0) - retval = hal_set_lock(HAL_LOCK_ALL); - - if (retval != 0) { - sprintf(errorStr, "HAL:%d: Locking failed", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doUnlock(char *command, connectionRecType *context) -{ - int retval=0; - const char *nakStr = "SET UNLOCK NAK"; - - /* if command is blank, want to lock everything */ - if (*command == '\0') - retval = hal_set_lock(HAL_LOCK_NONE); - else - if (strcmp(command, "all") == 0) - retval = hal_set_lock(HAL_LOCK_NONE); - else - if (strcmp(command, "tune") == 0) - retval = hal_set_lock(HAL_LOCK_LOAD & HAL_LOCK_CONFIG); - - if (retval != 0) { - sprintf(errorStr, "HAL:%d: Unlocking failed", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doLinkpp(char *first_pin_name, char *second_pin_name, connectionRecType *context) -{ - int retval; - hal_pin_t *first_pin, *second_pin; - const char *nakStr = "SET LINKPP NAK"; - - rtapi_mutex_get(&(hal_data->mutex)); - /* check if the pins are there */ - first_pin = halpr_find_pin_by_name(first_pin_name); - second_pin = halpr_find_pin_by_name(second_pin_name); - if (first_pin == 0) { - /* first pin not found*/ - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, "HAL:%d: ERROR: pin '%s' not found\n", linenumber, first_pin_name); - sockWriteError(nakStr, context); - return -EINVAL; - } - else - if (second_pin == 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, "HAL:%d: ERROR: pin '%s' not found", linenumber, second_pin_name); - sockWriteError(nakStr, context); - return -EINVAL; - } - - /* give the mutex, as the other functions use their own mutex */ - rtapi_mutex_give(&(hal_data->mutex)); - - /* check that both pins have the same type, - don't want ot create a sig, which after that won't be usefull */ - if (first_pin->type != second_pin->type) { - sprintf(errorStr, "HAL:%d: ERROR: pins '%s' and '%s' not of the same type", - linenumber, first_pin_name, second_pin_name); - sockWriteError(nakStr, context); - return -EINVAL; - } - - /* now create the signal */ - retval = hal_signal_new(first_pin_name, first_pin->type); - - if (retval == 0) { - /* if it worked, link the pins to it */ - retval = hal_link(first_pin_name, first_pin_name); - - if ( retval == 0 ) - /* if that worked, link the second pin to the new signal */ - retval = hal_link(second_pin_name, first_pin_name); - } - if (retval < 0) { - sprintf(errorStr, "HAL:%d: linkpp failed", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -int doLinkPS(char *pin, char *sig, connectionRecType *context) -{ - int retval; - const char *nakStr = "SET NET NAK"; - - retval = hal_link(pin, sig); - if (retval == 0) { - /* print success message */ -// halcmd_info("Pin '%s' linked to signal '%s'\n", pin, sig); - sprintf(errorStr, "Pin '%s' linked to signal '%s'", pin, sig); - sockWriteError(nakStr, context); - } else { -// halcmd_error("link failed\n"); - sprintf(errorStr, "link failed"); - sockWriteError(nakStr, context); - } - return retval; -} - - -static int preflightNet(char *signal, hal_sig_t *sig, char *pins[], connectionRecType *context) -{ - int i, type=-1, writers=0, bidirs=0, pincnt=0; - const char *nakStr = "SET NET NAK"; - - /* if signal already exists, use its info */ - if (sig) { - type = sig->type; - writers = sig->writers; - bidirs = sig->bidirs; - } - - for(i=0; pins[i] && *pins[i]; i++) { - hal_pin_t *pin = 0; - pin = halpr_find_pin_by_name(pins[i]); - if(!pin) { -// halcmd_error("pin '%s' does not exist\n", pins[i]); - sprintf(errorStr, "pin '%s' does not exist", pins[i]); - sockWriteError(nakStr, context); - return -ENOENT; - } - if(SHMPTR(pin->signal) == sig) { - /* Already on this signal */ - pincnt++; - continue; - } else if(pin->signal != 0) { -// halcmd_error("pin '%s' was already linked\n", pin->name); - sprintf(errorStr, "pin '%s' was already linked", pin->name); - sockWriteError(nakStr, context); - return -EINVAL; - } - if (type == -1) { - /* no pre-existing type, use this pin's type */ - type = pin->type; - } - if(type != pin->type) { -// halcmd_error("Type mismatch on pin '%s'\n", pin->name); - sprintf(errorStr, "Type mismatch on pin '%s'", pin->name); - sockWriteError(nakStr, context); - return -EINVAL; - } - if(pin->dir == HAL_OUT) { - if(writers || bidirs) { -// halcmd_error("Signal '%s' can not add OUT pin '%s'\n", signal, pin->name); - sprintf(errorStr, "Signal '%s' can not add OUT pin '%s'", signal, pin->name); - sockWriteError(nakStr, context); - return -EINVAL; - } - writers++; - } - if(pin->dir == HAL_IO) { - if(writers) { -// halcmd_error("Signal '%s' can not add I/O pin '%s'\n", signal, pin->name); - sprintf(errorStr, "Signal '%s' can not add I/O pin '%s'", signal, pin->name); - sockWriteError(nakStr, context); - return -EINVAL; - } - bidirs++; - } - pincnt++; - } - if(pincnt) - return 0; -// halcmd_error("'net' requires at least one pin, none given\n"); - sprintf(errorStr, "'net' requires at least one pin, none given"); - sockWriteError(nakStr, context); - return -EINVAL; -} - - -int doNet(char *signal, char *pins[], connectionRecType *context) -{ - hal_sig_t *sig; - int i, retval; - const char *nakStr = "SET NET NAK"; - - rtapi_mutex_get(&(hal_data->mutex)); - /* see if signal already exists */ - sig = halpr_find_sig_by_name(signal); - - /* verify that everything matches up (pin types, etc) */ - retval = preflightNet(signal, sig, pins, context); - if(retval < 0) { - rtapi_mutex_give(&(hal_data->mutex)); - return retval; - } - - { - hal_pin_t *pin = halpr_find_pin_by_name(signal); - if(pin) { -// halcmd_error("Signal name '%s' must not be the same as a pin.\n", signal); - sprintf(errorStr, "Signal name '%s' must not be the same as a pin.", signal); - sockWriteError(nakStr, context); - rtapi_mutex_give(&(hal_data->mutex)); - return -ENOENT; - } - } - if(!sig) { - /* Create the signal with the type of the first pin */ - hal_pin_t *pin = halpr_find_pin_by_name(pins[0]); - rtapi_mutex_give(&(hal_data->mutex)); - if(!pin) { - return -ENOENT; - } - retval = hal_signal_new(signal, pin->type); - } else { - /* signal already exists */ - rtapi_mutex_give(&(hal_data->mutex)); - } - /* add pins to signal */ - for(i=0; retval == 0 && pins[i] && *pins[i]; i++) { - retval = doLinkPS(pins[i], signal, context); - } - - return retval; -} - - -static int doLink(char *pin, char *sig, connectionRecType *context) -{ - int retval; - const char *nakStr = "SET LINKPS NAK"; - - /* if sig is blank, want to unlink pin */ - if (*sig == '\0') { - /* unlink the pin */ - retval = hal_unlink(pin); - } else { - /* make the link */ - retval = hal_link(pin, sig); - } - if (retval != 0) { - sprintf(errorStr, "HAL:%d: link failed", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doNewsig(char *name, char *type, connectionRecType *context) -{ - int retval; - const char *nakStr = "SET NEWSIG NAK"; - - if (strcasecmp(type, "bit") == 0) - retval = hal_signal_new(name, HAL_BIT); - else - if (strcasecmp(type, "float") == 0) - retval = hal_signal_new(name, HAL_FLOAT); - else - if (strcasecmp(type, "u16") == 0) - retval = hal_signal_new(name, HAL_U32); - else - if (strcasecmp(type, "s32") == 0) - retval = hal_signal_new(name, HAL_S32); - else { - sprintf(errorStr, "HAL:%d: Unknown signal type '%s'", - linenumber, type); - sockWriteError(nakStr, context); - retval = -EINVAL; - } - if (retval < 0) { - sprintf(errorStr, "HAL:%d: newsig failed", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int set_common(hal_type_t type, void *d_ptr, char *value, connectionRecType *context) { - // This function assumes that the mutex is held - int retval = 0; - double fval; - long lval; - unsigned long ulval; - char *cp = value; - - switch (type) { - case HAL_BIT: - if ((strcmp("1", value) == 0) || (strcasecmp("TRUE", value) == 0)) { - *(hal_bit_t *) (d_ptr) = 1; - } else if ((strcmp("0", value) == 0) - || (strcasecmp("FALSE", value)) == 0) { - *(hal_bit_t *) (d_ptr) = 0; - } else { - retval = -EINVAL; - } - break; - case HAL_FLOAT: - fval = strtod ( value, &cp ); - if ((*cp != '\0') && (!isspace(*cp))) { - /* invalid character(s) in string */ - retval = -EINVAL; - } else { - *((hal_float_t *) (d_ptr)) = fval; - } - break; - case HAL_S32: - lval = strtol(value, &cp, 0); - if ((*cp != '\0') && (!isspace(*cp))) { - /* invalid chars in string */ - retval = -EINVAL; - } else { - *((hal_s32_t *) (d_ptr)) = lval; - } - break; - case HAL_U32: - ulval = strtoul(value, &cp, 0); - if ((*cp != '\0') && (!isspace(*cp))) { - /* invalid chars in string */ - retval = -EINVAL; - } else { - *((hal_u32_t *) (d_ptr)) = ulval; - } - break; - default: - /* Shouldn't get here, but just in case... */ - retval = -EINVAL; - } - return retval; -} - -static int doSetp(char *name, char *value, connectionRecType *context) -{ - const char *nakStr = "SET SETP NAK"; - int retval; - hal_param_t *param; - hal_pin_t *pin; - hal_type_t type; - void *d_ptr; - - /* get mutex before accessing shared data */ - rtapi_mutex_get(&(hal_data->mutex)); - /* search param list for name */ - param = halpr_find_param_by_name(name); - if (param == 0) { - pin = halpr_find_pin_by_name(name); - if(pin == 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, - "HAL:%d: ERROR: parameter or pin '%s' not found\n", linenumber, name); - sockWriteError(nakStr, context); - return -EINVAL; - } else { - /* found it */ - type = pin->type; - if(pin->dir == HAL_OUT) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, - "HAL:%d: ERROR: pin '%s' is not writable\n", linenumber, name); - sockWriteError(nakStr, context); - return -EINVAL; - } - if(pin->signal != 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, - "HAL:%d: ERROR: pin '%s' is connected to a signal\n", linenumber, name); - sockWriteError(nakStr, context); - return -EINVAL; - } - // d_ptr = (void*)SHMPTR(pin->dummysig); - d_ptr = (void*)&pin->dummysig; - } - } else { - /* found it */ - type = param->type; - /* is it read only? */ - if (param->dir == HAL_RO) { - rtapi_mutex_give(&(hal_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: param '%s' is not writable\n", linenumber, name); - return -EINVAL; - } - d_ptr = SHMPTR(param->data_ptr); - } - - retval = set_common(type, d_ptr, value, context); - - rtapi_mutex_give(&(hal_data->mutex)); - if (retval != 0) { - sprintf(errorStr, "HAL:%d: setp failed\n", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doSets(char *name, char *value, connectionRecType *context) -{ - const char *nakStr = "SET SETS NAK"; - int retval; - hal_sig_t *sig; - hal_type_t type; - void *d_ptr; - - /* get mutex before accessing shared data */ - rtapi_mutex_get(&(hal_data->mutex)); - /* search signal list for name */ - sig = halpr_find_sig_by_name(name); - if (sig == 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, - "HAL:%d: ERROR: signal '%s' not found\n", linenumber, name); - sockWriteError(nakStr, context); - return -EINVAL; - } - /* found it - does it have a writer? */ - if (sig->writers > 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, - "HAL:%d: ERROR: signal '%s' already has writer(s)\n", linenumber, name); - sockWriteError(nakStr, context); - return -EINVAL; - } - /* no writer, so we can safely set it */ - type = sig->type; - d_ptr = SHMPTR(sig->data_ptr); - retval = set_common(type, d_ptr, value, context); - rtapi_mutex_give(&(hal_data->mutex)); - if (retval != 0) { - sprintf(errorStr, "HAL:%d: sets failed\n", linenumber); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doAddf(char *name, char *thread, char *parm, connectionRecType *context) -{ - int retval; - const char *nakStr = "SET ADDF NAK"; - - if (parm[0] == '\0') - /* no - add function at end of thread */ - retval = hal_add_funct_to_thread(name, thread, -1); - else - retval = hal_add_funct_to_thread(name, thread, atoi(parm)); - if (retval != 0) { - /* print fail message */ - sprintf(errorStr, "HAL:%d: Unable to add function '%s' to thread '%s'", linenumber, name, thread); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doDelf(char *name, char *thread, connectionRecType *context) -{ - int retval; - const char *nakStr = "SET DELF NAK"; - - retval = hal_del_funct_from_thread(name, thread); - if (retval != 0) { - /* print success message */ - sprintf(errorStr, "Failed to remove function '%s' from thread '%s'", name, thread); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doStart(connectionRecType *context) -{ - int retval; - const char *nakStr = "SET START NAK"; - - retval = hal_start_threads(); - if (retval != 0) { - /* print success message */ - sprintf(errorStr, "Failed to start realtime threads"); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doStop(connectionRecType *context) -{ - int retval; - const char *nakStr = "SET STOP NAK"; - - retval = hal_stop_threads(); - if (retval != 0) { - /* print success message */ - sprintf(errorStr, "Unable to stop realtime threads"); - sockWriteError(nakStr, context); - } - return retval; -} - -static int doLoadRt(char *mod_name, char *args[], connectionRecType *context) -{ - char arg_string[MAX_CMD_LEN+1]; - int m=0, n=0, retval=0; - hal_comp_t *comp; - char *argv[MAX_TOK+3]; - char *cp1; - const char *nakStr = "SET LOADRT NAK"; - -#if defined(BUILD_SYS_USER_DSO) - char rtapi_app[PATH_MAX]; - - if (get_rtapi_config(rtapi_app,"rtapi_app",PATH_MAX) != 0) { - sprintf(errorStr,"Unable to read rtapi_app parameter " - "from configuration\n"); - sockWriteError(nakStr, context); - return -EINVAL; - } - - argv[m++] = "-Wn"; - argv[m++] = mod_name; - argv[m++] = rtapi_app; - argv[m++] = "load"; - argv[m++] = mod_name; - /* loop thru remaining arguments */ - while ( args[n] && args[n][0] != '\0' ) { - argv[m++] = args[n++]; - } - argv[m++] = NULL; -// retval = do_loadusr_cmd(argv); -#else - char mod_path[PATH_MAX]; - - if (hal_get_lock()&HAL_LOCK_LOAD) { - sprintf(errorStr, "HAL is locked, loading of modules is not permitted"); - sockWriteError(nakStr, context); - return -EPERM; - } - - /* get module path */ - if (module_path(mod_path,mod_name) != 0) { - /* can't find it */ - sprintf(errorStr, "Can't find module '%s'", mod_name); - sockWriteError(nakStr, context); - return -1; - } - - argv[0] = EMC2_BIN_DIR "/linuxcnc_module_helper"; - argv[1] = "insert"; - argv[2] = mod_path; - /* loop thru remaining arguments */ - n = 0; - m = 3; - while ( args[n] && args[n][0] != '\0' ) { - argv[m++] = args[n++]; - } - /* add a NULL to terminate the argv array */ - argv[m] = NULL; -/* sprintf(context->outBuf, "Setup argv %s %s %s", argv[0], argv[1], argv[2]); - sockWrite(context); - return 0; */ - - - retval = hal_systemv(argv, context); -#endif - - if ( retval != 0 ) { - sprintf(errorStr, "insmod failed, returned %d", retval); - sockWriteError(nakStr, context); - return -1; - } - /* make the args that were passed to the module into a single string */ - n = 0; - arg_string[0] = '\0'; - while ( args[n] && args[n][0] != '\0' ) { - strncat(arg_string, args[n++], MAX_CMD_LEN); - strncat(arg_string, " ", MAX_CMD_LEN); - } - /* allocate HAL shmem for the string */ - cp1 = hal_malloc(strlen(arg_string)+1); - if ( cp1 == NULL ) { - sprintf(errorStr, "failed to allocate memory for module args"); - sockWriteError(nakStr, context); - return -1; - } - /* copy string to shmem */ - strcpy (cp1, arg_string); - /* get mutex before accessing shared data */ - rtapi_mutex_get(&(hal_data->mutex)); - /* search component list for the newly loaded component */ - comp = halpr_find_comp_by_name(mod_name); - if (comp == 0) { - rtapi_mutex_give(&(hal_data->mutex)); - sprintf(errorStr, "module '%s' not loaded", mod_name); - sockWriteError(nakStr, context); - return -EINVAL; - } - /* link args to comp struct */ - comp->insmod_args = SHMOFF(cp1); - rtapi_mutex_give(&(hal_data->mutex)); - /* print success message */ -// halcmd_info("Realtime module '%s' loaded\n", mod_name); - return 0; -} - -static int doDelsig(char *mod_name, connectionRecType *context) -{ - int next, retval, retval1, n; - hal_sig_t *sig; - char sigs[MAX_EXPECTED_SIGS][HAL_NAME_LEN+1]; - const char *nakStr = "SET DELSIG NAK"; - - /* check for "all" */ - if ( strcmp(mod_name, "all" ) != 0 ) { - retval = hal_signal_delete(mod_name); - return retval; - } - else { - /* build a list of signal(s) to delete */ - n = 0; - rtapi_mutex_get(&(hal_data->mutex)); - - next = hal_data->sig_list_ptr; - while (next != 0) { - sig = SHMPTR(next); - /* we want to unload this signal, remember it's name */ - if (n < ( MAX_EXPECTED_SIGS - 1)) { - strncpy(sigs[n], sig->name, HAL_NAME_LEN ); - sigs[n][HAL_NAME_LEN] = '\0'; - n++; - } - next = sig->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); - sigs[n][0] = '\0'; - - if ((sigs[0][0] == '\0')) { - /* desired signals not found */ - sprintf(errorStr, "HAL:%d: ERROR: no signals found to be deleted", linenumber); - sockWriteError(nakStr, context); - return -1; - } - /* we now have a list of components, unload them */ - n = 0; - retval1 = 0; - while (sigs[n][0] != '\0') { - retval = hal_signal_delete(sigs[n]); - /* check for fatal error */ - if (retval < -1) - return retval; - /* check for other error */ - if (retval != 0) - retval1 = retval; - n++; - } - } - return retval1; -} - -static int doUnload(char *mod_name, connectionRecType *context) -{ - int next, retval, retval1, n, all; - hal_comp_t *comp; - char comps[64][HAL_NAME_LEN+1]; - const char *nakStr = "SET UNLOAD NAK"; - - /* check for "all" */ - if ( strcmp(mod_name, "all" ) == 0 ) { - all = 1; - } else { - all = 0; - } - /* build a list of component(s) to unload */ - n = 0; - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->comp_list_ptr; - while (next != 0) { - comp = SHMPTR(next); - if ( comp->type == 1 ) { - /* found a realtime component */ - if ( all || ( strcmp(mod_name, comp->name) == 0 )) { - /* we want to unload this component, remember its name */ - if ( n < 63 ) { - strncpy(comps[n], comp->name, HAL_NAME_LEN ); - comps[n][HAL_NAME_LEN] = '\0'; - n++; - } - } - } - next = comp->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); - /* mark end of list */ - comps[n][0] = '\0'; - if ( !all && ( comps[0][0] == '\0' )) { - /* desired component not found */ -// halcmd_error("component '%s' is not loaded\n", mod_name); - sprintf(errorStr, "component '%s' is not loaded", mod_name); - sockWriteError(nakStr, context); - return -1; - } - /* we now have a list of components, unload them */ - n = 0; - retval1 = 0; - while ( comps[n][0] != '\0' ) { - retval = unloadrt_comp(comps[n++]); - /* check for fatal error */ - if ( retval < -1 ) { - return retval; - } - /* check for other error */ - if ( retval != 0 ) { - retval1 = retval; - } - } -/* if (retval1 < 0) { - sprintf(errorStr, "unloadrt failed"); - sockWriteError(nakStr, context); - } */ - return retval1; -} - -static int unloadrt_comp(char *mod_name) -{ - int retval, status; - char *argv[4]; - pid_t pid; - - /* now we need to fork, and then exec rmmod.... */ - /* disconnect from the HAL shmem area before forking */ - hal_exit(comp_id); - comp_id = 0; - /* now the fork() */ - pid = fork(); - if ( pid < 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: unloadrt fork() failed\n", linenumber); - /* reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - if (comp_id < 0) { - fprintf(stderr, "halrmt: hal_init() failed after fork: %d\n", - comp_id); - exit(-1); - } - hal_ready(comp_id); - return -1; - } - if ( pid == 0 ) { - /* this is the child process - prepare to exec() rmmod */ - argv[0] = EMC2_BIN_DIR "/linuxcnc_module_helper"; - argv[1] = "remove"; - argv[2] = mod_name; - /* add a NULL to terminate the argv array */ - argv[3] = NULL; - /* print debugging info if "very verbose" (-V) */ - rtapi_print_msg(RTAPI_MSG_DBG, "%s %s %s\n", argv[0], argv[1], argv[2] ); - /* call execv() to invoke rmmod */ - execv(argv[0], argv); - /* should never get here */ - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: execv(%s) failed\n", linenumber, argv[0] ); - exit(1); - } - /* this is the parent process, wait for child to end */ - retval = waitpid ( pid, &status, 0 ); - /* reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - if (comp_id < 0) { - fprintf(stderr, "halrmt: hal_init() failed after unloadrt: %d\n", - comp_id ); - exit(-1); - } - hal_ready(comp_id); - /* check result of waitpid() */ - if ( retval < 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: waitpid(%d) failed\n", linenumber, pid); - return -1; - } - if ( WIFEXITED(status) == 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: child did not exit normally\n", linenumber); - return -1; - } - retval = WEXITSTATUS(status); - if ( retval != 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: rmmod failed, returned %d\n", linenumber, retval); - return -1; - } - /* print success message */ - rtapi_print_msg(RTAPI_MSG_INFO, "Realtime module '%s' unloaded\n", - mod_name); - return 0; -} - -static int doLoadUsr(char *args[]) -{ - int wait_flag, wait_comp_flag, name_flag, ignore_flag; - char *prog_name, *new_comp_name; - char prog_path[MAX_CMD_LEN+1]; - char *cp1, *cp2, *envpath; - struct stat stat_buf; - char *argv[MAX_TOK+1]; - int n, m, retval, status; - pid_t pid; - - if (hal_get_lock()&HAL_LOCK_LOAD) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: HAL is locked, loading of programs is not permitted\n", linenumber); - return -EPERM; - } - /* check for options (-w, -i, and/or -r) */ - wait_flag = 0; - wait_comp_flag = 0; - name_flag = 0; - ignore_flag = 0; - prog_name = NULL; - while ( **args == '-' ) { - /* this argument contains option(s) */ - cp1 = *args; - cp1++; - while ( *cp1 != '\0' ) { - if ( *cp1 == 'w' ) { - wait_flag = 1; - } else if ( *cp1 == 'W' ) { - wait_comp_flag = 1; - } else if ( *cp1 == 'i' ) { - ignore_flag = 1; - } else if ( *cp1 == 'n' ) { - name_flag = 1; - } else { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: unknown loadusr option '-%c'\n", linenumber, *cp1); - return -EINVAL; - } - cp1++; - } - /* move to next arg */ - args++; - } - /* get program and component name */ - if(name_flag) { - new_comp_name = *args++; - prog_name = *args++; - } else { - new_comp_name = prog_name = *args++; - } - /* need to find path to a program matching "prog_name" */ - prog_path[0] = '\0'; - if ( prog_path[0] == '\0' ) { - /* try the name by itself */ - strncpy (prog_path, prog_name, MAX_CMD_LEN); - rtapi_print_msg(RTAPI_MSG_DBG, "Trying '%s'\n", prog_path); - if ( stat(prog_path, &stat_buf) != 0 ) { - /* no luck, clear prog_path to indicate failure */ - prog_path[0] = '\0'; - } - } - if ( prog_path[0] == '\0' ) { - /* no luck yet, try the emc2/bin directory where - the halrmt executable is located */ - n = readlink("/proc/self/exe", prog_path, MAX_CMD_LEN-10); - if ( n > 0 ) { - prog_path[n] = '\0'; - /* have path to executabie, find last '/' */ - cp2 = ""; - cp1 = prog_path; - while ( *cp1 != '\0' ) { - if ( *cp1 == '/' ) { - cp2 = cp1; - } - cp1++; - } - if ( *cp2 == '/' ) { - /* chop "halrmt" from end of path */ - *(++cp2) = '\0'; - /* append the program name */ - strncat(prog_path, prog_name, MAX_CMD_LEN-strlen(prog_path)); - /* and try it */ - rtapi_print_msg(RTAPI_MSG_DBG, "Trying '%s'\n", prog_path); - if ( stat(prog_path, &stat_buf) != 0 ) { - /* no luck, clear prog_path to indicate failure */ - prog_path[0] = '\0'; - } - } - } - } - if ( prog_path[0] == '\0' ) { - /* no luck yet, try the user's PATH */ - envpath = getenv("PATH"); - if ( envpath != NULL ) { - while ( *envpath != '\0' ) { - /* copy a single directory from the PATH env variable */ - n = 0; - while ( (*envpath != ':') && (*envpath != '\0') && (n < MAX_CMD_LEN)) { - prog_path[n++] = *envpath++; - } - /* append '/' and program name */ - if ( n < MAX_CMD_LEN ) { - prog_path[n++] = '/'; - } - cp1 = prog_name; - while ((*cp1 != '\0') && ( n < MAX_CMD_LEN)) { - prog_path[n++] = *cp1++; - } - prog_path[n] = '\0'; - rtapi_print_msg(RTAPI_MSG_DBG, "Trying '%s'\n", prog_path); - if ( stat(prog_path, &stat_buf) != 0 ) { - /* no luck, clear prog_path to indicate failure */ - prog_path[0] = '\0'; - /* and get ready to try the next directory */ - if ( *envpath == ':' ) { - envpath++; - } - } else { - /* success, break out of loop */ - break; - } - } - } - } - if ( prog_path[0] == '\0' ) { - /* still can't find a program to run */ - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: Can't find program '%s'\n", linenumber, prog_name); - return -1; - } - - /* now we need to fork, and then exec the program.... */ - /* disconnect from the HAL shmem area before forking */ - hal_exit(comp_id); - comp_id = 0; - /* now the fork() */ - pid = fork(); - if ( pid < 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: loadusr fork() failed\n", linenumber); - /* reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - if (comp_id < 0) { - fprintf(stderr, "halrmt: hal_init() failed after fork: %d\n", - comp_id); - exit(-1); - } - hal_ready(comp_id); - return -1; - } - if ( pid == 0 ) { - /* this is the child process - prepare to exec() the program */ - argv[0] = prog_name; - /* loop thru remaining arguments */ - n = 0; - m = 1; - while ( args[n][0] != '\0' ) { - argv[m++] = args[n++]; - } - /* add a NULL to terminate the argv array */ - argv[m] = NULL; - /* print debugging info if "very verbose" (-V) */ - rtapi_print_msg(RTAPI_MSG_DBG, "%s ", argv[0] ); - n = 1; - while ( argv[n] != NULL ) { - rtapi_print_msg(RTAPI_MSG_DBG, "%s ", argv[n++] ); - } - rtapi_print_msg(RTAPI_MSG_DBG, "\n" ); - /* call execv() to invoke the program */ - execv(prog_path, argv); - /* should never get here */ - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: execv(%s) failed: %s\n", linenumber, prog_name, - strerror(errno)); - exit(1); - } - /* this is the parent process, reconnect to the HAL shmem area */ - comp_id = hal_init(comp_name); - if (comp_id < 0) { - fprintf(stderr, "halrmt: hal_init() failed after loadusr: %d\n", - comp_id); - exit(-1); - } - hal_ready(comp_id); - if ( wait_comp_flag ) { - int ready = 0, count=0; - int next; - while(!ready) { - struct timespec ts = {0, 10 * 1000 * 1000}; // 10ms - nanosleep(&ts, NULL); - retval = waitpid( pid, &status, WNOHANG ); - if(retval != 0) goto wait_common; - - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->comp_list_ptr; - while(next) { - hal_comp_t *comp = SHMPTR(next); - next = comp->next_ptr; - if(strcmp(comp->name, new_comp_name) == 0 && (comp->state > COMP_INITIALIZING)) { - ready = 1; - break; - } - } - rtapi_mutex_give(&(hal_data->mutex)); - - count++; - if(count == 100) { - fprintf(stderr, "Waiting for component '%s' to become ready.", - new_comp_name); - fflush(stderr); - } else if(count > 100 && count % 10 == 0) { - fprintf(stderr, "."); - fflush(stderr); - } - } - if (count >= 100) { - fprintf(stderr, "\n"); - } - rtapi_print_msg(RTAPI_MSG_INFO, "Component '%s' ready\n", new_comp_name); - } - if ( wait_flag ) { - /* wait for child process to complete */ - retval = waitpid ( pid, &status, 0 ); - /* check result of waitpid() */ -wait_common: - if ( retval < 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: waitpid(%d) failed\n", linenumber, pid); - return -1; - } - if ( WIFEXITED(status) == 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: program '%s' did not exit normally\n", linenumber, prog_name ); - return -1; - } - if ( ignore_flag == 0 ) { - retval = WEXITSTATUS(status); - if ( retval != 0 ) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL:%d: ERROR: program '%s' failed, returned %d\n", linenumber, prog_name, retval ); - return -1; - } - } - /* print success message */ - rtapi_print_msg(RTAPI_MSG_INFO, "Program '%s' finished\n", prog_name); - } else { - /* print success message */ - rtapi_print_msg(RTAPI_MSG_INFO, "Program '%s' started\n", prog_name); - } - return 0; -} - -static void getCompInfo(char *pattern, connectionRecType *context) -{ - int next, len; - hal_comp_t *comp; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next = hal_data->comp_list_ptr; - while (next != 0) { - comp = SHMPTR(next); - if (strncmp(pattern, comp->name, len) == 0) { - sprintf(context->outBuf, "COMP %s %02d %s", comp->name, comp->comp_id, (comp->type ? "RT " : "User")); - sockWrite(context); - } - next = comp->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - - -static void getPinInfo(char *pattern, int valuesOnly, connectionRecType *context) -{ - int next, len; - hal_pin_t *pin; - hal_comp_t *comp; - hal_sig_t *sig; - void *dptr; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next = hal_data->pin_list_ptr; - while (next != 0) { - pin = SHMPTR(next); - if (strncmp(pattern, pin->name, len) == 0) { - comp = halpr_find_owning_comp(pin->owner_id); - if (pin->signal != 0) { - sig = SHMPTR(pin->signal); - dptr = SHMPTR(sig->data_ptr); - } - else { - sig = 0; - dptr = &(pin->dummysig); - } - if (valuesOnly == 0) - sprintf(context->outBuf, "PIN %s %s %02d %s %s", - pin->name, - data_value2((int) pin->type, dptr), - comp->comp_id, - data_type((int) pin->type), - pin_data_dir((int) pin->dir)); - else - sprintf(context->outBuf, "PINVAL %s %s", - pin->name, - data_value2((int) pin->type, dptr)); - sockWrite(context); - } - next = pin->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - - -static void getSigInfo(char *pattern, int valuesOnly, connectionRecType *context) -{ - int next, len; - hal_sig_t *sig; - void *dptr; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next = hal_data->sig_list_ptr; - while (next != 0) { - sig = SHMPTR(next); - if (strncmp(pattern, sig->name, len) == 0) { - dptr = SHMPTR(sig->data_ptr); - if (valuesOnly == 0) - sprintf(context->outBuf, "SIGNAL %s %s %s", - sig->name, - data_value((int) sig->type, dptr), - data_type((int) sig->type)); - else - sprintf(context->outBuf, "SIGNALVAL %s %s", sig->name, data_value((int) sig->type, dptr)); - sockWrite(context); - } - next = sig->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void getParamInfo(char *pattern, int valuesOnly, connectionRecType *context) -{ - int next, len; - hal_param_t *param; - hal_comp_t *comp; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next = hal_data->param_list_ptr; - while (next != 0) { - param = SHMPTR(next); - if ( strncmp(pattern, param->name, len) == 0 ) { - comp = halpr_find_owning_comp(param->owner_id); - if (valuesOnly == 0) - sprintf(context->outBuf, "PARAM %s %s %02d %s %s", - param->name, - data_value((int) param->type, SHMPTR(param->data_ptr)), - comp->comp_id, - data_type((int) param->type), - param_data_dir((int) param->dir)); - else - sprintf(context->outBuf, "PARAMVAL %s %s", - param->name, - data_value((int) param->type, SHMPTR(param->data_ptr))); - sockWrite(context); - } - next = param->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void getFunctInfo(char *pattern, connectionRecType *context) -{ - int next, len; - hal_funct_t *fptr; - hal_comp_t *comp; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next = hal_data->funct_list_ptr; - while (next != 0) { - fptr = SHMPTR(next); - if (strncmp(pattern, hh_get_name(&fptr->hdr), len) == 0) { - comp = halpr_find_owning_comp(hh_get_owner_id(&fptr->hdr)); - sprintf(context->outBuf, "FUNCT %s %02d %08lX %08lX %s %3d", - hh_get_name(&fptr->hdr), - comp->comp_id, - (unsigned long)fptr->funct.l, - (unsigned long)fptr->arg, - (fptr->uses_fp ? "YES" : "NO"), - fptr->users); - sockWrite(context); - } - next = fptr->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void getThreadInfo(char *pattern, connectionRecType *context) -{ - int next_thread, len, n; - hal_thread_t *tptr; - hal_list_t *list_root, *list_entry; - hal_funct_entry_t *fentry; - hal_funct_t *funct; - - rtapi_mutex_get(&(hal_data->mutex)); - len = strlen(pattern); - next_thread = hal_data->thread_list_ptr; - while (next_thread != 0) { - tptr = SHMPTR(next_thread); - if (strncmp(pattern, tptr->name, len) == 0) { - sprintf(context->outBuf, "THREAD %s %11d %s %d %d", - tptr->name, - (unsigned int)tptr->period, - (tptr->uses_fp ? "YES" : "NO "), - (unsigned int)tptr->runtime, - (unsigned int)tptr->maxtime); - sockWrite(context); - list_root = &(tptr->funct_list); - list_entry = dlist_next(list_root); - n = 1; - while (list_entry != list_root) { - /* print the function info */ - fentry = (hal_funct_entry_t *) list_entry; - funct = SHMPTR(fentry->funct_ptr); - /* scriptmode only uses one line per thread, which contains: - thread period, FP flag, name, then all functs separated by spaces */ - sprintf(context->outBuf, "SUBTHREAD %s %2d", funct->name, n); - sockWrite(context); - n++; - list_entry = dlist_next(list_entry); - } - } - next_thread = tptr->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - - -/* Switch function for pin/sig/param type for the print_*_list functions */ -static const char *data_type(int type) -{ - const char *type_str; - - switch (type) { - case HAL_BIT: - type_str = "bit "; - break; - case HAL_FLOAT: - type_str = "float"; - break; - case HAL_S32: - type_str = "s32 "; - break; - case HAL_U32: - type_str = "u32 "; - break; - default: - /* Shouldn't get here, but just in case... */ - type_str = "undef"; - } - return type_str; -} - -/* Switch function for pin direction for the print_*_list functions */ -static const char *pin_data_dir(int dir) -{ - const char *pin_dir; - - switch (dir) { - case HAL_IN: - pin_dir = "IN "; - break; - case HAL_OUT: - pin_dir = "OUT"; - break; - case HAL_IO: - pin_dir = "I/O"; - break; - default: - /* Shouldn't get here, but just in case... */ - pin_dir = "???"; - } - return pin_dir; -} - -/* Switch function for param direction for the print_*_list functions */ -static const char *param_data_dir(int dir) -{ - const char *param_dir; - - switch (dir) { - case HAL_RO: - param_dir = "RO"; - break; - case HAL_RW: - param_dir = "RW"; - break; - default: - /* Shouldn't get here, but just in case... */ - param_dir = "??"; - } - return param_dir; -} - -/* Switch function for arrow direction for the print_*_list functions */ -static const char *data_arrow1(int dir) -{ - const char *arrow; - - switch (dir) { - case HAL_IN: - arrow = "<=="; - break; - case HAL_OUT: - arrow = "==>"; - break; - case HAL_IO: - arrow = "<=>"; - break; - default: - /* Shouldn't get here, but just in case... */ - arrow = "???"; - } - return arrow; -} - -/* Switch function for arrow direction for the print_*_list functions */ -static const char *data_arrow2(int dir) -{ - const char *arrow; - - switch (dir) { - case HAL_IN: - arrow = "==>"; - break; - case HAL_OUT: - arrow = "<=="; - break; - case HAL_IO: - arrow = "<=>"; - break; - default: - /* Shouldn't get here, but just in case... */ - arrow = "???"; - } - return arrow; -} - -/* Switch function to return var value for the print_*_list functions */ -/* the value is printed in a fixed width field */ -static char *data_value(int type, void *valptr) -{ - char *value_str; - static char buf[15]; - - switch (type) { - case HAL_BIT: - if (*((char *) valptr) == 0) - value_str = " FALSE"; - else - value_str = " TRUE"; - break; - case HAL_FLOAT: - snprintf(buf, 14, "%12.7g", (double)*((hal_float_t *) valptr)); - value_str = buf; - break; - case HAL_S32: - snprintf(buf, 14, " %10ld", (long)*((hal_u32_t *) valptr)); - value_str = buf; - break; - case HAL_U32: - snprintf(buf, 14, " %08lX", (unsigned long)*((hal_u32_t *) valptr)); - value_str = buf; - break; - default: - /* Shouldn't get here, but just in case... */ - value_str = " undef "; - } - return value_str; -} - -/* Switch function to return var value in string form */ -/* the value is printed as a packed string (no whitespace */ -static char *data_value2(int type, void *valptr) -{ - char *value_str; - static char buf[15]; - - switch (type) { - case HAL_BIT: - if (*((char *) valptr) == 0) - value_str = "FALSE"; - else - value_str = "TRUE"; - break; - case HAL_FLOAT: - snprintf(buf, 14, "%.7g", (double)*((hal_float_t *) valptr)); - value_str = buf; - break; - case HAL_S32: - snprintf(buf, 14, "%ld", (long)*((hal_s32_t *) valptr)); - value_str = buf; - break; - case HAL_U32: - snprintf(buf, 14, "%ld", (unsigned long)*((hal_u32_t *) valptr)); - value_str = buf; - break; - default: - /* Shouldn't get here, but just in case... */ - value_str = "unknown_type"; - } - return value_str; -} - -static int doSave(char *type, char *filename, connectionRecType *context) -{ - FILE *dst; - const char *nakStr = "SET SAVE NAK"; - - if (rtapi_get_msg_level() == RTAPI_MSG_NONE) { - /* must be -Q, don't print anything */ - return 0; - } - if (*filename == '\0' ) - dst = stdout; - else { - dst = fopen(filename, "w" ); - if (dst == NULL) { - sprintf(errorStr, "HAL:%d: Can't open 'save' destination '%s'", linenumber, filename); - sockWriteError(nakStr, context); - return -1; - } - } - if (*type == '\0') - type = "all"; - if (strcmp(type, "all" ) == 0) { - /* save everything */ - save_comps(dst); - save_signals(dst); - save_links(dst, 0); - save_params(dst); - save_threads(dst); - } - else - if (strcmp(type, "comp") == 0) - save_comps(dst); - else - if (strcmp(type, "sig") == 0) - save_signals(dst); - else - if (strcmp(type, "link") == 0) - save_links(dst, 0); - else - if (strcmp(type, "linka") == 0) - save_links(dst, 1); - else - if (strcmp(type, "net") == 0) - save_nets(dst, 0); - else - if (strcmp(type, "neta") == 0) - save_nets(dst, 1); - else - if (strcmp(type, "param") == 0) - save_params(dst); - else - if (strcmp(type, "thread") == 0) - save_threads(dst); - else { - sprintf(errorStr, "HAL:%d: Unknown 'save' type '%s'", linenumber, type); - sockWriteError(nakStr, context); - fclose(dst); - return -1; - } - if (*filename != '\0' ) - fclose(dst); - return 0; -} - -static void save_comps(FILE *dst) -{ - int next; - hal_comp_t *comp; - - fprintf(dst, "# components\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->comp_list_ptr; - while (next != 0) { - comp = SHMPTR(next); - if ( comp->type == 1 ) { - /* only print realtime components */ - if ( comp->insmod_args == 0 ) { - fprintf(dst, "#loadrt %s (not loaded by loadrt, no args saved)\n", comp->name); - } else { - fprintf(dst, "loadrt %s %s\n", comp->name, - (char *)SHMPTR(comp->insmod_args)); - } - } - next = comp->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void save_signals(FILE *dst) -{ - int next; - hal_sig_t *sig; - - fprintf(dst, "# signals\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->sig_list_ptr; - while (next != 0) { - sig = SHMPTR(next); - fprintf(dst, "newsig %s %s\n", sig->name, data_type((int) sig->type)); - next = sig->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void save_links(FILE *dst, int arrow) -{ - int next; - hal_pin_t *pin; - hal_sig_t *sig; - const char *arrow_str; - - fprintf(dst, "# links\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->pin_list_ptr; - while (next != 0) { - pin = SHMPTR(next); - if (pin->signal != 0) { - sig = SHMPTR(pin->signal); - if (arrow != 0) { - arrow_str = data_arrow1((int) pin->dir); - } else { - arrow_str = "\0"; - } - fprintf(dst, "linkps %s %s %s\n", pin->name, arrow_str, sig->name); - } - next = pin->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void save_nets(FILE *dst, int arrow) -{ - int next; - hal_pin_t *pin; - hal_sig_t *sig; - const char *arrow_str; - - fprintf(dst, "# nets\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->sig_list_ptr; - while (next != 0) { - sig = SHMPTR(next); - fprintf(dst, "newsig %s %s\n", sig->name, data_type((int) sig->type)); - pin = halpr_find_pin_by_sig(sig, 0); - while (pin != 0) { - if (arrow != 0) { - arrow_str = data_arrow2((int) pin->dir); - } else { - arrow_str = "\0"; - } - fprintf(dst, "linksp %s %s %s\n", sig->name, arrow_str, pin->name); - pin = halpr_find_pin_by_sig(sig, pin); - } - next = sig->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void save_params(FILE *dst) -{ - int next; - hal_param_t *param; - - fprintf(dst, "# parameter values\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->param_list_ptr; - while (next != 0) { - param = SHMPTR(next); - if (param->dir != HAL_RO) { - /* param is writable, save it's value */ - fprintf(dst, "setp %s %s\n", param->name, - data_value((int) param->type, SHMPTR(param->data_ptr))); - } - next = param->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static void save_threads(FILE *dst) -{ - int next_thread; - hal_thread_t *tptr; - hal_list_t *list_root, *list_entry; - hal_funct_entry_t *fentry; - hal_funct_t *funct; - - fprintf(dst, "# realtime thread/function links\n"); - rtapi_mutex_get(&(hal_data->mutex)); - next_thread = hal_data->thread_list_ptr; - while (next_thread != 0) { - tptr = SHMPTR(next_thread); - list_root = &(tptr->funct_list); - list_entry = dlist_next(list_root); - while (list_entry != list_root) { - /* print the function info */ - fentry = (hal_funct_entry_t *) list_entry; - funct = SHMPTR(fentry->funct_ptr); - fprintf(dst, "addf %s %s\n", funct->name, tptr->name); - list_entry = dlist_next(list_entry); - } - next_thread = tptr->next_ptr; - } - rtapi_mutex_give(&(hal_data->mutex)); -} - -static int do_help_cmd(char *command) -{ - - if (strcmp(command, "help") == 0) { - printf("If you need help to use 'help', then I can't help you.\n"); - } else if (strcmp(command, "loadrt") == 0) { - printf("loadrt modname [modarg(s)]\n"); - printf(" Loads realtime HAL module 'modname', passing 'modargs'\n"); - printf(" to the module.\n"); - } else if (strcmp(command, "unloadrt") == 0) { - printf("unloadrt modname\n"); - printf(" Unloads realtime HAL module 'modname'. If 'modname'\n"); - printf(" is 'all', unloads all realtime modules.\n"); - } else if (strcmp(command, "loadusr") == 0) { - printf("loadusr [options] progname [progarg(s)]\n"); - printf(" Starts user space program 'progname', passing\n"); - printf(" 'progargs' to it. Options are:\n"); - printf(" -w wait for program to finish\n"); - printf(" -i ignore program return value (use with -w)\n"); - } else if ((strcmp(command, "linksp") == 0) || (strcmp(command,"linkps") == 0)) { - printf("linkps pinname [arrow] signame\n"); - printf("linksp signame [arrow] pinname\n"); - printf(" Links pin 'pinname' to signal 'signame'. Both forms do\n"); - printf(" the same thing. Use whichever makes sense. The optional\n"); - printf(" 'arrow' can be '==>', '<==', or '<=>' and is ignored. It\n"); - printf(" can be used in files to show the direction of data flow,\n"); - printf(" but don't use arrows on the command line.\n"); - } else if (strcmp(command, "linkpp") == 0) { - printf("linkpp firstpin secondpin\n"); - printf(" Creates a signal with the name of the first pin,\n"); printf(" then links both pins to the signal. \n"); - }else if (strcmp(command, "unlinkp") == 0) { - printf("unlinkp pinname\n"); - printf(" Unlinks pin 'pinname' if it is linked to any signal.\n"); - } else if (strcmp(command, "lock") == 0) { - printf("lock [all|tune|none]\n"); - printf(" Locks HAL to some degree.\n"); - printf(" none - no locking done.\n"); - printf(" tune - some tuning is possible (setp & such).\n"); - printf(" all - HAL completely locked.\n"); - } else if (strcmp(command, "unlock") == 0) { - printf("unlock [all|tune]\n"); - printf(" Unlocks HAL to some degree.\n"); - printf(" tune - some tuning is possible (setp & such).\n"); - printf(" all - HAL completely unlocked.\n"); - } else if (strcmp(command, "newsig") == 0) { - printf("newsig signame type\n"); - printf(" Creates a new signal called 'signame'. Type is 'bit',\n"); - printf(" 'float', 'u8', 's8', 'u16', 's16', 'u32', or 's32'.\n"); - } else if (strcmp(command, "delsig") == 0) { - printf("delsig signame\n"); - printf(" Deletes signal 'signame'. If 'signame is 'all',\n"); - printf(" deletes all signals\n"); - } else if (strcmp(command, "setp") == 0) { - printf("setp paramname value\n"); - printf("paramname = value\n"); - printf(" Sets parameter 'paramname' to 'value' (if writable).\n"); - printf(" 'setp' and '=' work the same, don't use '=' on the\n"); - printf(" command line. 'value' may be a constant such as 1.234\n"); - printf(" or TRUE, or a reference to an environment variable,\n"); -#ifdef NO_INI - printf(" using the syntax '$name'./n"); -#else - printf(" using the syntax '$name'. If option -i was given,\n"); - printf(" 'value' may also be a reference to an ini file entry\n"); - printf(" using the syntax '[section]name'.\n"); -#endif - } else if (strcmp(command, "sets") == 0) { - printf("sets signame value\n"); - printf(" Sets signal 'signame' to 'value' (if sig has no writers).\n"); - } else if (strcmp(command, "getp") == 0) { - printf("getp paramname\n"); - printf(" Gets the value of parameter 'paramname'.\n"); - } else if (strcmp(command, "gets") == 0) { - printf("gets signame\n"); - printf(" Gets the value of signal 'signame'.\n"); - } else if (strcmp(command, "addf") == 0) { - printf("addf functname threadname [position]\n"); - printf(" Adds function 'functname' to thread 'threadname'. If\n"); - printf(" 'position' is specified, adds the function to that spot\n"); - printf(" in the thread, otherwise adds it to the end. Negative\n"); - printf(" 'position' means position with respect to the end of the\n"); - printf(" thread. For example '1' is start of thread, '-1' is the\n"); - printf(" end of the thread, '-3' is third from the end.\n"); - } else if (strcmp(command, "delf") == 0) { - printf("delf functname threadname\n"); - printf(" Removes function 'functname' from thread 'threadname'.\n"); - } else if (strcmp(command, "show") == 0) { - printf("show [type] [pattern]\n"); - printf(" Prints info about HAL items of the specified type.\n"); - printf(" 'type' is 'comp', 'pin', 'sig', 'param', 'funct',\n"); - printf(" 'thread', or 'all'. If 'type' is omitted, it assumes\n"); - printf(" 'all' with no pattern. If 'pattern' is specified\n"); - printf(" it prints only those items whose names match the\n"); - printf(" pattern (no fancy regular expressions, just a simple\n"); - printf(" match: 'foo' matches 'foo', 'foobar' and 'foot' but\n"); - printf(" not 'fo' or 'frobz' or 'ffoo').\n"); - } else if (strcmp(command, "list") == 0) { - printf("list type [pattern]\n"); - printf(" Prints the names of HAL items of the specified type.\n"); - printf(" 'type' is 'comp', 'pin', 'sig', 'param', 'funct', or\n"); - printf(" 'thread'. If 'pattern' is specified it prints only\n"); - printf(" those names that match the pattern (no fancy regular\n"); - printf(" expressions, just a simple match: 'foo' matches 'foo',\n"); - printf(" 'foobar' and 'foot' but not 'fo' or 'frobz' or 'ffoo').\n"); - printf(" Names are printed on a single line, space separated.\n"); - } else if (strcmp(command, "status") == 0) { - printf("status [type]\n"); - printf(" Prints status info about HAL.\n"); - printf(" 'type' is 'lock', 'mem', or 'all'. \n"); - printf(" If 'type' is omitted, it assumes\n"); - printf(" 'all'.\n"); - } else if (strcmp(command, "save") == 0) { - printf("save [type] [filename]\n"); - printf(" Prints HAL state to 'filename' (or stdout), as a series\n"); - printf(" of HAL commands. State can later be restored by using\n"); - printf(" \"halrmt -f filename\".\n"); - printf(" Type can be 'comp', 'sig', 'link[a]', 'net[a]', 'param',\n"); - printf(" or 'thread'. ('linka' and 'neta' show arrows for pin\n"); - printf(" direction.) If 'type' is omitted or 'all', does the\n"); - printf(" equivalent of 'comp', 'sig', 'link', 'param', and 'thread'.\n"); - } else if (strcmp(command, "start") == 0) { - printf("start\n"); - printf(" Starts all realtime threads.\n"); - } else if (strcmp(command, "stop") == 0) { - printf("stop\n"); - printf(" Stops all realtime threads.\n"); - } else if (strcmp(command, "quit") == 0) { - printf("quit\n"); - printf(" Stop processing input and terminate halrmt (when\n"); - printf(" reading from a file or stdin).\n"); - } else if (strcmp(command, "exit") == 0) { - printf("exit\n"); - printf(" Stop processing input and terminate halrmt (when\n"); - printf(" reading from a file or stdin).\n"); - } else { - printf("No help for unknown command '%s'\n", command); - } - return 0; -} - -static void print_help_general(int showR) -{ - printf("\nUsage: halrmt [options] [cmd [args]]\n\n"); - printf("options:\n\n"); - printf(" -f [filename] Read commands from 'filename', not command\n"); - printf(" line. If no filename, read from stdin.\n"); -#ifndef NO_INI - printf(" -i filename Open .ini file 'filename', allow commands\n"); - printf(" to get their values from ini file.\n"); -#endif - printf(" -q Quiet - print errors only (default).\n"); - printf(" -Q Very quiet - print nothing.\n"); - if (showR != 0) { - printf(" -R Release mutex (for crash recovery only).\n"); - } - printf(" -s Script friendly - don't print headers on output.\n"); - printf(" -v Verbose - print result of every command.\n"); - printf(" -V Very verbose - print lots of junk.\n"); - printf(" -h Help - print this help screen and exit.\n\n"); - printf("commands:\n\n"); - printf(" loadrt, unloadrt, loadusr, lock, unlock, linkps, linksp, linkpp,\n"); - printf(" unlinkp, newsig, delsig, setp, getp, sets, gets, addf, delf, show,\n"); - printf(" list, save, status, start, stop, quit, exit\n"); - printf(" help Lists all commands with short descriptions\n"); - printf(" help command Prints detailed help for 'command'\n\n"); -} - -static halCommandType lookupHalCommand(char *s) -{ - halCommandType i = hcEcho; - int temp; - - while (i < hcUnknown) { - if (strcmp(halCommands[i], s) == 0) return i; -// (int)i += 1; - temp = i; - temp++; - i = (halCommandType) temp; - } - return i; -} - - static int commandHello(connectionRecType *context) -{ - char *pch; -// const char *password = "EMC"; - - pch = strtok(NULL, delims); - if (pch == NULL) return -1; - if (strcmp(pch, pwd) != 0) return -1; - pch = strtok(NULL, delims); - if (pch == NULL) return -1; - strcpy(context->hostName, pch); - pch = strtok(NULL, delims); - if (pch == NULL) return -1; - context->linked = 1; - strcpy(context->version, pch); - printf("Connected to %s\n\r", context->hostName); - return 0; -} - -static cmdResponseType getEcho(char *s, connectionRecType *context) -{ - const char *pEchoStr = "ECHO %s"; - - if (context->echo == 1) sprintf(context->outBuf, pEchoStr, "ON"); - else sprintf(context->outBuf, pEchoStr, "OFF"); - return rtNoError; -} - -static cmdResponseType getVerbose(char *s, connectionRecType *context) -{ - const char *pVerboseStr = "VERBOSE %s"; - - if (context->verbose == 1) sprintf(context->outBuf, pVerboseStr, "ON"); - else sprintf(context->outBuf, pVerboseStr, "OFF"); - return rtNoError; -} - -static cmdResponseType getEnable(char *s, connectionRecType *context) -{ - const char *pEnableStr = "ENABLE %s"; - - if (context->cliSock == enabledConn) sprintf(context->outBuf, pEnableStr, "ON"); - else sprintf(context->outBuf, pEnableStr, "OFF"); - return rtNoError; -} - -static cmdResponseType getConfig(char *s, connectionRecType *context) -{ - const char *pConfigStr = "CONFIG"; - - strcpy(context->outBuf, pConfigStr); - return rtNoError; -} - -static cmdResponseType getCommMode(char *s, connectionRecType *context) -{ - const char *pCommModeStr = "COMM_MODE %s"; - - switch (context->commMode) { - case 0: sprintf(context->outBuf, pCommModeStr, "ASCII"); break; - case 1: sprintf(context->outBuf, pCommModeStr, "BINARY"); break; - } - return rtNoError; -} - -static cmdResponseType getCommProt(char *s, connectionRecType *context) -{ - const char *pCommProtStr = "COMM_PROT %s"; - - sprintf(context->outBuf, pCommProtStr, context->version); - return rtNoError; -} - -static cmdResponseType getComps(char *s, connectionRecType *context) -{ - if (s == NULL) - getCompInfo("", context); - else - getCompInfo(s, context); - return rtHandledNoError; -} - -static cmdResponseType getPins(char *s, connectionRecType *context) -{ - if (s == NULL) - getPinInfo("", 0, context); - else - getPinInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getPinVals(char *s, connectionRecType *context) - -{ - if (s == NULL) - getPinInfo("", 1, context); - else - getPinInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getSignals(char *s, connectionRecType *context) -{ - if (s == NULL) - getSigInfo("", 0, context); - else - getSigInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getSignalVals(char *s, connectionRecType *context) -{ - if (s == NULL) - getSigInfo("", 1, context); - else - getSigInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getParams(char *s, connectionRecType *context) -{ - if (s == NULL) - getParamInfo("", 0, context); - else - getParamInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getParamVals(char *s, connectionRecType *context) -{ - if (s == NULL) - getParamInfo("", 1, context); - else - getParamInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getFuncts(char *s, connectionRecType *context) -{ - if (s == NULL) - getFunctInfo("", context); - else - getFunctInfo(s, context); - return rtHandledNoError; -} - -static cmdResponseType getThreads(char *s, connectionRecType *context) -{ - if (s == NULL) - getThreadInfo("", context); - else - getThreadInfo(s, context); - return rtHandledNoError; -} - -static cmdResponseType getComp(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getCompInfo(s, context); - return rtHandledNoError; -} - -static cmdResponseType getPin(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getPinInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getPinVal(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getPinInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getSignal(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getSigInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getSignalVal(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getSigInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getParam(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getParamInfo(s, 0, context); - return rtHandledNoError; -} - -static cmdResponseType getParamVal(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getParamInfo(s, 1, context); - return rtHandledNoError; -} - -static cmdResponseType getFunct(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getFunctInfo(s, context); - return rtHandledNoError; -} - -static cmdResponseType getThread(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - getThreadInfo(s, context); - return rtHandledNoError; -} - -int commandGet(connectionRecType *context) -{ - static char *setNakStr = "GET NAK\r\n"; - static char *setCmdNakStr = "GET %s NAK\r\n"; - halCommandType cmd; - char *pch; - int retval; - cmdResponseType ret = rtNoError; - - pch = strtok(NULL, delims); - if (pch == NULL) { - retval = write(context->cliSock, setNakStr, strlen(setNakStr)); - return 0; - } - strupr(pch); - cmd = lookupHalCommand(pch); - switch (cmd) { - case hcEcho: ret = getEcho(pch, context); break; - case hcVerbose: ret = getVerbose(pch, context); break; - case hcEnable: ret = getEnable(pch, context); break; - case hcConfig: ret = getConfig(pch, context); break; - case hcCommMode: ret = getCommMode(pch, context); break; - case hcCommProt: ret = getCommProt(pch, context); break; - case hcComps: ret = getComps(strtok(NULL, delims), context); break; - case hcPins: ret = getPins(strtok(NULL, delims), context); break; - case hcPinVals: ret = getPinVals(pch, context); break; - case hcSigs: ret = getSignals(strtok(NULL, delims), context); break; - case hcSigVals: ret = getSignalVals(strtok(NULL, delims), context); break; - case hcParams: ret = getParams(strtok(NULL, delims), context); break; - case hcParamVals: ret = getParamVals(strtok(NULL, delims), context); break; - case hcFuncts: ret = getFuncts(strtok(NULL, delims), context); break; - case hcThreads: ret = getThreads(strtok(NULL, delims), context); break; - case hcComp: ret = getComp(strtok(NULL, delims), context); break; - case hcPin: ret = getPin(strtok(NULL, delims), context); break; - case hcPinVal: ret = getPinVal(strtok(NULL, delims), context); break; - case hcSig: ret = getSignal(strtok(NULL, delims), context); break; - case hcSigVal: ret = getSignalVal(strtok(NULL, delims), context); break; - case hcParam: ret = getParam(strtok(NULL, delims), context); break; - case hcParamVal: ret = getParamVal(strtok(NULL, delims), context); break; - case hcFunct: ret = getFunct(strtok(NULL, delims), context); break; - case hcThread: ret = getThread(strtok(NULL, delims), context); break; - case hcLoadRt: ; - case hcUnload: ; - case hcLoadUsr: ; - case hcLinkps: ; - case hcLinksp: ; - case hcLinkpp: ; - case hcNet: ; - case hcUnlinkp: ; - case hcLock: ; - case hcUnlock: ; - case hcNewSig: ; - case hcDelSig: ; - case hcSetP: ; - case hcSetS: ; - case hcAddF: ; - case hcDelF: ; - case hcSave: ; - case hcStart: ; - case hcStop: ; - case hcUnknown: ret = rtStandardError; - } - switch (ret) { - case rtNoError: // Standard ok response, just write value in buffer - sockWrite(context); - break; - case rtHandledNoError: // Custom ok response already handled, take no action - break; - case rtStandardError: // Standard error response - sprintf(context->outBuf, setCmdNakStr, pch); - sockWrite(context); - break; - case rtCustomError: // Custom error response entered in buffer - sockWrite(context); - break; - case rtCustomHandledError: ;// Custom error respose handled, take no action - } - return 0; -} - -static int checkOnOff(char *s) -{ - static char *onStr = "ON"; - static char *offStr = "OFF"; - - if (s == NULL) return -1; - strupr(s); - if (strcmp(s, onStr) == 0) return 0; - if (strcmp(s, offStr) == 0) return 1; - return -1; -} - -static int checkBinaryASCII(char *s) -{ - static char *binaryStr = "BINARY"; - static char *ASCIIStr = "ASCII"; - - if (s == NULL) return -1; - strupr(s); - if (strcmp(s, ASCIIStr) == 0) return 0; - if (strcmp(s, binaryStr) == 0) return 1; - return -1; -} - -static cmdResponseType setEcho(char *s, connectionRecType *context) -{ - - switch (checkOnOff(s)) { - case -1: return rtStandardError; - case 0: context->echo = 1; break; - case 1: context->echo = 0; - } - return rtNoError; -} - -static cmdResponseType setVerbose(char *s, connectionRecType *context) -{ - - switch (checkOnOff(s)) { - case -1: return rtStandardError; - case 0: context->verbose = 1; break; - case 1: context->verbose = 0; - } - return rtNoError; -} - -static cmdResponseType setEnable(char *s, connectionRecType *context) -{ - if (strcmp(s, enablePWD) == 0) { - enabledConn = context->cliSock; - context->enabled = 1; - return rtNoError; - } - else - if (checkOnOff(s) == 1) { - context->enabled = 0; - enabledConn = -1; - return rtNoError; - } - else return rtStandardError; -} - -static cmdResponseType setConfig(char *s, connectionRecType *context) -{ - return rtNoError; -} - -static cmdResponseType setCommMode(char *s, connectionRecType *context) -{ - int ret; - - ret = checkBinaryASCII(s); - if (ret == -1) return rtStandardError; - context->commMode = ret; - return rtNoError; -} - -static cmdResponseType setCommProt(char *s, connectionRecType *context) -{ - char *pVersion; - - pVersion = strtok(NULL, delims); - if (pVersion == NULL) return rtStandardError; - strcpy(context->version, pVersion); - return rtNoError; -} - -static cmdResponseType setLoadRt(char *s, connectionRecType *context) -{ - char *pch; - char *args[MAX_TOK+3]; - int i; - - if (s == '\0') return rtCustomHandledError; - i = 0; - pch = strtok(NULL, delims); - while (pch != NULL) { - args[i] = pch; - pch = strtok(NULL, delims); - i++; - } - args[i] = '\0'; - if (doLoadRt(s, args, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setUnload(char *s, connectionRecType *context) -{ - if (doUnload(s, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setLoadUsr(char *s, connectionRecType *context) -{ - char *argv[MAX_TOK+1]; - - argv[0] = s; - argv[1] = "\0"; - if (doLoadUsr(argv) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setLinkps(char *p, char *s, connectionRecType *context) -{ - if ((p == NULL) || (s == NULL)) return rtStandardError; - if (doLink(p, s, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setLinksp(char *p, char *s, connectionRecType *context) -{ - if ((p == NULL) || (s == NULL)) return rtStandardError; - if (doLink(s, p, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setLinkpp(char *p1, char *p2, connectionRecType *context) -{ - if ((p1 == NULL) || (p2 == NULL)) return rtStandardError; - if (doLinkpp(p1, p2, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setNet(char *p1, connectionRecType *context) -{ - char *argv[MAX_TOK]; - int i; - char *pch; - - if (p1 == NULL) return rtStandardError; - i = 0; - - do { - pch = strtok(NULL, delims); - if (pch == NULL) break; - argv[i] = pch; - i++; - if (i >= MAX_TOK) return rtStandardError; // too many pins to link to the net - } while(1); - - if (i == 0) return rtStandardError; // no pins to link to the net - else - if (doNet(p1, argv, context) == 0) - return rtNoError; - else return rtCustomHandledError; -} - -static cmdResponseType setUnlink(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - if (doLink(s, "\0", context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setLock(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - if (doLock(s, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setUnlock(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - if (doUnlock(s, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setNewsig(char *s, char *t, connectionRecType *context) -{ - if ((s == NULL) || (t == NULL)) return rtStandardError; - if (doNewsig(s, t, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setDelsig(char *s, connectionRecType *context) -{ - if (s == NULL) return rtStandardError; - if (doDelsig(s, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setSetp(char *s, char *p, connectionRecType *context) -{ - if ((s == NULL) || (p == NULL)) return rtStandardError; - if (doSetp(s, p, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setSets(char *s, char *p, connectionRecType *context) -{ - if ((s == NULL) || (p == NULL)) return rtStandardError; - if (doSets(s, p, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setAddf(char *s, char *t, char *p, connectionRecType *context) -{ - if ((s == NULL) || (t == NULL)) return rtStandardError; - if (doAddf(s, t, p, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setDelf(char *s, char *t, connectionRecType *context) -{ - if ((s == NULL) || (t == NULL)) return rtStandardError; - if (doDelf(s, t, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setSave(char *type, char *fileName, connectionRecType *context) -{ - if (doSave(type, fileName, context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setStart(connectionRecType *context) -{ - if (doStart(context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -static cmdResponseType setStop(connectionRecType *context) -{ - if (doStop(context) == 0) - return rtNoError; - else - return rtCustomHandledError; -} - -#define MAX_TOKENS 5 - -int commandSet(connectionRecType *context) -{ - static char *setNakStr = "SET NAK\n\r"; - static char *setCmdNakStr = "SET %s NAK\n\r"; - static char *ackStr = "SET %s ACK\n\r"; - halCommandType cmd; - char *tokens[MAX_TOKENS]; - int i; - char *pch; - char *pcmd; - int retval; - cmdResponseType ret = rtNoError; - - pcmd = strtok(NULL, delims); - if (pcmd == NULL) { - retval = write(context->cliSock, setNakStr, strlen(setNakStr)); - return 0; - } - strupr(pcmd); - cmd = lookupHalCommand(pcmd); - if ((cmd >= hcCommProt) && (context->cliSock != enabledConn)) { - sprintf(context->outBuf, setCmdNakStr, pcmd); - retval = write(context->cliSock, context->outBuf, strlen(context->outBuf)); - return 0; - } - pch = strtok(NULL, delims); - i = 0; - while (pch != NULL) { - tokens[i] = pch; - i++; - pch = strtok(NULL, delims); - } - switch (cmd) { - case hcEcho: ret = setEcho(tokens[0], context); break; - case hcVerbose: ret = setVerbose(tokens[0], context); break; - case hcEnable: ret = setEnable(tokens[0], context); break; - case hcConfig: ret = setConfig(tokens[0], context); break; - case hcCommMode: ret = setCommMode(tokens[0], context); break; - case hcCommProt: ret = setCommProt(tokens[0], context); break; - case hcComps: break; - case hcPins: break; - case hcPinVals: break; - case hcSigs: break; - case hcSigVals: break; - case hcParams: break; - case hcParamVals: break; - case hcFuncts: break; - case hcThreads: break; - case hcComp: break; - case hcPin: break; - case hcPinVal: break; - case hcSig: break; - case hcSigVal: break; - case hcParam: break; - case hcParamVal: break; - case hcFunct: break; - case hcThread: break; - case hcLoadRt: ret = setLoadRt(tokens[0], context); break; - case hcUnload: ret = setUnload(tokens[0], context); break; - case hcLoadUsr: ret = setLoadUsr(tokens[0], context); break; - case hcLinkps: setLinkps(tokens[0], tokens[1], context); break; - case hcLinksp: setLinksp(tokens[0], tokens[1], context); break; - case hcLinkpp: setLinkpp(tokens[0], tokens[1], context); break; - case hcNet: setNet(tokens[0], context); break; - case hcUnlinkp: setUnlink(tokens[0], context); break; - case hcLock: setLock(tokens[0], context); break; - case hcUnlock: setUnlock(tokens[0], context); break;; - case hcNewSig: setNewsig(tokens[0], tokens[1], context); break; - case hcDelSig: setDelsig(tokens[0], context); break; - case hcSetP: setSetp(tokens[0], tokens[1], context); break; - case hcSetS: setSets(tokens[0], tokens[1], context); break; - case hcAddF: setAddf(tokens[0], tokens[1], tokens[2], context); break; - case hcDelF: setDelf(tokens[0], tokens[1], context); break; - case hcSave: setSave(tokens[0], tokens[1], context); break; - case hcStart: setStart(context); break; - case hcStop: setStop(context); break; - case hcUnknown: ret = rtStandardError; - } - switch (ret) { - case rtNoError: - if (context->verbose) { - sprintf(context->outBuf, ackStr, pcmd); - retval = write(context->cliSock, context->outBuf, strlen(context->outBuf)); - } - break; - case rtHandledNoError: // Custom ok response already handled, take no action - break; - case rtStandardError: - sprintf(context->outBuf, setCmdNakStr, pcmd); - retval = write(context->cliSock, context->outBuf, strlen(context->outBuf)); - break; - case rtCustomError: // Custom error response entered in buffer - retval = write(context->cliSock, context->outBuf, strlen(context->outBuf)); - break; - case rtCustomHandledError: ;// Custom error respose handled, take no action - } - return 0; -} - -int commandQuit(connectionRecType *context) -{ - printf("Closing connection with %s\n", context->hostName); - return -1; -} - -int commandShutdown(connectionRecType *context) -{ - if (context->cliSock == enabledConn) { - printf("Shutting down\n"); - hal_flag = 1; - hal_exit(comp_id); - exit(0); - return -1; - } - else - return 0; -} - -static int helpGeneral(connectionRecType *context) -{ - sprintf(context->outBuf, "Available commands:\n\r"); - strcat(context->outBuf, " Hello \n\r"); - strcat(context->outBuf, " Get \n\r"); - strcat(context->outBuf, " Set \n\r"); - strcat(context->outBuf, " Quit\n\r"); - strcat(context->outBuf, " Shutdown\n\r"); - strcat(context->outBuf, " Help \n\r"); - sockWrite(context); - return 0; -} - -static int helpHello(connectionRecType *context) -{ - sprintf(context->outBuf, "Usage:\n\r"); - strcat(context->outBuf, " Hello \n\rWhere:\n\r"); - strcat(context->outBuf, " Password is the connection password to allow communications with the CNC server.\n\r"); - strcat(context->outBuf, " Client Name is the name of client trying to connect, typically the network name of the client.\n\r"); - strcat(context->outBuf, " Protocol Version is the version of the protocol with which the client wishes to use.\n\r\n\r"); - strcat(context->outBuf, " With valid password, server responds with:\n\r"); - strcat(context->outBuf, " Hello Ack \n\rWhere:\n\r"); - strcat(context->outBuf, " Ack is acknowledging the connection has been made.\n\r"); - strcat(context->outBuf, " Server Name is the name of the EMC Server to which the client has connected.\n\r"); - strcat(context->outBuf, " Protocol Version is the cleint requested version or latest version support by server if"); - strcat(context->outBuf, " the client requests a version later than that supported by the server.\n\r\n\r"); - strcat(context->outBuf, " With invalid password, the server responds with:\n\r"); - strcat(context->outBuf, " Hello Nak\n\r"); - sockWrite(context); - return 0; -} - -static int helpGet(connectionRecType *context) -{ - sprintf(context->outBuf, "Usage:\n\rGet \n\r"); - strcat(context->outBuf, " Get commands require that a hello has been successfully negotiated.\n\r"); - strcat(context->outBuf, " Emc command may be one of:\n\r"); - strcat(context->outBuf, " Comm_mode\n\r"); - strcat(context->outBuf, " Comm_prot\n\r"); - strcat(context->outBuf, " Comp outBuf, " Comps\n\r"); - strcat(context->outBuf, " Echo\n\r"); - strcat(context->outBuf, " Enable\n\r"); - strcat(context->outBuf, " Funct \n\r"); - strcat(context->outBuf, " Functs\n\r"); - strcat(context->outBuf, " Param \n\r"); - strcat(context->outBuf, " Params\n\r"); - strcat(context->outBuf, " ParamVal \n\r"); - strcat(context->outBuf, " ParamVals\n\r"); - strcat(context->outBuf, " Pin \n\r"); - strcat(context->outBuf, " PinVal \n\r"); - strcat(context->outBuf, " Pins\n\r"); - strcat(context->outBuf, " PinVals\n\r"); - strcat(context->outBuf, " Signal \n\r"); - strcat(context->outBuf, " Signals\n\r"); - strcat(context->outBuf, " SigVal \n\r"); - strcat(context->outBuf, " SigVals\n\r"); - strcat(context->outBuf, " Thread \n\r"); - strcat(context->outBuf, " Threads\n\r"); - strcat(context->outBuf, " Verbose\n\r"); -// strcat(outBuf, "CONFIG\n\r"); - sockWrite(context); - return 0; -} - -static int helpSet(connectionRecType *context) -{ - sprintf(context->outBuf, "Usage:\n\r Set \n\r"); - strcat(context->outBuf, " Set commands require that a hello has been successfully negotiated,\n\r"); - strcat(context->outBuf, " in most instances requires that control be enabled by the connection.\n\r"); - strcat(context->outBuf, " The set commands not requiring control enabled are:\n\r"); - strcat(context->outBuf, " Comm_mode \n\r"); - strcat(context->outBuf, " Comm_prot \n\r"); - strcat(context->outBuf, " Echo \n\r"); - strcat(context->outBuf, " Enable \n\r"); - strcat(context->outBuf, " Verbose \n\r\n\r"); - strcat(context->outBuf, " The set commands requiring control enabled are:\n\r"); - strcat(context->outBuf, " Addf []\n\r"); - strcat(context->outBuf, " Delf \n\r"); - strcat(context->outBuf, " DelSig \n\r"); - strcat(context->outBuf, " Linkpp \n\r"); - strcat(context->outBuf, " Linkps \n\r"); - strcat(context->outBuf, " Linksp \n\r"); - strcat(context->outBuf, " Loadrt \n\r"); - strcat(context->outBuf, " Loadusr [ .. ]\n\r"); - strcat(context->outBuf, " Lock \n\r"); - strcat(context->outBuf, " Net [ .. \n\r"); - strcat(context->outBuf, " NewSig \n\r"); - strcat(context->outBuf, " Save [ []]\n\r"); - strcat(context->outBuf, " Setp \n\r"); - strcat(context->outBuf, " Sets \n\r"); - strcat(context->outBuf, " Start\n\r"); - strcat(context->outBuf, " Stop\n\r"); - strcat(context->outBuf, " Unlink \n\r"); - strcat(context->outBuf, " Unload \n\r"); - strcat(context->outBuf, " Unlock \n\r"); - - sockWrite(context); - return 0; -} - -static int helpQuit(connectionRecType *context) -{ - sprintf(context->outBuf, "Usage:\n\r"); - strcat(context->outBuf, " The quit command has the server initiate a disconnect from the client,\n\r"); - strcat(context->outBuf, " the command has no parameters and no requirements to have negotiated\n\r"); - strcat(context->outBuf, " a hello, or be in control."); - sockWrite(context); - return 0; -} - -static int helpShutdown(connectionRecType *context) -{ - sprintf(context->outBuf, "Usage:\n\r"); - strcat(context->outBuf, " The shutdown command terminates the connection with all clients,\n\r"); - strcat(context->outBuf, " and initiates a shutdown of EMC. The command has no parameters, and\n\r"); - strcat(context->outBuf, " can only be issued by the connection having control.\n\r"); - sockWrite(context); - return 0; -} - -static int helpHelp(connectionRecType *context) -{ - sprintf(context->outBuf, "If you need help on help, it is time to look into another line of work.\n\r"); - sockWrite(context); - return 0; -} - -int commandHelp(connectionRecType *context) -{ - char *pch; - - pch = strtok(NULL, delims); - if (pch == NULL) return (helpGeneral(context)); - strupr(pch); - printf("Command = %s", pch); - if (strcmp(pch, "HELLO") == 0) return (helpHello(context)); - if (strcmp(pch, "GET") == 0) return (helpGet(context)); - if (strcmp(pch, "SET") == 0) return (helpSet(context)); - if (strcmp(pch, "QUIT") == 0) return (helpQuit(context)); - if (strcmp(pch, "SHUTDOWN") == 0) return (helpShutdown(context)); - if (strcmp(pch, "HELP") == 0) return (helpHelp(context)); - sprintf(context->outBuf, "%s is not a valid command.", pch); - sockWrite(context); - return 0; -} - -commandTokenType lookupToken(char *s) -{ - commandTokenType i = cmdHello; - int temp; - - while (i < cmdUnknown) { - if (strcmp(commands[i], s) == 0) return i; -// (int)i += 1; - temp = i; - temp++; - i = (commandTokenType) temp; - } - return i; -} - -int parseCommand(connectionRecType *context) -{ - int ret = 0; - char *pch; - char s[64]; - static char *helloNakStr = "HELLO NAK\r\n"; - static char *helloAckStr = "HELLO ACK %s 1.1\r\n"; - static char *setNakStr = "SET NAK\r\n"; - - pch = strtok(context->inBuf, delims); - sprintf(s, helloAckStr, serverName); - if (pch != NULL) { - strupr(pch); - switch (lookupToken(pch)) { - case cmdHello: - if (commandHello(context) == -1) - ret = write(context->cliSock, helloNakStr, strlen(helloNakStr)); - else - ret = write(context->cliSock, s, strlen(s)); - break; - case cmdGet: - ret = commandGet(context); - break; - case cmdSet: - if (context->linked == 0) - ret = write(context->cliSock, setNakStr, strlen(setNakStr)); - else ret = commandSet(context); - break; - case cmdQuit: - ret = commandQuit(context); - break; - case cmdShutdown: - ret = commandShutdown(context); - break; - case cmdHelp: - ret = commandHelp(context); - break; - case cmdUnknown: ret = -2; - } - } - return ret; -} - -void *readClient(void *arg) -{ - char str[1600]; - char buf[1600]; - unsigned int i, j; - int len; - int ret; - connectionRecType *context; - - -// res = 1; - context = (connectionRecType *) malloc(sizeof(connectionRecType)); - context->cliSock = client_sockfd; - context->linked = 0; - context->echo = 1; - context->verbose = 0; - strcpy(context->version, "1.0"); - strcpy(context->hostName, "Default"); - connCount++; - context->commMode = 0; - context->commProt = 0; - context->inBuf[0] = 0; - buf[0] = 0; - - while (1) { - len = read(context->cliSock, &str, 1600); - if (len <= 0) goto finished; - str[len] = 0; - strcat(buf, str); - if (!memchr(str, 0x0d, strlen(str))) continue; - if ((context->echo == 1) && (context->linked) == 1) - ret = write(context->cliSock, &buf, strlen(buf)); - i = 0; - j = 0; - while (i <= strlen(buf)) { - if ((buf[i] != '\n') && (buf[i] != '\r')) { - context->inBuf[j] = buf[i]; - j++; - } - else - if (j > 0) - { - context->inBuf[j] = 0; - if (parseCommand(context) == -1) goto finished; - j = 0; - } - i++; - } - buf[0] = 0; - } - -finished: - close(context->cliSock); - free(context); - pthread_exit((void *)0); -} - -/*********************************************************************** -* MAIN PROGRAM * -************************************************************************/ - - /* main() is responsible for parsing command line options, and then - parsing either a single command from the command line or a series - of commands from a file or standard input. It breaks the command[s] - into tokens, and passes them to parse_cmd() which does the actual - work for each command. -*/ - -int sockMain() -{ - pthread_t thrd; - int res; - - while (1) { - - client_len = sizeof(client_address); - client_sockfd = accept(server_sockfd, - (struct sockaddr *)&client_address, &client_len); - if (client_sockfd < 0) exit(0); - res = pthread_create(&thrd, NULL, readClient, (void *)NULL); - if (res != 0) - close(client_sockfd); - } - return 0; -} - -int main(int argc, char **argv) -{ - int n, fd; - int errorcount; - int opt; - char *cp1, *filename = NULL; - FILE *srcfile = NULL; - - /* set default level of output - 'quiet' */ - rtapi_set_msg_level(RTAPI_MSG_ERR); - /* set default for other options */ - // process halrmt command line args - while((opt = getopt_long(argc, argv, "e:n:p:s:w:", longopts, NULL)) != -1) { - switch(opt) { - case 'e': strncpy(enablePWD, optarg, strlen(optarg) + 1); break; - case 'n': strncpy(serverName, optarg, strlen(optarg) + 1); break; - case 'p': sscanf(optarg, "%d", &port); break; - case 's': sscanf(optarg, "%d", &maxSessions); break; - case 'w': strncpy(pwd, optarg, strlen(optarg) + 1); break; - } - } - - /* start parsing halcmd options */ - n = optind; - while ((n < argc) && (argv[n][0] == '-')) { - cp1 = argv[n++]; - /* loop to parse grouped options */ - while (*(++cp1) != '\0') { - switch (*cp1) { - case 'R': - /* force an unlock of the HAL mutex - to be used after a segfault in a hal program */ - if (release_HAL_mutex() < 0) { - printf("halrmt: Release Mutex failed!\n"); - return 1; - } - return 0; - break; - case 'h': - /* -h = help */ - if (argc > n) { /* there are more arguments, n has been incremented already */ - do_help_cmd(argv[n]); - } else - print_help_general(1); - return 0; - break; - case 'q': - /* -q = quiet (default) */ - rtapi_set_msg_level(RTAPI_MSG_ERR); - break; - case 'Q': - /* -Q = very quiet */ - rtapi_set_msg_level(RTAPI_MSG_NONE); - break; - case 's': - /* script friendly mode */ - scriptmode = 1; - break; - case 'v': - /* -v = verbose */ - rtapi_set_msg_level(RTAPI_MSG_INFO); - break; - case 'V': - /* -V = very verbose */ - rtapi_set_msg_level(RTAPI_MSG_ALL); - break; - case 'f': - /* -f = read from file (or stdin) */ - if (srcfile == NULL) { - /* it's the first -f (ignore repeats) */ - if ((n < argc) && (argv[n][0] != '-')) { - /* there is a following arg, and it's not an option */ - filename = argv[n++]; - srcfile = fopen(filename, "r"); - if (srcfile == NULL) { - fprintf(stderr, - "Could not open command file '%s'\n", - filename); - exit(-1); - } - /* make sure file is closed on exec() */ - fd = fileno(srcfile); - fcntl(fd, F_SETFD, FD_CLOEXEC); - } else { - /* no filename followed -f option, use stdin */ - srcfile = stdin; - prompt_mode = 1; - } - } - break; -#ifndef NO_INI - case 'i': - /* -i = allow reading 'setp' values from an ini file */ - if (inifile == NULL) { - /* it's the first -i (ignore repeats) */ - if ((n < argc) && (argv[n][0] != '-')) { - /* there is a following arg, and it's not an option */ - filename = argv[n++]; - inifile = fopen(filename, "r"); - if (inifile == NULL) { - fprintf(stderr, - "Could not open ini file '%s'\n", - filename); - exit(-1); - } - /* make sure file is closed on exec() */ - fd = fileno(inifile); - fcntl(fd, F_SETFD, FD_CLOEXEC); - } else { - /* no filename followed -i option, error */ - fprintf(stderr, - "No missing ini filename for -i option\n"); - exit(-1); - } - } - break; -#endif /* NO_INI */ - default: - /* unknown option */ - printf("Unknown option '-%c'\n", *cp1); - break; - } - } - } - signal(SIGINT, quit); - signal(SIGTERM, quit); - signal(SIGPIPE, SIG_IGN); - /* at this point all options are parsed, connect to HAL */ - /* create a unique module name, to allow for multiple halrmt's */ - snprintf(comp_name, HAL_NAME_LEN, "halrmt%d", getpid()); - /* tell the signal handler that we might have the mutex */ - hal_flag = 1; - /* connect to the HAL */ - comp_id = hal_init(comp_name); - /* done with mutex */ - hal_flag = 0; - /* check result */ - if (comp_id < 0) { - fprintf(stderr, "halrmt: hal_init() failed: %d\n", comp_id ); - fprintf(stderr, "NOTE: 'rtapi' kernel module must be loaded\n" ); - return 1; - } - hal_ready(comp_id); - errorcount = 0; - initSockets(); - /* HAL init is OK, let's process the command(s) */ - /* tell the signal handler we might have the mutex */ - sockMain(); - hal_flag = 1; - hal_exit(comp_id); - if ( errorcount > 0 ) { - return 1; - } else { - return 0; - } -} - diff --git a/src/hal/vtable-example/Submakefile b/src/hal/vtable-example/Submakefile index 6e94fb5ef0..f3ad69666b 100644 --- a/src/hal/vtable-example/Submakefile +++ b/src/hal/vtable-example/Submakefile @@ -4,18 +4,8 @@ INCLUDES += $(VTABLEEXAMPLE_DIR) ../include/%.h: ./$(VTABLEEXAMPLE_DIR)/%.h cp $^ $@ -obj-m += vtexport.o -vtexport-objs := \ - $(VTABLEEXAMPLE_DIR)/vtexport.o \ - $(VTABLEEXAMPLE_DIR)/vcode.o +$(eval $(call c_comp_build_rules, \ + hal/vtable-example/vtexport.o, \ + hal/vtable-example/vcode.o)) -obj-m += vtuse.o -vtuse-objs := \ - $(VTABLEEXAMPLE_DIR)/vtuse.o \ - -ifneq "$(filter normal user-dso,$(BUILD_SYS))" "" -$(RTLIBDIR)/vtexport$(MODULE_EXT): \ - $(addprefix $(OBJDIR)/,$(vtexport-objs)) -$(RTLIBDIR)/vtuse$(MODULE_EXT): \ - $(addprefix $(OBJDIR)/,$(vtuse-objs)) -endif +$(eval $(call c_comp_build_rules,$(VTABLEEXAMPLE_DIR)/vtuse.o)) diff --git a/src/libnml/posemath/sincos.c b/src/libnml/posemath/sincos.c index 101d7bb059..232a9df26d 100644 --- a/src/libnml/posemath/sincos.c +++ b/src/libnml/posemath/sincos.c @@ -6,7 +6,7 @@ * Author: * License: LGPL Version 2 * System: Linux -* +* * Copyright (c) 2004 All rights reserved. ********************************************************************/ /* @@ -19,10 +19,6 @@ #include "config.h" -#if defined(RTAPI) && !defined(BUILD_SYS_USER_DSO) -#undef HAVE_SINCOS -#endif - #ifndef HAVE_SINCOS #include "rtapi_math.h" diff --git a/src/machinekitcfg.py-tmp.in b/src/machinekitcfg.py-tmp.in index 167bbef38c..6f9518abaf 100644 --- a/src/machinekitcfg.py-tmp.in +++ b/src/machinekitcfg.py-tmp.in @@ -77,7 +77,6 @@ class Config(object): self.BUILD_DRIVERS="@BUILD_DRIVERS@" self.SUBST="@BUILD_DRIVERS@" self.MACHINEKIT_INI="@MACHINEKIT_INI@" - self.BUILD_THREAD_FLAVORS="@BUILD_THREAD_FLAVORS@" # Directories self.prefix="@prefix@" @@ -142,9 +141,7 @@ class Config(object): self.TARGET_PLATFORM_BEAGLEBONE = "@TARGET_PLATFORM_BEAGLEBONE@" self.TARGET_PLATFORM_RASPBERRY = "@TARGET_PLATFORM_RASPBERRY@" - self.USERMODE_PCI="@USERMODE_PCI@" - - #libudev for if USERMODE_PCI==yes + # libudev self.LIBUDEV_CFLAGS="@LIBUDEV_CFLAGS@" self.LIBUDEV_LIBS="@LIBUDEV_LIBS@" diff --git a/src/machinetalk/Submakefile b/src/machinetalk/Submakefile index 14dbd22fd7..94a691de2d 100644 --- a/src/machinetalk/Submakefile +++ b/src/machinetalk/Submakefile @@ -116,8 +116,6 @@ NANOPB_CFLAGS := -DPB_FIELD_32BIT '-DPB_SYSTEM_HEADER=<'$(MACHINETALK)'/include/ NANOPB_OPTIONS := $(MACHINETALK)/nanopb.options # any extra flags to C compile nanopb bindings -# this gets exported to RTFLAGS so dont add -fPIC here (stalls kthreads build) -# machinetalk/msgcomponents/Submakefile:RTFLAGS += $(PROTO_NANOPB_CFLAGS) PROTO_NANOPB_CFLAGS := $(NANOPB_CFLAGS) # nanopb library .h/.c files diff --git a/src/machinetalk/haltalk/Submakefile b/src/machinetalk/haltalk/Submakefile index 2df9949284..dd6fa81348 100644 --- a/src/machinetalk/haltalk/Submakefile +++ b/src/machinetalk/haltalk/Submakefile @@ -17,6 +17,7 @@ HALTALK_CXXFLAGS := -DULAPI \ HALTALK_LDFLAGS := \ $(PROTOBUF_LIBS) \ $(UUID_LIBS) \ + $(ZMQ_LIBS) \ $(CZMQ_LIBS) \ $(JANSSON_LIBS) \ $(AVAHI_LIBS) \ @@ -28,6 +29,7 @@ $(call TOOBJSDEPS, $(HALTALK_SRCS)) : EXTRAFLAGS += $(HALTALK_CXXFLAGS) ../lib/libmtalk.so.0 \ ../lib/libmachinetalk-pb2++.so.0 \ ../lib/liblinuxcnchal.so.0 \ + ../lib/liblinuxcnculapi.so.0 \ ../lib/liblinuxcncini.so.0 $(ECHO) Linking $(notdir $@) $(Q)$(CC) -o $@ $^ $(LDFLAGS) $(HALTALK_LDFLAGS) diff --git a/src/machinetalk/msgcomponents/Submakefile b/src/machinetalk/msgcomponents/Submakefile index dc0325867b..c3e699b982 100644 --- a/src/machinetalk/msgcomponents/Submakefile +++ b/src/machinetalk/msgcomponents/Submakefile @@ -7,8 +7,7 @@ MSGCOMP_DIR=machinetalk/msgcomponents RTFLAGS += $(PROTO_NANOPB_CFLAGS) -obj-m += pbmsgs.o -pbmsgs-objs := \ +$(eval $(call c_comp_build_rules,machinetalk/msgcomponents/pbmsgs.o, \ $(MSGCOMP_DIR)/pbmsgs.o \ $(PBGEN)/$(NAMESPACEDIR)/canon.npb.o \ $(PBGEN)/$(NAMESPACEDIR)/emcclass.npb.o \ @@ -27,18 +26,10 @@ pbmsgs-objs := \ $(PBGEN)/$(NAMESPACEDIR)/ros.npb.o \ $(PBGEN)/$(NAMESPACEDIR)/sample.npb.o \ $(PBGEN)/$(NAMESPACEDIR)/jplan.npb.o \ - $(PBGEN)/$(NAMESPACEDIR)/value.npb.o - - -#obj-m += pbring.o -#pbring-objs := $(MSGCOMP_DIR)/pbring.o - - -ifneq "$(filter normal user-dso,$(BUILD_SYS))" "" -$(RTLIBDIR)/pbmsgs$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pbmsgs-objs)) -#$(RTLIBDIR)/pbring$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(pbring-objs)) -endif + $(PBGEN)/$(NAMESPACEDIR)/value.npb.o \ +)) +#$$(eval $(call c_comp_build_rules,machinetalk/msgcomponents/pbring.o)) ../include/%.h: ./$(MSGCOMP_DIR)/%.h $(ECHO) Copying header file $@ diff --git a/src/module_helper/Submakefile b/src/module_helper/Submakefile deleted file mode 100644 index d19ae8ab1f..0000000000 --- a/src/module_helper/Submakefile +++ /dev/null @@ -1,15 +0,0 @@ -MODULE_HELPERSRCS := \ - module_helper/module_helper.c \ - rtapi/rtapi_compat.c -USERSRCS += $(MODULE_HELPERSRCS) - -$(call TOOBJSDEPS, $(MODULE_HELPERSRCS)) : \ - EXTRAFLAGS += -Wall -Werror $(THREADS_CFLAGS) - -../libexec/linuxcnc_module_helper: $(call TOOBJS, $(MODULE_HELPERSRCS)) \ - ../lib/liblinuxcncini.so.0 - $(ECHO) Linking $(notdir $@) - @mkdir -p $(dir $@) - $(Q)$(CXX) $(LDFLAGS) -o $@ $^ - -TARGETS += ../libexec/linuxcnc_module_helper diff --git a/src/module_helper/module_helper.c b/src/module_helper/module_helper.c deleted file mode 100644 index c67571c4ea..0000000000 --- a/src/module_helper/module_helper.c +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2006-2010, various authors -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -/* -This module_helper program, installed setuid, allows the user to add -and remove modules necessary to run LinuxCNC. It looks for modules in -the RTLIB_DIR directory, and if not found there, looks in RTDIR (if -defined; needed by RTAI only). - -Without a scheme like this, we have to rely on sudo to start AND EXIT -our program, and that may require the user to enter a password. -Prompting for a password to exit a program is bad. If the user -cancels at that phase of the run, it's also bad since we leave -realtime modules inserted and he'll probably end up being forced to -reboot. - -In summary, I don't like this any more than you do, but I can't -think of a better way. -*/ - -#include -#include -#include -#include -#include // PATH_MAX - -#include "rtapi.h" -#include "rtapi_compat.h" - -void error(int argc, char **argv) { - int i; - int res; - char *prog = argv[0]; - - /* drop root privs permanently */ - res = setuid(getuid()); - if(res != 0) - { - perror("setuid"); - exit(1); - } - - fprintf(stderr, "%s: Invalid usage with args:", argv[0]); - for(i=1; i -#include - -int main(int argc, char **argv) { - char *mod; - int i; - int inserting = 0; - int res; - char **exec_argv; - char modpath[PATH_MAX]; - - if(geteuid() != 0) { - fprintf(stderr, "module_helper is not setuid root\n"); - return 1; - } - /* drop root privs temporarily */ - res = seteuid(getuid()); - if(res != 0) - { - perror("seteuid"); - return 1; - } - - if(argc < 3) error(argc, argv); - if(strcmp(argv[1], "insert") && strcmp(argv[1], "remove")) error(argc, argv); - exec_argv = malloc(argc * sizeof(char *)); - - if(!strcmp(argv[1], "insert")) - inserting = 1; - - mod = argv[2]; - - if(inserting) { - // Construct the module path - if (module_path(modpath, mod) < 0) { - // Failed to find module path - fprintf(stderr, "%s: Unable to locate module '%s'\n", argv[0], - mod); - exit(1); - } - - exec_argv[0] = "/sbin/insmod"; - exec_argv[1] = modpath; - - for(i=3; i&1 | wc -l` - case $LINES in - 1) echo "Test OK: $@" ;; - *) echo "*** TEST FAILED ***" - echo "Test: $@" - echo "Output:" - "$@" 2>&1 ;; - esac -} - -FAIL () { - LINES=`"$@" 2>&1 | wc -l` - case $LINES in - 1) echo "*** TEST FAILED ***" - echo "Test: $@" - echo "Output:" - "$@" 2>&1 ;; - *) echo "Test OK: $@" ;; - esac -} - -# These should succeed -SUCCEED ./linuxcnc_module_helper insert /lib/modules/rtapi.ko -SUCCEED ./linuxcnc_module_helper insert /lib/modules/cheese/rtapi.o - -SUCCEED ./linuxcnc_module_helper remove rtapi - -# These should fail -FAIL ./linuxcnc_module_helper insert /lib/modules/../../rtapi.ko -FAIL ./linuxcnc_module_helper insert /lib/modules/rtapi.ok -FAIL ./linuxcnc_module_helper insert /lib/modules/rtapi.oo -FAIL ./linuxcnc_module_helper insert /lib/modules/rtapicheese.ko -FAIL ./linuxcnc_module_helper insert /lib/modules/r.ko -FAIL ./linuxcnc_module_helper insert /lib/modules/rtapi.cheese.ko -FAIL ./linuxcnc_module_helper insert /lib/modules/.cheese.ko -FAIL ./linuxcnc_module_helper insert /lib/modules/.ko - -FAIL ./linuxcnc_module_helper remove rtapicheese -FAIL ./linuxcnc_module_helper remove r -FAIL ./linuxcnc_module_helper remove rtapi.cheese diff --git a/src/regressions/check-tests/Submakefile b/src/regressions/check-tests/Submakefile index b38e3bbce5..b66a79d5cb 100644 --- a/src/regressions/check-tests/Submakefile +++ b/src/regressions/check-tests/Submakefile @@ -8,7 +8,7 @@ INCLUDES += $(CHECK_TESTS) TESTS = check_tests -check_PROGRAMS = ../bin/check_tests +check_PROGRAMS = ../bin/check_tests check_tests_SOURCES = $(addprefix $(CHECK_TESTS)/, \ timers.c \ check-util.c \ @@ -22,7 +22,7 @@ check_tests_LDADD = ../lib/libmtalk.so.0 \ ../lib/liblinuxcncini.so.0 $(call TOOBJSDEPS, $(check_tests_SOURCES)) : EXTRAFLAGS += \ - $(CHECK_CFLAGS) -DULAPI -DBUILD_SYS_USER_DSO -fPIC -pthread + $(CHECK_CFLAGS) -DULAPI -fPIC -pthread TARGETS += $(check_PROGRAMS) @@ -38,7 +38,7 @@ USERSRCS += $(check_tests_SOURCES) # /tmp/foo_ring_expanded-c.i: -# $(CC) -E $(CFLAGS) $(CHECK_CFLAGS) -DULAPI -DBUILD_SYS_USER_DSO -I. -Irtapi -x c -std=c11 \ +# $(CC) -E $(CFLAGS) $(CHECK_CFLAGS) -DULAPI -I. -Irtapi -x c -std=c11 \ # $(CHECK_TESTS)/check_tests.c | $(CB) > $@ # TARGETS += /tmp/foo_ring_expanded-c.i endif diff --git a/src/rtapi/.gitignore b/src/rtapi/.gitignore deleted file mode 100644 index 0118579203..0000000000 --- a/src/rtapi/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# ignore ulapi.so build artifacts -# - symlink hack to build separate ulapi.so per flavor -/posix -/rt-preempt -/xenomai -/rtai-kernel -/xenomai-kernel -/.flavor-*-link-create-stamp diff --git a/src/rtapi/README b/src/rtapi/README index 1284db0889..addb20cb3d 100644 --- a/src/rtapi/README +++ b/src/rtapi/README @@ -1,7 +1,7 @@ README for RTAPI -*-auto-fill-*- -RTAPI is a wrapper API that allows realtime programs to use either -RTLinux or RTAI with no code changes. +RTAPI is a wrapper API that allows realtime programs to use +RT_PREEMPT, POSIX or Xenomai threads with no code changes. Files: @@ -10,10 +10,6 @@ README : this file rtapi.h : decls for the generic RTAPI functions. rtapi_app.h : decls for the kernel modules rtapi_common.h : Collection of typedefs, etc, used internally by RTAPI. -procfs_macros.h : Macros used to implement the /proc interface -rtapi_proc.h : more stuff implementing the /proc interface -$(THREADS).h : Thread system-specific headers -$(THREADS).c : Thread system-specific definitions, esp. RTAPI hooks ../../Makefile.inc : contains compile-time flags, etc. diff --git a/src/rtapi/Submakefile b/src/rtapi/Submakefile index 7326b1bb3a..fe65515274 100644 --- a/src/rtapi/Submakefile +++ b/src/rtapi/Submakefile @@ -1,4 +1,4 @@ -INCLUDES += rtapi rtapi_export +INCLUDES += rtapi rtapi_export rtapi/flavor # this covers the userpci and shmdrv directories too, in a bit cludgy way ../include/%.h: ./rtapi/%.h @@ -14,53 +14,46 @@ INCLUDES += rtapi rtapi_export @mkdir -p ../include/shmdrv $(Q)cp $^ $@ -########################################## -# Separate sources hack -# -# ulapi.so needs sources to be built separately for each flavor. The -# Makefile rules, and TOOBJS & friends, always build the same source -# file into the same object file. -# -# Hack around this by creating a symlink 'rtapi/' that points -# back to the rtapi directory. Then the same source can be referred -# to as 'rtapi//foo.c' or 'rtapi//foo.c', and thus -# be built into separate object files. +../include/%.h: ./rtapi/flavor/%.h + $(ECHO) Copying header file $@ + @mkdir -p ../include/flavor + $(Q)cp $^ $@ -rtapi/$(threads)/%: rtapi/.flavor-$(threads)-link-create-stamp - @: # do nothing +ifeq ($(HAVE_XENOMAI_THREADS),yes) +XENOMAI_SRC = rtapi/flavor/xenomai.c +XENOMAI_HEADER = rtapi/flavor/xenomai.h +endif -rtapi/.flavor-$(threads)-link-create-stamp: - ln -s . rtapi/$(threads) - @touch $@ +HEADERS += \ + rtapi/flavor/rtapi_flavor.h \ + rtapi/flavor/rt-preempt.h \ + $(XENOMAI_HEADER) ########################################## # Clean up modclean: modclean-rtapi modclean-rtapi: - for flav in $(BUILD_THREAD_FLAVORS); do \ - rm -f rtapi/$$flav; \ - rm -f rtapi/.flavor-$$flav-link-create-stamp; \ - rm -f ../lib/ulapi-$$flav.so; \ - rm -f ../libexec/rtapi_app_$$flav; \ - done + rm -f ../libexec/rtapi_app .PHONY: modclean-rtapi ########################################## -# defaults for all thread styles +# Common to both RTAPI and ULAPI -# Sources/objects included in both RTAPI and ULAPI, both kbuild and -# user threads -XXAPI_COMMON_SRCS := \ +# Sources/objects included in both RTAPI and ULAPI +XXAPI_COMMON_SRCS := $(patsubst %, rtapi/%, \ + rtapi.c \ rtapi_support.c \ rtapi_hexdump.c \ - rtapi_common.c \ rtapi_task.c \ rtapi_shmem.c \ rtapi_time.c \ rtapi_exception.c \ rtapi_heap.c \ - $(THREADS_SOURCE).c + rtapi_compat.c \ + flavor/rtapi_flavor.c \ + flavor/rtapi_flavor_hook_wrappers.c \ + ) # rtapi_compat needs to know where rtapi.ini lives %/rtapi_compat.o: \ @@ -68,61 +61,23 @@ XXAPI_COMMON_SRCS := \ %/rtapi_compat.o: \ EXTRA_CFLAGS += -DEMC2_SYSTEM_CONFIG_DIR=\"$(EMC2_SYSTEM_CONFIG_DIR)\" -# ULAPI: ../lib/ulapi$THREADSTYLE.so (TBD) -# -# List of sources whose objects objects/rtapi/*.o link into -# ../lib/ulapi$THREADSTYLE.soiblinuxcnchal.so; -# -ULAPI_SRCS := \ - $(patsubst %,rtapi/$(threads)/%,$(XXAPI_COMMON_SRCS)) \ - rtapi/$(threads)/ulapi_main.c -ifeq ($(BUILD_SYS),kbuild) -ULAPI_SRCS += rtapi/$(threads)/rtapi_module.c -endif - -# resolved at loadtime -$(call TOOBJSDEPS, $(ULAPI_SRCS)): EXTRAFLAGS += \ - $(THREADS_RTFLAGS) -fPIC - -ULAPISO := ../rtlib/ulapi-$(threads).so - -$(ULAPISO): ../lib/liblinuxcnchal.so ../lib/liblinuxcncshm.so \ - $(call TOOBJS, $(ULAPI_SRCS)) - $(ECHO) Creating shared object $(notdir $@) - @mkdir -p ../rtlib - @rm -f $@ - $(Q)$(CC) $(LDFLAGS) -Wl,-soname,$(notdir $@) -shared \ - -o $@ $^ $(ULAPISO_LIBS) $(RT_LDFLAGS) \ - ../lib/liblinuxcncshm.so \ - ../lib/liblinuxcnchal.so - -# Plumb in the ulapi-.so build during 2nd-level recursive make -# modules run -ifeq ($(BUILD_THREAD_MODULES),yes) -USERSRCS += $(ULAPI_SRCS) -modules: $(ULAPISO) -endif - ################################################################## -# The ulapi autoload library -# -# provides ULAPI with loading-on-first-reference of RTAPI methods +# The ulapi library ################################################################## -ULAPI_AUTOLOAD_SRCS := \ - rtapi/ulapi_autoload.c \ - rtapi/rtapi_compat.c \ +ULAPI_SRCS := \ + rtapi/flavor/ulapi.c \ + machinetalk/lib/syslog_async.c \ rtapi/rtapi_hexdump.c \ - rtapi/rtapi_support.c \ - machinetalk/lib/syslog_async.c + $(XXAPI_COMMON_SRCS) -USERSRCS += $(ULAPI_AUTOLOAD_SRCS) +USERSRCS += $(ULAPI_SRCS) -ULAPI_AUTOLOAD_LIB := ../lib/liblinuxcnculapi.so +ULAPI_LIB := ../lib/liblinuxcnculapi.so -$(call TOOBJSDEPS, $(ULAPI_AUTOLOAD_SRCS)): EXTRAFLAGS += -DULAPI -fPIC +$(call TOOBJSDEPS, $(ULAPI_SRCS)): EXTRAFLAGS += -fPIC -$(ULAPI_AUTOLOAD_LIB).0: $(call TOOBJS, $(ULAPI_AUTOLOAD_SRCS)) \ +$(ULAPI_LIB).0: $(call TOOBJS, $(ULAPI_SRCS)) \ ../lib/liblinuxcncini.so \ ../lib/liblinuxcncshm.so $(ECHO) Creating shared library $(notdir $@) @@ -130,20 +85,64 @@ $(ULAPI_AUTOLOAD_LIB).0: $(call TOOBJS, $(ULAPI_AUTOLOAD_SRCS)) \ @rm -f $@ $(Q)$(CC) $(LDFLAGS) -Wl,-rpath,$(EMC2_RTLIB_DIR) \ -Wl,-soname,$(notdir $@) -shared \ - -o $@ $^ -ldl $(RT_LDFLAGS) + -o $@ $^ -ldl -TARGETS += $(ULAPI_AUTOLOAD_LIB) $(ULAPI_AUTOLOAD_LIB).0 +TARGETS += $(ULAPI_LIB) $(ULAPI_LIB).0 ################################################################## -# rtapi_app - now all thread styles +# rtapi.so and flavor modules ################################################################## -# rtapi_app_ + +ifeq ($(HAS_SYS_IO),yes) +PCI_SRC:= rtapi/rtapi_pci.c +else +PCI_SRC:= +endif + +$(eval $(call c_comp_build_rules,rtapi/rtapi.o,$(patsubst %.c,%.o,\ + $(XXAPI_COMMON_SRCS) \ + rtapi/flavor/rt-preempt.c \ + $(XENOMAI_SRC) \ + $(PCI_SRC) \ + machinetalk/support/nanopb.c \ + machinetalk/nanopb/pb_decode.c \ + machinetalk/nanopb/pb_encode.c \ + machinetalk/nanopb/pb_common.c \ +))) + +ifeq ($(HAS_SYS_IO),yes) +# compile userland PCI support with udev cflags if any +$(call TORTOBJS, rtapi/rtapi_pci.c): EXTRAFLAGS += $(LIBUDEV_CFLAGS) +endif + +$(call TORTOBJS, rtapi/flavor/rt-preempt.c): \ + EXTRAFLAGS += $(LIBCGROUP_CFLAGS) + +# userland PCI support needs -ludev for rtapi.so +$(RTLIBDIR)/rtapi.so: EXTRA_LDFLAGS += \ + $(LIBUDEV_LIBS) $(RT_LDFLAGS) $(LIBCGROUP_LIBS) + +ifeq ($(HAVE_XENOMAI_THREADS),yes) +# Build xenomai_loader.so linked to Xenmai libs +$(eval $(call c_comp_build_rules,rtapi/flavor/xenomai_loader.o)) +$(RTLIBDIR)/xenomai_loader.so: \ + EXTRA_LDFLAGS += $(XENOMAI_LDFLAGS) + +# Set Xenomai CFLAGS +$(call TORTOBJS, $(XENOMAI_SRC)): \ + EXTRA_CFLAGS += $(XENOMAI_RTFLAGS) +$(call TORTOBJS, rtapi/flavor/xenomai_loader.c): \ + EXTRA_CFLAGS += $(XENOMAI_RTFLAGS) +endif + +################################################################## +# rtapi_app +################################################################## +# rtapi_app # -# A matching rtapi_app_ is built for each userland thread -# flavor at the same time as RTAPI module flavor builds. +# One rtapi_app is built for all userland thread flavors. # -# rtapi_app_ requires two sources plus one already in -# ulapi.so. +# rtapi_app requires two sources plus one already in ulapi.so. # rtapi_app symbols, and the "RT space" (components loaded via dlopen(3)) #------------------------------------------------------------------------ @@ -164,7 +163,7 @@ TARGETS += $(ULAPI_AUTOLOAD_LIB) $(ULAPI_AUTOLOAD_LIB).0 # API functions and no accidential symbol resolution can happen. # # Note these 'RT objects' (really shared libraries) run in the context of -# the rtapi_app_ process and hence shares symbols between rtapi_app +# the rtapi_app process and hence shares symbols between rtapi_app # and the RT objects. This introduces the chance that symbols used and # (and maybe accidentially exported by) rtapi_app are carried over into # the symbol set seen by the RT objects. @@ -226,10 +225,9 @@ TARGETS += $(ULAPI_AUTOLOAD_LIB) $(ULAPI_AUTOLOAD_LIB).0 RTAPI_APP_SRCS := \ - rtapi/$(threads)/rtapi_app.cc \ - rtapi/$(threads)/rtapi_compat.c \ - rtapi/$(threads)/rtapi_hexdump.c \ - rtapi/$(threads)/rtapi_support.c + rtapi/rtapi_app.cc \ + rtapi/rtapi_support.c \ + rtapi/rtapi_compat.c USERSRCS += $(RTAPI_APP_SRCS) @@ -239,10 +237,10 @@ ifeq ($(RUN_IN_PLACE),yes) RTAPI_APP_RPATH=-Wl,-rpath,$(LIB_DIR) endif -$(call TOOBJSDEPS, rtapi/$(threads)/rtapi_app.cc): EXTRAFLAGS = \ - $(PROTOBUF_CFLAGS) $(CZMQ_CFLAGS) $(LTTNG_UST_CFLAGS) +$(call TOOBJSDEPS, rtapi/rtapi_app.cc): \ + EXTRAFLAGS = $(PROTOBUF_CFLAGS) $(CZMQ_CFLAGS) $(LTTNG_UST_CFLAGS) -../libexec/rtapi_app_$(threads): \ +../libexec/rtapi_app: \ $(call TOOBJS, $(RTAPI_APP_SRCS)) \ ../lib/liblinuxcncini.so.0 \ ../lib/liblinuxcncshm.so \ @@ -257,92 +255,13 @@ $(call TOOBJSDEPS, rtapi/$(threads)/rtapi_app.cc): EXTRAFLAGS = \ -o $@ \ $^ \ $(LDFLAGS) \ - $($(THREADS)_THREADS_LDFLAGS) \ + $(THREADS_LDFLAGS) $(LIBUDEV_LIBS) \ $(PROTOBUF_LIBS) $(CZMQ_LIBS) $(LTTNG_UST_LIBS) \ -lstdc++ -ldl -luuid # $(LIBBACKTRACE) # already linked into libmtalk -modules: ../libexec/rtapi_app_$(threads) -################################################################## -# USERLAND THREAD STYLES -################################################################## -ifeq ($(BUILD_SYS),user-dso) -# Build only during real module build, i.e. when 'make modules -# threads=' -ifeq ($(BUILD_THREAD_MODULES),yes) - -# the rtapi.so module -obj-$(CONFIG_RTAPI) += rtapi.o - -rtapi-objs := \ - $(patsubst %.c,rtapi/%.o,$(XXAPI_COMMON_SRCS)) \ - rtapi/rtapi_main.o \ - rtapi/rtapi_compat.o -rtapi-objs += machinetalk/support/nanopb.o -rtapi-objs += machinetalk/nanopb/pb_decode.o -rtapi-objs += machinetalk/nanopb/pb_encode.o -rtapi-objs += machinetalk/nanopb/pb_common.o - - -ifeq ($(USERMODE_PCI),yes) - -# compile userland PCI support with udev cflags if any -$(call TOOBJSDEPS, rtapi/rtapi_pci.c): EXTRAFLAGS += $(LIBUDEV_CFLAGS) - -# link in userland PCI support into rtapi.so -rtapi-objs += rtapi/rtapi_pci.o - -# userland PCI support needs -ludev for rtapi.so -$(RTLIBDIR)/rtapi$(MODULE_EXT): EXTRA_LDFLAGS += $(LIBUDEV_LIBS) -endif - -$(RTLIBDIR)/rtapi$(MODULE_EXT): EXTRA_LDFLAGS += $(RT_LDFLAGS) - -# rule for kernel module, moved from src/Makefile -$(RTLIBDIR)/rtapi$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(rtapi-objs)) - -endif # BUILD_THREAD_MODULES - - -################################################################## -# KERNEL THREAD STYLES -################################################################## -else # BUILD_SYS == kbuild - -obj-$(CONFIG_RTAPI) += rtapi.o - -rtapi-objs := \ - $(patsubst %.c,rtapi/%.o,$(XXAPI_COMMON_SRCS)) \ - rtapi/rtapi_module.o -rtapi-objs += machinetalk/support/nanopb.o -rtapi-objs += machinetalk/nanopb/pb_decode.o -rtapi-objs += machinetalk/nanopb/pb_encode.o -rtapi-objs += machinetalk/nanopb/pb_common.o - -# rule for kernel module, moved from src/Makefile -$(RTLIBDIR)/rtapi$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(rtapi-objs)) - -endif # BUILD_SYS == kbuild - -################################################################## -# the kdetect test program -################################################################## -RTAPI_KDETECT_SRCS = rtapi/rtapi_kdetect.c -USERSRCS += $(RTAPI_KDETECT_SRCS) -RTAPI_KDETECT_OBJS := \ - $(call TOOBJS, $(RTAPI_KDETECT_SRCS)) - -$(call TOOBJSDEPS, $(RTAPI_KDETECT_SRCS)): \ - EXTRAFLAGS += -DTEST - -# Build target -../libexec/kdetect: $(RTAPI_KDETECT_OBJS) ../lib/liblinuxcnchal.so - $(ECHO) Linking $(notdir $@) - @mkdir -p $(dir $@) - $(Q)$(CC) $(LDFLAGS) -o $@ $^ -lrt -ldl - -TARGETS += ../libexec/kdetect +modules: ../libexec/rtapi_app ################################################################## # the rtapi message demon @@ -364,7 +283,7 @@ RTAPI_MSGD_CFLAGS := \ RTAPI_MSGD_LDFLAGS := \ $(PROTOBUF_LIBS) $(CZMQ_LIBS) $(AVAHI_LIBS) \ - -lstdc++ -ldl -luuid -latomic -lrt -lzmq + -lstdc++ -ldl -luuid -latomic -lzmq # $(LIBBACKTRACE) # already linked into libmtalk @@ -375,26 +294,14 @@ $(call TOOBJSDEPS, $(RTAPI_MSGD_SRCS)): \ ../lib/liblinuxcncshm.so \ ../lib/liblinuxcncini.so \ ../lib/libmtalk.so.0 \ - ../lib/libmachinetalk-pb2++.so + ../lib/libmachinetalk-pb2++.so $(ECHO) Linking $(notdir $@) @mkdir -p $(dir $@) - $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(RTAPI_MSGD_LDFLAGS) + $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(RTAPI_MSGD_LDFLAGS) -lrt $(ZMQ_LIBS) USERSRCS += $(RTAPI_MSGD_SRCS) TARGETS += ../libexec/rtapi_msgd -# lock debugging help plus a bit of API example -FLAVOR_SRCS = rtapi/flavor.c rtapi/rtapi_compat.c - -../libexec/flavor: $(call TOOBJS, $(FLAVOR_SRCS)) \ - ../lib/liblinuxcncshm.so ../lib/liblinuxcncini.so - $(ECHO) Linking $(notdir $@) - @mkdir -p $(dir $@) - $(Q)$(CC) $(LDFLAGS) -o $@ $^ -lrt - -USERSRCS += $(FLAVOR_SRCS) -TARGETS += ../libexec/flavor - ################################################################## # rtapi.ini config file ################################################################## @@ -404,3 +311,23 @@ TARGETS += ../libexec/flavor bash $< > $@ TARGETS += ../etc/linuxcnc/rtapi.ini + +################################################################## +# C unit tests +################################################################## + +# ULAPI: use -DULAPI XXAPI_COMMON_SRCS +$(eval $(call setup_test,rtapi/tests/rtapi_flavor, ULAPI,\ + $(XXAPI_COMMON_SRCS) machinetalk/lib/syslog_async.c rtapi/flavor/ulapi.c,\ + , \ + ../lib/liblinuxcncshm.so ../lib/liblinuxcncini.so, \ + , \ + flavor_can_run_flavor getenv)) + +# RTAPI: use -DRTAPI XXAPI_COMMON_SRCS; link in pthreads and libcgroup +$(eval $(call setup_test,rtapi/tests/rtapi_flavor, RTAPI,\ + machinetalk/lib/syslog_async.c rtapi/flavor/ulapi.c, \ + $(XXAPI_COMMON_SRCS) rtapi/flavor/rt-preempt.c $(XENOMAI_SRC), \ + ../lib/liblinuxcncshm.so ../lib/liblinuxcncini.so, \ + -pthread $(LIBCGROUP_LIBS), \ + flavor_can_run_flavor getenv)) diff --git a/src/rtapi/chkenv.c b/src/rtapi/chkenv.c index 871e0fa3f1..e844ae7181 100644 --- a/src/rtapi/chkenv.c +++ b/src/rtapi/chkenv.c @@ -11,12 +11,11 @@ struct passwd *pw; char path[80]; char *flavour = NULL; char *id = NULL; -char *build_sys = NULL; pw = getpwuid(getuid()); strcpy(path, pw->pw_dir); strcat(path, "/.bashrc"); - + FILE *fp; fp = fopen((const char *) path, "a+"); flavour = getenv ("FLAVOR"); @@ -24,18 +23,14 @@ char *build_sys = NULL; // occurs if .bashrc has `export FLAVOR=$(flavor)` say, but flavor binary not built yet if (flavour == NULL || (flavour != NULL && strlen(flavour) < 2)) fprintf(fp, "\nexport FLAVOR=$(echo $(flavor))\n"); - + id = getenv ("FLAVOR_ID"); if (id == NULL || (flavour != NULL && strlen(flavour) < 2)) fprintf(fp, "\nexport FLAVOR_ID=$(echo $(flavor -d))\n"); - - build_sys = getenv ("BUILD_SYS"); - if (build_sys == NULL || (flavour != NULL && strlen(flavour) < 2)) - fprintf(fp, "\nexport BUILD_SYS=$(echo $(flavor -b))\n"); - + fclose(fp); - - if(flavour == NULL | id == NULL | build_sys == NULL) + + if(flavour == NULL | id == NULL) { printf("Shell environment was incomplete - update bash shell\n"); return (1); diff --git a/src/rtapi/flavor.c b/src/rtapi/flavor.c deleted file mode 100644 index 2f7f74bba3..0000000000 --- a/src/rtapi/flavor.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2012, 2013 Michael Haberler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -// inspect the current default flavor. - -#include "rtapi.h" - -#include -#include -#include -#include "config.h" - -#include -#include -#include -#include - -#include "rtapi.h" -#include "rtapi_compat.h" - -int shmdrv_loaded; -size_t page_size; - -int main(int argc, char **argv) -{ - char *progname = argv[0]; - flavor_ptr flavor; - - flavor = default_flavor(); - - if (!flavor) { - fprintf(stderr,"%s: could not detect default flavor\n", progname); - exit(1); - } - - if (argc == 1) { - printf("%s\n", flavor->name); - } else if (strcmp(argv[1],"-m") == 0) { - printf("%s\n", flavor->mod_ext); - } else if (strcmp(argv[1],"-b") == 0) { - printf("%s\n", flavor->build_sys); - } else if (strcmp(argv[1],"-d") == 0) { - printf("%d\n", flavor->flavor_id); - } else { - fprintf(stderr, "Unknown option '%s'\n",argv[1]); - exit(1); - } - exit(0); -} diff --git a/src/rtapi/rt-preempt.c b/src/rtapi/flavor/rt-preempt.c similarity index 57% rename from src/rtapi/rt-preempt.c rename to src/rtapi/flavor/rt-preempt.c index aeedb7b265..847a5d35c2 100644 --- a/src/rtapi/rt-preempt.c +++ b/src/rtapi/flavor/rt-preempt.c @@ -3,8 +3,8 @@ * * This file, 'rt-preempt.c', implements the unique * functions for the RT_PREEMPT thread system. -* -* Copyright (C) 2012, 2013 Michael Büsch , +* +* Copyright (C) 2012, 2013 Michael Büsch , * John Morris , * Michael Haberler * @@ -12,23 +12,29 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ********************************************************************/ -#include "config.h" + +#include "rtapi_flavor.h" +#include "rt-preempt.h" #include "rtapi.h" #include "rtapi_common.h" #include +#include "config.h" +#include // sched_get_priority_*() +#include /* pthread_* */ + /*********************************************************************** * TASK FUNCTIONS * ************************************************************************/ @@ -43,11 +49,19 @@ #include // syscall(SYS_gettid); #include // prctl(PR_SET_NAME) +// if this exists, and contents is '1', it's RT_PREEMPT +#define PREEMPT_RT_SYSFS "/sys/kernel/realtime" + +// Access the rtpreempt_stats_t thread status object +#define FTS(ts) ((rtpreempt_stats_t *)&(ts->flavor)) +// Access the rtpreempt_exception_t thread exception detail object +#define FED(detail) ((rtpreempt_exception_t)detail.flavor) + /* Lock for task_array and module_array allocations */ static pthread_key_t task_key; static pthread_once_t task_key_once = PTHREAD_ONCE_INIT; -int _rtapi_task_self_hook(void); +int posix_task_self_hook(void); typedef struct { @@ -72,29 +86,9 @@ extra_task_data_t extra_task_data[RTAPI_MAX_TASKS + 1]; int have_cg; // true when libcgroup initialized successfully #endif /* RTAPI */ -#ifdef HAVE_RTAPI_GET_CLOCKS_HOOK -long long int _rtapi_get_clocks_hook(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000LL + ts.tv_nsec; -} - -#endif - - -int _rtapi_init(const char *modname) { - return _rtapi_next_handle(); -} - -int _rtapi_exit(int module_id) { - /* do nothing for ULAPI */ - return 0; -} - #ifdef RTAPI -void _rtapi_module_init_hook(void) +int posix_module_init_hook(void) { int ret; @@ -105,9 +99,10 @@ void _rtapi_module_init_hook(void) else rtapi_print_msg(RTAPI_MSG_INFO, "libcgroup initialization failed: (%d) %s\n", ret, cgroup_strerror(ret)); + return ret; } #else -void _rtapi_module_init_hook(void) {} +int posix_module_init_hook(void) { return 0; } #endif #ifdef RTAPI @@ -119,14 +114,14 @@ static inline int task_id(task_data *task) { /*********************************************************************** * RT thread statistics update * ************************************************************************/ -int _rtapi_task_update_stats_hook(void) +int posix_task_update_stats_hook(void) { - int task_id = _rtapi_task_self_hook(); + int task_id = posix_task_self_hook(); // paranoia if ((task_id < 0) || (task_id > RTAPI_MAX_TASKS)) { rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_task_update_stats_hook: BUG -" + "rtapi_task_update_stats_hook: BUG -" " task_id out of range: %d\n", task_id); return -ENOENT; @@ -142,17 +137,17 @@ int _rtapi_task_update_stats_hook(void) rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; - ts->flavor.rtpreempt.utime_usec = ru.ru_utime.tv_usec; - ts->flavor.rtpreempt.utime_sec = ru.ru_utime.tv_sec; + FTS(ts)->utime_usec = ru.ru_utime.tv_usec; + FTS(ts)->utime_sec = ru.ru_utime.tv_sec; - ts->flavor.rtpreempt.stime_usec = ru.ru_stime.tv_usec; - ts->flavor.rtpreempt.stime_sec = ru.ru_stime.tv_sec; + FTS(ts)->stime_usec = ru.ru_stime.tv_usec; + FTS(ts)->stime_sec = ru.ru_stime.tv_sec; - ts->flavor.rtpreempt.ru_minflt = ru.ru_minflt; - ts->flavor.rtpreempt.ru_majflt = ru.ru_majflt; - ts->flavor.rtpreempt.ru_nsignals = ru.ru_nsignals; - ts->flavor.rtpreempt.ru_nivcsw = ru.ru_nivcsw; - ts->flavor.rtpreempt.ru_nivcsw = ru.ru_nivcsw; + FTS(ts)->ru_minflt = ru.ru_minflt; + FTS(ts)->ru_majflt = ru.ru_majflt; + FTS(ts)->ru_nsignals = ru.ru_nsignals; + FTS(ts)->ru_nivcsw = ru.ru_nivcsw; + FTS(ts)->ru_nivcsw = ru.ru_nivcsw; ts->num_updates++; @@ -199,7 +194,7 @@ static task_data *rtapi_this_task() { return (task_data *)pthread_getspecific(task_key); } -int _rtapi_task_new_hook(task_data *task, int task_id) { +int posix_task_new_hook(task_data *task, int task_id) { void *stackaddr; stackaddr = malloc(task->stacksize); @@ -214,31 +209,34 @@ int _rtapi_task_new_hook(task_data *task, int task_id) { return task_id; } -void _rtapi_task_delete_hook(task_data *task, int task_id) { - int err; +int posix_task_delete_hook(task_data *task, int task_id) { + int err_cancel, err_join; void *returncode; /* Signal thread termination and wait for the thread to exit. */ if (!extra_task_data[task_id].deleted) { + rtapi_print_msg(RTAPI_MSG_DBG, "Deleting RT thread '%s'\n", task->name); extra_task_data[task_id].deleted = 1; // pthread_cancel() will get the thread out of any blocking system // calls listed under 'Cancellation points' in man 7 pthreads // read(), poll() being important ones - err = pthread_cancel(extra_task_data[task_id].thread); - if (err) + err_cancel = pthread_cancel(extra_task_data[task_id].thread); + if (err_cancel) rtapi_print_msg(RTAPI_MSG_ERR, "pthread_cancel() on RT thread '%s': %d %s\n", - task->name, err, strerror(err)); - err = pthread_join(extra_task_data[task_id].thread, &returncode); - if (err) + task->name, err_cancel, strerror(err_cancel)); + err_join = pthread_join(extra_task_data[task_id].thread, &returncode); + if (err_join) rtapi_print_msg(RTAPI_MSG_ERR, "pthread_join() on RT thread '%s': %d %s\n", - task->name, err, strerror(err)); + task->name, err_join, strerror(err_join)); } /* Free the thread stack. */ free(extra_task_data[task_id].stackaddr); extra_task_data[task_id].stackaddr = NULL; + + return err_cancel || err_join; } static int realtime_set_affinity(task_data *task) { @@ -249,7 +247,7 @@ static int realtime_set_affinity(task_data *task) { sizeof(set), &set); if (task->cpu > -1) { // CPU set explicitly if (!CPU_ISSET(task->cpu, &set)) { - rtapi_print_msg(RTAPI_MSG_ERR, + rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: realtime_set_affinity(%s): " "CPU %d not available\n", task->name, task->cpu); @@ -283,8 +281,8 @@ static int realtime_set_affinity(task_data *task) { task_id(task), task->name, use_cpu, strerror(errno)); return -EINVAL; } - rtapi_print_msg(RTAPI_MSG_INFO, - "realtime_set_affinity(): task %s assigned to CPU %d\n", + rtapi_print_msg(RTAPI_MSG_DBG, + "realtime_set_affinity(): task %s assigned to CPU %d\n", task->name, use_cpu); return 0; } @@ -328,8 +326,12 @@ static void *realtime_thread(void *arg) { task_id(task), extra_task_data[task_id(task)].tid, (task->flags & TF_NONRT) ? "non-RT" : "RT"); - if (realtime_set_affinity(task)) + if ((ret = realtime_set_affinity(task))) { + rtapi_print_msg( + RTAPI_MSG_ERR, "Task '%s' realtime_set_affinity() failed %d\n", + task->name, ret); goto error; + } // cgroup cpuset if (task->cgname && task->cgname[0]) { @@ -350,23 +352,32 @@ static void *realtime_thread(void *arg) { task->name, task->cgname, cgroup_strerror(ret)); goto error; } - rtapi_print_msg(RTAPI_MSG_INFO, + rtapi_print_msg(RTAPI_MSG_DBG, "Moved task '%s' to cpuset '%s'", task->name, task->cgname); } if (!(task->flags & TF_NONRT)) { - if (realtime_set_priority(task)) { -#ifdef RTAPI_POSIX // This requires privs - tell user how to obtain them - rtapi_print_msg(RTAPI_MSG_ERR, - "to get non-preemptive scheduling with POSIX threads,"); - rtapi_print_msg(RTAPI_MSG_ERR, - "you need to run 'sudo setcap cap_sys_nice=pe libexec/rtapi_app_posix'"); - rtapi_print_msg(RTAPI_MSG_ERR, - "your might have to install setcap (e.g.'sudo apt-get install libcap2-bin') to do this."); -#else - goto error; -#endif - } + if ((ret = realtime_set_priority(task))) { + if (!(flavor_descriptor->flags && FLAVOR_IS_RT)) { + // This requires privs - tell user how to obtain them + rtapi_print_msg( + RTAPI_MSG_ERR, + "to get non-preemptive scheduling with POSIX threads,"); + rtapi_print_msg( + RTAPI_MSG_ERR, + "you need to run " + "'sudo setcap cap_sys_nice=pe libexec/rtapi_app_posix'"); + rtapi_print_msg( + RTAPI_MSG_ERR, + "you might have to install setcap " + "(e.g.'sudo apt-get install libcap2-bin') to do this."); + } else { + rtapi_print_msg( + RTAPI_MSG_ERR, "Task %s realtime_set_priority() failed %d", + task->name, ret); + goto error; + } + } } /* We're done initializing. Open the barrier. */ @@ -376,7 +387,7 @@ static void *realtime_thread(void *arg) { _rtapi_advance_time(&extra_task_data[task_id(task)].next_time, task->period + task->pll_correction, 0); - _rtapi_task_update_stats_hook(); // inital stats update + posix_task_update_stats_hook(); // inital stats update /* The task should not pagefault at all. So record initial counts now. * Note that currently we _do_ receive a few pagefaults in the @@ -391,9 +402,9 @@ static void *realtime_thread(void *arg) { } else { rtapi_threadstatus_t *ts = &global_data->thread_status[task_id(task)]; - ts->flavor.rtpreempt.startup_ru_nivcsw = ru.ru_nivcsw; - ts->flavor.rtpreempt.startup_ru_minflt = ru.ru_minflt; - ts->flavor.rtpreempt.startup_ru_majflt = ru.ru_majflt; + FTS(ts)->startup_ru_nivcsw = ru.ru_nivcsw; + FTS(ts)->startup_ru_minflt = ru.ru_minflt; + FTS(ts)->startup_ru_majflt = ru.ru_majflt; } } @@ -409,37 +420,58 @@ static void *realtime_thread(void *arg) { return NULL; error: /* Signal that we're dead and open the barrier. */ + rtapi_print_msg(RTAPI_MSG_ERR,"Deleting task %s\n", task->name); extra_task_data[task_id(task)].deleted = 1; pthread_barrier_wait(&extra_task_data[task_id(task)].thread_init_barrier); return NULL; } -int _rtapi_task_start_hook(task_data *task, int task_id) { +int posix_task_start_hook(task_data *task, int task_id) { pthread_attr_t attr; int retval; +#define TRY_OR_ERR(func_call, func_name) \ + do { \ + if ((retval = func_call)) { \ + rtapi_print_msg(RTAPI_MSG_ERR, "Thread %s %s() failed %d\n", \ + task->name, func_name, retval); \ + return -retval; \ + } \ + } while (0) + extra_task_data[task_id].deleted = 0; - pthread_barrier_init(&extra_task_data[task_id].thread_init_barrier, - NULL, 2); - pthread_attr_init(&attr); - pthread_attr_setstack(&attr, extra_task_data[task_id].stackaddr, - task->stacksize); + TRY_OR_ERR(pthread_barrier_init( + &extra_task_data[task_id].thread_init_barrier, NULL, 2), + "pthread_barrier_init"); + + TRY_OR_ERR(pthread_attr_init(&attr), "pthread_attr_init"); + + TRY_OR_ERR(pthread_attr_setstack( + &attr, extra_task_data[task_id].stackaddr, task->stacksize), + "pthread_attr_setstack"); + rtapi_print_msg(RTAPI_MSG_DBG, "About to pthread_create task %d\n", task_id); retval = pthread_create(&extra_task_data[task_id].thread, - &attr, realtime_thread, (void *)task); - rtapi_print_msg(RTAPI_MSG_DBG,"Created task %d\n", task_id); - pthread_attr_destroy(&attr); + &attr, realtime_thread, (void *)task); + + rtapi_print_msg(RTAPI_MSG_DBG, + "Created task %s (%d)\n", task->name, task_id); + TRY_OR_ERR(pthread_attr_destroy(&attr), "pthread_attr_destroy"); if (retval) { - pthread_barrier_destroy - (&extra_task_data[task_id].thread_init_barrier); - rtapi_print_msg(RTAPI_MSG_ERR, "Failed to create realtime thread\n"); - return -ENOMEM; + rtapi_print_msg(RTAPI_MSG_ERR, "Thread %s pthread_create() failed; " + "cleaning up\n", task->name); + TRY_OR_ERR(pthread_barrier_destroy + (&extra_task_data[task_id].thread_init_barrier), + "pthread_barrier_destroy"); + return -retval; } /* Wait for the thread to do basic initialization. */ pthread_barrier_wait(&extra_task_data[task_id].thread_init_barrier); - pthread_barrier_destroy(&extra_task_data[task_id].thread_init_barrier); + TRY_OR_ERR(pthread_barrier_destroy( + &extra_task_data[task_id].thread_init_barrier), + "pthread_barrier_destroy"); if (extra_task_data[task_id].deleted) { /* The thread died in the init phase. */ rtapi_print_msg(RTAPI_MSG_ERR, @@ -447,16 +479,17 @@ int _rtapi_task_start_hook(task_data *task, int task_id) { return -ENOMEM; } rtapi_print_msg(RTAPI_MSG_DBG, - "Task %d finished its basic init\n", task_id); + "Task %s (%d) finished basic init\n", task->name, task_id); return 0; } -void _rtapi_task_stop_hook(task_data *task, int task_id) { +int posix_task_stop_hook(task_data *task, int task_id) { extra_task_data[task_id].destroyed = 1; + return 0; } -int _rtapi_wait_hook(const int flags) { +int posix_wait_hook(const int flags) { struct timespec ts; task_data *task = rtapi_this_task(); @@ -478,25 +511,25 @@ int _rtapi_wait_hook(const int flags) { // timing went wrong: // update stats counters in thread status - _rtapi_task_update_stats_hook(); + posix_task_update_stats_hook(); rtapi_threadstatus_t *ts = &global_data->thread_status[task_id(task)]; - ts->flavor.rtpreempt.wait_errors++; + FTS(ts)->wait_errors++; -#ifndef RTAPI_POSIX - rtapi_exception_detail_t detail = {0}; - detail.task_id = task_id(task); + if (!(flavor_descriptor->flags && FLAVOR_IS_RT)) { + rtapi_exception_detail_t detail = {0}; + detail.task_id = task_id(task); - if (rt_exception_handler) - rt_exception_handler(RTP_DEADLINE_MISSED, &detail, ts); -#endif + if (rt_exception_handler) + rt_exception_handler(RTP_DEADLINE_MISSED, &detail, ts); + } } return 0; } -void _rtapi_delay_hook(long int nsec) +void posix_task_delay_hook(long int nsec) { struct timespec t; @@ -506,7 +539,7 @@ void _rtapi_delay_hook(long int nsec) } -int _rtapi_task_self_hook(void) { +int posix_task_self_hook(void) { int n; /* ask OS for pointer to its data for the current pthread */ @@ -524,15 +557,15 @@ int _rtapi_task_self_hook(void) { return -EINVAL; } -long long _rtapi_task_pll_get_reference_hook(void) { - int task_id = _rtapi_task_self_hook(); +long long posix_task_pll_get_reference_hook(void) { + int task_id = posix_task_self_hook(); if (task_id < 0) return 0; return extra_task_data[task_id].next_time.tv_sec * 1000000000LL + extra_task_data[task_id].next_time.tv_nsec; } -int _rtapi_task_pll_set_correction_hook(long value) { - int task_id = _rtapi_task_self_hook(); +int posix_task_pll_set_correction_hook(long value) { + int task_id = posix_task_self_hook(); task_data *task = &task_array[task_id]; if (task <= 0) return -EINVAL; if (value > task->pll_correction_limit) @@ -546,4 +579,128 @@ int _rtapi_task_pll_set_correction_hook(long value) { return 0; } +int kernel_is_rtpreempt() +{ + FILE *fd; + int retval = 0; + + if ((fd = fopen(PREEMPT_RT_SYSFS,"r")) != NULL) { + int flag; + retval = ((fscanf(fd, "%d", &flag) == 1) && (flag)); + fclose(fd); + } + return retval; +} + +int posix_can_run_flavor() +{ + return 1; +} + +int rtpreempt_can_run_flavor() +{ + return kernel_is_rtpreempt(); +} + + +void rtpreempt_print_thread_stats(int task_id) +{ + rtapi_threadstatus_t *ts = + &global_data->thread_status[task_id]; + + rtapi_print(" wait_errors=%d\t", + FTS(ts)->wait_errors); + rtapi_print("usercpu=%lduS\t", + FTS(ts)->utime_sec * 1000000 + + FTS(ts)->utime_usec); + rtapi_print("syscpu=%lduS\t", + FTS(ts)->stime_sec * 1000000 + + FTS(ts)->stime_usec); + rtapi_print("nsigs=%ld\n", + FTS(ts)->ru_nsignals); + rtapi_print(" ivcsw=%ld\t", + FTS(ts)->ru_nivcsw - + FTS(ts)->startup_ru_nivcsw); + rtapi_print(" minflt=%ld\t", + FTS(ts)->ru_minflt - + FTS(ts)->startup_ru_minflt); + rtapi_print(" majflt=%ld\n", + FTS(ts)->ru_majflt - + FTS(ts)->startup_ru_majflt); + rtapi_print("\n"); +} + + +void rtpreempt_exception_handler_hook(int type, + rtapi_exception_detail_t *detail, + int level) +{ + rtapi_threadstatus_t *ts = &global_data->thread_status[detail->task_id]; + switch ((rtpreempt_exception_id_t)type) { + // Timing violations + case RTP_DEADLINE_MISSED: + rtapi_print_msg(level, + "%d: Unexpected realtime delay on RT thread %d ", + type, detail->task_id); + rtpreempt_print_thread_stats(detail->task_id); + break; + + default: + rtapi_print_msg(level, + "%d: unspecified exception detail=%p ts=%p", + type, detail, ts); + + } +} + +flavor_descriptor_t flavor_rt_prempt_descriptor = { + .name = "rt-preempt", + .flavor_id = RTAPI_FLAVOR_RT_PREEMPT_ID, + .flags = FLAVOR_DOES_IO + FLAVOR_IS_RT, + .can_run_flavor = rtpreempt_can_run_flavor, + .exception_handler_hook = rtpreempt_exception_handler_hook, + .module_init_hook = posix_module_init_hook, + .module_exit_hook = NULL, + .task_update_stats_hook = NULL, + .task_print_thread_stats_hook = rtpreempt_print_thread_stats, + .task_new_hook = posix_task_new_hook, + .task_delete_hook = posix_task_delete_hook, + .task_start_hook = posix_task_start_hook, + .task_stop_hook = posix_task_stop_hook, + .task_pause_hook = NULL, + .task_wait_hook = posix_wait_hook, + .task_resume_hook = NULL, + .task_delay_hook = posix_task_delay_hook, + .get_time_hook = NULL, + .get_clocks_hook = NULL, + .task_self_hook = posix_task_self_hook, + .task_pll_get_reference_hook = posix_task_pll_get_reference_hook, + .task_pll_set_correction_hook = posix_task_pll_set_correction_hook +}; + +flavor_descriptor_t flavor_posix_descriptor = { + .name = "posix", + .flavor_id = RTAPI_FLAVOR_POSIX_ID, + .flags = 0, + .can_run_flavor = posix_can_run_flavor, + .exception_handler_hook = NULL, + .module_init_hook = posix_module_init_hook, + .module_exit_hook = NULL, + .task_update_stats_hook = NULL, + .task_print_thread_stats_hook = rtpreempt_print_thread_stats, + .task_new_hook = posix_task_new_hook, + .task_delete_hook = posix_task_delete_hook, + .task_start_hook = posix_task_start_hook, + .task_stop_hook = posix_task_stop_hook, + .task_pause_hook = NULL, + .task_wait_hook = posix_wait_hook, + .task_resume_hook = NULL, + .task_delay_hook = posix_task_delay_hook, + .get_time_hook = NULL, + .get_clocks_hook = NULL, + .task_self_hook = posix_task_self_hook, + .task_pll_get_reference_hook = posix_task_pll_get_reference_hook, + .task_pll_set_correction_hook = posix_task_pll_set_correction_hook +}; + #endif /* RTAPI */ diff --git a/src/rtapi/flavor/rt-preempt.h b/src/rtapi/flavor/rt-preempt.h new file mode 100644 index 0000000000..5056628c1b --- /dev/null +++ b/src/rtapi/flavor/rt-preempt.h @@ -0,0 +1,67 @@ +/******************************************************************** +* Description: rt-preempt.h +* RT_PREEMPT flavor descriptors +* +* +* Copyright (C) 2019 John Morris +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +********************************************************************/ + +#include "rtapi_flavor.h" + +typedef enum { + RTP_EXCEPTION_NONE=0, + + RTP_DEADLINE_MISSED, // clock_gettime(CLOCK_MONOTONIC) returned 'too late' + + RTP_EXCEPTION_LAST, + +} rtpreempt_exception_id_t; + +typedef struct { + // RTP_SIGNAL: unhandled signal: siginfo_t reference + // currently unused - signals handled in rtapi_app + void *siginfo; +} rtpreempt_exception_t; +// Check the exception struct size +ASSERT_SIZE_WITHIN(rtpreempt_exception_t, MAX_FLAVOR_EXCEPTION_SIZE); + +typedef struct { + + int wait_errors; // RT deadline missed + + // filled in by rtapi_thread_update_stats() RTAPI method + long utime_sec; // user CPU time used + long utime_usec; + + long stime_sec; // system CPU time used + long stime_usec; + + long ru_minflt; // page reclaims (soft page faults) + long ru_majflt; // page faults (hard page faults) + long ru_nsignals; // signals received + long ru_nivcsw; // involuntary context switches + + long startup_ru_minflt; // page fault counts at end of + long startup_ru_majflt; // initalisation + long startup_ru_nivcsw; // + +} rtpreempt_stats_t; +// Check the stats struct size +ASSERT_SIZE_WITHIN(rtpreempt_stats_t, MAX_FLAVOR_THREADSTATUS_SIZE); + +extern flavor_descriptor_t flavor_rt_prempt_descriptor; +extern flavor_descriptor_t flavor_posix_descriptor; diff --git a/src/rtapi/flavor/rtapi_flavor.c b/src/rtapi/flavor/rtapi_flavor.c new file mode 100644 index 0000000000..95837292cf --- /dev/null +++ b/src/rtapi/flavor/rtapi_flavor.c @@ -0,0 +1,170 @@ +#include // getenv + +#ifdef ULAPI +#include "ulapi.h" +#endif +#ifdef RTAPI +#include "rtapi_flavor.h" +#include "rt-preempt.h" +#endif +#ifdef HAVE_XENOMAI_THREADS +#include "xenomai.h" +#endif + +// Help for unit test mocking +int flavor_mocking = 0; // Signal from tests +int flavor_mocking_err = 0; // Pass error to tests +// - Mock exit(status), returning NULL and passing error out of band +#define EXIT_NULL(status) do { \ + if (flavor_mocking) { \ + flavor_mocking_err = status; return NULL; \ + } else exit(status); \ + } while (0) +// - Mock exit(status), returning (nothing) and passing error out of band +#define EXIT_NORV(status) do { \ + if (flavor_mocking) { \ + flavor_mocking_err = status; return; \ + } else exit(status); \ + } while (0) + + +// Global flavor descriptor gets set after a flavor is chosen +flavor_descriptor_ptr flavor_descriptor = NULL; + +// List of flavors compiled in +static flavor_descriptor_ptr flavor_list[] = { +#ifdef ULAPI + &flavor_ulapi_descriptor, +#endif +#ifdef RTAPI + &flavor_posix_descriptor, + &flavor_rt_prempt_descriptor, +# ifdef HAVE_XENOMAI_THREADS + &flavor_xenomai_descriptor, +# endif +#endif + NULL +}; + + +const char * flavor_names(flavor_descriptor_ptr ** fd) +{ + const char * name; + do { + if (*fd == NULL) + // Init to beginning of list + *fd = flavor_list; + else + // Go to next in list + (*fd)++; + } while (**fd != NULL && !flavor_can_run_flavor(**fd)); + + if (**fd == NULL) + // End of list; no name + name = NULL; + else + // Not end; return name + name = (**fd)->name; + return name; +} + +flavor_descriptor_ptr flavor_byname(const char *flavorname) +{ + flavor_descriptor_ptr * i; + for (i = flavor_list; *i != NULL; i++) { + if (!strcasecmp(flavorname, (*i)->name)) + break; + } + return *i; +} + +flavor_descriptor_ptr flavor_byid(rtapi_flavor_id_t flavor_id) +{ + flavor_descriptor_ptr * i; + for (i = flavor_list; *i != NULL; i++) { + if ((*i)->flavor_id == flavor_id) + break; + } + return *i; +} + +flavor_descriptor_ptr flavor_default(void) +{ + const char *fname = getenv("FLAVOR"); + flavor_descriptor_ptr * flavor_handle = NULL; + flavor_descriptor_ptr flavor = NULL; + + if (fname && fname[0]) { + // $FLAVOR set in environment: verify it or fail + flavor = flavor_byname(fname); + if (flavor == NULL) { + rtapi_print_msg(RTAPI_MSG_ERR, "FATAL: No such flavor '%s';" + " valid flavors are\n", fname); + for (flavor_handle=NULL; (fname=flavor_names(&flavor_handle)); ) + rtapi_print_msg(RTAPI_MSG_ERR, "FATAL: %s\n", + (*flavor_handle)->name); + EXIT_NULL(100); + } + if (!flavor_can_run_flavor(flavor)) { + rtapi_print_msg(RTAPI_MSG_ERR, "FATAL: Flavor '%s' from" + " environment cannot run\n", fname); + EXIT_NULL(101); + } else { + rtapi_print_msg(RTAPI_MSG_INFO, + "INFO: Picked flavor '%s' id %d (from environment)\n", + flavor->name, flavor->flavor_id); + return flavor; + } + + } else { + // Find best flavor automatically + flavor = NULL; + for (flavor_handle = flavor_list; + *flavor_handle != NULL; + flavor_handle++) { + // Best is highest ID that can run + if ( (!flavor || (*flavor_handle)->flavor_id > flavor->flavor_id) + && flavor_can_run_flavor(*flavor_handle) ) + flavor = (*flavor_handle); + } + if (!flavor) { + // This should never happen: POSIX can always run + rtapi_print_msg(RTAPI_MSG_ERR, + "ERROR: Unable to find runnable flavor\n"); + EXIT_NULL(102); + } else { + rtapi_print_msg(RTAPI_MSG_INFO, "INFO: Picked default flavor '%s'" + " automatically\n", flavor->name); + return flavor; + } + } +} + +void flavor_install(flavor_descriptor_ptr flavor) +{ + if (flavor_descriptor != NULL) { + rtapi_print_msg(RTAPI_MSG_ERR, "FATAL: Flavor '%s' already" + " configured\n", flavor_descriptor->name); + EXIT_NORV(103); + } + if (!flavor_can_run_flavor(flavor)) { + rtapi_print_msg(RTAPI_MSG_ERR, "FATAL: Flavor '%s' cannot run\n", + flavor->name); + EXIT_NORV(104); + } + flavor_descriptor = flavor; + rtapi_print_msg(RTAPI_MSG_DBG, "Installed flavor '%s'\n", flavor->name); +} + +int flavor_is_configured(void) +{ + return flavor_descriptor != NULL; +} + +#ifdef RTAPI +EXPORT_SYMBOL(flavor_names); +EXPORT_SYMBOL(flavor_is_configured); +EXPORT_SYMBOL(flavor_byname); +EXPORT_SYMBOL(flavor_default); +EXPORT_SYMBOL(flavor_install); +#endif diff --git a/src/rtapi/flavor/rtapi_flavor.h b/src/rtapi/flavor/rtapi_flavor.h new file mode 100644 index 0000000000..b2d810bd43 --- /dev/null +++ b/src/rtapi/flavor/rtapi_flavor.h @@ -0,0 +1,155 @@ +#ifndef RTAPI_FLAVOR_H +#define RTAPI_FLAVOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rtapi_common.h" + +// Flavor features: flavor_descriptor_t.flags bits for configuring flavor +// - Whether iopl() needs to be called +#define FLAVOR_DOES_IO RTAPI_BIT(0) +// - Whether flavor has hard real-time latency +#define FLAVOR_IS_RT RTAPI_BIT(1) +// - Whether flavor has hard real-time latency +#define FLAVOR_TIME_NO_CLOCK_MONOTONIC RTAPI_BIT(2) +// - Whether flavor runs outside RTAPI threads +#define FLAVOR_NOT_RTAPI RTAPI_BIT(3) + +#define MAX_FLAVOR_NAME_LEN 20 + +// The exception code puts structs in shm in an opaque blob; this is used to +// check the allocated storage is large enough +// https://stackoverflow.com/questions/807244/ +#define ASSERT_SIZE_WITHIN(type, size) \ + typedef char assertion_failed_##type##_[2*!!(sizeof(type) <= size)-1] + + +// Put these in order of preference + typedef enum RTAPI_FLAVOR_ID { + RTAPI_FLAVOR_UNCONFIGURED_ID = 0, + RTAPI_FLAVOR_ULAPI_ID, + RTAPI_FLAVOR_POSIX_ID, + RTAPI_FLAVOR_RT_PREEMPT_ID, + RTAPI_FLAVOR_XENOMAI_ID, + } rtapi_flavor_id_t; + + + // Hook type definitions for the flavor_descriptor_t struct + typedef int (*rtapi_can_run_flavor_t)(void); + typedef void (*rtapi_exception_handler_hook_t)( + int type, rtapi_exception_detail_t *detail, int level); + typedef int (*rtapi_module_init_hook_t)(void); + typedef void (*rtapi_module_exit_hook_t)(void); + typedef int (*rtapi_task_update_stats_hook_t)(void); + typedef void (*rtapi_print_thread_stats_hook_t)(int task_id); + typedef int (*rtapi_task_new_hook_t)(task_data *task, int task_id); + typedef int (*rtapi_task_delete_hook_t)(task_data *task, int task_id); + typedef int (*rtapi_task_start_hook_t)(task_data *task, int task_id); + typedef int (*rtapi_task_stop_hook_t)(task_data *task, int task_id); + typedef int (*rtapi_task_pause_hook_t)(task_data *task, int task_id); + typedef int (*rtapi_task_wait_hook_t)(const int flags); + typedef int (*rtapi_task_resume_hook_t)(task_data *task, int task_id); + typedef void (*rtapi_delay_hook_t)(long int nsec); + typedef long long int (*rtapi_get_time_hook_t)(void); + typedef long long int (*rtapi_get_clocks_hook_t)(void); + typedef int (*rtapi_task_self_hook_t)(void); + typedef long long (*rtapi_task_pll_get_reference_hook_t)(void); + typedef int (*rtapi_task_pll_set_correction_hook_t)(long value); + + // All flavor-specific data is represented in this struct + typedef struct { + const char *name; + const rtapi_flavor_id_t flavor_id; + const unsigned long flags; + const rtapi_can_run_flavor_t can_run_flavor; + rtapi_exception_handler_hook_t exception_handler_hook; + rtapi_module_init_hook_t module_init_hook; + rtapi_module_exit_hook_t module_exit_hook; + rtapi_task_update_stats_hook_t task_update_stats_hook; + rtapi_print_thread_stats_hook_t task_print_thread_stats_hook; + rtapi_task_new_hook_t task_new_hook; + rtapi_task_delete_hook_t task_delete_hook; + rtapi_task_start_hook_t task_start_hook; + rtapi_task_stop_hook_t task_stop_hook; + rtapi_task_pause_hook_t task_pause_hook; + rtapi_task_wait_hook_t task_wait_hook; + rtapi_task_resume_hook_t task_resume_hook; + rtapi_delay_hook_t task_delay_hook; + rtapi_get_time_hook_t get_time_hook; + rtapi_get_clocks_hook_t get_clocks_hook; + rtapi_task_self_hook_t task_self_hook; + rtapi_task_pll_get_reference_hook_t task_pll_get_reference_hook; + rtapi_task_pll_set_correction_hook_t task_pll_set_correction_hook; + } flavor_descriptor_t; + typedef flavor_descriptor_t * flavor_descriptor_ptr; + + // The global flavor_descriptor; points at the configured flavor + extern flavor_descriptor_ptr flavor_descriptor; + + // Wrappers around flavor_descriptor + typedef const char * (flavor_names_t)(flavor_descriptor_ptr ** fd); + extern flavor_names_t flavor_names; + typedef flavor_descriptor_ptr (flavor_byname_t)(const char *flavorname); + extern flavor_byname_t flavor_byname; + extern flavor_descriptor_ptr flavor_byid(rtapi_flavor_id_t flavor_id); + typedef flavor_descriptor_ptr (flavor_default_t)(void); + extern flavor_default_t flavor_default; + typedef int (flavor_is_configured_t)(void); + extern flavor_is_configured_t flavor_is_configured; + typedef void (flavor_install_t)(flavor_descriptor_ptr flavor_id); + extern flavor_install_t flavor_install; + + // Wrappers for functions in the flavor_descriptor_t + extern int flavor_can_run_flavor(flavor_descriptor_ptr f); + extern int flavor_exception_handler_hook( + flavor_descriptor_ptr f, int type, rtapi_exception_detail_t *detail, + int level); + extern int flavor_module_init_hook(flavor_descriptor_ptr f); + extern void flavor_module_exit_hook(flavor_descriptor_ptr f); + extern int flavor_task_update_stats_hook(flavor_descriptor_ptr f); + extern void flavor_task_print_thread_stats_hook( + flavor_descriptor_ptr f, int task_id); + extern int flavor_task_new_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern int flavor_task_delete_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern int flavor_task_start_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern int flavor_task_stop_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern int flavor_task_pause_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern int flavor_task_wait_hook(flavor_descriptor_ptr f, const int flags); + extern int flavor_task_resume_hook( + flavor_descriptor_ptr f, task_data *task, int task_id); + extern void flavor_task_delay_hook(flavor_descriptor_ptr f, long int nsec); + extern long long int flavor_get_time_hook(flavor_descriptor_ptr f); + extern long long int flavor_get_clocks_hook(flavor_descriptor_ptr f); + extern int flavor_task_self_hook(flavor_descriptor_ptr f); + extern long long flavor_task_pll_get_reference_hook( + flavor_descriptor_ptr f); + extern int flavor_task_pll_set_correction_hook( + flavor_descriptor_ptr f, long value); + + // Accessors for flavor_descriptor + typedef const char * (flavor_name_t)(flavor_descriptor_ptr f); + extern flavor_name_t flavor_name; + extern int flavor_id(flavor_descriptor_ptr f); + typedef int (flavor_feature_t)(flavor_descriptor_ptr f, int feature); + extern flavor_feature_t flavor_feature; + + // Prototype for plugin flavor descriptor updater + typedef void (*plugin_flavor_descriptor_updater_t)(flavor_descriptor_ptr); + + // Help for unit test mocking + extern int flavor_mocking; + extern int flavor_mocking_err; + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/rtapi/flavor/rtapi_flavor_hook_wrappers.c b/src/rtapi/flavor/rtapi_flavor_hook_wrappers.c new file mode 100644 index 0000000000..1c4e03e9df --- /dev/null +++ b/src/rtapi/flavor/rtapi_flavor_hook_wrappers.c @@ -0,0 +1,180 @@ +// These accessors make hook access slightly more convenient, and most important +// make mocking possible for unit testing. +// +// They must be in a separate file from functions calling them for mock calls to +// work. +#include "rtapi_flavor.h" + +#define SET_FLAVOR_DESCRIPTOR_DEFAULT() \ + do { if (f == NULL) f = flavor_descriptor; } while (0) +int flavor_can_run_flavor(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->can_run_flavor) + return f->can_run_flavor(); + else + return 1; +} +int flavor_exception_handler_hook( + flavor_descriptor_ptr f, int type, rtapi_exception_detail_t *detail, + int level) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->exception_handler_hook) { + f->exception_handler_hook(type, detail, level); + return 0; + } else + return -ENOSYS; // Unimplemented +} +int flavor_module_init_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->module_init_hook) + return f->module_init_hook(); + else + return 0; +} +void flavor_module_exit_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->module_exit_hook) + f->module_exit_hook(); +} +int flavor_task_update_stats_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_update_stats_hook) + return f->task_update_stats_hook(); + else + return 0; +} +void flavor_task_print_thread_stats_hook(flavor_descriptor_ptr f, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_print_thread_stats_hook) + f->task_print_thread_stats_hook(task_id); +} +int flavor_task_new_hook(flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (flavor_descriptor->task_new_hook) + return f->task_new_hook(task, task_id); + else + return -ENOSYS; // Unimplemented +} +int flavor_task_delete_hook( + flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_delete_hook) + return f->task_delete_hook(task, task_id); + else + return 0; +} +int flavor_task_start_hook( + flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + return f->task_start_hook(task, task_id); +} +int flavor_task_stop_hook( + flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + return f->task_stop_hook(task, task_id); +} +int flavor_task_pause_hook( + flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_pause_hook) + return f->task_pause_hook(task, task_id); + else + return 0; +} +int flavor_task_wait_hook(flavor_descriptor_ptr f, const int flags) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_wait_hook) + return f->task_wait_hook(flags); + else + return 0; +} +int flavor_task_resume_hook( + flavor_descriptor_ptr f, task_data *task, int task_id) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_resume_hook) + return f->task_resume_hook(task, task_id); + else + return -ENOSYS; // Unimplemented +} +void flavor_task_delay_hook(flavor_descriptor_ptr f, long int nsec) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->task_delay_hook) + f->task_delay_hook(nsec); +} +long long int flavor_get_time_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->get_time_hook) + return f->get_time_hook(); + else + return -ENOSYS; // Unimplemented +} +long long int flavor_get_clocks_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (f->get_clocks_hook) + return f->get_clocks_hook(); + else + return -ENOSYS; // Unimplemented +} +int flavor_task_self_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (flavor_descriptor->task_self_hook) + return f->task_self_hook(); + else + return -ENOSYS; +} +long long flavor_task_pll_get_reference_hook(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (flavor_descriptor->task_pll_get_reference_hook) + return f->task_pll_get_reference_hook(); + else + return 0; +} +int flavor_task_pll_set_correction_hook(flavor_descriptor_ptr f, long value) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + if (flavor_descriptor->task_pll_set_correction_hook) + return f->task_pll_set_correction_hook(value); + else + return 0; +} + +const char * flavor_name(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + return f->name; +} + +int flavor_id(flavor_descriptor_ptr f) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + return f->flavor_id; +} + +int flavor_feature(flavor_descriptor_ptr f, int feature) +{ + SET_FLAVOR_DESCRIPTOR_DEFAULT(); + return (f->flags & feature); +} + +#ifdef RTAPI +EXPORT_SYMBOL(flavor_name); +EXPORT_SYMBOL(flavor_feature); +#endif diff --git a/src/rtapi/flavor/ulapi.c b/src/rtapi/flavor/ulapi.c new file mode 100644 index 0000000000..fe6a1160c1 --- /dev/null +++ b/src/rtapi/flavor/ulapi.c @@ -0,0 +1,44 @@ +#include "rtapi_flavor.h" + +int ulapi_module_init_hook(void) { + if (global_data->magic != GLOBAL_READY) { + rtapi_print_msg(RTAPI_MSG_ERR, + "ULAPI:%d ERROR: global segment invalid magic:" + " expected: 0x%x, actual: 0x%x\n", + rtapi_instance, GLOBAL_READY, + global_data->magic); + return -EINVAL; + } + + rtapi_print_msg(RTAPI_MSG_DBG, "ulapi_init(): ulapi loaded\n"); + + // switch logging level to what was set in global via msgd: + rtapi_set_msg_level(global_data->user_msg_level); + return 0; +} + +flavor_descriptor_t flavor_ulapi_descriptor = { + .name = "ulapi", + .flavor_id = RTAPI_FLAVOR_ULAPI_ID, + .flags = FLAVOR_NOT_RTAPI, + .can_run_flavor = NULL, + .exception_handler_hook = NULL, + .module_init_hook = ulapi_module_init_hook, + .module_exit_hook = NULL, + .task_update_stats_hook = NULL, + .task_print_thread_stats_hook = NULL, + .task_new_hook = NULL, + .task_delete_hook = NULL, + .task_start_hook = NULL, + .task_stop_hook = NULL, + .task_pause_hook = NULL, + .task_wait_hook = NULL, + .task_resume_hook = NULL, + .task_delay_hook = NULL, + .get_time_hook = NULL, + .get_clocks_hook = NULL, + .task_self_hook = NULL, + .task_pll_get_reference_hook = NULL, + .task_pll_set_correction_hook = NULL +}; + diff --git a/src/rtapi/flavor/ulapi.h b/src/rtapi/flavor/ulapi.h new file mode 100644 index 0000000000..f951293062 --- /dev/null +++ b/src/rtapi/flavor/ulapi.h @@ -0,0 +1,25 @@ +/******************************************************************** +* Description: ulapi.h +* ULAPI flavor descriptors +* +* +* Copyright (C) 2019 John Morris +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +********************************************************************/ + +#include "rtapi_flavor.h" + +extern flavor_descriptor_t flavor_ulapi_descriptor; diff --git a/src/rtapi/flavor/xenomai.c b/src/rtapi/flavor/xenomai.c new file mode 100644 index 0000000000..1435eb5bdc --- /dev/null +++ b/src/rtapi/flavor/xenomai.c @@ -0,0 +1,218 @@ +/******************************************************************** +* Description: xenomai.c +* This file, 'xenomai.c', implements the unique +* functions for the Xenomai userland thread system. +* +* Copyright (C) 2012 - 2013 John Morris +* Michael Haberler +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +********************************************************************/ + +#include // stat() +#include // getgroups() +#include // calloc(), free(), exit() +#include // dlopen(), dlsym(), dlerror() + +#include "xenomai.h" +#include // XNHEAP_DEV_NAME +#define PROC_IPIPE_XENOMAI "/proc/ipipe/Xenomai" +#define XENO_GID_SYSFS "/sys/module/xeno_nucleus/parameters/xenomai_gid" + +#ifdef USE_SIGXCPU +#include /* sigaction/SIGXCPU handling */ +#endif + +/*********************************************************************** +* rtapi_main.c +*/ + +// Forward-declare the plugin loader +int load_xenomai_plugin(void); + +int xenomai_module_init_hook(void) +{ + if (! load_xenomai_plugin()) + return -1; + + +#ifdef USE_SIGXCPU + struct sigaction sig_act; + + sigemptyset( &sig_act.sa_mask ); + sig_act.sa_sigaction = signal_handler; + sig_act.sa_flags = SA_SIGINFO; + + // SIGXCPU delivery must be enabled within the thread by + // rt_task_set_mode(0, T_WARNSW, NULL); + // see _rtapi_task_wrapper() + if (sigaction(SIGXCPU, &sig_act, (struct sigaction *) NULL)) + rtapi_print_msg(RTAPI_MSG_ERR, + "rtapi_module_init_hook(sigaction): %d %s\n", + errno, strerror(errno)); +#endif + return 0; +} + +void xenomai_module_exit_hook(void) +{ +#ifdef USE_SIGXCPU + struct sigaction sig_act; + + // ignore SIGXCPU + sigemptyset( &sig_act.sa_mask ); + sig_act.sa_handler = SIG_IGN; + if (sigaction(SIGXCPU, &sig_act, (struct sigaction *) NULL)) + rtapi_print_msg(RTAPI_MSG_ERR, + "rtapi_module_exit_hook(sigaction): %d %s\n", + errno, strerror(errno)); +#endif +} + + + +int kernel_is_xenomai() +{ + struct stat sb; + + return ((stat(XNHEAP_DEV_NAME, &sb) == 0) && + (stat(PROC_IPIPE_XENOMAI, &sb) == 0) && + (stat(XENO_GID_SYSFS, &sb) == 0)); +} + +int xenomai_flavor_check(void); + +int xenomai_can_run_flavor() +{ + if (! kernel_is_xenomai()) + return 0; + + if (! xenomai_flavor_check()) + return 0; + + return 1; +} + +int xenomai_gid() +{ + FILE *fd; + int gid = -1; + + if ((fd = fopen(XENO_GID_SYSFS,"r")) != NULL) { + if (fscanf(fd, "%d", &gid) != 1) { + fclose(fd); + return -EBADF; // garbage in sysfs device + } else { + fclose(fd); + return gid; + } + } + return -ENOENT; // sysfs device cant be opened +} + +int user_in_xenomai_group() +{ + int numgroups, i; + gid_t *grouplist; + int gid = xenomai_gid(); + + if (gid < 0) + return gid; + + numgroups = getgroups(0,NULL); + grouplist = (gid_t *) calloc( numgroups, sizeof(gid_t)); + if (grouplist == NULL) + return -ENOMEM; + if (getgroups( numgroups, grouplist) > 0) { + for (i = 0; i < numgroups; i++) { + if (grouplist[i] == (unsigned) gid) { + free(grouplist); + return 1; + } + } + } else { + free(grouplist); + return errno; + } + return 0; +} + +int xenomai_flavor_check(void) { + // catch installation error: user not in xenomai group + int retval = user_in_xenomai_group(); + + switch (retval) { + case 1: // yes + break; + case 0: + fprintf(stderr, "this user is not member of group xenomai\n"); + fprintf(stderr, "please 'sudo adduser xenomai'," + " logout and login again\n"); + exit(EXIT_FAILURE); + + default: + fprintf(stderr, "cannot determine if this user " + "is a member of group xenomai: %s\n", + strerror(-retval)); + exit(EXIT_FAILURE); + } + return retval; +} + + + +// The Xenomai flavor descriptor data before loading the plugin +flavor_descriptor_t flavor_xenomai_descriptor = { + .name = "xenomai", + .flavor_id = RTAPI_FLAVOR_XENOMAI_ID, + .flags = FLAVOR_DOES_IO + FLAVOR_IS_RT + FLAVOR_TIME_NO_CLOCK_MONOTONIC, + .can_run_flavor = xenomai_can_run_flavor, + .module_init_hook = xenomai_module_init_hook, + .module_exit_hook = xenomai_module_exit_hook, + .task_pll_get_reference_hook = NULL, + .task_pll_set_correction_hook = NULL, + .task_new_hook = NULL, + // The following are set during module init when Xenomai libs are loaded + .task_update_stats_hook = NULL, + .exception_handler_hook = NULL, + .task_print_thread_stats_hook = NULL, + .task_delete_hook = NULL, + .task_start_hook = NULL, + .task_stop_hook = NULL, + .task_pause_hook = NULL, + .task_wait_hook = NULL, + .task_resume_hook = NULL, + .task_delay_hook = NULL, + .get_time_hook = NULL, + .get_clocks_hook = NULL, + .task_self_hook = NULL, +}; + +int load_xenomai_plugin(void) +{ + // Load the xenomai_loader.so module that does the real work + void *mod_handle = dlopen("xenomai_loader.so", RTLD_GLOBAL |RTLD_NOW); + if (!mod_handle) { + rtapi_print_msg(RTAPI_MSG_ERR, + "Unable to load xenomai_stub.so: %s\n", + dlerror()); + return -1; + } + // Fill out missing parts of the flavor descriptor + plugin_flavor_descriptor_updater_t xenomai_descriptor_updater = + dlsym(mod_handle, "xenomai_descriptor_updater"); + xenomai_descriptor_updater(&flavor_xenomai_descriptor); + return 0; +} diff --git a/src/rtapi/flavor/xenomai.h b/src/rtapi/flavor/xenomai.h new file mode 100644 index 0000000000..db39c194e8 --- /dev/null +++ b/src/rtapi/flavor/xenomai.h @@ -0,0 +1,69 @@ +/******************************************************************** +* Description: xenomai.h +* This file defines the differences specific to the +* the Xenomai user land thread system +* +* Copyright (C) 2012 - 2013 John Morris +* Michael Haberler +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +********************************************************************/ + +#include "rtapi_flavor.h" + +typedef enum { + XU_EXCEPTION_NONE=0, + + XU_SIGXCPU, // RT task switched to secondary domain + XU_SIGXCPU_BUG, // same, but failed to identify RT thread + XU_ETIMEDOUT, // release point was missed + XU_EWOULDBLOCK, // rt_task_wait_period() without previous rt_task_set_periodic() + XU_EINTR, // rt_task_unblock() called before release point + XU_EPERM, // cannot rt_task_wait_period() from this context + XU_UNDOCUMENTED, // unknown error code + + XU_EXCEPTION_LAST, + +} xenomai_exception_id_t; + +typedef struct { + // passed by ref from rt_task_wait_period() + unsigned long overruns; +} xenomai_exception_t; +// Check the exception struct size +ASSERT_SIZE_WITHIN(xenomai_exception_t, MAX_FLAVOR_EXCEPTION_SIZE); + +typedef struct { + // as reported by rt_task_inquire() + // filled in by rtapi_thread_updatestats(task_id) RTAPI call (TBD) + int modeswitches; + int ctxswitches; + int pagefaults; + long long exectime; // Execution time in primary mode in nanoseconds. + unsigned status; // T_BLOCKED etc. + + // errors returned by rt_task_wait_period(): + // set by -ETIMEDOUT: + int wait_errors; // total times the release point was missed + int total_overruns; // running count of the above + // the -EWOULDBLOCK and -EINTR returns are API violations + // and increment api_errors + + // all others increment other_errors +} xenomai_stats_t; +// Check the stats struct size +ASSERT_SIZE_WITHIN(xenomai_stats_t, MAX_FLAVOR_THREADSTATUS_SIZE); + +extern flavor_descriptor_t flavor_xenomai_descriptor; diff --git a/src/rtapi/xenomai.c b/src/rtapi/flavor/xenomai_loader.c similarity index 64% rename from src/rtapi/xenomai.c rename to src/rtapi/flavor/xenomai_loader.c index d35b4cee2c..e5ad357d63 100644 --- a/src/rtapi/xenomai.c +++ b/src/rtapi/flavor/xenomai_loader.c @@ -1,7 +1,12 @@ /******************************************************************** -* Description: xenomai.c -* This file, 'xenomai.c', implements the unique -* functions for the Xenomai userland thread system. +* Description: xenomai_loader.c +* +* Alongside `xenomai.c`, implement the unique functions for the Xenomai userland +* thread system. The Xenomai DLL .so libraries will exit the program if +* `/dev/rtheap` doesn't exist, so those libraries can't be linked directly +* against `rtapi.so` and still work in environments without Xenomai. The +* `xenomai.c` file checks to see whether Xenomai is available, and if so loads +* this code, built as a plugin linked against Xenomai libraries. * * Copyright (C) 2012 - 2013 John Morris * Michael Haberler @@ -21,60 +26,43 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ********************************************************************/ -#include "config.h" -#include "xenomai-common.h" -#include "rtapi.h" -#include "rtapi_common.h" +#include "xenomai.h" -#include /* munlockall() */ -#include XENOMAI_INCLUDE(task.h) /* RT_TASK, rt_task_*() */ -#include XENOMAI_INCLUDE(timer.h) /* rt_timer_*() */ -#include /* sigaction/SIGXCPU handling */ -#include -#include // getpid() -#include // cpu sets +#include // RT_TASK, rt_task_*() +#include // rt_timer_*() +#include // abort() -#ifdef RTAPI -#include XENOMAI_INCLUDE(mutex.h) -#include // abort() +#ifdef USE_SIGXCPU +#include // sigaction/SIGXCPU handling +#endif + +// Access the xenomai_stats_t thread status object +#define FTS(ts) ((xenomai_stats_t *)&(ts->flavor)) +// Access the xenomai_exception_t thread exception detail object +#define FTED(detail) ((xenomai_exception_t *)&(detail.flavor)) /* RTAPI task functions */ RT_TASK ostask_array[RTAPI_MAX_TASKS + 1]; // this is needed due to the weirdness of the rt_task_self return value - -// it does _not_ match the address of the RT_TASK structure it was +// it does _not_ match the address of the RT_TASK structure it was // created with RT_TASK *ostask_self[RTAPI_MAX_TASKS + 1]; -#endif // RTAPI +int xenomai_task_self_hook(void); -/* rtapi_init() and rtapi_exit() */ /*********************************************************************** -* INIT AND EXIT FUNCTIONS * -************************************************************************/ - -int _rtapi_init(const char *modname) { - - return _rtapi_next_handle(); -} - -int _rtapi_exit(int module_id) { - return 0; -} - -/*********************************************************************** -* RT thread statistics update * -************************************************************************/ -#ifdef RTAPI -int _rtapi_task_update_stats_hook(void) +* RT thread statistics update +*/ +int xenomai_task_update_stats_hook(void) { - int task_id = _rtapi_task_self(); + int task_id = xenomai_task_self_hook(); // paranoia if ((task_id < 0) || (task_id > RTAPI_MAX_TASKS)) { rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_task_update_stats_hook: BUG -" + "rtapi_task_update_stats_hook: BUG -" " task_id out of range: %d\n", task_id); return -ENOENT; @@ -92,27 +80,26 @@ int _rtapi_task_update_stats_hook(void) rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; #ifdef XENOMAI_V2 - ts->flavor.xeno.modeswitches = rtinfo.modeswitches; - ts->flavor.xeno.ctxswitches = rtinfo.ctxswitches; - ts->flavor.xeno.pagefaults = rtinfo.pagefaults; - ts->flavor.xeno.exectime = rtinfo.exectime; - ts->flavor.xeno.status = rtinfo.status; + FTS(ts)->modeswitches = rtinfo.modeswitches; + FTS(ts)->ctxswitches = rtinfo.ctxswitches; + FTS(ts)->pagefaults = rtinfo.pagefaults; + FTS(ts)->exectime = rtinfo.exectime; + FTS(ts)->status = rtinfo.status; #else - ts->flavor.xeno.modeswitches = rtinfo.stat.msw; - ts->flavor.xeno.ctxswitches = rtinfo.stat.csw; - ts->flavor.xeno.pagefaults = rtinfo.stat.pf; - ts->flavor.xeno.exectime = rtinfo.stat.xtime; - ts->flavor.xeno.status = rtinfo.stat.status; + FTS(ts)->modeswitches = rtinfo.stat.msw; + FTS(ts)->ctxswitches = rtinfo.stat.csw; + FTS(ts)->pagefaults = rtinfo.stat.pf; + FTS(ts)->exectime = rtinfo.stat.xtime; + FTS(ts)->status = rtinfo.stat.status; #endif ts->num_updates++; return task_id; } -#endif /*********************************************************************** -* Xenomai Domain switching handling * +* Xenomai Domain switching handling * * if an RT thread does something silly, like a system call * (e.g. write(2) caused by a printf()), the Xenomai scheduler will @@ -131,15 +118,15 @@ int _rtapi_task_update_stats_hook(void) * Update: this does not work reliably and is not strictly necessary * since thread stats will report domain switches anyway without a * signal handler. Better stay with synchronous reporting. -************************************************************************/ -#ifdef RTAPI +*/ + extern rtapi_exception_handler_t rt_exception_handler; #ifdef USE_SIGXCPU // trampoline to current handler static void signal_handler(int sig, siginfo_t *si, void *uctx) { - int task_id = _rtapi_task_update_stats_hook(); + int task_id = xenomai_task_update_stats_hook(); if (task_id > -1) { rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; @@ -155,58 +142,12 @@ static void signal_handler(int sig, siginfo_t *si, void *uctx) } } #endif -#endif - -/*********************************************************************** -* rtapi_main.c * -************************************************************************/ -#ifdef RTAPI -void _rtapi_module_init_hook(void) -{ - -#ifdef USE_SIGXCPU - struct sigaction sig_act; - - sigemptyset( &sig_act.sa_mask ); - sig_act.sa_sigaction = signal_handler; - sig_act.sa_flags = SA_SIGINFO; - - // SIGXCPU delivery must be enabled within the thread by - // rt_task_set_mode(0, T_WARNSW, NULL); - // see _rtapi_task_wrapper() - if (sigaction(SIGXCPU, &sig_act, (struct sigaction *) NULL)) - rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_module_init_hook(sigaction): %d %s\n", - errno, strerror(errno)); -#endif -} - -void _rtapi_module_exit_hook(void) -{ -#ifdef USE_SIGXCPU - struct sigaction sig_act; - - // ignore SIGXCPU - sigemptyset( &sig_act.sa_mask ); - sig_act.sa_handler = SIG_IGN; - if (sigaction(SIGXCPU, &sig_act, (struct sigaction *) NULL)) - rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_module_exit_hook(sigaction): %d %s\n", - errno, strerror(errno)); -#endif -} -#else -void _rtapi_module_init_hook(void) {} -void _rtapi_module_exit_hook(void) {} -#endif - /*********************************************************************** -* rtapi_task.c * -************************************************************************/ +* rtapi_task.c +*/ -#ifdef RTAPI -int _rtapi_task_delete_hook(task_data *task, int task_id) { +int xenomai_task_delete_hook(task_data *task, int task_id) { int retval = 0; if ((retval = rt_task_delete( &ostask_array[task_id] )) < 0) { @@ -257,9 +198,9 @@ void _rtapi_task_wrapper(void * task_id_hack) { rt_task_set_mode(0, T_WARNSW, NULL); #endif - _rtapi_task_update_stats_hook(); // initial recording + xenomai_task_update_stats_hook(); // initial recording - #ifdef TRIGGER_SIGXCPU_ONCE +#ifdef TRIGGER_SIGXCPU_ONCE // enable this for testing only: // this should cause a domain switch due to the write() // system call and hence a single SIGXCPU posted, @@ -271,16 +212,16 @@ void _rtapi_task_wrapper(void * task_id_hack) { /* call the task function with the task argument */ (task->taskcode) (task->arg); - + /* if the task ever returns, we record that fact */ task->state = ENDED; rtapi_print_msg(RTAPI_MSG_ERR, - "ERROR: reached end of wrapper for task %d '%s'\n", + "ERROR: reached end of wrapper for task %d '%s'\n", task_id, task->name); } -int _rtapi_task_start_hook(task_data *task, int task_id) { +int xenomai_task_start_hook(task_data *task, int task_id) { int which_cpu = 0; int uses_fpu = 0; int retval; @@ -310,7 +251,7 @@ int _rtapi_task_start_hook(task_data *task, int task_id) { int prio = (task->flags & TF_NONRT) ? 0 :task->prio; - if ((retval = rt_task_create (&ostask_array[task_id], task->name, + if ((retval = rt_task_create (&ostask_array[task_id], task->name, task->stacksize, prio, uses_fpu | which_cpu | T_JOINABLE) ) != 0) { @@ -337,7 +278,7 @@ int _rtapi_task_start_hook(task_data *task, int task_id) { return 0; } -int _rtapi_task_stop_hook(task_data *task, int task_id) { +int xenomai_task_stop_hook(task_data *task, int task_id) { int retval; if ((retval = rt_task_delete( &ostask_array[task_id] )) < 0) { @@ -349,15 +290,15 @@ int _rtapi_task_stop_hook(task_data *task, int task_id) { return 0; } -int _rtapi_task_pause_hook(task_data *task, int task_id) { +int xenomai_task_pause_hook(task_data *task, int task_id) { return rt_task_suspend( &ostask_array[task_id] ); } -int _rtapi_task_resume_hook(task_data *task, int task_id) { +int xenomai_task_resume_hook(task_data *task, int task_id) { return rt_task_resume( &ostask_array[task_id] ); } -int _rtapi_wait_hook(const int flags) { +int xenomai_wait_hook(const int flags) { if (flags & TF_NOWAIT) return 0; @@ -369,7 +310,7 @@ int _rtapi_wait_hook(const int flags) { // something went wrong: // update stats counters in thread status - int task_id = _rtapi_task_update_stats_hook(); + int task_id = xenomai_task_update_stats_hook(); // paranoid, but you never know; this index off and @@ -387,7 +328,7 @@ int _rtapi_wait_hook(const int flags) { rtapi_exception_detail_t detail = {0}; rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; - rtapi_exception_t type; + xenomai_exception_id_t type; // exception descriptor detail.task_id = task_id; @@ -398,11 +339,11 @@ int _rtapi_wait_hook(const int flags) { case -ETIMEDOUT: // release point was missed - detail.flavor.xeno.overruns = overruns; + FTED(detail)->overruns = overruns; // update thread status in global_data - ts->flavor.xeno.wait_errors++; - ts->flavor.xeno.total_overruns += overruns; + FTS(ts)->wait_errors++; + FTS(ts)->total_overruns += overruns; type = XU_ETIMEDOUT; break; @@ -446,7 +387,7 @@ int _rtapi_wait_hook(const int flags) { return 0; } -int _rtapi_task_self_hook(void) { +int xenomai_task_self_hook(void) { RT_TASK *ptr; int n; @@ -469,22 +410,18 @@ int _rtapi_task_self_hook(void) { return -EINVAL; } -#endif /* RTAPI */ - /*********************************************************************** -* rtapi_time.c * -************************************************************************/ +* rtapi_time.c +*/ -#ifdef RTAPI -void _rtapi_delay_hook(long int nsec) +void xenomai_task_delay_hook(long int nsec) { long long int release = rt_timer_read() + nsec; while (rt_timer_read() < release); } -#endif -long long int _rtapi_get_time_hook(void) { +long long int xenomai_get_time_hook(void) { /* The value returned will represent a count of jiffies if the native skin is bound to a periodic time base (see CONFIG_XENO_OPT_NATIVE_PERIOD), or nanoseconds otherwise. */ @@ -496,6 +433,110 @@ long long int _rtapi_get_time_hook(void) { other disgusting, non-realtime oriented behavior. But at least it doesn't take a week every time you call it. */ -long long int _rtapi_get_clocks_hook(void) { +long long int xenomai_get_clocks_hook(void) { return rt_timer_read(); } + + +void xenomai_print_thread_stats(int task_id) +{ + rtapi_threadstatus_t *ts = + &global_data->thread_status[task_id]; + + // generic statistics counters + rtapi_print(" updates=%d\t", ts->num_updates); + if (ts->num_updates) { + rtapi_print("api_err=%d\t", ts->api_errors); + rtapi_print("other_err=%d\n", ts->api_errors); + } + + rtapi_print(" wait_errors=%d\t", FTS(ts)->wait_errors); + rtapi_print("overruns=%d\t", FTS(ts)->total_overruns); + rtapi_print("modeswitches=%d\t", FTS(ts)->modeswitches); + rtapi_print("contextswitches=%d\n", FTS(ts)->ctxswitches); + rtapi_print(" pagefaults=%d\t", FTS(ts)->pagefaults); + rtapi_print("exectime=%llduS\t", FTS(ts)->exectime/1000); + rtapi_print("status=0x%x\n", FTS(ts)->status); + rtapi_print("\n"); +} + + +void xenomai_exception_handler_hook(int type, + rtapi_exception_detail_t *detail, + int level) +{ + rtapi_threadstatus_t *ts = &global_data->thread_status[detail->task_id]; + switch ((xenomai_exception_id_t)type) { + // Timing violations + case XU_ETIMEDOUT: + rtapi_print_msg(level, + "%d: Unexpected realtime delay on RT thread %d ", + type, detail->task_id); + xenomai_print_thread_stats(detail->task_id); + break; + // Xenomai User errors + case XU_SIGXCPU: // Xenomai Domain switch + rtapi_print_msg(level, + "%d: Xenomai Domain switch for thread %d", + type, detail->task_id); + xenomai_print_thread_stats(detail->task_id); + break; + case XU_EWOULDBLOCK: + rtapi_print_msg(level, + "API usage bug: rt_task_set_periodic() not called: " + "thread %d - errno %d", + detail->task_id, + detail->error_code); + break; + + case XU_EINTR: + rtapi_print_msg(level, + "API usage bug: rt_task_unblock() called before" + " release point: thread %d -errno %d", + detail->task_id, + detail->error_code); + break; + + case XU_EPERM: + rtapi_print_msg(level, + "API usage bug: cannot call service from current" + " context: thread %d - errno %d", + detail->task_id, + detail->error_code); + break; + + case XU_UNDOCUMENTED: + rtapi_print_msg(level, + "%d: unspecified Xenomai error: thread %d - errno %d", + type, + detail->task_id, + detail->error_code); + break; + + default: + rtapi_print_msg(level, + "%d: unspecified exception detail=%p ts=%p", + type, detail, ts); + } +} + +void xenomai_descriptor_updater(flavor_descriptor_ptr fd) +{ + // Update flavor descriptor with functions from this plugin + fd->task_update_stats_hook = xenomai_task_update_stats_hook; + fd->exception_handler_hook = xenomai_exception_handler_hook; + fd->task_print_thread_stats_hook = xenomai_print_thread_stats; + fd->task_delete_hook = xenomai_task_delete_hook; + fd->task_start_hook = xenomai_task_start_hook; + fd->task_stop_hook = xenomai_task_stop_hook; + fd->task_pause_hook = xenomai_task_pause_hook; + fd->task_wait_hook = xenomai_wait_hook; + fd->task_resume_hook = xenomai_task_resume_hook; + fd->task_delay_hook = xenomai_task_delay_hook; + fd->get_time_hook = xenomai_get_time_hook; + fd->get_clocks_hook = xenomai_get_clocks_hook; + fd->task_self_hook = xenomai_task_self_hook; +} + +// Not really needed except to keep the build system from barfing +EXPORT_SYMBOL(xenomai_descriptor_updater); diff --git a/src/rtapi/procfs_macros.h b/src/rtapi/procfs_macros.h deleted file mode 100644 index 8ba386d259..0000000000 --- a/src/rtapi/procfs_macros.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 1999-2014 Paolo Mantegazza - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _RTAI_PROC_FS_H -#define _RTAI_PROC_FS_H - -extern struct proc_dir_entry *rtai_proc_root; - -#include -#include - -#define PROC_READ_FUN(read_fun_name) \ - int read_fun_name(struct seq_file *pf, void *v) - -#define PROC_READ_WRITE_OPEN_OPS(rtai_proc_fops, \ - read_fun_name, write_fun_name) \ - \ - static int read_fun_name##_open(struct inode *inode, \ - struct file *file) { \ - return single_open(file, read_fun_name, NULL); \ - } \ - \ - static const struct file_operations rtai_proc_fops = { \ - .owner = THIS_MODULE, \ - .open = read_fun_name##_open, \ - .read = seq_read, \ - .write = write_fun_name, \ - .llseek = seq_lseek, \ - .release = single_release \ - }; - -#define PROC_READ_OPEN_OPS(rtai_proc_fops, read_fun_name) \ - PROC_READ_WRITE_OPEN_OPS(rtai_proc_fops, read_fun_name, NULL) - -static inline void *CREATE_PROC_ENTRY(const char *name, umode_t mode, - void *parent, - const struct file_operations *proc_fops) -{ - return !parent ? proc_mkdir(name, NULL) : - proc_create(name, mode, parent, proc_fops); -} - -#define SET_PROC_READ_ENTRY(entry, read_fun) do { } while(0) - -#define PROC_PRINT_VARS - -#define PROC_PRINT(fmt, args...) \ - do { seq_printf(pf, fmt, ##args); } while(0) - -#define PROC_PRINT_RETURN do { goto done; } while(0) - -#define PROC_PRINT_DONE do { return 0; } while(0) - -#endif /* !_RTAI_PROC_FS_H */ diff --git a/src/rtapi/rt-preempt.h b/src/rtapi/rt-preempt.h deleted file mode 100644 index b69bee8af0..0000000000 --- a/src/rtapi/rt-preempt.h +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************** -* Description: rt-preempt.h -* This file defines the differences specific to the -* the RT_PREEMPT thread system -* -* It should be included in rtapi_common.h -* -* -* Copyright (C) 2012, 2013 Michael Büsch , -* John Morris -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -/*********************************************************************** -* TASK FUNCTIONS * -************************************************************************/ - -#include "config.h" -#include // sched_get_priority_*() -#include /* pthread_* */ - -#if THREAD_FLAVOR_ID == RTAPI_POSIX_ID -#define FLAVOR_FLAGS POSIX_FLAVOR_FLAGS // see rtapi_compat.h -#endif - -#if THREAD_FLAVOR_ID == RTAPI_RT_PREEMPT_ID -#define FLAVOR_FLAGS RTPREEMPT_FLAVOR_FLAGS -#endif - -/* rtapi_task.c */ -#define PRIO_LOWEST sched_get_priority_min(SCHED_FIFO) -#define PRIO_HIGHEST sched_get_priority_max(SCHED_FIFO) - -#define HAVE_RTAPI_TASK_NEW_HOOK -#define HAVE_RTAPI_TASK_DELETE_HOOK -#define HAVE_RTAPI_TASK_STOP_HOOK -#define HAVE_RTAPI_WAIT_HOOK -#define HAVE_RTAPI_TASK_SELF_HOOK -#define HAVE_RTAPI_TASK_UPDATE_STATS_HOOK -#define HAVE_RTAPI_TASK_PLL_GET_REFERENCE_HOOK -#define HAVE_RTAPI_TASK_PLL_SET_CORRECTION_HOOK - -#if !defined(__i386__) && !defined(__x86_64__) -#define HAVE_RTAPI_GET_CLOCKS_HOOK // needed for e.g. ARM, see rtapi_time.c -#endif - - -/* rtapi_main.c */ -#define HAVE_RTAPI_MODULE_INIT_HOOK // init cgroups - -/* misc */ -#define HAVE_RTAPI_TASK_FREE -#define HAVE_DROP_RESTORE_PRIVS diff --git a/src/rtapi/rtai-kernel.c b/src/rtapi/rtai-kernel.c deleted file mode 100644 index acf76b5aa8..0000000000 --- a/src/rtapi/rtai-kernel.c +++ /dev/null @@ -1,230 +0,0 @@ -#include "config.h" -#include "rtapi.h" -#include "rtapi_common.h" - -#include -#include - -#ifdef MODULE -#include // udelay() -#endif - -#ifdef RTAPI -extern rtapi_exception_handler_t rt_exception_handler; -#endif - -/*********************************************************************** -* rtapi_time.c * -************************************************************************/ - -#ifdef RTAPI -void _rtapi_module_timer_stop(void) { - stop_rt_timer(); -#if RTAI_VERSION <= 400 - rt_free_timer(); -#else - rt_free_timers(); -#endif -} - - -void _rtapi_clock_set_period_hook(long int nsecs, RTIME *counts, - RTIME *got_counts) { - rt_set_periodic_mode(); - *counts = nano2count((RTIME) nsecs); - if(count2nano(*counts) > nsecs) (*counts)--; - *got_counts = start_rt_timer(*counts); - rtapi_data->timer_period = count2nano(*got_counts); -} - - -void _rtapi_delay_hook(long int nsec) -{ - udelay(nsec / 1000); -} - -long long int _rtapi_get_time_hook(void) { - //struct timeval tv; - - //AJ: commenting the following code out, as it seems on some systems it - // really breaks - - /* call the kernel's internal implementation of gettimeofday() */ - /* unfortunately timeval has only usec, struct timespec would be - better, it has nsec resolution. Doing this right probably - involves a number of ifdefs based on kernel version and such */ - /*do_gettimeofday(&tv);*/ - /* convert to nanoseconds */ - /*return (tv.tv_sec * 1000000000LL) + (tv.tv_usec * 1000L);*/ - - //reverted to old code for now - /* this is a monstrosity that seems to take several MICROSECONDS!!! - on some boxes. Why the RTAI folks even bothered I have no idea! - If you have any need for speed at all use _rtapi_get_clocks()!! - */ - return rt_get_cpu_time_ns(); -} -#endif /* RTAPI */ - - -/*********************************************************************** -* rtapi_task.c * -************************************************************************/ - -#ifdef RTAPI - -# if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) -# define IP(x) ((x)->ip) -# elif defined(__i386__) -# define IP(x) ((x)->eip) -# else -# define IP(x) ((x)->rip) -# endif - -static int _rtapi_trap_handler(int vec, int signo, struct pt_regs *regs, - void *task) { - int task_id = _rtapi_task_self(); - - rtapi_exception_detail_t detail = {0}; - - detail.task_id = task_id; - detail.flavor.rtai.vector = vec; - detail.flavor.rtai.signo = signo; - detail.flavor.rtai.ip = (exc_register_t) IP(regs); - - if (rt_exception_handler) - rt_exception_handler(RTAI_TRAP, &detail, - (task_id > -1) ? - &global_data->thread_status[task_id] : NULL); - - _rtapi_task_pause(task_id); - return 0; -} - - -static void _rtapi_task_wrapper(long task_id) { - task_data *task; - - /* point to the task data */ - task = &task_array[task_id]; - /* call the task function with the task argument */ - (task->taskcode) (task->arg); - /* if the task ever returns, we record that fact */ - task->state = ENDED; - /* and return to end the thread */ - return; -} - -int _rtapi_task_new_hook(task_data *task, int task_id) { - int retval, v; - retval = rt_task_init_cpuid(ostask_array[task_id], _rtapi_task_wrapper, - task_id, task->stacksize, task->prio, - task->uses_fp, 0 /* signal */, task->cpu); - if (retval) return retval; - - /* request to handle traps in the new task */ -#ifdef HAL_NR_FAULTS - for(v=0; v RTAPI_MAX_TASKS)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_wait_hook: BUG - task_id out of range: %d\n", - task_id); - return; - } - rtapi_exception_detail_t detail = {0}; - rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; - rtapi_exception_t type; - - detail.task_id = task_id; - detail.error_code = result; - - switch (result) { - - case RTE_TMROVRN: - // an immediate return was taken because the time - // deadline has already expired - ts->flavor.rtai.wait_errors++; - type = RTAI_RTE_TMROVRN; - break; - - case RTE_UNBLKD: - // the task was unblocked while sleeping - // an API usage error - ts->api_errors++; - type = RTAI_RTE_UNBLKD; - break; - - default: - // whzat? - ts->other_errors++; - type = RTAI_RTE_UNCLASSIFIED; - } - - if (rt_exception_handler) - rt_exception_handler(type, &detail, ts); - - } -} - -int _rtapi_task_self_hook(void) { - RT_TASK *ptr; - int n; - - /* ask OS for pointer to its data for the current task */ - ptr = rt_whoami(); - if (ptr == NULL) { - /* called from outside a task? */ - return -EINVAL; - } - /* find matching entry in task array */ - n = 1; - while (n <= RTAPI_MAX_TASKS) { - if (ostask_array[n] == ptr) { - /* found a match */ - return n; - } - n++; - } - return -EINVAL; -} -#endif /* RTAPI */ - diff --git a/src/rtapi/rtai-kernel.h b/src/rtapi/rtai-kernel.h deleted file mode 100644 index 38698676d3..0000000000 --- a/src/rtapi/rtai-kernel.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************** -* Description: rtai.h -* This file defines the differences specific to the -* the RTAI thread system -* -* Copyright 2006-2010 Various Authors -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -********************************************************************/ - -#include /* RT_TASK */ - -#define FLAVOR_FLAGS RTAI_KERNEL_FLAVOR_FLAGS // see rtapi_compat.h - -/* rtapi_module.c */ -#define RT_LINUX_USE_FPU - - -/* rtapi_time.c */ -#define HAVE_RTAPI_MODULE_TIMER_STOP -#define HAVE_RTAPI_CLOCK_SET_PERIOD_HOOK -#ifdef RTAPI // no rt_get_cpu_time_ns() in RTAI userland -#define HAVE_RTAPI_GET_TIME_HOOK -#endif - -/* rtapi_task.c */ - -/* RTAI uses 0 as the highest priority; higher numbers are lower - priority */ -#define INVERSE_PRIO -#define PRIO_LOWEST 0xFFF -#define PRIO_HIGHEST 0 - -#define HAVE_RTAPI_TASK_NEW_HOOK -#define HAVE_RTAPI_WAIT_HOOK -#define HAVE_RTAPI_TASK_SELF_HOOK - diff --git a/src/rtapi/rtapi.c b/src/rtapi/rtapi.c new file mode 100644 index 0000000000..0792baea8c --- /dev/null +++ b/src/rtapi/rtapi.c @@ -0,0 +1,345 @@ +// Copyright 2006-2013 Various Authors +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#include // strtol + +#include "rtapi_flavor.h" +#include "config.h" +#include "rtapi.h" +#include "rtapi_common.h" +#include "rtapi_compat.h" +#include "shmdrv.h" /* common shm driver API */ +#include "ring.h" + +/* these pointers are initialized at startup to point + to resource data in the master data structure above + all access to the data structure should uses these + pointers, they take into account the mapping of + shared memory into either kernel or user space. + (the RTAPI kernel module and each ULAPI user process + has its own set of these vars, initialized to match + that process's memory mapping.) +*/ + +// in the userland threads scenario, there is no point in having this +// in shared memory, so keep it here +static rtapi_data_t local_rtapi_data; +rtapi_data_t *rtapi_data = &local_rtapi_data; +task_data *task_array = local_rtapi_data.task_array; +shmem_data *shmem_array = local_rtapi_data.shmem_array; +module_data *module_array = local_rtapi_data.module_array; + +int rtapi_instance; // instance id, visible throughout RTAPI + +global_data_t *global_data = NULL; // visible to all RTAPI modules +struct rtapi_heap *global_heap = NULL; + +ringbuffer_t rtapi_message_buffer; // error ring access strcuture + +#ifdef ULAPI +// use 'ULAPI_DEBUG= ' to trace ulapi loading +static int ulapi_debug = RTAPI_MSG_NONE; +#endif + +#ifdef RTAPI +#define LOGTAG "ULAPI" +#else +#define LOGTAG "RTAPI" +#endif + +int shmdrv_loaded; // set in rtapi_app_main FIXME +long page_size; // set in rtapi_app_main + +void rtapi_autorelease_mutex(void *variable) +{ + if (rtapi_data != NULL) + rtapi_mutex_give(&(rtapi_data->mutex)); + else + // programming error + rtapi_print_msg(RTAPI_MSG_ERR, + "rtapi_autorelease_mutex: rtapi_data == NULL!\n"); +} + +// in the RTAPI scenario, +// global_data is exported by instance.ko and referenced +// by rtapi.ko and hal_lib.ko + +// in ULAPI, we have only hal_lib which calls 'down' +// onto ulapi.so to init, so in this case global_data +// is exported by hal_lib and referenced by ulapi.so + + +/* global init code */ + +void init_rtapi_data(rtapi_data_t * data) +{ + int n, m; + + /* has the block already been initialized? */ + if (data->magic == RTAPI_MAGIC) { + /* yes, nothing to do */ + return; + } + /* no, we need to init it, grab mutex unconditionally */ + rtapi_mutex_try(&(data->mutex)); + /* set magic number so nobody else init's the block */ + data->magic = RTAPI_MAGIC; + /* set version code and flavor ID so other modules can check it */ + data->serial = RTAPI_SERIAL; + data->ring_mutex = 0; + /* and get busy */ + data->rt_module_count = 0; + data->ul_module_count = 0; + data->task_count = 0; + data->shmem_count = 0; + data->timer_running = 0; + data->timer_period = 0; + /* init the arrays */ + for (n = 0; n <= RTAPI_MAX_MODULES; n++) { + data->module_array[n].state = EMPTY; + data->module_array[n].name[0] = '\0'; + } + for (n = 0; n <= RTAPI_MAX_TASKS; n++) { + data->task_array[n].state = EMPTY; + data->task_array[n].prio = 0; + data->task_array[n].owner = 0; + data->task_array[n].taskcode = NULL; + data->task_array[n].cpu = -1; // use default + } + for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { + data->shmem_array[n].key = 0; + data->shmem_array[n].rtusers = 0; + data->shmem_array[n].ulusers = 0; + data->shmem_array[n].size = 0; + for (m = 0; m < RTAPI_BITMAP_SIZE(RTAPI_MAX_SHMEMS +1); m++) { + data->shmem_array[n].bitmap[m] = 0; + } + } + + /* done, release the mutex */ + rtapi_mutex_give(&(data->mutex)); + return; +} + +/*********************************************************************** +* MODULE INIT FUNCTIONS * +************************************************************************/ + +int rtapi_module_init() +{ + int retval; + int size = 0; + +#ifdef ULAPI + // Set the rtapi_instance global for HAL library instances; + // rtapi_instance set in rtapi_app.cc for RTAPI instances + char *instance = getenv("MK_INSTANCE"); + if (instance != NULL) + rtapi_instance = atoi(instance); + + char *debug_env = getenv("ULAPI_DEBUG"); + if (debug_env) + ulapi_debug = atoi(debug_env); + rtapi_set_msg_level(ulapi_debug); + + // Set up the ulapi flavor + flavor_install(flavor_byname("ulapi")); +#endif + + int globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance); + + shm_common_init(); + + // tag messages originating from RT proper + rtapi_set_logtag(LOGTAG); + + // flavor + rtapi_print_msg(RTAPI_MSG_DBG,"%s:%d %s %s init\n", + LOGTAG, + rtapi_instance, + flavor_name(NULL), + GIT_VERSION); + + // attach to global segment which rtapi_msgd owns and already + // has set up: + retval = shm_common_new(globalkey, &size, + rtapi_instance, (void **) &global_data, 0); + + if (retval == -ENOENT) { + // the global_data segment does not exist. + rtapi_print_msg(RTAPI_MSG_ERR, + "%s:%d ERROR: global segment 0x%x does not exist" + " (rtapi_msgd not started?)\n", + LOGTAG, rtapi_instance, globalkey); + return -EBUSY; + } + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "%s:%d ERROR: shm_common_new() failed key=0x%x %s\n", + LOGTAG, rtapi_instance, globalkey, strerror(-retval)); + return retval; + } + if (size < sizeof(global_data_t)) { + rtapi_print_msg(RTAPI_MSG_ERR, + "%s:%d ERROR: unexpected global shm size:" + " expected: >%zu actual:%d\n", + LOGTAG, rtapi_instance, sizeof(global_data_t), size); + return -EINVAL; + } + + // good to use global_data from here on + + // this heap is inited in rtapi_msgd.cc + // make it accessible in RTAPI + global_heap = &global_data->heap; + + // make the message ringbuffer accessible + ringbuffer_init(shm_ptr(global_data, global_data->rtapi_messages_ptr), + &rtapi_message_buffer); + rtapi_message_buffer.header->refcount++; // rtapi is 'attached' + + // flavor + init_rtapi_data(rtapi_data); + + retval = flavor_module_init_hook(NULL); + + return retval; +} + +int rtapi_app_main() +{ + return rtapi_module_init(); +} + +void rtapi_app_exit(void) +{ + flavor_module_exit_hook(NULL); + + rtapi_message_buffer.header->refcount--; + + rtapi_print_msg(RTAPI_MSG_DBG,"%s:%d exit\n", LOGTAG, rtapi_instance); + + rtapi_data = NULL; +} + +/*********************************************************************** +* INIT AND EXIT FUNCTIONS * +************************************************************************/ + +int rtapi_init(const char *modname) { +#ifdef ULAPI + int res; + + // Load ULAPI if global_data hasn't been set up yet + if (global_data == NULL && (res = rtapi_module_init())) { + rtapi_print_msg(RTAPI_MSG_ERR, + "FATAL: Failed to initialize module '%s'\n", modname); + return res; + } + rtapi_print_msg(RTAPI_MSG_DBG, + "Module '%s' finished ULAPI init\n", modname); +#endif + + return rtapi_next_handle(); +} + +int rtapi_exit(int module_id) { + /* do nothing for ULAPI */ + return 0; +} + + +/*********************************************************************** +* RT Thread statistics collection * +* +* Thread statistics are recorded in the global_data_t thread_status. +* array. Values therein are updated when: +* +* - an exception happens, and it is safe to do so +* - by an explicit call to rtapi_task_update_stats() from an RT thread +* +* This avoids the overhead of permanently updating thread status, while +* giving the user the option to track thread status from a HAL component +* thread function if so desired. +* +* Updating thread status is necessarily a flavor-dependent +* operation and hence goes through a hook. +* +* Inspecting thread status (e.g. in halcmd) needs to evaluate +* the thread status information based on the current flavor. +************************************************************************/ + +#ifdef RTAPI +int rtapi_task_update_stats(void) +{ + return flavor_task_update_stats_hook(NULL); +} +#endif +/*********************************************************************** +* RT exception handling * +* +* all exceptions are funneled through a common exception handler +* the default exception handler is defined in rtapi_exception.c but +* may be redefined by a user-defined handler. +* +* NB: the exception handler executes in a restricted context like +* an in-kernel trap, or a signal handler. Limit processing in the +* handler to an absolute minimum, and watch the stack size. +************************************************************************/ + +#ifdef RTAPI +// not available in ULAPI +extern rtapi_exception_handler_t rt_exception_handler; + +// may override default exception handler +// returns the current handler so it might be restored +rtapi_exception_handler_t rtapi_set_exception(rtapi_exception_handler_t h) +{ + rtapi_exception_handler_t previous = rt_exception_handler; + rt_exception_handler = h; + return previous; +} +#endif + +// defined and initialized in rtapi_main.c (userthreads) +extern ringbuffer_t rtapi_message_buffer; // error ring access strcuture + +int rtapi_next_handle(void) +{ + return rtapi_add_and_fetch(1, &global_data->next_handle); +} + +long int simple_strtol(const char *nptr, char **endptr, int base) { + return strtol(nptr, endptr, base); +} + + +#ifdef RTAPI +EXPORT_SYMBOL(rtapi_instance); +EXPORT_SYMBOL(global_data); +EXPORT_SYMBOL(global_heap); +EXPORT_SYMBOL(rtapi_autorelease_mutex); +EXPORT_SYMBOL(init_rtapi_data); +EXPORT_SYMBOL(rtapi_module_init); +EXPORT_SYMBOL(rtapi_app_main); +EXPORT_SYMBOL(rtapi_app_exit); +EXPORT_SYMBOL(rtapi_init); +EXPORT_SYMBOL(rtapi_exit); +EXPORT_SYMBOL(rtapi_task_update_stats); +EXPORT_SYMBOL(rtapi_set_exception); +EXPORT_SYMBOL(rtapi_next_handle); +EXPORT_SYMBOL(simple_strtol); +#endif diff --git a/src/rtapi/rtapi.h b/src/rtapi/rtapi.h index 094ecf05d1..1388529526 100644 --- a/src/rtapi/rtapi.h +++ b/src/rtapi/rtapi.h @@ -2,7 +2,7 @@ #define RTAPI_H /** RTAPI is a library providing a uniform API for several real time - operating systems. As of ver 2.0, RTLinux and RTAI are supported. + operating systems. */ /******************************************************************** * Description: rtapi.h @@ -83,17 +83,6 @@ #include // provides NULL, offset_of #include "rtapi_int.h" - -/* LINUX_VERSION_CODE for rtapi_{module,io}.c */ -#ifdef MODULE -#ifndef LINUX_VERSION_CODE -#include -#endif -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif -#endif - #include // need RTAPI_CACHELINE for rtapi_global.h @@ -196,7 +185,6 @@ static inline shmoff_t shm_off(const void *base, const void *p) { /*********************************************************************** * INIT AND EXIT FUNCTIONS * ************************************************************************/ -/* implemented in $THREADS.c (rt-preempt.c, xenomai.c, etc.) */ /** 'rtapi_init() sets up the RTAPI. It must be called by any module that intends to use the API, before any other RTAPI @@ -211,10 +199,7 @@ static inline shmoff_t shm_off(const void *base, const void *p) { above. Call only from within user or init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_init_t)(const char *); -#define rtapi_init(modname) \ - rtapi_switch->rtapi_init(modname) -extern int _rtapi_init(const char *modname); +int rtapi_init(const char *modname); /** 'rtapi_exit()' shuts down and cleans up the RTAPI. It must be called prior to exit by any module that called rtapi_init. @@ -226,70 +211,37 @@ extern int _rtapi_init(const char *modname); code within the module. Call only from within user or init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_exit_t)(int); -#define rtapi_exit(module_id) \ - rtapi_switch->rtapi_exit(module_id) -extern int _rtapi_exit(int module_id); +int rtapi_exit(int module_id); /** 'rtapi_next_handle()' returns a globally unique int ID */ -typedef int (*rtapi_next_handle_t)(void); -#define rtapi_next_handle() \ - rtapi_switch->rtapi_next_handle() -extern int _rtapi_next_handle(void); +extern int rtapi_next_handle(void); /*********************************************************************** * shared memory allocator * ************************************************************************/ -typedef void * (*rtapi_malloc_t)(struct rtapi_heap *h, size_t nbytes); -#define rtapi_malloc(h, nbytes) \ - rtapi_switch->rtapi_malloc(h, nbytes) +void * rtapi_malloc_aligned(struct rtapi_heap *h, size_t nbytes, size_t align); -typedef void * (*rtapi_malloc_aligned_t)(struct rtapi_heap *h, - size_t nbytes, - size_t align); -#define rtapi_malloc_aligned(h, nbytes, align) \ - rtapi_switch->rtapi_malloc_aligned(h, nbytes, align) +void * rtapi_calloc(struct rtapi_heap *h, size_t n, size_t size); -typedef void * (*rtapi_calloc_t)(struct rtapi_heap *h, size_t n, size_t size); -#define rtapi_calloc(h, n, size) \ - rtapi_switch->rtapi_calloc(h, n, size) +void * rtapi_realloc(struct rtapi_heap *h, void *p, size_t size); -typedef void * (*rtapi_realloc_t)(struct rtapi_heap *h, void *p, size_t size); -#define rtapi_realloc(h, p, size) \ - rtapi_switch->rtapi_realloc(h, p size) +void rtapi_free(struct rtapi_heap *h, void *p); -typedef void (*rtapi_free_t)(struct rtapi_heap *h, void *p); -#define rtapi_free(h, p) \ - rtapi_switch->rtapi_free(h, p) +size_t rtapi_allocsize(struct rtapi_heap *h, const void *p); -typedef size_t (*rtapi_allocsize_t)(struct rtapi_heap *h, const void *p); -#define rtapi_allocsize(h, p) \ - rtapi_switch->rtapi_allocsize(h, p) - -typedef int (*rtapi_heap_init_t)(struct rtapi_heap *h, const char *name); -#define rtapi_heap_init(h, n) \ - rtapi_switch->rtapi_heap_init(h, n) +int rtapi_heap_init(struct rtapi_heap *h, const char *name); // any memory added to the heap must lie above the rtapi_heap structure: -typedef int (*rtapi_heap_addmem_t)(struct rtapi_heap *h, void *space, size_t size); -#define rtapi_heap_addmem(h, s, size) \ - rtapi_switch->rtapi_heap_addmem(h, s, size) +int rtapi_heap_addmem(struct rtapi_heap *h, void *space, size_t size); -typedef size_t (*rtapi_heap_status_t)(struct rtapi_heap *h, struct rtapi_heap_stat *hs); -#define rtapi_heap_status(h, hs) \ - rtapi_switch->rtapi_heap_status(h, hs) +size_t rtapi_heap_status(struct rtapi_heap *h, struct rtapi_heap_stat *hs); -typedef int (*rtapi_heap_setflags_t)(struct rtapi_heap *h, int flags); -#define rtapi_heap_setflags(h, flags) \ - rtapi_switch->rtapi_heap_setflags(h, flags) +int rtapi_heap_setflags(struct rtapi_heap *h, int flags); -typedef size_t (*rtapi_heap_walk_freelist_t)(struct rtapi_heap *h, - chunk_t cb, void *user); -#define rtapi_heap_walk_freelist(h, cb, u) \ - rtapi_switch->rtapi_heap_walk_freelist(h, cb, u) +size_t rtapi_heap_walk_freelist(struct rtapi_heap *h, chunk_t cb, void *user); @@ -507,11 +459,7 @@ typedef struct { /*********************************************************************** * LIGHTWEIGHT MUTEX FUNCTIONS * ************************************************************************/ -#ifdef MODULE /* kernel code */ -#include /* for blocking when needed */ -#else /* userland code */ #include /* for blocking when needed */ -#endif #include "rtapi_bitops.h" /* atomic bit ops for lightweight mutex */ /** These three functions provide a very simple way to do mutual @@ -551,11 +499,7 @@ typedef struct { */ static __inline__ void rtapi_mutex_get(unsigned long *mutex) { while (rtapi_test_and_set_bit(0, mutex)) { -#ifdef MODULE /* kernel code */ - schedule(); -#else /* userland code */ sched_yield(); -#endif } } @@ -629,10 +573,7 @@ static inline void _autorelease_mutex_if(struct _mutex_cleanup *c) { init/cleanup code, not from realtime tasks. This function is not available from user (non-realtime) code. */ -typedef long int (*rtapi_clock_set_period_t)(long int); -#define rtapi_clock_set_period(nsecs) \ - rtapi_switch->rtapi_clock_set_period(nsecs) -extern long int _rtapi_clock_set_period(long int nsecs); +extern long int rtapi_clock_set_period(long int nsecs); /** rtapi_delay() is a simple delay. It is intended only for short delays, since it simply loops, wasting CPU cycles. 'nsec' is the @@ -645,15 +586,9 @@ extern long int _rtapi_clock_set_period(long int nsecs); as one nano-second, or as bad as a several microseconds. May be called from init/cleanup code, and from within realtime tasks. */ -typedef void (*rtapi_delay_t)(long int); -#define rtapi_delay(nsec) \ - rtapi_switch->rtapi_delay(nsec) -extern void _rtapi_delay(long int nsec); +extern void rtapi_delay(long int nsec); -typedef long int (*rtapi_delay_max_t)(void); -#define rtapi_delay_max() \ - rtapi_switch->rtapi_delay_max() -extern long int _rtapi_delay_max(void); +extern long int rtapi_delay_max(void); /** Support external clock tracking for linuxcnc-ethercat */ #define RTAPI_TASK_PLL_SUPPORT @@ -663,10 +598,7 @@ extern long int _rtapi_delay_max(void); Returns 0 if not called from within task context or on platforms that do not support this. */ -typedef long long (*rtapi_task_pll_get_reference_t)(void); -#define rtapi_task_pll_get_reference() \ - rtapi_switch->rtapi_task_pll_get_reference() -extern long long _rtapi_task_pll_get_reference(void); +extern long long rtapi_task_pll_get_reference(void); /** 'rtapi_task_pll_set_correction()' sets the correction value for the next scheduling cycle of the current task. This could be @@ -674,10 +606,7 @@ extern long long _rtapi_task_pll_get_reference(void); Returns -EINVAL if not called from within task context or on platforms that do not support this. */ -typedef int (*rtapi_task_pll_set_correction_t)(long); -#define rtapi_task_pll_set_correction(value) \ - rtapi_switch->rtapi_task_pll_set_correction(value) -extern int _rtapi_task_pll_set_correction(long value); +extern int rtapi_task_pll_set_correction(long value); #endif /* RTAPI */ @@ -705,10 +634,7 @@ extern int _rtapi_task_pll_set_correction(long value); rtapi_get_time, and deltat is an ordinary long int (32 bits). This will work for times up to about 2 seconds. */ -typedef long long int (*rtapi_get_time_t)(void); -#define rtapi_get_time() \ - rtapi_switch->rtapi_get_time() -extern long long int _rtapi_get_time(void); +extern long long int rtapi_get_time(void); /** rtapi_get_clocks returns the current time in CPU clocks. It is fast, since it just reads the TSC in the CPU instead of calling a @@ -735,10 +661,7 @@ extern long long int _rtapi_get_time(void); CPU clock frequency. It is best used for millisecond and microsecond scale measurements though. */ -typedef long long int (*rtapi_get_clocks_t)(void); -#define rtapi_get_clocks() \ - rtapi_switch->rtapi_get_clocks() -extern long long int _rtapi_get_clocks(void); +extern long long int rtapi_get_clocks(void); /*********************************************************************** @@ -799,21 +722,11 @@ typedef struct { } rtapi_task_args_t; -typedef int (*rtapi_prio_highest_lowest_t)(void); -#define rtapi_prio_highest() \ - rtapi_switch->rtapi_prio_highest() -extern int _rtapi_prio_highest(void); -#define rtapi_prio_lowest() \ - rtapi_switch->rtapi_prio_lowest() -extern int _rtapi_prio_lowest(void); +extern int rtapi_prio_highest(void); +extern int rtapi_prio_lowest(void); -typedef int (*rtapi_prio_next_higher_lower_t)(int); -#define rtapi_prio_next_higher(prio) \ - rtapi_switch->rtapi_prio_next_higher(prio) -extern int _rtapi_prio_next_higher(int prio); -#define rtapi_prio_next_lower(prio) \ - rtapi_switch->rtapi_prio_next_lower(prio) -extern int _rtapi_prio_next_lower(int prio); +extern int rtapi_prio_next_higher(int prio); +extern int rtapi_prio_next_lower(int prio); #ifdef RTAPI @@ -845,11 +758,7 @@ extern int _rtapi_prio_next_lower(int prio); #define RTAPI_NO_FP 0 #define RTAPI_USES_FP 1 -typedef int (*rtapi_task_new_t)(const rtapi_task_args_t *args); - -#define rtapi_task_new(args) \ - rtapi_switch->rtapi_task_new(args) -extern int _rtapi_task_new(const rtapi_task_args_t *args); +extern int rtapi_task_new(const rtapi_task_args_t *args); /** 'rtapi_task_delete()' deletes a task. 'task_id' is a task ID from a previous call to rtapi_task_new(). It frees memory @@ -858,10 +767,7 @@ extern int _rtapi_task_new(const rtapi_task_args_t *args); it. Returns a status code. Call only from within init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_task_delete_t)(int); -#define rtapi_task_delete(task_id) \ - rtapi_switch->rtapi_task_delete(task_id) -extern int _rtapi_task_delete(int task_id); +extern int rtapi_task_delete(int task_id); /** 'rtapi_task_start()' starts a task in periodic mode. 'task_id' is a task ID from a call to rtapi_task_new(). The task must be in @@ -872,20 +778,14 @@ extern int _rtapi_task_delete(int task_id); set equal to the clock period. Call only from within init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_task_start_t)(int, unsigned long int); -#define rtapi_task_start(task_id, period_nsec) \ - rtapi_switch->rtapi_task_start(task_id, period_nsec) -extern int _rtapi_task_start(int task_id, unsigned long int period_nsec); +extern int rtapi_task_start(int task_id, unsigned long int period_nsec); /** 'rtapi_wait()' suspends execution of the current task until the next period. The task must be periodic, if not, the result is undefined. The function will return at the beginning of the next period. Call only from within a realtime task. */ -typedef int (*rtapi_wait_t)(int); -#define rtapi_wait(flag) \ - rtapi_switch->rtapi_wait(flag) -extern int _rtapi_wait(const int flag); +extern int rtapi_wait(const int flag); /** 'rtapi_task_resume() starts a task in free-running mode. 'task_id' is a task ID from a call to rtapi_task_new(). The task must be in @@ -898,10 +798,7 @@ extern int _rtapi_wait(const int flag); 3) it is returned to the "paused" state by rtapi_task_pause(). May be called from init/cleanup code, and from within realtime tasks. */ -typedef int (*rtapi_task_resume_t)(int); -#define rtapi_task_resume(task_id) \ - rtapi_switch->rtapi_task_resume(task_id) -extern int _rtapi_task_resume(int task_id); +extern int rtapi_task_resume(int task_id); /** 'rtapi_task_pause() causes 'task_id' to stop execution and change to the "paused" state. 'task_id' can be free-running or periodic. @@ -911,18 +808,12 @@ extern int _rtapi_task_resume(int task_id); rtapi_task_start() is called. May be called from init/cleanup code, and from within realtime tasks. */ -typedef int (*rtapi_task_pause_t)(int); -#define rtapi_task_pause(task_id) \ - rtapi_switch->rtapi_task_pause(task_id) -extern int _rtapi_task_pause(int task_id); +extern int rtapi_task_pause(int task_id); /** 'rtapi_task_self()' returns the task ID of the current task. Call only from a realtime task. */ -typedef int (*rtapi_task_self_t)(void); -#define rtapi_task_self() \ - rtapi_switch->rtapi_task_self() -extern int _rtapi_task_self(void); +extern int rtapi_task_self(void); /** 'rtapi_task_update_stats()' will update the thread statistics in the global_data_t structure. @@ -930,10 +821,7 @@ extern int _rtapi_task_self(void); Call only from a realtime task. returns a negative value on error, or the thread's task id. */ -typedef int (*rtapi_task_update_stats_t)(void); -#define rtapi_task_update_stats() \ - rtapi_switch->rtapi_task_update_stats() -extern int _rtapi_task_update_stats(void); +extern int rtapi_task_update_stats(void); #endif /* RTAPI */ @@ -958,19 +846,13 @@ extern int _rtapi_task_update_stats(void); returns a negative error code. Call only from within user or init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_shmem_new_t)(int, int, unsigned long int); -#define rtapi_shmem_new(key, module_id, size) \ - rtapi_switch->rtapi_shmem_new(key, module_id, size) -extern int _rtapi_shmem_new(int key, int module_id, +extern int rtapi_shmem_new(int key, int module_id, unsigned long int size); /** 'rtapi_shmem_new_inst()' does the same for a particular instance. **/ -typedef int (*rtapi_shmem_new_inst_t)(int, int, int, unsigned long int); -#define rtapi_shmem_new_inst(key, instance, module_id, size) \ - rtapi_switch->rtapi_shmem_new_inst(key, instance, module_id, size) -extern int _rtapi_shmem_new_inst(int key, int instance, int module_id, +extern int rtapi_shmem_new_inst(int key, int instance, int module_id, unsigned long int size); /** 'rtapi_shmem_delete()' frees the shared memory block associated @@ -978,15 +860,9 @@ extern int _rtapi_shmem_new_inst(int key, int instance, int module_id, Returns a status code. Call only from within user or init/cleanup code, not from realtime tasks. */ -typedef int (*rtapi_shmem_delete_t)(int, int); -#define rtapi_shmem_delete(shmem_id, module_id) \ - rtapi_switch->rtapi_shmem_delete(shmem_id, module_id) -extern int _rtapi_shmem_delete(int shmem_id, int module_id); +extern int rtapi_shmem_delete(int shmem_id, int module_id); -typedef int (*rtapi_shmem_delete_inst_t)(int, int, int); -#define rtapi_shmem_delete_inst(shmem_id, instance, module_id) \ - rtapi_switch->rtapi_shmem_delete_inst(shmem_id, instance, module_id) -extern int _rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id); +extern int rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id); /** 'rtapi_shmem_getptr()' sets '*ptr' to point to shared memory block associated with 'shmem_id'. Returns a status code. May be called @@ -995,25 +871,16 @@ extern int _rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id); If non-NULL, *size is set to the size of the shared memory block. */ -typedef int (*rtapi_shmem_getptr_t)(int, void **, unsigned long int *); -#define rtapi_shmem_getptr(shmem_id, ptr, size) \ - rtapi_switch->rtapi_shmem_getptr(shmem_id, ptr, size) -extern int _rtapi_shmem_getptr(int shmem_id, void **ptr, unsigned long int *size); +extern int rtapi_shmem_getptr(int shmem_id, void **ptr, unsigned long int *size); -typedef int (*rtapi_shmem_getptr_inst_t)(int, int, void **, unsigned long int *); -#define rtapi_shmem_getptr_inst(shmem_id, instance, ptr, size) \ - rtapi_switch->rtapi_shmem_getptr_inst(shmem_id, instance, ptr, size) -extern int _rtapi_shmem_getptr_inst(int shmem_id, int instance, void **ptr, unsigned long int *size); +extern int rtapi_shmem_getptr_inst(int shmem_id, int instance, void **ptr, unsigned long int *size); /* rtapi_shmem_exists() tests whether a shared memory segment exists and can be attached; it does not actually attach it. The argument is a shared memory key. Not callable from realtime tasks. */ -typedef int (*rtapi_shmem_exists_t)(int); -#define rtapi_shmem_exists(key) \ - rtapi_switch->rtapi_shmem_exists(key) -extern int _rtapi_shmem_exists(int key); +extern int rtapi_shmem_exists(int key); /*********************************************************************** * Callback on RT scheduling violation * @@ -1026,16 +893,12 @@ extern int _rtapi_shmem_exists(int key); ************************************************************************/ // rtapi_exception_handler_t is defined in rtapi_exception.h -typedef rtapi_exception_handler_t (*rtapi_set_exception_t) (rtapi_exception_handler_t); -#define rtapi_set_exception(handler) \ - rtapi_switch->rtapi_set_exception(handler) -extern rtapi_exception_handler_t _rtapi_set_exception(rtapi_exception_handler_t h); +extern rtapi_exception_handler_t rtapi_set_exception(rtapi_exception_handler_t h); /*********************************************************************** * I/O RELATED FUNCTIONS * ************************************************************************/ - #if (defined(RTAPI) && defined(BUILD_DRIVERS)) /** 'rtapi_request_region() reserves I/O memory starting at 'base', going for 'size' bytes, for component 'name'. @@ -1046,18 +909,10 @@ extern rtapi_exception_handler_t _rtapi_set_exception(rtapi_exception_handler_t a non-NULL value. */ # include -# if !defined(BUILD_SYS_USER_DSO) -# include -# include -# endif // BUILD_SYS_USER_DSO static __inline__ void *rtapi_request_region(unsigned long base, unsigned long size, const char *name) { -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && !defined(BUILD_SYS_USER_DSO) - return (void*)request_region(base, size, name); -# else return (void*)-1; -# endif } /** 'rtapi_release_region() releases I/O memory reserved by @@ -1067,116 +922,12 @@ extern rtapi_exception_handler_t _rtapi_set_exception(rtapi_exception_handler_t */ static __inline__ void rtapi_release_region(unsigned long base, unsigned long int size) { -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && !defined(BUILD_SYS_USER_DSO) - release_region(base, size); -# endif } #endif // RTAPI && BUILD_DRIVERS /*********************************************************************** * RTAPI SWITCH * ************************************************************************/ -/** rtapi_switch contains pointers to the _rtapi_* functions declared - above. The struct is initialized in rtapi_common.c. - - Each thread system needs a member in the thread_flavor_id_t enum, - and should set the macro THREAD_FLAVOR_ID to that enumerator. -*/ - -// prototype for dummy rtapi placeholder function -typedef int (*rtapi_dummy_t)(void); - -typedef struct { - const char *git_version; - const char *thread_flavor_name; // for messsages - int thread_flavor_id; - unsigned long thread_flavor_flags; - - // init & exit functions - rtapi_init_t rtapi_init; - rtapi_exit_t rtapi_exit; - rtapi_next_handle_t rtapi_next_handle; - // time functions -#ifdef RTAPI - rtapi_clock_set_period_t rtapi_clock_set_period; - rtapi_delay_t rtapi_delay; - rtapi_delay_max_t rtapi_delay_max; - rtapi_task_pll_get_reference_t rtapi_task_pll_get_reference; - rtapi_task_pll_set_correction_t rtapi_task_pll_set_correction; -#else - rtapi_dummy_t rtapi_clock_set_period; - rtapi_dummy_t rtapi_delay; - rtapi_dummy_t rtapi_delay_max; - rtapi_dummy_t rtapi_task_pll_get_reference; - rtapi_dummy_t rtapi_task_pll_set_correction; -#endif - rtapi_get_time_t rtapi_get_time; - rtapi_get_clocks_t rtapi_get_clocks; - // task functions - rtapi_prio_highest_lowest_t rtapi_prio_highest; - rtapi_prio_highest_lowest_t rtapi_prio_lowest; - rtapi_prio_next_higher_lower_t rtapi_prio_next_higher; - rtapi_prio_next_higher_lower_t rtapi_prio_next_lower; -#ifdef RTAPI - rtapi_task_new_t rtapi_task_new; - rtapi_task_delete_t rtapi_task_delete; - rtapi_task_start_t rtapi_task_start; - rtapi_wait_t rtapi_wait; - rtapi_task_resume_t rtapi_task_resume; - rtapi_task_pause_t rtapi_task_pause; - rtapi_task_self_t rtapi_task_self; - -#else - rtapi_dummy_t rtapi_task_new; - rtapi_dummy_t rtapi_task_delete; - rtapi_dummy_t rtapi_task_start; - rtapi_dummy_t rtapi_wait; - rtapi_dummy_t rtapi_task_resume; - rtapi_dummy_t rtapi_task_pause; - rtapi_dummy_t rtapi_task_self; -#endif - // shared memory functions - rtapi_shmem_new_t rtapi_shmem_new; - rtapi_shmem_new_inst_t rtapi_shmem_new_inst; - rtapi_shmem_delete_t rtapi_shmem_delete; - rtapi_shmem_delete_inst_t rtapi_shmem_delete_inst; - rtapi_shmem_getptr_t rtapi_shmem_getptr; - rtapi_shmem_getptr_inst_t rtapi_shmem_getptr_inst; - rtapi_shmem_exists_t rtapi_shmem_exists; - -#ifdef RTAPI - rtapi_set_exception_t rtapi_set_exception; -#else - rtapi_dummy_t rtapi_set_exception; -#endif -#ifdef RTAPI - rtapi_task_update_stats_t rtapi_task_update_stats; -#else - rtapi_dummy_t rtapi_task_update_stats; -#endif - rtapi_malloc_t rtapi_malloc; - rtapi_malloc_aligned_t rtapi_malloc_aligned; - rtapi_calloc_t rtapi_calloc; - rtapi_realloc_t rtapi_realloc; - rtapi_free_t rtapi_free; - rtapi_allocsize_t rtapi_allocsize; - rtapi_heap_init_t rtapi_heap_init; - rtapi_heap_addmem_t rtapi_heap_addmem; - rtapi_heap_status_t rtapi_heap_status; - rtapi_heap_setflags_t rtapi_heap_setflags; - rtapi_heap_walk_freelist_t rtapi_heap_walk_freelist; -} rtapi_switch_t; - -// using code is responsible to define this: -// this extern is not used within RTAPI -extern rtapi_switch_t *rtapi_switch; - -/** 'rtapi_get_handle()' returns a pointer to the rtapi_switch - structure, such that using code may refernce rtapi - methods. - */ -typedef rtapi_switch_t *(*rtapi_get_handle_t)(void); -extern rtapi_switch_t *rtapi_get_handle(void); // autorelease the rtapi mutex on scope exit // declare a variable like so in the scope to be protected: @@ -1191,28 +942,7 @@ extern void rtapi_autorelease_mutex(void *variable); // configurable at rtapi.so module load time _only_ extern int rtapi_instance; -#if defined(BUILD_SYS_USER_DSO) extern long int simple_strtol(const char *nptr, char **endptr, int base); -#endif - -#ifdef ULAPI -// the ulapi constructor and destructor -// these attach/detach the rtapi shm segments to/from ULAPI -typedef int (*ulapi_main_t)(int, int, global_data_t *); -typedef int (*ulapi_exit_t)(int); -extern int ulapi_main(int instance, int flavor, global_data_t *global); -extern int ulapi_exit(int instance); - -// ULAPI cleanup. Call the exit handler and unload ulapi-.so. -extern void ulapi_cleanup(void); - -// Check that a ulapi module is compatible with the running kernel -// from rtapi_compat.c -extern void ulapi_kernel_compat_check(rtapi_switch_t *rtapi_switch, - char *ulapi_lib); -extern int ulapi_loaded(void); - -#endif // elf section name where capability strings reside #define RTAPI_TAGS ".rtapi_tags" @@ -1245,15 +975,6 @@ extern int ulapi_loaded(void); #include -#if !defined(BUILD_SYS_USER_DSO) -#ifndef LINUX_VERSION_CODE -#include -#endif -#endif -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - #ifndef LINUX_VERSION_CODE #define LINUX_VERSION_CODE 0 #endif @@ -1264,8 +985,6 @@ extern int ulapi_loaded(void); // compile-time assert #define rtapi_ct_assert(cond, failure) _Static_assert(cond, failure) -#if defined(BUILD_SYS_USER_DSO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - #define RTAPI_MP_INT(var,descr) \ MODULE_PARM(var,"i"); \ MODULE_PARM_DESC(var,descr); @@ -1327,92 +1046,6 @@ extern int ulapi_loaded(void); INSTANCE_PARM_DESC(var,descr); -#else /* version 2.6 or later */ - -#include - -#define RTAPI_MP_INT(var,descr) \ - module_param(var, int, 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_UINT(var,descr) \ - module_param(var, uint, 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_LONG(var,descr) \ - module_param(var, long, 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_STRING(var,descr) \ - module_param(var, charp, 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_ARRAY_INT(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, int, &(__dummy_##var), 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_ARRAY_LONG(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, long, &(__dummy_##var), 0); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_MP_ARRAY_STRING(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, charp, &(__dummy_##var), 0); \ - MODULE_PARM_DESC(var,descr); - -// for kthreads, export params in -// /sys/modules//parameters/ -#define RTAPI_IP_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) - -#define RTAPI_IP_INT(var,descr) \ - module_param(var, int, RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_IP_UINT(var,descr) \ - module_param(var, uint, RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_IP_LONG(var,descr) \ - module_param(var, long, RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_IP_STRING(var,descr) \ - module_param(var, charp, RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#ifdef _NOTYET - -// no param array support for instance params yet -#define RTAPI_IP_ARRAY_INT(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, int, &(__dummy_##var), RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_IP_ARRAY_LONG(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, long, &(__dummy_##var), RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#define RTAPI_IP_ARRAY_STRING(var,num,descr) \ - int __dummy_##var; \ - module_param_array(var, charp, &(__dummy_##var), RTAPI_IP_MODE); \ - MODULE_PARM_DESC(var,descr); - -#endif // _NOTYET - -#endif /* version < 2.6 */ - -#if !defined(BUILD_SYS_USER_DSO) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#define MODULE_LICENSE(license) \ -static const char __module_license[] __attribute__((section(".modinfo"))) = \ -"license=" license -#endif -#endif - - // module tagging for feature inspection #define _RTAPI_TAG(line, key, value) \ diff --git a/src/rtapi/rtapi_app.cc b/src/rtapi/rtapi_app.cc index c26d573cee..eb6075858b 100644 --- a/src/rtapi/rtapi_app.cc +++ b/src/rtapi/rtapi_app.cc @@ -25,7 +25,6 @@ * * CAP_SYS_RAWIO open /dev/mem and /dev/kmem & Perform I/O port operations * CAP_SYS_NICE set real-time scheduling policies, set CPU affinity - * CAP_SYS_MODULE Load and unload kernel modules * * NB: Capabilities are a per-thread attribute, * so this might need to be done on a per-thread basis @@ -77,10 +76,12 @@ using namespace google::protobuf; #include "rtapi_global.h" #include "rtapi_compat.h" #include "rtapi_export.h" +#include "rtapi_flavor.h" // flavor_* #include "hal.h" #include "hal_priv.h" #include "shmdrv.h" -#ifdef USERMODE_PCI + +#ifdef SYS_IO_DEFINED #include "rtapi_io.h" #endif @@ -128,8 +129,7 @@ static void remove_module(std::string name); static struct rusage rusage; static unsigned long minflt, majflt; -static int instance_id; -flavor_ptr flavor; +static int rtapi_instance_loc; static int use_drivers = 0; static int foreground; static int debug = 0; @@ -161,21 +161,22 @@ static FILE *inifp; static AvahiCzmqPoll *av_loop; #endif -// the following two variables, despite extern, are in fact private to rtapi_app -// in the sense that they are not visible in the RT space (the namespace -// of dlopen'd modules); these are supposed to be 'ships in the night' -// relative to any symbols exported by rtapi_app. -// -// global_data is set in attach_global_segment() which was already +// RTAPI flavor functions are dynamically linked in through rtapi.so +// - Pointers to functions +flavor_name_t * flavor_name_ptr; +flavor_names_t * flavor_names_ptr; +flavor_is_configured_t * flavor_is_configured_ptr; +flavor_feature_t * flavor_feature_ptr; +flavor_byname_t * flavor_byname_ptr; +flavor_default_t * flavor_default_ptr; +flavor_install_t * flavor_install_ptr; +// - Keep track of whether pointers have been set +static int have_flavor_funcs = 0; +// - For storing the `-f` option until flavors are ready to be configured +static char flavor_name_opt[MAX_FLAVOR_NAME_LEN] = {0}; + +// global_data is set in attach_global_segment() which was already // created by rtapi_msgd -// rtapi_switch is set once rtapi.so has been loaded by calling the -// rtapi_get_handle() method in rtapi.so. -// Once set, rtapi methods in rtapi.so can be called normally through -// the rtapi_switch redirection (see rtapi.h). - -// NB: do _not_ call any rtapi_* methods before these variables are set -// except for rtapi_msg* and friends (those do not go through the rtapi_switch). -rtapi_switch_t *rtapi_switch; global_data_t *global_data; static const char *rpath; static int init_actions(int instance); @@ -184,6 +185,55 @@ static int harden_rt(void); static void stderr_rtapi_msg_handler(msg_level_t level, const char *fmt, va_list ap); static int record_instparms(char *fname, modinfo_t &mi); +static void configure_flavor(machinetalk::Container &pbreply) +{ + + // Retrieve the flavor_*_ptr() addresses so rtapi flavor functions can be + // called. + if (have_flavor_funcs) return; // Already did this + + // Load pointers +# define GET_FLAVOR_FUNC(name) do { \ + name ## _ptr = (name ## _t *)dlsym(mi.handle, #name); \ + if (name ## _ptr == NULL) { \ + const char *err = dlerror(); \ + if (err) note_printf(pbreply, "BUG: %s:", err); \ + } \ + assert(name ## _ptr != NULL); \ + } while (0) + + modinfo_t &mi = modules[RTAPIMOD]; + + dlerror(); + GET_FLAVOR_FUNC(flavor_name); + GET_FLAVOR_FUNC(flavor_names); + GET_FLAVOR_FUNC(flavor_is_configured); + GET_FLAVOR_FUNC(flavor_feature); + GET_FLAVOR_FUNC(flavor_byname); + GET_FLAVOR_FUNC(flavor_default); + GET_FLAVOR_FUNC(flavor_install); + + flavor_descriptor_ptr flavor = NULL; + if (flavor_name_opt[0]) { + // Configure flavor from -f cmdline arg + if ((flavor = (*flavor_byname_ptr)(flavor_name_opt)) == NULL) { + fprintf(stderr, "No such flavor '%s'; valid flavors are:\n", + flavor_name_opt); + flavor_descriptor_ptr * f_handle; + const char * fname; + for (f_handle=NULL; (fname=(*flavor_names_ptr)(&f_handle)); ) + fprintf(stderr, " %s\n", fname); + exit(1); + } + } else { + // Configure flavor from environment or automatically + flavor = (*flavor_default_ptr)(); // Exits on error + } + (*flavor_install_ptr)(flavor); // Exits on error + have_flavor_funcs = 1; // Don't run this again +} + + static int do_one_item(char item_type_char, const string ¶m_name, const string ¶m_value, @@ -323,53 +373,6 @@ static int do_module_args(modinfo_t &mi, return 0; } -// kthreads: -// only instance args are exported in sysfs, module params are not -// see RTAPI_IP_MODEin src/rtapi/rtapi.h -// therefore, if we see a param on kthreads newinst, we just -// overwrite the previous value via sysfs -static int do_kmodinst_args(const string &comp, - pbstringarray_t args, - machinetalk::Container &pbreply) -{ - for (int i = 0; i < args.size(); i++) { - string s(args.Get(i)); - remove_quotes(s); - size_t idx = s.find('='); - if(idx == string::npos) { - note_printf(pbreply, "Invalid parameter `%s'", - s.c_str()); - return -1; - } - string param_name(s, 0, idx); - string param_value(s, idx+1); - - // ls /sys/module/brd/parameters/ - // max_part rd_nr rd_size - - string path = "/sys/module/" + comp + "/parameters/" + param_name; - struct stat sb; - if (stat(path.c_str(), &sb) < 0) { - // if param_name is an instance param, it's exported in sysfs - note_printf(pbreply, "newinst '%s': no such instance parameter '%s'", - comp.c_str(), - param_name.c_str()); - return -ENOENT; - } - int retval = rtapi_fs_write(path.c_str(), param_value.c_str()); - if (retval < 0) { - note_printf(pbreply, "newinst %s: setting param %s to %s failed: %d - %s", - comp.c_str(), - param_name.c_str(), - param_value.c_str(), - retval, - strerror(-retval)); - return retval; - } - } - return 0; -} - static const char **pbargv(const pbstringarray_t &args) { const char **argv, **s; @@ -451,72 +454,62 @@ static int do_newinst_cmd(int instance, int retval = -1; - if (kernel_threads(flavor)) { - string s = pbconcat(args); - retval = do_kmodinst_args(comp,args,pbreply); - if (retval) return retval; - return rtapi_fs_write(PROCFS_RTAPICMD,"call newinst %s %s %s", - comp.c_str(), - instname.c_str(), - s.c_str()); - } else { - if (call_usrfunct == NULL) { - pbreply.set_retcode(1); - pbreply.add_note("this HAL library version does " - "not support user functions - version problem?"); - return -1; - } - if (modules.count(comp) == 0) { - // if newinst via halcmd, it should have been automatically loaded already - note_printf(pbreply, - "newinst: component '%s' not loaded", - comp.c_str()); - return -1; - } - modinfo_t &mi = modules[comp]; - dlerror(); - - string s = pbconcat(mi.iparm); - - // set the default instance parameters which were recorded during - // initial load with record_instanceparams() - retval = do_module_args(mi, mi.iparm, RTAPI_IP_SYMPREFIX, pbreply); - if (retval < 0) { - note_printf(pbreply, - "passing default instance args for '%s' failed: '%s'", - instname.c_str(), s.c_str()); - return retval; - } + if (call_usrfunct == NULL) { + pbreply.set_retcode(1); + pbreply.add_note("this HAL library version does " + "not support user functions - version problem?"); + return -1; + } + if (modules.count(comp) == 0) { + // if newinst via halcmd, it should have been automatically loaded already + note_printf(pbreply, + "newinst: component '%s' not loaded", + comp.c_str()); + return -1; + } + modinfo_t &mi = modules[comp]; + dlerror(); - s = pbconcat(args); - pbstringarray_t kvpairs, leftovers; - separate_kv(kvpairs, leftovers, args); + string s = pbconcat(mi.iparm); - // set the instance parameters - retval = do_module_args(mi, kvpairs, RTAPI_IP_SYMPREFIX, pbreply); - if (retval < 0) { - note_printf(pbreply, - "passing args for '%s' failed: '%s'", - instname.c_str(), s.c_str()); - return retval; - } - rtapi_print_msg(RTAPI_MSG_DBG, - "%s: instargs='%s'\n",__FUNCTION__, - s.c_str()); + // set the default instance parameters which were recorded during + // initial load with record_instanceparams() + retval = do_module_args(mi, mi.iparm, RTAPI_IP_SYMPREFIX, pbreply); + if (retval < 0) { + note_printf(pbreply, + "passing default instance args for '%s' failed: '%s'", + instname.c_str(), s.c_str()); + return retval; + } - // massage the argv for the newinst user function, - // and call it - pbstringarray_t a; - a.Add()->assign(comp); - a.Add()->assign(instname); - a.MergeFrom(leftovers); - const char **argv = pbargv(a); // pass non-kv pairs only - int ureturn = 0; - retval = call_usrfunct("newinst", a.size(), argv, &ureturn ); - if (argv) free(argv); - if (retval == 0) retval = ureturn; - usrfunct_error(retval, "newinst", args, pbreply); + s = pbconcat(args); + pbstringarray_t kvpairs, leftovers; + separate_kv(kvpairs, leftovers, args); + + // set the instance parameters + retval = do_module_args(mi, kvpairs, RTAPI_IP_SYMPREFIX, pbreply); + if (retval < 0) { + note_printf(pbreply, + "passing args for '%s' failed: '%s'", + instname.c_str(), s.c_str()); + return retval; } + rtapi_print_msg(RTAPI_MSG_DBG, + "%s: instargs='%s'\n",__FUNCTION__, + s.c_str()); + + // massage the argv for the newinst user function, + // and call it + pbstringarray_t a; + a.Add()->assign(comp); + a.Add()->assign(instname); + a.MergeFrom(leftovers); + const char **argv = pbargv(a); // pass non-kv pairs only + int ureturn = 0; + retval = call_usrfunct("newinst", a.size(), argv, &ureturn ); + if (argv) free(argv); + if (retval == 0) retval = ureturn; + usrfunct_error(retval, "newinst", args, pbreply); return retval; } @@ -528,23 +521,20 @@ static int do_delinst_cmd(int instance, string s; - if (kernel_threads(flavor)) { - return rtapi_fs_write(PROCFS_RTAPICMD,"call delinst %s", instname.c_str()); - } else { - if (call_usrfunct == NULL) { - pbreply.set_retcode(1); - pbreply.add_note("this HAL library version does not support user functions - version problem?"); - return -1; - } - pbstringarray_t a; - a.Add()->assign(instname); - const char **argv = pbargv(a); - int ureturn = 0; - retval = call_usrfunct("delinst", a.size(), argv, &ureturn); - if (argv) free(argv); - if (retval == 0) retval = ureturn; - usrfunct_error(retval, "delinst", a, pbreply); + if (call_usrfunct == NULL) { + pbreply.set_retcode(1); + pbreply.add_note("this HAL library version does not support " + "user functions - version problem?"); + return -1; } + pbstringarray_t a; + a.Add()->assign(instname); + const char **argv = pbargv(a); + int ureturn = 0; + retval = call_usrfunct("delinst", a.size(), argv, &ureturn); + if (argv) free(argv); + if (retval == 0) retval = ureturn; + usrfunct_error(retval, "delinst", a, pbreply); return retval; } @@ -555,25 +545,21 @@ static int do_callfunc_cmd(int instance, { int retval = -1; - if (kernel_threads(flavor)) { - string s = pbconcat(args); - return rtapi_fs_write(PROCFS_RTAPICMD,"call %s %s", func.c_str(), s.c_str()); - } else { - if (call_usrfunct == NULL) { - pbreply.set_retcode(1); - pbreply.add_note("this HAL library version does not support user functions - version problem?"); - return -1; - } - const char **argv = pbargv(args); - int ureturn = 0; - retval = call_usrfunct(func.c_str(), - args.size(), - argv, - &ureturn); - if (argv) free(argv); - if (retval == 0) retval = ureturn; - usrfunct_error(retval, func, args, pbreply); + if (call_usrfunct == NULL) { + pbreply.set_retcode(1); + pbreply.add_note("this HAL library version does not support user " + "functions - version problem?"); + return -1; } + const char **argv = pbargv(args); + int ureturn = 0; + retval = call_usrfunct(func.c_str(), + args.size(), + argv, + &ureturn); + if (argv) free(argv); + if (retval == 0) retval = ureturn; + usrfunct_error(retval, func, args, pbreply); return retval; } @@ -585,87 +571,64 @@ static int do_load_cmd(int instance, machinetalk::Container &pbreply) { char module_path[PATH_MAX]; - int retval; // For modules given as paths, use the path basename as the module name string name = path; if (name.find_last_of("/") != string::npos) name = name.substr(name.find_last_of("/") + 1); - if (modules.count(name) == 0) { - if (kernel_threads(flavor)) { - string cmdargs = pbconcat(args, " ", "'"); - retval = run_module_helper( - "insert %s %s", path.c_str(), cmdargs.c_str()); - if (retval) { - note_printf( - pbreply, "couldnt insmod %s - see dmesg\n", path.c_str()); - } else { - modules[name] = modinfo(); - loading_order.push_back(name); - } - return retval; - } else { - strncpy(module_path, (path + flavor->mod_ext).c_str(), - PATH_MAX); - modinfo_t mi = modinfo_t(); - - mi.handle = dlopen(module_path, RTLD_GLOBAL |RTLD_NOW); - if (!mi.handle) { - string errmsg(dlerror()); - note_printf(pbreply, "%s: dlopen: %s", - __FUNCTION__, errmsg.c_str()); - note_printf(pbreply, "rpath=%s", rpath == NULL ? "" : rpath); - return -1; - } - // first load of a module. Record default instanceparams - // so they can be replayed before newinst - record_instparms(module_path, mi); - - // retrieve the address of rtapi_switch_struct - // so rtapi functions can be called and members - // accessed - // RTAPIMOD only will have that, but we need that as soon as - // possible so not much use in testing the name - if (rtapi_switch == NULL) { - rtapi_get_handle_t rtapi_get_handle; - dlerror(); - rtapi_get_handle = (rtapi_get_handle_t)dlsym(mi.handle, - "rtapi_get_handle"); - if (rtapi_get_handle != NULL) { - rtapi_switch = rtapi_get_handle(); - assert(rtapi_switch != NULL); - } - } + rtapi_print_msg(RTAPI_MSG_DBG, "Loading from %s\n", path.c_str()); // FIXME - int (*start)(void) = DLSYM(mi.handle, "rtapi_app_main"); - if (!start) { - note_printf(pbreply, "%s: dlsym: %s\n", - name.c_str(), dlerror()); - return -1; - } - int result; + if (modules.count(name) == 0) { + strncpy(module_path, (path + ".so").c_str(), + PATH_MAX); + modinfo_t mi = modinfo_t(); + + mi.handle = dlopen(module_path, RTLD_GLOBAL |RTLD_NOW); + if (!mi.handle) { + string errmsg(dlerror()); + note_printf(pbreply, "%s: dlopen: %s", + __FUNCTION__, errmsg.c_str()); + note_printf(pbreply, "rpath=%s", rpath == NULL ? "" : rpath); + return -1; + } + // first load of a module. Record default instanceparams + // so they can be replayed before newinst + record_instparms(module_path, mi); + + int (*rtapi_app_main_dlsym)(void) = + DLSYM(mi.handle, "rtapi_app_main"); + if (!rtapi_app_main_dlsym) { + note_printf(pbreply, "%s: dlsym: %s\n", + name.c_str(), dlerror()); + return -1; + } + int result; - result = do_module_args(mi, args, RTAPI_MP_SYMPREFIX, pbreply); - if (result < 0) { - dlclose(mi.handle); - return -1; - } + result = do_module_args(mi, args, RTAPI_MP_SYMPREFIX, pbreply); + if (result < 0) { + dlclose(mi.handle); + return -1; + } - // need to call rtapi_app_main with as root - // RT thread creation and hardening requires this - if ((result = start()) < 0) { - note_printf(pbreply, "rtapi_app_main(%s): %d %s\n", - name.c_str(), result, strerror(-result)); - return result; - } - modules[name] = mi; - loading_order.push_back(name); + // Configure flavor, needed even before `rtapi_app_main_dlsym()` runs + // next. This runs at every module load, but only does anything after + // RTAPIMOD, the first module loaded. + configure_flavor(pbreply); + + // need to call rtapi_app_main with as root + // RT thread creation and hardening requires this + if ((result = rtapi_app_main_dlsym()) < 0) { + note_printf(pbreply, "rtapi_app_main(%s): %d %s\n", + name.c_str(), result, strerror(-result)); + return result; + } + modules[name] = mi; + loading_order.push_back(name); - rtapi_print_msg(RTAPI_MSG_DBG, "%s: loaded from %s\n", - name.c_str(), module_path); - return 0; - } + rtapi_print_msg(RTAPI_MSG_DBG, "%s: loaded from %s\n", + name.c_str(), module_path); + return 0; } else { note_printf(pbreply, "%s: already loaded\n", name.c_str()); return -1; @@ -683,24 +646,12 @@ static int do_load_cmd(int instance, return -1; } else { modinfo_t &mi = modules[name]; - if (kernel_threads(flavor)) { - retval = run_module_helper("remove %s", name.c_str()); - if (retval) { - note_printf(reply, "couldnt rmmod %s - see dmesg\n", - name.c_str()); - return retval; - } else { - modules.erase(modules.find(name)); - remove_module(name); - } - } else { - int (*stop)(void) = DLSYM(mi.handle, "rtapi_app_exit"); - if (stop) - stop(); - dlclose(mi.handle); - modules.erase(modules.find(name)); - remove_module(name); - } + int (*stop)(void) = DLSYM(mi.handle, "rtapi_app_exit"); + if (stop) + stop(); + dlclose(mi.handle); + modules.erase(modules.find(name)); + remove_module(name); } rtapi_print_msg(RTAPI_MSG_DBG, " '%s' unloaded\n", name.c_str()); return retval; @@ -745,73 +696,30 @@ static void exit_actions(int instance) static int init_actions(int instance) { int retval; - char moddir[PATH_MAX]; - - get_rtapi_config(moddir,"MODULES",PATH_MAX); - - if (kernel_threads(flavor)) { - // kthreads cant possibly run without shmdrv, so bail - // also, cannot load it here because rtapi_msgd already needs this - // so it'd be too late here - if (!is_module_loaded("shmdrv")) { - rtapi_print_msg(RTAPI_MSG_ERR, "shmdrv not loaded"); - return -1; - } - // leftovers or running session? - if (is_module_loaded(RTAPIMOD)) { - rtapi_print_msg(RTAPI_MSG_ERR, "rtapi already loaded"); - return -1; - } - if (is_module_loaded(HALMOD)) { - rtapi_print_msg(RTAPI_MSG_ERR, "hal_lib already loaded"); - return -1; - } - char *m = strtok(moddir, "\t "); - while (m != NULL) { - char cmdline[PATH_MAX]; - if (!strcmp(m, RTAPIMOD)) { - snprintf(cmdline, sizeof(cmdline), - "insert %s rtapi_instance=%d", m, instance_id); - } else { - snprintf(cmdline, sizeof(cmdline), "insert %s", m); - } - rtapi_print_msg(RTAPI_MSG_DBG, "running '%s'", cmdline); - retval = run_module_helper(cmdline); - if (retval) { - rtapi_print_msg(RTAPI_MSG_ERR, - "linuxcnc_module_helper '%s' failed - see dmesg\n", - cmdline); - return retval; - } else - rtapi_print_msg(RTAPI_MSG_DBG, "'%s' loaded\n", m); - m = strtok(NULL, "\t "); - } - } machinetalk::Container reply; + retval = do_load_cmd(instance, RTAPIMOD, pbstringarray_t(), reply); if (retval) return retval; if ((retval = do_load_cmd(instance, HALMOD, pbstringarray_t(), reply))) return retval; - if (!kernel_threads(flavor)) { - // resolve the "hal_call_usrfunct" for later - // callfunc, newinst & delinst need it - modinfo_t &hallib = modules[HALMOD]; - dlerror(); - call_usrfunct = (hal_call_usrfunct_t) dlsym(hallib.handle, - "hal_call_usrfunct"); - - if (call_usrfunct == NULL) { - rtapi_print_msg(RTAPI_MSG_ERR, - "cant resolve 'hal_call_usrfunct' in " - "hal_lib - version problem?"); - char *s = dlerror(); - if (s) - rtapi_print_msg(RTAPI_MSG_ERR, "dlsym(hal_call_usrfunct): '%s'", s); - return -1; - } + // resolve the "hal_call_usrfunct" for later + // callfunc, newinst & delinst need it + modinfo_t &hallib = modules[HALMOD]; + dlerror(); + call_usrfunct = (hal_call_usrfunct_t) dlsym(hallib.handle, + "hal_call_usrfunct"); + + if (call_usrfunct == NULL) { + rtapi_print_msg(RTAPI_MSG_ERR, + "cant resolve 'hal_call_usrfunct' in " + "hal_lib - version problem?"); + char *s = dlerror(); + if (s) + rtapi_print_msg(RTAPI_MSG_ERR, "dlsym(hal_call_usrfunct): '%s'", s); + return -1; } return 0; } @@ -820,20 +728,20 @@ static int init_actions(int instance) static int attach_global_segment() { int retval = 0; - int globalkey = OS_KEY(GLOBAL_KEY, instance_id); + int globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance_loc); int size = 0; int tries = 10; // 5 sec deadline for msgd/globaldata to come up shm_common_init(); do { retval = shm_common_new(globalkey, &size, - instance_id, (void **) &global_data, 0); + rtapi_instance_loc, (void **) &global_data, 0); if (retval < 0) { tries--; if (tries == 0) { syslog_async(LOG_ERR, "rtapi_app:%d: ERROR: cannot attach global segment key=0x%x %s\n", - instance_id, globalkey, strerror(-retval)); + rtapi_instance_loc, globalkey, strerror(-retval)); return retval; } struct timespec ts = {0, 500 * 1000 * 1000}; //ms @@ -844,7 +752,7 @@ static int attach_global_segment() if (size < (int) sizeof(global_data_t)) { syslog_async(LOG_ERR, "rtapi_app:%d global segment size mismatch: expect >%zu got %d\n", - instance_id, sizeof(global_data_t), size); + rtapi_instance_loc, sizeof(global_data_t), size); return -EINVAL; } @@ -854,12 +762,16 @@ static int attach_global_segment() if (tries == 0) { syslog_async(LOG_ERR, "rtapi_app:%d: ERROR: global segment magic not changing to ready: magic=0x%x\n", - instance_id, global_data->magic); + rtapi_instance_loc, global_data->magic); return -EINVAL; } struct timespec ts = {0, 500 * 1000 * 1000}; //ms nanosleep(&ts, NULL); } + syslog_async(LOG_DEBUG, + "rtapi_app:%d: Attached global segment magic=0x%x\n", + rtapi_instance_loc, global_data->magic); + return retval; } @@ -871,6 +783,10 @@ static int rtapi_request(zloop_t *loop, zsock_t *socket, void *arg) char *origin = zmsg_popstr (r); zframe_t *request_frame = zmsg_pop (r); static bool force_exit = false; + modinfo_t mi; + int retval; + int (*create_thread)(const hal_threadargs_t*); + int (*delete_thread)(const char *); if(request_frame == NULL){ rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_request(): NULL zframe_t 'request_frame' passed"); @@ -901,7 +817,7 @@ static int rtapi_request(zloop_t *loop, zsock_t *socket, void *arg) char buffer[LINELEN]; snprintf(buffer, sizeof(buffer), "pid=%d flavor=%s gcc=%s git=%s", - getpid(),flavor->name, __VERSION__, GIT_VERSION); + getpid(), (*flavor_name_ptr)(NULL), __VERSION__, GIT_VERSION); pbreply.add_note(buffer); pbreply.set_retcode(0); break; @@ -986,44 +902,33 @@ static int rtapi_request(zloop_t *loop, zsock_t *socket, void *arg) assert(pbreq.rtapicmd().has_instance()); assert(pbreq.rtapicmd().has_flags()); - if (kernel_threads(flavor)) { - int retval = rtapi_fs_write(PROCFS_RTAPICMD,"newthread %s %d %d %d %d", - pbreq.rtapicmd().threadname().c_str(), - pbreq.rtapicmd().threadperiod(), - pbreq.rtapicmd().use_fp(), - pbreq.rtapicmd().cpu(), - pbreq.rtapicmd().flags()); - pbreply.set_retcode(retval < 0 ? retval:0); - - } else { - if (modules.count(HALMOD) == 0) { - pbreply.add_note("hal_lib not loaded"); - pbreply.set_retcode(-1); - break; - } - modinfo_t &mi = modules[HALMOD]; - int (*create_thread)(const hal_threadargs_t*) = - DLSYM(mi.handle, - "hal_create_xthread"); - if (create_thread == NULL) { - pbreply.add_note("symbol 'hal_create_thread' not found in hal_lib"); - pbreply.set_retcode(-1); - break; - } - hal_threadargs_t args; - args.name = pbreq.rtapicmd().threadname().c_str(); - args.period_nsec = pbreq.rtapicmd().threadperiod(); - args.uses_fp = pbreq.rtapicmd().use_fp(); - args.cpu_id = pbreq.rtapicmd().cpu(); - args.flags = (rtapi_thread_flags_t) pbreq.rtapicmd().flags(); - strncpy(args.cgname, pbreq.rtapicmd().cgname().c_str(), LINELEN); - - int retval = create_thread(&args); - if (retval < 0) { - pbreply.add_note("hal_create_xthread() failed, see log"); - } - pbreply.set_retcode(retval); - } + if (modules.count(HALMOD) == 0) { + pbreply.add_note("hal_lib not loaded"); + pbreply.set_retcode(-1); + break; + } + mi = modules[HALMOD]; + create_thread = + DLSYM(mi.handle, + "hal_create_xthread"); + if (create_thread == NULL) { + pbreply.add_note("symbol 'hal_create_thread' not found in hal_lib"); + pbreply.set_retcode(-1); + break; + } + hal_threadargs_t args; + args.name = pbreq.rtapicmd().threadname().c_str(); + args.period_nsec = pbreq.rtapicmd().threadperiod(); + args.uses_fp = pbreq.rtapicmd().use_fp(); + args.cpu_id = pbreq.rtapicmd().cpu(); + args.flags = (rtapi_thread_flags_t) pbreq.rtapicmd().flags(); + strncpy(args.cgname, pbreq.rtapicmd().cgname().c_str(), LINELEN); + + retval = create_thread(&args); + if (retval < 0) { + pbreply.add_note("hal_create_xthread() failed, see log"); + } + pbreply.set_retcode(retval); break; case machinetalk::MT_RTAPI_APP_DELTHREAD: @@ -1031,27 +936,21 @@ static int rtapi_request(zloop_t *loop, zsock_t *socket, void *arg) assert(pbreq.rtapicmd().has_threadname()); assert(pbreq.rtapicmd().has_instance()); - if (kernel_threads(flavor)) { - int retval = rtapi_fs_write(PROCFS_RTAPICMD, "delthread %s", - pbreq.rtapicmd().threadname().c_str()); - pbreply.set_retcode(retval < 0 ? retval:0); - } else { - if (modules.count(HALMOD) == 0) { - pbreply.add_note("hal_lib not loaded"); - pbreply.set_retcode(-1); - break; - } - modinfo_t &mi = modules[HALMOD]; - int (*delete_thread)(const char *) = - DLSYM(mi.handle, "hal_thread_delete"); - if (delete_thread == NULL) { - pbreply.add_note("symbol 'hal_thread_delete' not found in hal_lib"); - pbreply.set_retcode(-1); - break; - } - int retval = delete_thread(pbreq.rtapicmd().threadname().c_str()); - pbreply.set_retcode(retval); - } + if (modules.count(HALMOD) == 0) { + pbreply.add_note("hal_lib not loaded"); + pbreply.set_retcode(-1); + break; + } + mi = modules[HALMOD]; + delete_thread = + DLSYM(mi.handle, "hal_thread_delete"); + if (delete_thread == NULL) { + pbreply.add_note("symbol 'hal_thread_delete' not found in hal_lib"); + pbreply.set_retcode(-1); + break; + } + retval = delete_thread(pbreq.rtapicmd().threadname().c_str()); + pbreply.set_retcode(retval); break; default: @@ -1174,7 +1073,7 @@ static int s_handle_signal(zloop_t *loop, zmq_pollitem_t *poller, void *arg) rtapi_print_msg(RTAPI_MSG_INFO, "signal %d - '%s' received, exiting", fdsi.ssi_signo, strsignal(fdsi.ssi_signo)); - exit_actions(instance_id); + exit_actions(rtapi_instance_loc); interrupted = true; // make mainloop exit if (global_data) global_data->rtapi_app_pid = 0; @@ -1197,7 +1096,7 @@ s_handle_timer(zloop_t *loop, int timer_id, void *args) if (global_data->rtapi_msgd_pid == 0) { // cant log this via rtapi_print, since msgd is gone syslog_async(LOG_ERR,"rtapi_msgd went away, exiting\n"); - exit_actions(instance_id); + exit_actions(rtapi_instance_loc); if (global_data) global_data->rtapi_app_pid = 0; exit(EXIT_FAILURE); @@ -1213,7 +1112,7 @@ static int mainloop(size_t argc, char **argv) static char proctitle[20]; // set new process name - snprintf(proctitle, sizeof(proctitle), "rtapi:%d",instance_id); + snprintf(proctitle, sizeof(proctitle), "rtapi:%d",rtapi_instance_loc); size_t argv0_len = strlen(argv[0]); size_t procname_len = strlen(proctitle); size_t max_procname_len = (argv0_len > procname_len) ? @@ -1242,7 +1141,7 @@ static int mainloop(size_t argc, char **argv) exit(retval); } - // make sure rtapi_msgd's pid is valid and msgd is running, + // make sure rtapi_msgd's pid is valid and msgd is running, // in case we caught a leftover shmseg // otherwise log messages would vanish if ((global_data->rtapi_msgd_pid == 0) || @@ -1252,28 +1151,27 @@ static int mainloop(size_t argc, char **argv) exit(EXIT_FAILURE); } - // from here on it is safe to use rtapi_print() and friends as + // from here on it is safe to use rtapi_print() and friends as // the error ring is now set up and msgd is logging it rtapi_set_logtag("rtapi_app"); rtapi_set_msg_level(global_data->rt_msg_level); - // obtain handle on flavor descriptor as detected by rtapi_msgd - flavor = flavor_byid(global_data->rtapi_thread_flavor); - if (flavor == NULL) { + // load rtapi and hal_lib + // - After this, it's safe to run any flavor_* stuff + if (init_actions(rtapi_instance_loc)) { rtapi_print_msg(RTAPI_MSG_ERR, - "FATAL - invalid flavor id: %d\n", - global_data->rtapi_thread_flavor); + "init_actions() failed\n"); global_data->rtapi_app_pid = 0; - exit(EXIT_FAILURE); + exit(1); } // make sure we're setuid root when we need to - if (use_drivers || (flavor->flags & FLAVOR_DOES_IO)) { + if (use_drivers || (*flavor_feature_ptr)(NULL, FLAVOR_DOES_IO)) { if (geteuid() != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app:%d need to" " 'sudo make setuid' to access I/O?\n", - instance_id); + rtapi_instance_loc); global_data->rtapi_app_pid = 0; exit(EXIT_FAILURE); } @@ -1283,20 +1181,12 @@ static int mainloop(size_t argc, char **argv) if ((retval = harden_rt())) { rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app:%d failed to setup " - "realtime environment - 'sudo make setuid' missing?\n", - instance_id); + "realtime environment - 'sudo make setuid' missing?\n", + rtapi_instance_loc); global_data->rtapi_app_pid = 0; exit(retval); } - // load rtapi and hal_lib - if (init_actions(instance_id)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "init_actions() failed\n"); - global_data->rtapi_app_pid = 0; - exit(1); - } - // block all signal delivery through signal handler // since we're using signalfd() // do this here so child threads inherit the sigmask @@ -1352,7 +1242,7 @@ static int mainloop(size_t argc, char **argv) { // always bind the IPC socket char uri[LINELEN]; snprintf(uri, sizeof(uri), ZMQIPC_FORMAT, - RUNDIR, instance_id, RTAPIMOD, service_uuid); + RUNDIR, rtapi_instance_loc, RTAPIMOD, service_uuid); mode_t prev = umask(S_IROTH | S_IWOTH | S_IXOTH); if ((z_port = zsock_bind(z_command, "%s", uri )) < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "cannot bind IPC socket '%s' - %s\n", @@ -1367,12 +1257,12 @@ static int mainloop(size_t argc, char **argv) assert(z_loop); zloop_set_verbose(z_loop, z_debug); - + if (trap_signals) { zmq_pollitem_t signal_poller = { 0, signal_fd, ZMQ_POLLIN }; zloop_poller (z_loop, &signal_poller, s_handle_signal, NULL); } - + zloop_reader(z_loop, z_command, rtapi_request, NULL); zloop_timer (z_loop, BACKGROUND_TIMER, 0, s_handle_timer, NULL); @@ -1383,7 +1273,7 @@ static int mainloop(size_t argc, char **argv) if (!(av_loop = avahi_czmq_poll_new(z_loop))) { rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app:%d: zeroconf: " "Failed to create avahi event loop object.", - instance_id); + rtapi_instance_loc); return -1; } else { char name[255]; @@ -1399,7 +1289,7 @@ static int mainloop(size_t argc, char **argv) av_loop); if (rtapi_publisher == NULL) { rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app:%d: failed to start zeroconf publisher", - instance_id); + rtapi_instance_loc); return -1; } } @@ -1407,8 +1297,9 @@ static int mainloop(size_t argc, char **argv) #endif // report success - rtapi_print_msg(RTAPI_MSG_INFO, "rtapi_app:%d ready flavor=%s gcc=%s git=%s", - instance_id, flavor->name, __VERSION__, GIT_VERSION); + rtapi_print_msg( + RTAPI_MSG_INFO, "rtapi_app:%d ready flavor=%s gcc=%s git=%s", + rtapi_instance_loc, (*flavor_name_ptr)(NULL), __VERSION__, GIT_VERSION); // the RT stack is now set up and good for use global_data->rtapi_app_pid = getpid(); @@ -1438,12 +1329,12 @@ static int configure_memory(void) unsigned int i, pagesize; char *buf; - if (global_data->rtapi_thread_flavor != RTAPI_POSIX_ID) { + if (use_drivers || (*flavor_feature_ptr)(NULL, FLAVOR_DOES_IO)) { // Realtime tweak requires privs /* Lock all memory. This includes all current allocations (BSS/data) * and future allocations. */ if (mlockall(MCL_CURRENT | MCL_FUTURE)) { - rtapi_print_msg(RTAPI_MSG_WARN, + rtapi_print_msg(RTAPI_MSG_WARN, "mlockall() failed: %d '%s'\n", errno,strerror(errno)); rtapi_print_msg(RTAPI_MSG_WARN, @@ -1513,7 +1404,7 @@ static int harden_rt() core_limit.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &core_limit) < 0) - rtapi_print_msg(RTAPI_MSG_WARN, + rtapi_print_msg(RTAPI_MSG_WARN, "setrlimit: %s - core dumps may be truncated or non-existant\n", strerror(errno)); @@ -1522,7 +1413,7 @@ static int harden_rt() // echo 1 > // might be needed to have setuid programs dump core if (prctl(PR_SET_DUMPABLE, 1) < 0) - rtapi_print_msg(RTAPI_MSG_WARN, + rtapi_print_msg(RTAPI_MSG_WARN, "prctl(PR_SET_DUMPABLE) failed: no core dumps will be created - %d - %s\n", errno, strerror(errno)); FILE *fd; @@ -1531,7 +1422,7 @@ static int harden_rt() if ((fscanf(fd, "%d", &flag) == 1) && (flag == 0)) { rtapi_print_msg(RTAPI_MSG_WARN, "rtapi:%d: cannot create core dumps - /proc/sys/fs/suid_dumpable contains 0", - instance_id); + rtapi_instance_loc); rtapi_print_msg(RTAPI_MSG_WARN, "you might have to run 'echo 1 > /proc/sys/fs/suid_dumpable'" " as root to enable rtapi_app core dumps"); @@ -1542,59 +1433,27 @@ static int harden_rt() configure_memory(); if (getrusage(RUSAGE_SELF, &rusage)) { - rtapi_print_msg(RTAPI_MSG_WARN, + rtapi_print_msg(RTAPI_MSG_WARN, "getrusage(RUSAGE_SELF) failed: %d '%s'\n", errno,strerror(errno)); } else { minflt = rusage.ru_minflt; majflt = rusage.ru_majflt; if (atexit(exit_handler)) { - rtapi_print_msg(RTAPI_MSG_WARN, + rtapi_print_msg(RTAPI_MSG_WARN, "atexit() failed: %d '%s'\n", errno,strerror(errno)); } } - if (flavor->flavor_id == RTAPI_XENOMAI_ID) { - int retval = user_in_xenomai_group(); - - switch (retval) { - case 1: - // { - // gid_t xg = xenomai_gid(); - // do_setuid(); - // if (setegid(xg)) - // rtapi_print_msg(RTAPI_MSG_ERR, - // "setegid(%d): %s", xg, strerror(errno)); - // undo_setuid(); - // rtapi_print_msg(RTAPI_MSG_ERR, - // "xg=%d egid now %d", xg, getegid()); - // } - break; - case 0: - rtapi_print_msg(RTAPI_MSG_ERR, - "this user is not member of group xenomai"); - rtapi_print_msg(RTAPI_MSG_ERR, - "please 'sudo adduser xenomai'," - " logout and login again"); - return -1; - - default: - rtapi_print_msg(RTAPI_MSG_ERR, - "cannot determine if this user is a member of group xenomai: %s", - strerror(-retval)); - return -1; - } - } - -#ifdef USERMODE_PCI +#if defined(SYS_IO_DEFINED) // this is a bit of a shotgun approach and should be made more selective // however, due to serial invocations of rtapi_app during setup it is not // guaranteed the process executing e.g. hal_parport's rtapi_app_main is // the same process which starts the RT threads, causing hal_parport // thread functions to fail on inb/outb - if (use_drivers || (flavor->flags & FLAVOR_DOES_IO)) { + if (use_drivers || (*flavor_feature_ptr)(NULL, FLAVOR_DOES_IO)) { if (iopl(3) < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "cannot gain I/O privileges - " @@ -1607,7 +1466,7 @@ static int harden_rt() } -static void usage(int argc, char **argv) +static void usage(int argc, char **argv) { printf("Usage: %s [options]\n", argv[0]); } @@ -1639,8 +1498,6 @@ int main(int argc, char **argv) uuid_unparse(process_uuid, process_uuid_str); int option = LOG_NDELAY; - - while (1) { int option_index = 0; int curind = optind; @@ -1672,20 +1529,11 @@ int main(int argc, char **argv) break; case 'I': - instance_id = atoi(optarg); + rtapi_instance_loc = atoi(optarg); break; case 'f': - if ((flavor = flavor_byname(optarg)) == NULL) { - fprintf(stderr, "no such flavor: '%s' -- valid flavors are:\n", - optarg); - flavor_ptr f = flavors; - while (f->name) { - fprintf(stderr, "\t%s\n", f->name); - f++; - } - exit(1); - } + strncpy(flavor_name_opt, optarg, MAX_FLAVOR_NAME_LEN); break; case 'U': @@ -1916,4 +1764,3 @@ static int record_instparms(char *fname, modinfo_t &mi) free(section); return 0; } - diff --git a/src/rtapi/rtapi_app.h b/src/rtapi/rtapi_app.h index bb3592e27d..4a4fd9a798 100644 --- a/src/rtapi/rtapi_app.h +++ b/src/rtapi/rtapi_app.h @@ -25,21 +25,12 @@ get full of ifdefs. */ -#if defined(BUILD_SYS_USER_DSO) - -#if defined(USERMODE_PCI) #include "userpci/module.h" -#endif -/* For kernel modules (hm2_pci, hostmot2) to compile in usermode without lots - of changes, the EXPORT_SYMBOL lines, below, need to be defined *ONLY* if - there is actually an rtapi_app_* function in the code. This is handeled - in the kernel module case by the simple define that renames the module - init/cleanup functions. - For the usermode case, turn the first instance of rtapi_app_* into a - function declaration, then export the symbol, then re-create the function - definition. This way the symbol is only exported if the function exists - in the code, and we don't have to have the ability to 'rewind' the C - preprocessor. + +/* Turn the first instance of rtapi_app_* into a function declaration, then + export the symbol, then re-create the function definition. This way the + symbol is only exported if the function exists in the code, and we don't + have to have the ability to 'rewind' the C preprocessor. */ #define rtapi_app_main(a) \ rtapi_app_main(a); \ @@ -49,10 +40,5 @@ rtapi_app_exit(a); \ EXPORT_SYMBOL(rtapi_app_exit); \ void rtapi_app_exit(a) -#else -#include -#define rtapi_app_main(a) init_module(a) -#define rtapi_app_exit(a) cleanup_module(a) -#endif #endif /* RTAPI_APP_H */ diff --git a/src/rtapi/rtapi_common.c b/src/rtapi/rtapi_common.c deleted file mode 100644 index bbd8c3be07..0000000000 --- a/src/rtapi/rtapi_common.c +++ /dev/null @@ -1,420 +0,0 @@ -// Copyright 2006-2013 Various Authors -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#include "config.h" -#include "rtapi.h" -#include "rtapi_common.h" -#include "rtapi_compat.h" -#include "ring.h" - -#ifndef MODULE -#include /* strtol() */ -#endif - -#if defined(BUILD_SYS_KBUILD) && defined(ULAPI) -#include /* putchar */ -#endif - - -/* these pointers are initialized at startup to point - to resource data in the master data structure above - all access to the data structure should uses these - pointers, they take into account the mapping of - shared memory into either kernel or user space. - (the RTAPI kernel module and each ULAPI user process - has its own set of these vars, initialized to match - that process's memory mapping.) -*/ - -#ifdef BUILD_SYS_USER_DSO -// in the userland threads scenario, there is no point in having this -// in shared memory, so keep it here -static rtapi_data_t local_rtapi_data; -rtapi_data_t *rtapi_data = &local_rtapi_data; -task_data *task_array = local_rtapi_data.task_array; -shmem_data *shmem_array = local_rtapi_data.shmem_array; -module_data *module_array = local_rtapi_data.module_array; -#else -rtapi_data_t *rtapi_data = NULL; -task_data *task_array = NULL; -shmem_data *shmem_array = NULL; -module_data *module_array = NULL; -#endif - -// RTAPI: -// global_data is exported by rtapi_module.c (kthreads) -// or rtapi_main.c (uthreads) -// ULAPI: exported in ulapi_autoload.c -extern global_data_t *global_data; - -/* - define the rtapi_switch struct, with pointers to all rtapi_* - functions - - ULAPI doesn't define all functions, so for missing functions point - to the dummy function _rtapi_dummy() in hopes of more graceful - failure -*/ - -int _rtapi_dummy(void) { - rtapi_print_msg(RTAPI_MSG_ERR, - "Error: _rtapi_dummy function called from rtapi_switch; " - "this should never happen!"); - return -EINVAL; -} - -static rtapi_switch_t rtapi_switch_struct = { - .git_version = GIT_VERSION, - .thread_flavor_name = THREAD_FLAVOR_NAME, - .thread_flavor_id = THREAD_FLAVOR_ID, - .thread_flavor_flags = FLAVOR_FLAGS, - - // init & exit functions - .rtapi_init = &_rtapi_init, - .rtapi_exit = &_rtapi_exit, - .rtapi_next_handle = &_rtapi_next_handle, - // messaging functions moved to instance, - // implemented in rtapi_support.c - // time functions -#ifdef RTAPI - .rtapi_clock_set_period = &_rtapi_clock_set_period, - .rtapi_delay = &_rtapi_delay, - .rtapi_delay_max = &_rtapi_delay_max, - .rtapi_task_pll_get_reference = &_rtapi_task_pll_get_reference, - .rtapi_task_pll_set_correction = &_rtapi_task_pll_set_correction, -#else - .rtapi_clock_set_period = &_rtapi_dummy, - .rtapi_delay = &_rtapi_dummy, - .rtapi_delay_max = &_rtapi_dummy, - .rtapi_task_pll_get_reference = &_rtapi_dummy, - .rtapi_task_pll_set_correction = &_rtapi_dummy, -#endif - .rtapi_get_time = &_rtapi_get_time, - .rtapi_get_clocks = &_rtapi_get_clocks, - // task functions - .rtapi_prio_highest = &_rtapi_prio_highest, - .rtapi_prio_lowest = &_rtapi_prio_lowest, - .rtapi_prio_next_higher = &_rtapi_prio_next_higher, - .rtapi_prio_next_lower = &_rtapi_prio_next_lower, -#ifdef RTAPI - .rtapi_task_new = &_rtapi_task_new, - .rtapi_task_delete = &_rtapi_task_delete, - .rtapi_task_start = &_rtapi_task_start, - .rtapi_wait = &_rtapi_wait, - .rtapi_task_resume = &_rtapi_task_resume, - .rtapi_task_pause = &_rtapi_task_pause, - .rtapi_task_self = &_rtapi_task_self, -#else - .rtapi_task_new = &_rtapi_dummy, - .rtapi_task_delete = &_rtapi_dummy, - .rtapi_task_start = &_rtapi_dummy, - .rtapi_wait = &_rtapi_dummy, - .rtapi_task_resume = &_rtapi_dummy, - .rtapi_task_pause = &_rtapi_dummy, - .rtapi_task_self = &_rtapi_dummy, -#endif - // shared memory functions - .rtapi_shmem_new = &_rtapi_shmem_new, - .rtapi_shmem_new_inst = &_rtapi_shmem_new_inst, - - .rtapi_shmem_delete = &_rtapi_shmem_delete, - .rtapi_shmem_delete_inst = &_rtapi_shmem_delete_inst, - - .rtapi_shmem_getptr = &_rtapi_shmem_getptr, - .rtapi_shmem_getptr_inst = &_rtapi_shmem_getptr_inst, - .rtapi_shmem_exists = &_rtapi_shmem_exists, - -#ifdef RTAPI - .rtapi_set_exception = &_rtapi_set_exception, -#else - .rtapi_set_exception = &_rtapi_dummy, -#endif -#ifdef RTAPI - .rtapi_task_update_stats = &_rtapi_task_update_stats, -#else - .rtapi_task_update_stats = &_rtapi_dummy, -#endif - .rtapi_malloc = &_rtapi_malloc, - .rtapi_malloc_aligned = &_rtapi_malloc_aligned, - .rtapi_calloc = &_rtapi_calloc, - .rtapi_realloc = &_rtapi_realloc, - .rtapi_free = &_rtapi_free, - .rtapi_allocsize = &_rtapi_allocsize, - .rtapi_heap_init = &_rtapi_heap_init, - .rtapi_heap_addmem = &_rtapi_heap_addmem, - .rtapi_heap_status = &_rtapi_heap_status, - .rtapi_heap_setflags = &_rtapi_heap_setflags, - .rtapi_heap_walk_freelist = &_rtapi_heap_walk_freelist, -}; - -// any API, any style: -rtapi_switch_t *rtapi_get_handle(void) { - return &rtapi_switch_struct; -} -#ifdef RTAPI -EXPORT_SYMBOL(rtapi_get_handle); -#endif - -#if defined(BUILD_SYS_KBUILD) -int shmdrv_loaded = 1; // implicit -#else -int shmdrv_loaded; // set in rtapi_app_main, and ulapi_main -#endif -long page_size; // set in rtapi_app_main - -void rtapi_autorelease_mutex(void *variable) -{ - if (rtapi_data != NULL) - rtapi_mutex_give(&(rtapi_data->mutex)); - else - // programming error - rtapi_print_msg(RTAPI_MSG_ERR, - "rtapi_autorelease_mutex: rtapi_data == NULL!\n"); -} - -// in the RTAPI scenario, -// global_data is exported by instance.ko and referenced -// by rtapi.ko and hal_lib.ko - -// in ULAPI, we have only hal_lib which calls 'down' -// onto ulapi.so to init, so in this case global_data -// is exported by hal_lib and referenced by ulapi.so - -extern global_data_t *global_data; - - -/* global init code */ - -void init_rtapi_data(rtapi_data_t * data) -{ - int n, m; - - /* has the block already been initialized? */ - if (data->magic == RTAPI_MAGIC) { - /* yes, nothing to do */ - return; - } - /* no, we need to init it, grab mutex unconditionally */ - rtapi_mutex_try(&(data->mutex)); - /* set magic number so nobody else init's the block */ - data->magic = RTAPI_MAGIC; - /* set version code and flavor ID so other modules can check it */ - data->serial = RTAPI_SERIAL; - data->thread_flavor_id = THREAD_FLAVOR_ID; - data->ring_mutex = 0; - /* and get busy */ - data->rt_module_count = 0; - data->ul_module_count = 0; - data->task_count = 0; - data->shmem_count = 0; - data->timer_running = 0; - data->timer_period = 0; - /* init the arrays */ - for (n = 0; n <= RTAPI_MAX_MODULES; n++) { - data->module_array[n].state = EMPTY; - data->module_array[n].name[0] = '\0'; - } - for (n = 0; n <= RTAPI_MAX_TASKS; n++) { - data->task_array[n].state = EMPTY; - data->task_array[n].prio = 0; - data->task_array[n].owner = 0; - data->task_array[n].taskcode = NULL; - data->task_array[n].cpu = -1; // use default - } - for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { - data->shmem_array[n].key = 0; - data->shmem_array[n].rtusers = 0; - data->shmem_array[n].ulusers = 0; - data->shmem_array[n].size = 0; - for (m = 0; m < RTAPI_BITMAP_SIZE(RTAPI_MAX_SHMEMS +1); m++) { - data->shmem_array[n].bitmap[m] = 0; - } - } - - /* done, release the mutex */ - rtapi_mutex_give(&(data->mutex)); - return; -} -/*********************************************************************** -* RT Thread statistics collection * -* -* Thread statistics are recorded in the global_data_t thread_status. -* array. Values therein are updated when: -* -* - an exception happens, and it is safe to do so -* - by an explicit call to rtapi_task_update_stats() from an RT thread -* -* This avoids the overhead of permanently updating thread status, while -* giving the user the option to track thread status from a HAL component -* thread function if so desired. -* -* Updating thread status is necessarily a flavor-dependent -* operation and hence goes through a hook. -* -* Inspecting thread status (e.g. in halcmd) needs to evaluate -* the thread status information based on the current flavor. -************************************************************************/ - -#ifdef RTAPI -int _rtapi_task_update_stats(void) -{ -#ifdef HAVE_RTAPI_TASK_UPDATE_STATS_HOOK - extern int _rtapi_task_update_stats_hook(void); - - return _rtapi_task_update_stats_hook(); -#else - return -ENOSYS; // not implemented in this flavor -#endif -} -#endif -/*********************************************************************** -* RT exception handling * -* -* all exceptions are funneled through a common exception handler -* the default exception handler is defined in rtapi_exception.c but -* may be redefined by a user-defined handler. -* -* NB: the exception handler executes in a restricted context like -* an in-kernel trap, or a signal handler. Limit processing in the -* handler to an absolute minimum, and watch the stack size. -************************************************************************/ - -#ifdef RTAPI -// not available in ULAPI -extern rtapi_exception_handler_t rt_exception_handler; - -// may override default exception handler -// returns the current handler so it might be restored -// does NOT go through rtapi_switch (!) -rtapi_exception_handler_t _rtapi_set_exception(rtapi_exception_handler_t h) -{ - rtapi_exception_handler_t previous = rt_exception_handler; - rt_exception_handler = h; - return previous; -} -#endif - -// defined and initialized in rtapi_module.c (kthreads), rtapi_main.c (userthreads) -extern ringbuffer_t rtapi_message_buffer; // error ring access strcuture - -int _rtapi_next_handle(void) -{ - return rtapi_add_and_fetch(1, &global_data->next_handle); -} - -/* simple_strtol defined in - /usr/src/kernels//include/linux/kernel.h */ -#ifndef MODULE -long int simple_strtol(const char *nptr, char **endptr, int base) { -# ifdef HAVE_RTAPI_SIMPLE_STRTOL_HOOK - return rtapi_simple_strtol_hook(nptr,endptr,base); -# else - return strtol(nptr, endptr, base); -# endif -} -#ifdef RTAPI -EXPORT_SYMBOL(simple_strtol); -#endif -#endif - -#if defined(BUILD_SYS_KBUILD) && defined(ULAPI) -/* This function is disabled everywhere... */ -void _rtapi_printall(void) { - module_data *modules; - task_data *tasks; - shmem_data *shmems; - int n, m; - - if (rtapi_data == NULL) { - rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_data = NULL, not initialized\n"); - return; - } - rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_data = %p\n", - rtapi_data); - rtapi_print_msg(RTAPI_MSG_DBG, " magic = %d\n", - rtapi_data->magic); - rtapi_print_msg(RTAPI_MSG_DBG, " serial = %d\n", - rtapi_data->serial); - rtapi_print_msg(RTAPI_MSG_DBG, " thread_flavor id = %d\n", - rtapi_data->thread_flavor_id); - rtapi_print_msg(RTAPI_MSG_DBG, " mutex = %lu\n", - rtapi_data->mutex); - rtapi_print_msg(RTAPI_MSG_DBG, " rt_module_count = %d\n", - rtapi_data->rt_module_count); - rtapi_print_msg(RTAPI_MSG_DBG, " ul_module_count = %d\n", - rtapi_data->ul_module_count); - rtapi_print_msg(RTAPI_MSG_DBG, " task_count = %d\n", - rtapi_data->task_count); - rtapi_print_msg(RTAPI_MSG_DBG, " shmem_count = %d\n", - rtapi_data->shmem_count); - rtapi_print_msg(RTAPI_MSG_DBG, " timer_running = %d\n", - rtapi_data->timer_running); - rtapi_print_msg(RTAPI_MSG_DBG, " timer_period = %ld\n", - rtapi_data->timer_period); - modules = &(rtapi_data->module_array[0]); - tasks = &(rtapi_data->task_array[0]); - shmems = &(rtapi_data->shmem_array[0]); - rtapi_print_msg(RTAPI_MSG_DBG, " module array = %p\n",modules); - rtapi_print_msg(RTAPI_MSG_DBG, " task array = %p\n", tasks); - rtapi_print_msg(RTAPI_MSG_DBG, " shmem array = %p\n", shmems); - for (n = 0; n <= RTAPI_MAX_MODULES; n++) { - if (modules[n].state != NO_MODULE) { - rtapi_print_msg(RTAPI_MSG_DBG, " module %02d\n", n); - rtapi_print_msg(RTAPI_MSG_DBG, " state = %d\n", - modules[n].state); - rtapi_print_msg(RTAPI_MSG_DBG, " name = %p\n", - modules[n].name); - rtapi_print_msg(RTAPI_MSG_DBG, " name = '%s'\n", - modules[n].name); - } - } - for (n = 0; n <= RTAPI_MAX_TASKS; n++) { - if (tasks[n].state != EMPTY) { - rtapi_print_msg(RTAPI_MSG_DBG, " task %02d\n", n); - rtapi_print_msg(RTAPI_MSG_DBG, " state = %d\n", - tasks[n].state); - rtapi_print_msg(RTAPI_MSG_DBG, " prio = %d\n", - tasks[n].prio); - rtapi_print_msg(RTAPI_MSG_DBG, " owner = %d\n", - tasks[n].owner); - rtapi_print_msg(RTAPI_MSG_DBG, " code = %p\n", - tasks[n].taskcode); - } - } - for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { - if (shmems[n].key != 0) { - rtapi_print_msg(RTAPI_MSG_DBG, " shmem %02d\n", n); - rtapi_print_msg(RTAPI_MSG_DBG, " key = %d\n", - shmems[n].key); - rtapi_print_msg(RTAPI_MSG_DBG, " rtusers = %d\n", - shmems[n].rtusers); - rtapi_print_msg(RTAPI_MSG_DBG, " ulusers = %d\n", - shmems[n].ulusers); - rtapi_print_msg(RTAPI_MSG_DBG, " size = %ld\n", - shmems[n].size); - rtapi_print_msg(RTAPI_MSG_DBG, " bitmap = "); - for (m = 0; m <= RTAPI_MAX_MODULES; m++) { - if (rtapi_test_bit(m, shmems[n].bitmap)) { - putchar('1'); - } else { - putchar('0'); - } - } - putchar('\n'); - } - } -} -#endif diff --git a/src/rtapi/rtapi_common.h b/src/rtapi/rtapi_common.h index 4cef6e0905..050a27d951 100644 --- a/src/rtapi/rtapi_common.h +++ b/src/rtapi/rtapi_common.h @@ -2,29 +2,27 @@ #define RTAPI_COMMON_H /** RTAPI is a library providing a uniform API for several real time - operating systems. As of ver 2.0, RTLinux and RTAI are supported. + operating systems. */ /******************************************************************** * Description: rtapi_common.h -* This file, 'rtapi_common.h', contains typedefs and -* other items common to both the realtime and +* This file, 'rtapi_common.h', contains typedefs and +* other items common to both the realtime and * non-realtime portions of the implementation. * * Author: John Kasunich, Paul Corner * License: LGPL Version 2 -* +* * Copyright (c) 2004 All rights reserved. * -* Last change: +* Last change: ********************************************************************/ /** This file, 'rtapi_common.h', contains typedefs and other items common to both the realtime and non-realtime portions of the - implementation. These items are also common to both the RTAI - and RTLinux implementations, and most likely to any other - implementations in the Linux environment. This data is INTERNAL - to the RTAPI implementation, and should not be included in any - application modules. + implementation. This data is INTERNAL to the RTAPI + implementation, and should not be included in any application + modules. */ /** Copyright (C) 2003 John Kasunich @@ -65,6 +63,8 @@ /* Keep the includes here - It might get messy.. */ +#include "rtapi.h" + #ifdef RTAPI #include /* for blocking when needed */ #else @@ -73,32 +73,18 @@ #include "rtapi_bitops.h" /* test_bit() et al. */ -#if defined(BUILD_SYS_USER_DSO) -#include /* IPC_* */ -#include -#include -#endif - -#if defined(BUILD_SYS_USER_DSO) #include /* IPC_* */ #include #include -#endif #ifndef NULL #define NULL 0 #endif -#include THREADS_HEADERS /* thread-specific headers */ - - -/* module information */ -#ifdef MODULE -MODULE_AUTHOR("John Kasunich, Fred Proctor, & Paul Corner"); -MODULE_DESCRIPTION("Portable Real Time API"); -MODULE_LICENSE("GPL"); -#endif +// The same in both Xenomai and RT_PREEMPT +#define PRIO_LOWEST 0 +#define PRIO_HIGHEST 99 // RTAPI_MAX_* moved to config.h @@ -111,12 +97,11 @@ MODULE_LICENSE("GPL"); #define MIN_STACKSIZE 32768 -/* This file contains data structures that live in shared memory and - are accessed by multiple different programs, both user processes - and kernel modules. If the structure layouts used by various - programs don't match, that's bad. So we have revision checking. - Whenever a module or program is loaded, thread_flavor_id and - serial is checked against the code in the shared memory area. If +/* This file contains data structures that live in shared memory and are + accessed by multiple different programs, both user processes and kernel + modules. If the structure layouts used by various programs don't match, + that's bad. So we have revision checking. Whenever a module or program is + loaded and serial is checked against the code in the shared memory area. If they don't match, the rtapi_init() call will fail. */ @@ -195,7 +180,6 @@ typedef struct { typedef struct { int magic; /* magic number to validate data */ int serial; /* revision code for matching */ - int thread_flavor_id; /* unique ID for each thread style: rtapi.h */ unsigned long mutex; /* mutex against simultaneous access */ unsigned long ring_mutex; /* layering RTAPI functions requires per-layer locks */ int rt_module_count; /* loaded RT modules */ @@ -209,54 +193,32 @@ typedef struct { task_data task_array[RTAPI_MAX_TASKS + 1]; /* data for tasks */ shmem_data shmem_array[RTAPI_MAX_SHMEMS + 1]; /* data for shared memory */ -#ifdef THREAD_RTAPI_DATA - THREAD_RTAPI_DATA; /* RTAPI data defined in thread system */ -#endif } rtapi_data_t; /* rtapi_common.c */ extern rtapi_data_t *rtapi_data; -#if defined(RTAPI) || defined(MODULE) +#if defined(RTAPI) extern void init_rtapi_data(rtapi_data_t * data); -extern void init_global_data(global_data_t * data, - int instance_id, int hal_size, +extern void init_global_data(global_data_t * data, + int instance_id, int hal_size, int rtlevel, int userlevel, const char *name); #endif -#if defined(RTAPI) && defined(BUILD_SYS_USER_DSO) +#if defined(RTAPI) extern int _next_handle(void); #endif // set first thing in rtapi_app_main -extern int shmdrv_loaded; extern long page_size; // for munmap /* rtapi_task.c */ extern task_data *task_array; -/* $(THREADS).c */ -/* RT_TASK is actually flavor-specific. It ought to be hookified, but - it isn't because the two kthreads flavors both use the same same - for this data type (perhaps because they share history and the - ipipe patch) - */ -#if defined(MODULE) -extern RT_TASK *ostask_array[]; -#endif - /* rtapi_time.c */ -#ifdef BUILD_SYS_USER_DSO extern int period; -#else /* BUILD_SYS_KBUILD */ -extern long int max_delay; -extern unsigned long timer_counts; -#endif -#ifdef HAVE_RTAPI_MODULE_TIMER_STOP -void _rtapi_module_timer_stop(void); -#endif /* rtapi_shmem.c */ @@ -267,9 +229,7 @@ extern shmem_data *shmem_array; extern void *shmem_addr_array[]; /* rtapi_module.c */ -#ifndef BUILD_SYS_USER_DSO extern int _init_master_shared_memory(rtapi_data_t **rtapi_data); -#endif extern module_data *module_array; #endif /* RTAPI_COMMON_H */ diff --git a/src/rtapi/rtapi_compat.c b/src/rtapi/rtapi_compat.c index 75cd4eb211..da95cebcfc 100644 --- a/src/rtapi/rtapi_compat.c +++ b/src/rtapi/rtapi_compat.c @@ -43,251 +43,8 @@ #include // get_rpath() #include -// really in nucleus/heap.h but we rather get away with minimum include files -#ifndef XNHEAP_DEV_NAME -#define XNHEAP_DEV_NAME "/dev/rtheap" -#endif - -// if this exists, and contents is '1', it's RT_PREEMPT -#define PREEMPT_RT_SYSFS "/sys/kernel/realtime" - -// Exists on RTAI and Xenomai -#define PROC_IPIPE "/proc/ipipe" - -// These exist on Xenomai but not on RTAI -#define PROC_IPIPE_XENOMAI "/proc/ipipe/Xenomai" -#define XENO_GID_SYSFS "/sys/module/xeno_nucleus/parameters/xenomai_gid" - -// static storage of kernel module directory -static char kmodule_dir[PATH_MAX]; - static FILE *rtapi_inifile = NULL; -static int check_rtapi_lib(char *name); - -int kernel_is_xenomai() -{ - struct stat sb; - - return ((stat(XNHEAP_DEV_NAME, &sb) == 0) && - (stat(PROC_IPIPE_XENOMAI, &sb) == 0) && - (stat(XENO_GID_SYSFS, &sb) == 0)); -} - -int kernel_is_rtai() -{ - struct stat sb; - - return ((stat(PROC_IPIPE, &sb) == 0) && - (stat(PROC_IPIPE_XENOMAI, &sb) != 0) && - (stat(XENO_GID_SYSFS, &sb) != 0)); -} - -int kernel_is_rtpreempt() -{ - FILE *fd; - int retval = 0; - - if ((fd = fopen(PREEMPT_RT_SYSFS,"r")) != NULL) { - int flag; - retval = ((fscanf(fd, "%d", &flag) == 1) && (flag)); - fclose(fd); - } - return retval; -} - -int xenomai_gid() -{ - FILE *fd; - int gid = -1; - - if ((fd = fopen(XENO_GID_SYSFS,"r")) != NULL) { - if (fscanf(fd, "%d", &gid) != 1) { - fclose(fd); - return -EBADF; // garbage in sysfs device - } else { - fclose(fd); - return gid; - } - } - return -ENOENT; // sysfs device cant be opened -} - -int user_in_xenomai_group() -{ - int numgroups, i; - gid_t *grouplist; - int gid = xenomai_gid(); - - if (gid < 0) - return gid; - - numgroups = getgroups(0,NULL); - grouplist = (gid_t *) calloc( numgroups, sizeof(gid_t)); - if (grouplist == NULL) - return -ENOMEM; - if (getgroups( numgroups, grouplist) > 0) { - for (i = 0; i < numgroups; i++) { - if (grouplist[i] == (unsigned) gid) { - free(grouplist); - return 1; - } - } - } else { - free(grouplist); - return errno; - } - return 0; -} - - -// there is no easy way to determine the RTAPI instance id -// of a kernel threads RTAPI instance, which is why this -// parameter is made visible through a procfs entry. -int kernel_instance_id() -{ - FILE *fd; - int retval = -1; - - if ((fd = fopen("/proc/rtapi/instance","r")) != NULL) { - int flag; - if (fscanf(fd, "%d", &flag) == 1) { - retval = flag; - } - fclose(fd); - } - return retval; -} - -flavor_t flavors[] = { - { .name = RTAPI_POSIX_NAME, - .mod_ext = ".so", - .so_ext = ".so", - .build_sys = "user-dso", - .flavor_id = RTAPI_POSIX_ID, - .flags = POSIX_FLAVOR_FLAGS // FLAVOR_USABLE - }, - { .name = "sim", // alias for above- old habíts die hard - .mod_ext = ".so", - .so_ext = ".so", - .build_sys = "user-dso", - .flavor_id = RTAPI_POSIX_ID, - .flags = POSIX_FLAVOR_FLAGS - }, - { .name = RTAPI_RT_PREEMPT_NAME, - .mod_ext = ".so", - .so_ext = ".so", - .build_sys = "user-dso", - .flavor_id = RTAPI_RT_PREEMPT_ID, - .flags = RTPREEMPT_FLAVOR_FLAGS - }, - { .name = RTAPI_XENOMAI_NAME, - .mod_ext = ".so", - .so_ext = ".so", - .build_sys = "user-dso", - .flavor_id = RTAPI_XENOMAI_ID, - .flags = XENOMAI_FLAVOR_FLAGS - }, - { .name = RTAPI_RTAI_KERNEL_NAME, - .mod_ext = ".ko", - .so_ext = ".so", - .build_sys = "kbuild", - .flavor_id = RTAPI_RTAI_KERNEL_ID, - .flags = RTAI_KERNEL_FLAVOR_FLAGS - }, - - { .name = RTAPI_XENOMAI_KERNEL_NAME, - .mod_ext = ".ko", - .so_ext = ".so", - .build_sys = "kbuild", - .flavor_id = RTAPI_XENOMAI_KERNEL_ID, - .flags = XENOMAI_KERNEL_FLAVOR_FLAGS - }, - - { .name = RTAPI_NOTLOADED_NAME, - .mod_ext = "", - .so_ext = "", - .build_sys = "n/a", - .flavor_id = RTAPI_NOTLOADED_ID, - .flags = 0 - }, - - { .name = NULL, // list sentinel - .flavor_id = -1, - .flags = 0 - } -}; - -flavor_ptr flavor_byname(const char *flavorname) -{ - flavor_ptr f = flavors; - while (f->name) { - if (!strcasecmp(flavorname, f->name)) - return f; - f++; - } - return NULL; -} - -flavor_ptr flavor_byid(int flavor_id) -{ - flavor_ptr f = flavors; - while (f->name) { - if (flavor_id == f->flavor_id) - return f; - f++; - } - return NULL; -} - -flavor_ptr default_flavor(void) -{ - char *fname = getenv("FLAVOR"); - flavor_ptr f, flavor; - - if (fname) { - if ((flavor = flavor_byname(fname)) == NULL) { - fprintf(stderr, - "FLAVOR=%s: no such flavor -- valid flavors are:\n", - fname); - f = flavors; - while (f->name) { - fprintf(stderr, "\t%s\n", f->name); - f++; - } - exit(1); - } - /* make sure corresponding rtapi lib is also present */ - if (check_rtapi_lib(fname)) - return flavor; - else - exit(1); - } - - if (kernel_is_rtai()) { - f = flavor_byid(RTAPI_RTAI_KERNEL_ID); - if (check_rtapi_lib((char *)f->name)) - return f; - } - if (kernel_is_xenomai()) { - /* check for userspace first */ - f = flavor_byid(RTAPI_XENOMAI_ID); - if (check_rtapi_lib((char *)f->name)) - return f; - /* else look for xenomai_kernel */ - f = flavor_byid(RTAPI_XENOMAI_KERNEL_ID); - if (check_rtapi_lib((char *)f->name)) - return f; - } - if (kernel_is_rtpreempt()) { - f = flavor_byid(RTAPI_RT_PREEMPT_ID); - if (check_rtapi_lib((char *)f->name)) - return f; - } - return flavor_byid(RTAPI_POSIX_ID); -} - - void check_rtapi_config_open() { /* Open rtapi.ini if needed. Private function used by @@ -312,31 +69,24 @@ void check_rtapi_config_open() } } -char *get_rtapi_param(const char *flavor, const char *param) +char *get_rtapi_param(const char *param) { char *val; - char buf[RTAPI_NAME_LEN+8]; // strlen("flavor_") + RTAPI_NAME_LEN + 1 // Open rtapi_inifile if it hasn't been already check_rtapi_config_open(); - - sprintf(buf, "flavor_%s", flavor); - val = (char *) iniFind(rtapi_inifile, param, buf); - - if (val==NULL) - val = (char *) iniFind(rtapi_inifile, param, "global"); + val = (char *) iniFind(rtapi_inifile, param, "global"); return val; } int get_rtapi_config(char *result, const char *param, int n) { - /* Read a parameter value from rtapi.ini. First try the flavor - section, then the global section. Copy max n-1 bytes into - result buffer. */ + /* Read a parameter value from rtapi.ini. Copy max n-1 bytes into result + buffer. */ char *val; - val = get_rtapi_param(default_flavor()->name, param); + val = get_rtapi_param(param); // Return if nothing found if (val==NULL) { @@ -349,141 +99,6 @@ int get_rtapi_config(char *result, const char *param, int n) return 0; } -int check_rtapi_lib(char *name) -{ - /* Check if the corresponding rtapi lib for a particular - flavor is present */ - char *val; - char fname[PATH_MAX]; - struct stat sb; - - val = get_rtapi_param(name, "RTLIB_DIR"); - - if (val==NULL) { - return 0; - } - - snprintf(fname, PATH_MAX,"%s/ulapi-%s.so", val, name); - - /* check if rtapi lib exists */ - return (stat(fname, &sb) == 0); -} - -// NB. compiler warnings re possible data truncation or overrun -// So long as a buffer of size PATH_MAX _plus_ extra formatting -// is being copied into another buffer of size PATH_MAX, -// you either restrict to size PATH_MAX and risk truncation or -// do not restrict and risk segfault on buffer overrun. -// Would require too much work to remove warnings at this time. - -int module_path(char *result, const char *basename) -{ - /* Find a kernel module's path */ - struct stat sb; - char buf[PATH_MAX]; - char rtlib_result[PATH_MAX]; - int has_rtdir; - struct utsname uts; - - // Initialize kmodule_dir, only once - if (kmodule_dir[0] == 0) { - uname(&uts); - - get_rtapi_config(buf,"RUN_IN_PLACE",4); - if (strncmp(buf,"yes",3) == 0) { - // Complete RTLIB_DIR should be // - if (get_rtapi_config(buf,"RTLIB_DIR",PATH_MAX) != 0) - return -ENOENT; - - if (strcmp(default_flavor()->build_sys,"user-dso") == 0) { - // point user threads to a common directory - snprintf(kmodule_dir,PATH_MAX,"%s/userland/%s", - buf, uts.release); - } else { - // kthreads each have their own directory - snprintf(kmodule_dir,PATH_MAX,"%s/%s/%s", - buf, default_flavor()->name, uts.release); - } - } else { - // Complete RTLIB_DIR should be /lib/modules//linuxcnc - snprintf(kmodule_dir, PATH_MAX, - "/lib/modules/%s/linuxcnc", uts.release); - } - } - - // Look for module in kmodule_dir/RTLIB_DIR - snprintf(result, PATH_MAX, "%s/%s.ko", kmodule_dir, basename); - if ((stat(result, &sb) == 0) && (S_ISREG(sb.st_mode))) - return 0; - - // Not found; save result for possible later diagnostic msg - strcpy(rtlib_result,result); - - // Check RTDIR as well (RTAI) - has_rtdir = (get_rtapi_config(buf, "RTDIR", PATH_MAX) == 0 && buf[0] != 0); - if (has_rtdir) { - snprintf(result, PATH_MAX, "%s/%s.ko", buf, basename); - if ((stat(result, &sb) == 0) && (S_ISREG(sb.st_mode))) - return 0; - } - - // Module not found - fprintf(stderr, "module '%s.ko' not found in directory\n\t%s\n", - basename, kmodule_dir); - if (has_rtdir) - fprintf(stderr, "\tor directory %s\n", buf); - - return -ENOENT; -} - -int is_module_loaded(const char *module) -{ - FILE *fd; - char line[100]; - int len = strlen(module); - - fd = fopen("/proc/modules", "r"); - if (fd == NULL) { - fprintf(stderr, "module_loaded: ERROR: cannot read /proc/modules\n"); - return -1; - } - while (fgets(line, sizeof(line), fd)) { - if (!strncmp(line, module, len)) { - fclose(fd); - return 1; - } - } - fclose(fd); - return 0; -} - -int run_module_helper(const char *format, ...) -{ - char mod_helper[PATH_MAX+100]; - - if (get_rtapi_config(mod_helper, "linuxcnc_module_helper", PATH_MAX) != 0) { - fprintf(stderr, "load_module: ERROR: failed to read " - "linuxcnc_module_helper path from rtapi config\n"); - return -1; - } - strcat(mod_helper, " "); - - int n = strlen(mod_helper); - va_list args; - int retval; - - va_start(args, format); - retval = vsnprintf(&mod_helper[n], sizeof(mod_helper) - n, format, args); - va_end(args); - - if (retval < 0 ) { - fprintf(stderr, "run_module_helper: invalid arguments\n"); - return retval; - } - return system(mod_helper); -} - -//int procfs_cmd(const char *path, const char *format, ...) // whatever is written is printf-style int rtapi_fs_write(const char *path, const char *format, ...) { @@ -556,17 +171,17 @@ int get_elf_section(const char *const fname, const char *section_name, void **de struct stat st; if (stat(fname, &st) != 0) { - perror("stat"); + perror("rtapi_compat.c: get_elf_section() stat"); return -1; } int fd = open(fname, O_RDONLY); if (fd < 0) { - perror("open"); + perror("rtapi_compat.c: get_elf_section() open"); return fd; } char *p = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (p == NULL) { - perror("mmap"); + perror("rtapi_compat.c: get_elf_section() mmap"); close(fd); return -1; } @@ -588,7 +203,7 @@ int get_elf_section(const char *const fname, const char *section_name, void **de if (dest) { *dest = malloc(size); if (*dest == NULL) { - perror("malloc"); + perror("rtapi_compat.c: get_elf_section() malloc"); size = -1; break; } @@ -616,7 +231,7 @@ int get_elf_section(const char *const fname, const char *section_name, void **de if (dest) { *dest = malloc(size); if (*dest == NULL) { - perror("malloc"); + perror("rtapi_compat.c: get_elf_section() malloc"); size = -1; break; } @@ -650,7 +265,7 @@ const char **get_caps(const char *const fname) const char **rv = malloc(sizeof(char*) * (n+1)); if (rv == NULL) { - perror("malloc"); + perror("rtapi_compat.c: get_caps() malloc"); return NULL; } n = 0; @@ -692,26 +307,15 @@ int rtapi_get_tags(const char *mod_name) int result = 0, n = 0; char *cp1 = ""; - flavor_ptr flavor = default_flavor(); - - if (kernel_threads(flavor)) { - if (module_path(modpath, mod_name) < 0) { - perror("module_path"); - return -1; - } - } else { - if (get_rtapi_config(modpath,"RTLIB_DIR",PATH_MAX) != 0) { - perror("cant get RTLIB_DIR ?\n"); - return -1; - } - strcat(modpath,"/"); - strcat(modpath, flavor->name); - strcat(modpath,"/"); - strcat(modpath,mod_name); - strcat(modpath, flavor->mod_ext); + if (get_rtapi_config(modpath,"RTLIB_DIR",PATH_MAX) != 0) { + perror("rtapi_compat.c: Can't get RTLIB_DIR"); + return -1; } - const char **caps = get_caps(modpath); + strcat(modpath,"/modules/"); + strcat(modpath,mod_name); + strcat(modpath, ".so"); + const char **caps = get_caps(modpath); char **p = (char **)caps; while (p && *p && strlen(*p)) { cp1 = *p++; @@ -724,41 +328,8 @@ int rtapi_get_tags(const char *mod_name) return result; } -// lifted from hm2_ether.c by Michael Geszkiewicz and Jeff Epler -int run_shell(char *format, ...) -{ - char command[PATH_MAX]; - va_list args; - int retval; - - va_start(args, format); - retval = vsnprintf(command, sizeof(command), format, args); - va_end(args); - - if (retval < 0) { - perror("vsnprintf"); - return retval; - } - char *const argv[] = {"sh", "-c", command, NULL}; - pid_t pid; - retval = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ); - if(retval < 0) - perror("posix_spawn"); - - int status; - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return WEXITSTATUS(status); - else if (WIFSTOPPED(status)) - return WTERMSIG(status)+128; - else - return status; -} - // those are ok to use from userland RT modules: -#if defined(BUILD_SYS_USER_DSO) && defined(RTAPI) -EXPORT_SYMBOL(run_shell); -EXPORT_SYMBOL(is_module_loaded); +#if defined(RTAPI) EXPORT_SYMBOL(rtapi_fs_read); EXPORT_SYMBOL(rtapi_fs_write); #endif diff --git a/src/rtapi/rtapi_compat.h b/src/rtapi/rtapi_compat.h index 306560e02f..e7bd9e79db 100644 --- a/src/rtapi/rtapi_compat.h +++ b/src/rtapi/rtapi_compat.h @@ -22,51 +22,8 @@ #define RTAPI_COMPAT_H #include "rtapi_bitops.h" - -/*********************************************************************** -* basic features of thread flavors. Needed to init the flavor * -* descriptor in rtapi_compat.h and rtapi_switch->flavor_flags * -* technically those are flavor configuration descriptiors * -************************************************************************/ - -#define FLAVOR_DOES_IO RTAPI_BIT(0) // userland: whether iopl() needs to be called -#define FLAVOR_KERNEL_BUILD RTAPI_BIT(1) // set when defined(BUILD_SYS_KBUILD) -#define FLAVOR_RTAPI_DATA_IN_SHM RTAPI_BIT(2) // this flavor keeps rtapi_data in a shm segment - -#define POSIX_FLAVOR_FLAGS 0 - -#define RTPREEMPT_FLAVOR_FLAGS (FLAVOR_DOES_IO) - -#define RTAI_KERNEL_FLAVOR_FLAGS (FLAVOR_DOES_IO| \ - FLAVOR_KERNEL_BUILD|\ - FLAVOR_RTAPI_DATA_IN_SHM) - -#define XENOMAI_KERNEL_FLAVOR_FLAGS (FLAVOR_DOES_IO|\ - FLAVOR_KERNEL_BUILD|\ - FLAVOR_RTAPI_DATA_IN_SHM) - -#define XENOMAI_FLAVOR_FLAGS (FLAVOR_DOES_IO) - - -/*********************************************************************** -* Support functions for autodetection and flavor handling * -* these are available to user processes regardless of defining * -* RTAPI or ULAPI, for instance rtapi_msgd or rtapistat. * -* exported by rtapi_compat.c . * -************************************************************************/ -#ifndef MODULE - #include // provides PATH_MAX -typedef struct { - const char *name; - const char *mod_ext; // RTAPI module extensions, .ko/.so - const char *so_ext; // ulapi.so module extension - const char *build_sys; - int flavor_id; - unsigned long flags; -} flavor_t, *flavor_ptr; - // these functions must work with or without rtapi.h included #if !defined(SUPPORT_BEGIN_DECLS) #if defined(__cplusplus) @@ -80,26 +37,8 @@ typedef struct { SUPPORT_BEGIN_DECLS -extern int is_module_loaded(const char *module); -extern int load_module(const char *module, const char *modargs); -extern int run_module_helper(const char *format, ...); extern long int simple_strtol(const char *nptr, char **endptr, int base); - -// simple interface to hal_create_thread()/hal_thread_delete() -// through /proc/rtapi/hal/rtapicmd (kernel threadstyles only) -// -// to start a thread, write 'newthread' ' -// example: -// echo newthread servo-thread 1000000 1 -1 >/proc/rtapi/hal/rtapicmd -// -// to delete a thread, write 'delthread ' -// echo delthread servo-thread >/proc/rtapi/hal/rtapicmd -// -// HAL return values are reflected in the return value to write() -// -#define PROCFS_RTAPICMD "/proc/rtapi/hal/rtapicmd" - // whatever is written is printf-style int rtapi_fs_write(const char *path, const char *format, ...); @@ -111,68 +50,8 @@ int rtapi_fs_write(const char *path, const char *format, ...); int rtapi_fs_read(char *buf, const size_t maxlen, const char *name, ...); -int run_shell(char *format, ...); - -//extern int procfs_cmd(const char *path, const char *format, ...); - -// kernel tests in rtapi_compat.c -extern int kernel_is_xenomai(); -extern int kernel_is_rtai(); -extern int kernel_is_rtpreempt(); - -// return the Xenomai group id from -// /sys/module/xeno_nucleus/parameters/xenomai_gid or -1 -extern int xenomai_gid(); - -// if the linuxCNC user is'nt member of the xenomai group, -// most xenomai system calls will fail -extern int user_in_xenomai_group(); - -// return the instance ID of a kernel threads instance -// by consulting /proc/rtapi/instance -extern int kernel_instance_id(); - -extern flavor_t flavors[]; -extern flavor_ptr flavor_byname(const char *flavorname); -extern flavor_ptr flavor_byid(int flavor_id); -extern flavor_ptr default_flavor(void); - -// determine if this is a userland or kthreads flavor -static inline int kernel_threads(flavor_ptr f) { - return (f->flags & FLAVOR_KERNEL_BUILD) != 0; -} - -/* - * Given a result buffer of PATH_MAX size and a module or shared - * library's basename (e.g. 'rtapi' with no directory or '.ko'), find - * the full path to a module/shared library as follows: - * - * Complete the module file name by appending mod_ext from flavor data - * to the basename (e.g. 'rtapi.ko'). - * - * For RIP builds, prepend RTLIB_DIR from rtapi.ini, flavor name and - * kernel release to the module file name - * (e.g. '/home/me/linuxcnc-dev/rtlib/rtai-kernel/2.6.38-rtai/rtapi.ko'); - * if the file exists, copy into *result and return 0. - * - * For non-RIP builds, prepend - * '/lib/modules//linuxcnc' to the module file name - * (e.g. '/lib/modules/2.6.38-rtai/linuxcnc/rtapi.ko'); if the file - * exists, copy into *result and return 0. - * - * Otherwise, prepend any (flavor-specific, currently RTAI only) RTDIR - * from rtapi.ini and prepend to module file name - * (e.g. '/usr/realtime/modules/rtai_hal.ko'); if the file exists, - * copy into *result and return 0. - * - * Otherwise return non-0. - */ - -extern int module_path(char *result, const char *basename); - /* - * Look up a parameter value in rtapi.ini, checking first the - * [flavor_] section, then the [global] section. Returns 0 if + * Look up a parameter value in rtapi.ini [global] section. Returns 0 if * successful, 1 otherwise. Maximum n-1 bytes of the value and a * trailing \0 is copied into *result. * @@ -207,12 +86,10 @@ const char **get_caps(const char *const fname); const char *get_cap(const char *const fname, const char *cap); -// given a module name and the flavor set, return the integer -// capability mask of tags. +// given a module name, return the integer capability mask of tags. int rtapi_get_tags(const char *mod_name); SUPPORT_END_DECLS -#endif // MODULE #endif // RTAPI_COMPAT_H diff --git a/src/rtapi/rtapi_ctype.h b/src/rtapi/rtapi_ctype.h index aaed49d865..fbeb3b845f 100644 --- a/src/rtapi/rtapi_ctype.h +++ b/src/rtapi/rtapi_ctype.h @@ -13,8 +13,4 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#ifdef MODULE -#include -#else #include -#endif diff --git a/src/rtapi/rtapi_errno.h b/src/rtapi/rtapi_errno.h index a48fd286f4..c15f2df833 100644 --- a/src/rtapi/rtapi_errno.h +++ b/src/rtapi/rtapi_errno.h @@ -13,9 +13,4 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#ifdef MODULE -#include -#else #include -#endif - diff --git a/src/rtapi/rtapi_exception.c b/src/rtapi/rtapi_exception.c index f771a843f7..ebc5bf0608 100644 --- a/src/rtapi/rtapi_exception.c +++ b/src/rtapi/rtapi_exception.c @@ -24,12 +24,13 @@ #include "config.h" #include "rtapi.h" #include "rtapi_exception.h" +#include "rtapi_flavor.h" #ifdef RTAPI #define MAX_RT_ERRORS 10 -static int rtapi_default_rt_exception_handler(rtapi_exception_t type, +static int rtapi_default_rt_exception_handler(int type, rtapi_exception_detail_t *detail, rtapi_threadstatus_t *ts); @@ -37,9 +38,6 @@ static int rtapi_default_rt_exception_handler(rtapi_exception_t type, rtapi_exception_handler_t rt_exception_handler = rtapi_default_rt_exception_handler; -static void log_thread_stats(rtapi_exception_t type, - rtapi_threadstatus_t *ts); - // The RTAPI default exception handler - // factored out as separate file to ease rolling your own in a component // @@ -52,136 +50,23 @@ static void log_thread_stats(rtapi_exception_t type, // hal/components/rtmon.comp which uses rtapi_set_exception(handler) // to override this default handler during module lifetime -static int rtapi_default_rt_exception_handler(rtapi_exception_t type, +static int rtapi_default_rt_exception_handler(int type, rtapi_exception_detail_t *detail, rtapi_threadstatus_t *ts) { static int error_printed = 0; int level = (error_printed == 0) ? RTAPI_MSG_ERR : RTAPI_MSG_WARN; + int res; if (error_printed < MAX_RT_ERRORS) { error_printed++; - // apply output policy in one place only. - switch (type) { - - // RTAI errors - case RTAI_RTE_UNCLASSIFIED: - rtapi_print_msg(level, - "%d: RT thread %d: " - "unknown return code from rt_task_wait_period(): %d ", - type, detail->task_id, detail->error_code); - break; - - case RTAI_RTE_UNBLKD: - rtapi_print_msg(level, - "%d: RT thread %d: rt_task_wait_period() " - "unblocked while sleeping: %d ", - type, detail->task_id, detail->error_code); - break; - - // Timing violations - case RTAI_RTE_TMROVRN: - case XK_ETIMEDOUT: - case XU_ETIMEDOUT: - case RTP_DEADLINE_MISSED: - rtapi_print_msg(level, - "%d: Unexpected realtime delay on RT thread %d ", - type, detail->task_id); - log_thread_stats(type, ts); - break; - - // Kernel traps - case RTAI_TRAP: + res = flavor_exception_handler_hook(NULL, type, detail, level); + if (res == -ENOSYS) // Unimplemented rtapi_print_msg(level, - "%d: trap event: thread %d " - "vec=%d signo=%d ip:%p", - type, detail->task_id, - detail->flavor.rtai.vector, - detail->flavor.rtai.signo, - detail->flavor.rtai.ip); - break; - - case XK_TRAP: - rtapi_print_msg(level, - "%d: trap event: thread %d - error %d " - "event=%d domain=%u ip:%p sp:%p", - type, detail->task_id, detail->error_code, - detail->flavor.xeno.event, - detail->flavor.xeno.domid, - detail->flavor.xeno.ip, - detail->flavor.xeno.sp); - break; - - // Xenomai Kernel errors - case XK_EINTR: - rtapi_print_msg(level, - "%d: API usage bug: rt_task_unblock() " - "called before release point: " - "thread %d - errno %d", - type, - detail->task_id, - detail->error_code); - break; - - case XK_EPERM: - rtapi_print_msg(level, - "%d: API usage bug: cannot call rt_task_wait_period()" - " from this context: " - "thread %d - errno %d", - type, - detail->task_id, - detail->error_code); - - break; - - // Xenomai User errors - case XU_SIGXCPU: // Xenomai Domain switch - rtapi_print_msg(level, - "%d: Xenomai Domain switch for thread %d", - type, detail->task_id); - log_thread_stats(type, ts); - break; - - case XU_EWOULDBLOCK: - case XK_EWOULDBLOCK: - rtapi_print_msg(level, - "API usage bug: rt_task_set_periodic() not called: " - "thread %d - errno %d", - detail->task_id, - detail->error_code); - break; - - case XU_EINTR: - rtapi_print_msg(level, - "API usage bug: rt_task_unblock() called before" - " release point: thread %d -errno %d", - detail->task_id, - detail->error_code); - break; - - case XU_EPERM: - rtapi_print_msg(level, - "API usage bug: cannot call service from current" - " context: thread %d - errno %d", - detail->task_id, - detail->error_code); - break; - - case XU_UNDOCUMENTED: - case XK_UNDOCUMENTED: - rtapi_print_msg(level, - "%d: unspecified Xenomai error: thread %d - errno %d", - type, - detail->task_id, - detail->error_code); - break; - - default: - rtapi_print_msg(level, - "%d: unspecified exceptiond detail=%p ts=%p", + "%d: unspecified exception detail=%p ts=%p", type, detail, ts); - } + if (error_printed == MAX_RT_ERRORS) rtapi_print_msg(RTAPI_MSG_WARN, "RTAPI: (further messages will be suppressed)\n"); @@ -189,41 +74,5 @@ static int rtapi_default_rt_exception_handler(rtapi_exception_t type, return 0; } -// not every exception might actually update the thread status, -// so output this only if known to be current -static void log_thread_stats(rtapi_exception_t type, - rtapi_threadstatus_t *ts) -{ - int flavor = global_data->rtapi_thread_flavor; - - // generic (flavor-independent) counters - rtapi_print_msg(RTAPI_MSG_WARN, - "updates=%d api_err=%d other_err=%d", - ts->num_updates, ts->api_errors, ts->other_errors); - - // flavor-specific counters - - switch (flavor) { - case RTAPI_XENOMAI_ID: - case RTAPI_XENOMAI_KERNEL_ID: - if (ts->num_updates) { - rtapi_print_msg(RTAPI_MSG_WARN, - "wait_errors=%d overruns=%d modesw=%d ctxsw=%d" - " pagefaults=%d exectime=%lldnS status=0x%x", - ts->flavor.xeno.wait_errors, - ts->flavor.xeno.total_overruns, - ts->flavor.xeno.modeswitches, - ts->flavor.xeno.ctxswitches, - ts->flavor.xeno.pagefaults, - ts->flavor.xeno.exectime, - ts->flavor.xeno.status); - } - break; - - - default: ; - } -} - #endif diff --git a/src/rtapi/rtapi_exception.h b/src/rtapi/rtapi_exception.h index f27babf0d2..8840cd4bb5 100644 --- a/src/rtapi/rtapi_exception.h +++ b/src/rtapi/rtapi_exception.h @@ -19,105 +19,10 @@ #ifndef _RTAPI_EXCEPTION_H #define _RTAPI_EXCEPTION_H -typedef void * exc_register_t; // questionable - -// this enum lists all possible cause codes -// passed in rtapi_exception_detai_t.type to the exception handler - -typedef enum { - RTAPI_EXCEPTION_NONE=0, - - // RTAI: failures of rt_task_wait_period(), traps - RTAI_RTE_TMROVRN, // an immediate return was taken because the - // next period has already expired. - RTAI_RTE_UNBLKD, // the task was unblocked while sleeping - RTAI_RTE_UNCLASSIFIED, // none of the previous two - RTAI_TRAP, // received via rtapi_trap_handler - - // Xenomai kernel - XK_TRAP, - XK_TRAP_BUG, // same, but failed to identify RT thread - XK_ETIMEDOUT, // release point was missed - // the next one is likely caused by a programming error: - XK_EWOULDBLOCK, // rt_task_wait_period() without previous rt_task_set_periodic() - XK_EINTR, // rt_task_unblock() called before release point - XK_EPERM, // cannot rt_task_wait_period() from this context - XK_UNDOCUMENTED, // unknown error code - - // Xenomai user - XU_SIGXCPU, // RT task switched to secondary domain - XU_SIGXCPU_BUG, // same, but failed to identify RT thread - XU_ETIMEDOUT, // release point was missed - XU_EWOULDBLOCK, // rt_task_wait_period() without previous rt_task_set_periodic() - XU_EINTR, // rt_task_unblock() called before release point - XU_EPERM, // cannot rt_task_wait_period() from this context - XU_UNDOCUMENTED, // unknown error code - - // RT-PREEMPT - RTP_DEADLINE_MISSED, // clock_gettime(CLOCK_MONOTONIC) returned 'too late' - - RTAPI_EXCEPTION_LAST, - -} rtapi_exception_t; - -// ---- per-flavor RT status descriptors ------- -// -// collect thread status variables from various flavors -// the intent is to collect everything 'interesting' -// about a thread and make it accessible via an RTAPI_MAX_TASKS sized array -// in global_data_t, so any HAL entity may peruse it -// this tries to abstract various fields of rather system-specific nature -// in a system-independent, fixed size structure -// the interpretation of members necessarily has to happen in a flavor-specific way -// - only a subset of the fields is valid per flavor - -typedef struct { // xenomai-kernel and xenomai user - // traps really are signals posted to an RT thread in-kernel - int trap_errors; - - // as reported by rt_task_inquire() - // filled in by rtapi_thread_updatestats(task_id) RTAPI call (TBD) - int modeswitches; - int ctxswitches; - int pagefaults; - long long exectime; // Execution time in primary mode in nanoseconds. - unsigned status; // T_BLOCKED etc. - - // errors returned by rt_task_wait_period(): - // set by -ETIMEDOUT: - int wait_errors; // total times the release point was missed - int total_overruns; // running count of the above - // the -EWOULDBLOCK and -EINTR returns are API violations - // and increment api_errors - - // all others increment other_errors -} xenomai_stats_t; - -typedef struct { - int wait_errors; // RT deadline missed -} rtai_stats_t; - -typedef struct { - - int wait_errors; // RT deadline missed +#define MAX_FLAVOR_THREADSTATUS_SIZE 256 +#define MAX_FLAVOR_EXCEPTION_SIZE 128 - // filled in by rtapi_thread_update_stats() RTAPI method - long utime_sec; // user CPU time used - long utime_usec; - - long stime_sec; // system CPU time used - long stime_usec; - - long ru_minflt; // page reclaims (soft page faults) - long ru_majflt; // page faults (hard page faults) - long ru_nsignals; // signals received - long ru_nivcsw; // involuntary context switches - - long startup_ru_minflt; // page fault counts at end of - long startup_ru_majflt; // initalisation - long startup_ru_nivcsw; // - -} rtprempt_stats_t; +typedef void * exc_register_t; // questionable // ---- the common thread status descriptor ------- @@ -134,48 +39,10 @@ typedef struct { int other_errors; // unclassified error returns - peruse log for details // flavor-specific - union { - xenomai_stats_t xeno; - rtai_stats_t rtai; - rtprempt_stats_t rtpreempt; - } flavor; + char flavor[MAX_FLAVOR_THREADSTATUS_SIZE]; } rtapi_threadstatus_t; -// ---- per-flavor exception descriptors ------- - -typedef struct { - // details for a Xenomai trap event - unsigned event; // Xenomai trap event number - unsigned domid; // Domain id - exc_register_t ip; // instruction pointer - exc_register_t sp; // stack pointer - int pid; // user process pid - int errcode; // xnthread_t.errcode - - // passed by ref from rt_task_wait_period() - unsigned long overruns; - - // XU_SIGXCPU: siginfo_t reference - void *siginfo; - -} xenomai_exception_t; - -typedef struct { - // details for a RTAI trap event - unsigned vector; // - int signo; - exc_register_t ip; // instruction pointer - -} rtai_exception_t; - -typedef struct { - // RTP_SIGNAL: unhandled signal: siginfo_t reference - // currently unused - signals handled in rtapi_app - void *siginfo; -} rtpreempt_exception_t; - - // ---- the common thread exception descriptor ------- typedef struct { @@ -183,15 +50,7 @@ typedef struct { int error_code; // as reported by the failing API or system call // flavor-specific - union { - // covers xenomai-user and xenomai-kernel: - xenomai_exception_t xeno; - - rtai_exception_t rtai; - - // covers RT-PREEMPT and Posix: - rtpreempt_exception_t rtpreempt; - } flavor; + char flavor[MAX_FLAVOR_EXCEPTION_SIZE]; } rtapi_exception_detail_t; // Exception handler signature @@ -203,7 +62,7 @@ typedef struct { // 'type' is guaranteed to be set // both of detail and threadstatus might be passed as NULL -typedef int (*rtapi_exception_handler_t) (rtapi_exception_t type, +typedef int (*rtapi_exception_handler_t) (int type, // which determines the interpretation of // the rtapi_exception_detail_t rtapi_exception_detail_t *, diff --git a/src/rtapi/rtapi_export.h b/src/rtapi/rtapi_export.h index 7dc8305e6e..cf927c79cc 100644 --- a/src/rtapi/rtapi_export.h +++ b/src/rtapi/rtapi_export.h @@ -1,16 +1,16 @@ /******************************************************************** * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -25,7 +25,6 @@ #define RTAPI_IP_SYMPREFIX "rtapi_instinfo_" -#if defined(BUILD_SYS_USER_DSO) #define MODULE_INFO1(t, a, c) __attribute__((section(".modinfo"))) \ t rtapi_info_##a = c; EXPORT_SYMBOL(rtapi_info_##a); #define MODULE_INFO2(t, a, b, c) __attribute__((section(".modinfo"))) \ @@ -51,7 +50,4 @@ #define INSTANCE_PARM_DESC(v,t) INSTANCE_INFO2(const char*, description, v, t) -#endif - - #endif //RTAPI_EXPORT_H diff --git a/src/rtapi/rtapi_global.h b/src/rtapi/rtapi_global.h index 16a56685a2..0a1ebce1ed 100644 --- a/src/rtapi/rtapi_global.h +++ b/src/rtapi/rtapi_global.h @@ -82,7 +82,6 @@ typedef struct { // this is set once on startup by rtapi_msgd and is to be considered a constant // throughout the session: int instance_id; - int rtapi_thread_flavor; // runtime parameters int rt_msg_level; // message level for RT diff --git a/src/rtapi/rtapi_heap.c b/src/rtapi/rtapi_heap.c index 85c0d6a50a..6717c9e14a 100644 --- a/src/rtapi/rtapi_heap.c +++ b/src/rtapi/rtapi_heap.c @@ -36,15 +36,11 @@ // so it can be used as a shared memory malloc static void _rtapi_unlocked_free(struct rtapi_heap *h, void *ap); -#ifdef MODULE -#define MSG_ORIGIN MSG_KERNEL -#else #ifdef RTAPI #define MSG_ORIGIN MSG_RTUSER #else #define MSG_ORIGIN MSG_ULAPI #endif -#endif #define HEAP_MUTEX(h) (&(h)->mutex) @@ -53,7 +49,7 @@ static void __attribute__((format(printf,3,4))) heap_print(struct rtapi_heap *h, int level, const char *fmt, ...) { static pid_t _pid; -#if !defined(RTAPI) && !defined(BUILD_SYS_KBUILD) +#if !defined(RTAPI) if (_pid == 0) _pid = getpid(); #endif @@ -65,12 +61,12 @@ heap_print(struct rtapi_heap *h, int level, const char *fmt, ...) static void *_rtapig_malloc(const int lock, struct rtapi_heap *h, size_t nbytes); -void *_rtapi_malloc(struct rtapi_heap *h, size_t nbytes) +void *rtapi_malloc(struct rtapi_heap *h, size_t nbytes) { return _rtapig_malloc(1, h, nbytes); } -void *_rtapi_malloc_aligned(struct rtapi_heap *h, size_t nbytes, size_t align) +void *rtapi_malloc_aligned(struct rtapi_heap *h, size_t nbytes, size_t align) { WITH_MUTEX(HEAP_MUTEX(h)); @@ -124,7 +120,7 @@ void *_rtapi_malloc_aligned(struct rtapi_heap *h, size_t nbytes, size_t align) return result; } -void _rtapi_free(struct rtapi_heap *h, void *); +void rtapi_free(struct rtapi_heap *h, void *); static void *_rtapig_malloc(const int lock, struct rtapi_heap *h, size_t nbytes) { @@ -153,7 +149,7 @@ static void *_rtapig_malloc(const int lock, struct rtapi_heap *h, size_t nbytes) } p->s.tag.attr = 0; h->free_p = heap_off(h, prevp); - size_t alloced = _rtapi_allocsize(h, p+1); + size_t alloced = rtapi_allocsize(h, p+1); h->requested += nbytes; h->allocated += alloced; if (h->flags & RTAPIHEAP_TRACE_MALLOC) @@ -185,7 +181,7 @@ static void _rtapi_unlocked_free(struct rtapi_heap *h, void *ap) if (h->flags & RTAPIHEAP_TRACE_FREE) heap_print(h, RTAPI_MSG_INFO, "%s: free aligned %p->%p size=%zu\n", - __FUNCTION__, ap, base, _rtapi_allocsize(h, base)); + __FUNCTION__, ap, base, rtapi_allocsize(h, base)); ap = base; } @@ -236,16 +232,16 @@ static void _rtapi_unlocked_free(struct rtapi_heap *h, void *ap) h->free_p = heap_off(h,p); } -void _rtapi_free(struct rtapi_heap *h,void *ap) +void rtapi_free(struct rtapi_heap *h,void *ap) { WITH_MUTEX(HEAP_MUTEX(h)); _rtapi_unlocked_free(h, ap); } -// given a pointer returned by _rtapi_malloc(), +// given a pointer returned by rtapi_malloc(), // returns number of bytes actually available for use (which // might be a bit larger than requested) due to chunk alignent) -size_t _rtapi_allocsize(struct rtapi_heap *h, const void *ap) +size_t rtapi_allocsize(struct rtapi_heap *h, const void *ap) { rtapi_malloc_tag_t *rt = ((rtapi_malloc_tag_t *) ap) - 1; @@ -257,33 +253,33 @@ size_t _rtapi_allocsize(struct rtapi_heap *h, const void *ap) return (p->s.tag.size -1) * sizeof (rtapi_malloc_hdr_t); } -void *_rtapi_calloc(struct rtapi_heap *h, size_t nelem, size_t elsize) +void *rtapi_calloc(struct rtapi_heap *h, size_t nelem, size_t elsize) { - void *p = _rtapi_malloc (h,nelem * elsize); + void *p = rtapi_malloc (h,nelem * elsize); if (!p) return NULL; memset(p, 0, nelem * elsize); return p; } -void *_rtapi_realloc(struct rtapi_heap *h, void *ptr, size_t size) +void *rtapi_realloc(struct rtapi_heap *h, void *ptr, size_t size) { - size_t sz = _rtapi_allocsize (h, ptr); + size_t sz = rtapi_allocsize (h, ptr); // requested size fits current allocation? if (size <= sz) // could use trim like in malloc_aligned but not much gained return ptr; // nothing to do - void *p = _rtapi_malloc (h, size); + void *p = rtapi_malloc (h, size); if (!p) return (p); memcpy(p, ptr, (sz > size) ? size : sz); - _rtapi_free(h, ptr); + rtapi_free(h, ptr); return p; } -size_t _rtapi_heap_walk_freelist(struct rtapi_heap *h, chunk_t callback, void *user) +size_t rtapi_heap_walk_freelist(struct rtapi_heap *h, chunk_t callback, void *user) { WITH_MUTEX(HEAP_MUTEX(h)); @@ -303,7 +299,7 @@ size_t _rtapi_heap_walk_freelist(struct rtapi_heap *h, chunk_t callback, void *u } } -int _rtapi_heap_addmem(struct rtapi_heap *h, void *space, size_t size) +int rtapi_heap_addmem(struct rtapi_heap *h, void *space, size_t size) { WITH_MUTEX(HEAP_MUTEX(h)); @@ -318,7 +314,7 @@ int _rtapi_heap_addmem(struct rtapi_heap *h, void *space, size_t size) return 0; } -int _rtapi_heap_init(struct rtapi_heap *heap, const char *name) +int rtapi_heap_init(struct rtapi_heap *heap, const char *name) { WITH_MUTEX(HEAP_MUTEX(heap)); @@ -331,7 +327,7 @@ int _rtapi_heap_init(struct rtapi_heap *heap, const char *name) heap->requested = 0; heap->allocated = 0; heap->freed = 0; - if (name) + if (name) strncpy(heap->name, name, sizeof(heap->name)); else { #ifdef RTAPI @@ -343,14 +339,14 @@ int _rtapi_heap_init(struct rtapi_heap *heap, const char *name) return 0; } -int _rtapi_heap_setflags(struct rtapi_heap *heap, int flags) +int rtapi_heap_setflags(struct rtapi_heap *heap, int flags) { int f = heap->flags; heap->flags = flags; return f; } -size_t _rtapi_heap_status(struct rtapi_heap *h, +size_t rtapi_heap_status(struct rtapi_heap *h, struct rtapi_heap_stat *hs) { WITH_MUTEX(HEAP_MUTEX(h)); @@ -380,3 +376,17 @@ size_t _rtapi_heap_status(struct rtapi_heap *h, } } + +#ifdef RTAPI +EXPORT_SYMBOL(rtapi_malloc); +EXPORT_SYMBOL(rtapi_malloc_aligned); +EXPORT_SYMBOL(rtapi_free); +EXPORT_SYMBOL(rtapi_allocsize); +EXPORT_SYMBOL(rtapi_calloc); +EXPORT_SYMBOL(rtapi_realloc); +EXPORT_SYMBOL(rtapi_heap_walk_freelist); +EXPORT_SYMBOL(rtapi_heap_addmem); +EXPORT_SYMBOL(rtapi_heap_init); +EXPORT_SYMBOL(rtapi_heap_setflags); +EXPORT_SYMBOL(rtapi_heap_status); +#endif diff --git a/src/rtapi/rtapi_hexdump.c b/src/rtapi/rtapi_hexdump.c index 1f99b7a4e8..e6a6994728 100644 --- a/src/rtapi/rtapi_hexdump.c +++ b/src/rtapi/rtapi_hexdump.c @@ -18,17 +18,6 @@ #include /* va_start and va_end macros */ -#ifdef MODULE -#include "rtapi_app.h" - -#include -#include -#include -#include - -#else /* user land */ - - #include #include #include @@ -40,14 +29,11 @@ typeof(y) _min2 = (y); \ (void) (&_min1 == &_min2); \ _min1 < _min2 ? _min1 : _min2; }) -#endif // API doc moved to rtapi_hexdump.h -#ifndef MODULE const char hex_asc[] = "0123456789abcdef"; -#endif void rtapi_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/src/rtapi/rtapi_int.h b/src/rtapi/rtapi_int.h index 4df53e4d9e..06b37c3c4c 100644 --- a/src/rtapi/rtapi_int.h +++ b/src/rtapi/rtapi_int.h @@ -11,7 +11,6 @@ only. Since we have a simulator that runs everything in user space, the non-underscore types should NEVER be used. */ -#if defined(BUILD_SYS_USER_DSO) #define __KERNEL_STRICT_NAMES # include @@ -25,14 +24,5 @@ typedef __s16 s16; typedef __s32 s32; typedef __s64 s64; #define __iomem /* Nothing */ -#else -# include - -#ifdef HAVE_CK -# include -#endif - -#endif - #endif // RTAPI_INT_H diff --git a/src/rtapi/rtapi_io.h b/src/rtapi/rtapi_io.h index 0575f2d194..9a23b4b369 100644 --- a/src/rtapi/rtapi_io.h +++ b/src/rtapi/rtapi_io.h @@ -3,22 +3,20 @@ * * This file, 'rtapi_io.h', implements the i/o- related * functions for realtime modules as a series of static -* inline functions. For now, it applies only to PC -* architecture with the `inb` and `outb` assembly -* instructions.. +* inline functions. * * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -26,6 +24,8 @@ #ifndef RTAPI_IO_H #define RTAPI_IO_H +#include "config.h" // build configuration +#include "rtapi.h" // these functions #include /* inb(), outb() */ /** 'rtapi_outb() writes 'byte' to 'port'. May be called from @@ -65,5 +65,4 @@ static inline unsigned short rtapi_inw(unsigned int port) return inw(port); } - -#endif // RTAPI_IO_H +#endif // RTAPI_IO_H \ No newline at end of file diff --git a/src/rtapi/rtapi_kdetect.c b/src/rtapi/rtapi_kdetect.c deleted file mode 100644 index f54dd7dda2..0000000000 --- a/src/rtapi/rtapi_kdetect.c +++ /dev/null @@ -1,232 +0,0 @@ -/******************************************************************** -* Copyright (C) 2012 - 2013 Michael Haberler -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -// this example program documents all the heuristics we know -// which can currently be used to tell various RT and non-RT kernels apart. -// the actual code in rtapi_compat.c just uses a subset of these methods -// for a few test functions (kernel_is_xenomai() etc) - -// kernel + userland environment autodetection -// dig various kernel attributes and libraries to derive a -// syndrome vector - -#include "rtapi.h" -#include "rtapi_kdetect.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef void (*pf)(); -static const char *progname = "rtapi_kdetect"; -int shmdrv_loaded; -long page_size; - -int rtapi_kdetect(unsigned long *feat) -{ - struct stat sb; - void *libxenomai, *libnative, *func; - const char *errmsg; - struct utsname u; - FILE *fd; - struct timespec ts; - - *feat = 0; - if (uname(&u)) { - rtapi_print_msg(RTAPI_MSG_ERR, "%s: uname(): %s\n", - progname, strerror(errno)); - return -1; - } - - // match u.release for soft hints - if ((strcasestr (u.release, "-rtai")) || \ - (strcasestr (u.release, ".rtai"))) - *feat |= UTSNAME_REL_RTAI; - else if (strcasestr (u.release, "-rt")) - *feat |= UTSNAME_REL_RT; - if ((strcasestr (u.release, "-xenomai")) || \ - (strcasestr (u.release, ".xenomai"))) - *feat |= UTSNAME_REL_XENOMAI; - - // a hint of dubious quality - if (strcasestr (u.version, "#rtai")) - *feat |= UTSNAME_VER_RTAI; - - // check for ipipe patch - strong hint for RTAI or Xenomai - if ((stat(PROC_IPIPE, &sb) == 0) && S_ISDIR(sb.st_mode & S_IFMT)) - *feat |= HAS_PROC_IPIPE; - - // Xenomai only: - if ((stat(PROC_IPIPE_XENOMAI, &sb) == 0) && S_ISREG(sb.st_mode)) - *feat |= HAS_PROC_IPIPE_XENOMAI; - - // Xenomai only: - if ((stat(XENO_GID_SYSFS, &sb) == 0) && S_ISREG(sb.st_mode)) - *feat |= HAS_XENO_GID_SYSFS; - - // a strong RT PREEMPT hint - if (strcasestr (u.version, "PREEMPT RT")) - *feat |= UTSNAME_VER_RT_PREEMPT; - - // a strong RT PREEMPT hint - if ((fd = fopen(PREEMPT_RT_SYSFS,"r")) != NULL) { - int flag; - if ((fscanf(fd, "%d", &flag) == 1) && (flag)) - *feat |= SYS_KERNEL_REALTIME_FOUND; - fclose(fd); - } - - // check for hires timers - // this is really a sanitary requirement - // it is 1ns on all kernels (RTAI, RT_PREEMPT, Xenomai, vanilla) - // and so has no discriminatory value - if (clock_getres(CLOCK_MONOTONIC, &ts)) { - rtapi_print_msg(RTAPI_MSG_ERR, "%s: clock_getres(): %s\n", - progname, strerror(errno)); - return -1; - } else { - if ((ts.tv_sec == 0) && (ts.tv_nsec == 1)) - *feat |= HAS_HIRES_TIMERS; - } - - // check for Xenomai fingerprint(s) - strong hint - if ((stat(XNHEAP_DEV_NAME, &sb) == 0) && S_ISCHR(sb.st_mode)) - *feat |= XENO_RTHEAP_FOUND; - - // might be able to run without /proc/xenomai but it's reassuring if it exists - if ((stat(PROC_XENOMAI, &sb) == 0) && S_ISDIR(sb.st_mode)) - *feat |= XENO_PROCENTRY_FOUND; - - // libnative on a non-xenomai kernel wont help, but checking for it might - // yield a useful error message like 'xenomai libraries available but no xenomai - // kernel running' - if ((libxenomai = dlopen(LIBXENOMAI, RTLD_NOW)) != NULL) - *feat |= XENO_LIBXENOMAI; - - if ((libnative = dlopen(LIBNATIVE, RTLD_NOW)) != NULL) - *feat |= XENO_LIBNATIVE; - - // see if we can resolve an important symbol in libnative - if ((libxenomai != NULL) && (libnative != NULL)) { - func = (pf) dlsym(libnative, LIBNATIVE_SYM); - if ( ((errmsg = dlerror()) == NULL) && (func != NULL)) - *feat |= XENO_LIBSYMBOL; - } - if (libxenomai) - dlclose(libxenomai); - if (libnative) - dlclose(libnative); - - // check for RTAI fingerprint(s) - this works only after 'realtime start'! - if ((stat(DEV_RTAI_SHM, &sb) == 0) && S_ISCHR(sb.st_mode)) - *feat |= DEV_RTAI_SHM_FOUND; - - return 0; -} - - -#ifdef TEST -int main(int argc, char **argv) -{ - unsigned long f; - struct utsname u; - - rtapi_set_msg_level(RTAPI_MSG_DBG); - if (uname(&u)) { - rtapi_print_msg(RTAPI_MSG_ERR, "main: uname(): %s\n", - strerror(errno)); - exit(1); - } - - if (!rtapi_kdetect(&f)) { - fprintf(stderr,"feature mask = 0x%lx\n",f); - if (!(f & HAS_HIRES_TIMERS)) { - fprintf(stderr, - "cant detect hires timers. What clunker of a kernel is this? if postwar, please report a bug.\n"); - exit(1); - } - if (f & XENO_RTHEAP_FOUND) { - fprintf(stderr, "a Xenomai kernel\n"); - - if ((f & (SYS_KERNEL_REALTIME_FOUND|UTSNAME_VER_RT_PREEMPT)) == - (SYS_KERNEL_REALTIME_FOUND|UTSNAME_VER_RT_PREEMPT)) { - fprintf(stderr, ".. which also has RT PREEMPT patches applied\n"); - } - - if (!(f & HAS_PROC_IPIPE_XENOMAI)) - fprintf(stderr, "ERROR: Xenomai lacks %s !!\n", PROC_IPIPE_XENOMAI); - - if (!(f & HAS_XENO_GID_SYSFS)) - fprintf(stderr, "ERROR: Xenomai lacks %s !!\n", XENO_GID_SYSFS); - - if (!(f & UTSNAME_REL_XENOMAI)) - fprintf(stderr, "utsname.release looked less than helpful: '%s'\n", - u.release); - - if (f & (UTSNAME_REL_RTAI|UTSNAME_REL_RT)) - fprintf(stderr, "utsname.release looks contradictory: '%s'\n", - u.release); - - if ((f & (XENO_LIBXENOMAI|XENO_LIBNATIVE|XENO_LIBSYMBOL)) == - (XENO_LIBXENOMAI|XENO_LIBNATIVE|XENO_LIBSYMBOL)) - fprintf(stderr, "Xenomai userland library support looks intact\n"); - else { - if (!(f & XENO_LIBXENOMAI)) - fprintf(stderr, "%s unusable\n", LIBXENOMAI); - if (!(f & XENO_LIBNATIVE)) - fprintf(stderr, "%s unusable\n", LIBNATIVE); - if (!(f & XENO_LIBSYMBOL)) - fprintf(stderr, "cant resolve %s in %s\n", LIBNATIVE_SYM, LIBNATIVE); - } - } else { - if ((f & (SYS_KERNEL_REALTIME_FOUND|UTSNAME_VER_RT_PREEMPT)) == - (SYS_KERNEL_REALTIME_FOUND|UTSNAME_VER_RT_PREEMPT)) { - fprintf(stderr, "an RT PREEMPT kernel\n"); - } else { - if (f & HAS_PROC_IPIPE) { - fprintf(stderr, "an RTAI kernel with RT modules %sloaded\n", - (f & DEV_RTAI_SHM_FOUND) ? "" : "not "); - } else { - fprintf(stderr, "assuming a vanilla kernel\n"); - if (f & UTSNAME_REL_RTAI) - fprintf(stderr, "however, utsname.release hints at RTAI: '%s'\n", - u.release); - if (f & UTSNAME_VER_RTAI) - fprintf(stderr, "however, utsname.version hints at RTAI: '%s'\n", - u.version); - if (f & UTSNAME_REL_XENOMAI) - fprintf(stderr, "however, utsname.release hints at Xenomai: '%s'\n", - u.release); - if (f & UTSNAME_REL_RT) - fprintf(stderr, "however, utsname.release hints at RT_PREEMPT: '%s'\n", - u.release); - } - } - } - } else - fprintf(stderr,"rtapi_kdetect failed\n"); - exit(0); -} -#endif diff --git a/src/rtapi/rtapi_kdetect.h b/src/rtapi/rtapi_kdetect.h deleted file mode 100644 index 1e057ed827..0000000000 --- a/src/rtapi/rtapi_kdetect.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************** - * Copyright (C) 2012, 2013 Michael Haberler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ********************************************************************/ - -// support for thread style autodetection based on digging in the kernel -// and userland libraries - -#include "rtapi_bitops.h" - -// utsname.release matches telltale strings (soft) -#define UTSNAME_REL_RTAI RTAPI_BIT(0) -#define UTSNAME_REL_RT RTAPI_BIT(1) -#define UTSNAME_REL_XENOMAI RTAPI_BIT(2) - -// utsname.version matches "PREEMPT RT" (hard) -#define UTSNAME_VER_RT_PREEMPT RTAPI_BIT(3) - -// utsname.version matches "#rtai" (soft) -#define UTSNAME_VER_RTAI RTAPI_BIT(4) - -#define XENO_RTHEAP_FOUND RTAPI_BIT(5) // /dev/rtheap seen (hard) -#define XENO_PROCENTRY_FOUND RTAPI_BIT(6) // /proc/xenomai seen (hard) - -#define HAS_HIRES_TIMERS RTAPI_BIT(7) // sanitary - assume vanilla if false. -#define SYS_KERNEL_REALTIME_FOUND RTAPI_BIT(8) // RT_PREEMPT (hard) - -#define DEV_RTAI_SHM_FOUND RTAPI_BIT(9) // RTAI (hard) - -// verify the Xenomai userland libraries are present and make sense (sanitary for xenomai) -#define XENO_LIBXENOMAI RTAPI_BIT(10) // can dlopen("libxenomai.so") -#define XENO_LIBNATIVE RTAPI_BIT(11) // can dlopen("libnative.so") -#define XENO_LIBSYMBOL RTAPI_BIT(12) // can resolve symbol in "libnative.so" - -// hard evidence for an ipipe patch in place (RTAI and Xenomai): -#define HAS_PROC_IPIPE RTAPI_BIT(13) // /proc/ipipe exists and is a directory - -// Exists on RTAI and Xenomai -#define PROC_IPIPE "/proc/ipipe" - -// really in nucleus/heap.h but we rather get away with minimum include files -#ifndef XNHEAP_DEV_NAME -#define XNHEAP_DEV_NAME "/dev/rtheap" -#endif - -// test for "/proc/xenomai" existance and a directory -#define PROC_XENOMAI "/proc/xenomai" - -// dlopen() these shared libraries -#define LIBXENOMAI "libxenomai.so" -#ifdef XENOMAI_V2 -#define LIBNATIVE "libnative.so" -#else -#define LIBNATIVE "libalchemy.so" -#endif -// and dig for LIBNATIVE_SYM -#define LIBNATIVE_SYM "rt_task_create" - -// if this exists, and contents is '1', it's RT_PREEMPT -#define PREEMPT_RT_SYSFS "/sys/kernel/realtime" - -// dev/rtai_shm visible only after 'realtime start' -#define DEV_RTAI_SHM "/dev/rtai_shm" - -// These exist on Xenomai but not on RTAI - regular files: -#define PROC_IPIPE_XENOMAI "/proc/ipipe/Xenomai" -#define XENO_GID_SYSFS "/sys/module/xeno_nucleus/parameters/xenomai_gid" - -// hard evidence for Xenomai -#define HAS_PROC_IPIPE_XENOMAI RTAPI_BIT(14) // /proc/ipipe/Xenomai exists -#define HAS_XENO_GID_SYSFS RTAPI_BIT(15) - -int rtapi_kdetect(unsigned long *feat); diff --git a/src/rtapi/rtapi_limits.h b/src/rtapi/rtapi_limits.h index 84b63620d4..1bb100b1fa 100644 --- a/src/rtapi/rtapi_limits.h +++ b/src/rtapi/rtapi_limits.h @@ -19,11 +19,6 @@ #define RTAPI_LIMITS_H #include "config.h" - -#if defined(RTAPI) && defined(BUILD_SYS_KBUILD) -#include -#else #include -#endif #endif diff --git a/src/rtapi/rtapi_main.c b/src/rtapi/rtapi_main.c deleted file mode 100644 index 645063862c..0000000000 --- a/src/rtapi/rtapi_main.c +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************** - * Description: rtapi_main.c - * - * This file, 'rtapi_main.c', implements the RTAPI - * rtapi_app_main() and rtapi_app_exit() functions - * for userspace thread systems. - * - * It should not be used for kernel thread systems. - * - * Copyright (C) 2012, 2013 John Morris - * Michael Haberler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ********************************************************************/ - - -#include /* ssize_t, _SC_PAGESIZE */ -#include -#include -#include -#include -#include - -#include "config.h" -#include "rtapi.h" /* RTAPI realtime OS API */ -#include "rtapi_app.h" /* RTAPI realtime module decls */ -#include "rtapi_common.h" /* global_data_t */ -#include "rtapi_compat.h" /* global_data_t */ -#include "ring.h" -#include "rtapi_heap.h" -#include "shmdrv.h" /* common shm driver API */ - -MODULE_AUTHOR("Michael Haberler"); -MODULE_DESCRIPTION("RTAPI module support - userland threads"); -MODULE_LICENSE("GPL"); - -// mostly for argument compatibility with kernel thread flavors -int rtapi_instance; // instance id, visible throughout RTAPI -RTAPI_MP_INT(rtapi_instance, "instance ID"); -EXPORT_SYMBOL(rtapi_instance); - -global_data_t *global_data = NULL; // visible to all RTAPI modules -EXPORT_SYMBOL(global_data); - -rtapi_switch_t *rtapi_switch = NULL; -EXPORT_SYMBOL(rtapi_switch); - -struct rtapi_heap *global_heap = NULL; -EXPORT_SYMBOL(global_heap); - -#ifdef HAVE_RTAPI_MODULE_INIT_HOOK -void _rtapi_module_init_hook(void); -#endif - -#ifdef HAVE_RTAPI_MODULE_EXIT_HOOK -void _rtapi_module_exit_hook(void); -#endif - -ringbuffer_t rtapi_message_buffer; // error ring access strcuture - -int rtapi_app_main(void) -{ - int retval; - int globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance); - int rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance); - int size = 0; - - rtapi_switch = rtapi_get_handle(); - shm_common_init(); - - // tag messages originating from RT proper - rtapi_set_logtag("rtapi"); - - rtapi_print_msg(RTAPI_MSG_DBG,"RTAPI:%d %s %s init\n", - rtapi_instance, - rtapi_switch->thread_flavor_name, - GIT_VERSION); - - // attach to global segment which rtapi_msgd owns and already - // has set up: - retval = shm_common_new(globalkey, &size, - rtapi_instance, (void **) &global_data, 0); - - if (retval == -ENOENT) { - // the global_data segment does not exist. - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: global segment 0x%x does not exist" - " (rtapi_msgd not started?)\n", - rtapi_instance, globalkey); - return -EBUSY; - } - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: shm_common_new() failed key=0x%x %s\n", - rtapi_instance, globalkey, strerror(-retval)); - return retval; - } - if (size < sizeof(global_data_t)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: unexpected global shm size:" - " expected: >%zu actual:%d\n", - rtapi_instance, sizeof(global_data_t), size); - return -EINVAL; - } - - // consistency check - if (global_data->rtapi_thread_flavor != THREAD_FLAVOR_ID) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d BUG: thread flavors dont match:" - " global %d rtapi %d\n", - rtapi_instance, global_data->rtapi_thread_flavor, - THREAD_FLAVOR_ID); - return -EINVAL; - } - - // good to use global_data from here on - - // this heap is inited in rtapi_msgd.cc - // make it accessible in RTAPI - global_heap = &global_data->heap; - - // make the message ringbuffer accessible - ringbuffer_init(shm_ptr(global_data, global_data->rtapi_messages_ptr), - &rtapi_message_buffer); - rtapi_message_buffer.header->refcount++; // rtapi is 'attached' - - - // some flavors might use a shared memory segment for rtapi data. That - // fact is recorded in rtapi_switch->flavor_flags - - if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) { - size = sizeof(rtapi_data_t); - retval = shm_common_new(rtapikey, &size, - rtapi_instance, (void **) &rtapi_data, 1); - if (retval == 0) { - // the rtapi_data segment already existed. - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: rtapi segment 0x%x already exists!\n", - rtapi_instance, rtapikey); - return -EBUSY; - } - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: shm_common_new() failed key=0x%x %s\n", - rtapi_instance, rtapikey, strerror(-retval)); - return retval; - } - if (size != sizeof(rtapi_data_t)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: unexpected rtapi shm size:" - " expected: %zd actual:%d\n", - rtapi_instance, sizeof(rtapi_data_t), size); - return -EINVAL; - } - } - - init_rtapi_data(rtapi_data); - -#ifdef HAVE_RTAPI_MODULE_INIT_HOOK - _rtapi_module_init_hook(); -#endif - return 0; -} - -void rtapi_app_exit(void) -{ - int retval; - - rtapi_print_msg(RTAPI_MSG_DBG,"RTAPI:%d exit\n", rtapi_instance); - -#ifdef HAVE_RTAPI_MODULE_EXIT_HOOK - _rtapi_module_exit_hook(); -#endif - - rtapi_message_buffer.header->refcount--; - - if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) { - - if ((retval = shm_common_detach(sizeof(rtapi_data_t), rtapi_data))) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: shm_common_detach(rtapi_data)" - " failed: %s\n", - rtapi_instance, strerror(-retval)); - } - shm_common_unlink(OS_KEY(RTAPI_KEY, rtapi_instance)); - } - rtapi_data = NULL; -} diff --git a/src/rtapi/rtapi_math/Submakefile b/src/rtapi/rtapi_math/Submakefile index b29c03900d..28c8746f71 100644 --- a/src/rtapi/rtapi_math/Submakefile +++ b/src/rtapi/rtapi_math/Submakefile @@ -1,54 +1,3 @@ -ifeq ($(BUILD_SYS),kbuild) - -rtapi_math-objs := rtapi/rtapi_math/s_floor.o -rtapi_math-objs += rtapi/rtapi_math/e_pow.o -rtapi_math-objs += rtapi/rtapi_math/w_pow.o -rtapi_math-objs += rtapi/rtapi_math/s_fabs.o -rtapi_math-objs += rtapi/rtapi_math/e_sqrt.o -rtapi_math-objs += rtapi/rtapi_math/w_sqrt.o -rtapi_math-objs += rtapi/rtapi_math/s_ceil.o -rtapi_math-objs += rtapi/rtapi_math/e_acos.o -rtapi_math-objs += rtapi/rtapi_math/w_acos.o -rtapi_math-objs += rtapi/rtapi_math/e_asin.o -rtapi_math-objs += rtapi/rtapi_math/w_asin.o -rtapi_math-objs += rtapi/rtapi_math/s_tan.o -rtapi_math-objs += rtapi/rtapi_math/k_tan.o -rtapi_math-objs += rtapi/rtapi_math/s_atan.o -rtapi_math-objs += rtapi/rtapi_math/w_atan2.o -rtapi_math-objs += rtapi/rtapi_math/e_atan2.o -rtapi_math-objs += rtapi/rtapi_math/s_sin.o -rtapi_math-objs += rtapi/rtapi_math/k_sin.o -rtapi_math-objs += rtapi/rtapi_math/s_cos.o -rtapi_math-objs += rtapi/rtapi_math/k_cos.o -rtapi_math-objs += rtapi/rtapi_math/e_rem_pio2.o -rtapi_math-objs += rtapi/rtapi_math/k_rem_pio2.o -rtapi_math-objs += rtapi/rtapi_math/s_scalbn.o -rtapi_math-objs += rtapi/rtapi_math/k_standard.o -rtapi_math-objs += rtapi/rtapi_math/s_cbrt.o -rtapi_math-objs += rtapi/rtapi_math/s_copysign.o -rtapi_math-objs += rtapi/rtapi_math/s_finite.o -rtapi_math-objs += rtapi/rtapi_math/s_rint.o -rtapi_math-objs += rtapi/rtapi_math/powidf.o -rtapi_math-objs += rtapi/rtapi_math/e_hypot.o -rtapi_math-objs += rtapi/rtapi_math/w_hypot.o -rtapi_math-objs += rtapi/rtapi_math/e_fmod.o -rtapi_math-objs += rtapi/rtapi_math/w_fmod.o -rtapi_math-objs += rtapi/rtapi_math/s_fabs.o -rtapi_math-objs += rtapi/rtapi_math/s_rint.o -rtapi_math-objs += rtapi/rtapi_math/s_fminmax.o -rtapi_math-objs += rtapi/rtapi_math/krtapi_math.o - -obj-m += rtapi_math.o - -ccflags-y := $(KERNEL_MATH_CFLAGS) \ - -D_IEEE_LIBM \ - -D_ISOC99_SOURCE \ - -D_SVID_SOURCE - -$(RTLIBDIR)/rtapi_math$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(rtapi_math-objs)) - -endif - LIBRMSRCS := rtapi/rtapi_math/s_floor.c LIBRMSRCS += rtapi/rtapi_math/e_pow.c LIBRMSRCS += rtapi/rtapi_math/w_pow.c diff --git a/src/rtapi/rtapi_math/k_standard.c b/src/rtapi/rtapi_math/k_standard.c index 54c662d2c6..baef666606 100644 --- a/src/rtapi/rtapi_math/k_standard.c +++ b/src/rtapi/rtapi_math/k_standard.c @@ -5,7 +5,7 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -19,12 +19,7 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $ extern int libm_errno; -#ifdef MODULE -#include -#define WRITE2(u,v) printk("%.*s",v,u) -#else #define WRITE2(u,v) (v) //rtapi_print("%.*s",v,u) /* FIXME, rtapi or userspace? */ -#endif #ifdef __STDC__ static const double zero = 0.0; /* used as const */ @@ -32,7 +27,7 @@ static const double zero = 0.0; /* used as const */ static double zero = 0.0; /* used as const */ #endif -/* +/* * Standard conformance (non-IEEE) on exception cases. * Mapping: * 1 -- acos(|x|>1) @@ -57,7 +52,7 @@ static double zero = 0.0; /* used as const */ * 20-- pow(0.0,0.0) * 21-- pow(x,y) overflow * 22-- pow(x,y) underflow - * 23-- pow(0,negative) + * 23-- pow(0,negative) * 24-- pow(neg,non-integral) * 25-- sinh(finite) overflow * 26-- sqrt(negative) @@ -81,14 +76,14 @@ static double zero = 0.0; /* used as const */ #ifdef __STDC__ - double __kernel_standard(double x, double y, int type) + double __kernel_standard(double x, double y, int type) #else - double __kernel_standard(x,y,type) + double __kernel_standard(x,y,type) double x,y; int type; #endif { struct exception exc; -#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ +#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ #define HUGE_VAL inf double inf = 0.0; @@ -465,7 +460,7 @@ static double zero = 0.0; /* used as const */ /* 0**neg */ exc.type = DOMAIN; exc.name = type < 100 ? "pow" : "powf"; - if (_LIB_VERSION == _SVID_) + if (_LIB_VERSION == _SVID_) exc.retval = zero; else exc.retval = -HUGE_VAL; @@ -483,11 +478,11 @@ static double zero = 0.0; /* used as const */ /* neg**non-integral */ exc.type = DOMAIN; exc.name = type < 100 ? "pow" : "powf"; - if (_LIB_VERSION == _SVID_) + if (_LIB_VERSION == _SVID_) exc.retval = zero; - else + else exc.retval = zero/zero; /* X/Open allow NaN */ - if (_LIB_VERSION == _POSIX_) + if (_LIB_VERSION == _POSIX_) libm_errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { @@ -645,7 +640,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 35: case 135: @@ -661,7 +656,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 36: case 136: @@ -677,7 +672,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 37: case 137: @@ -693,7 +688,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 38: case 138: @@ -709,7 +704,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 39: case 139: @@ -725,7 +720,7 @@ static double zero = 0.0; /* used as const */ (void) WRITE2(": TLOSS error\n", 14); } libm_errno = ERANGE; - } + } break; case 40: case 140: @@ -774,5 +769,5 @@ static double zero = 0.0; /* used as const */ } break; } - return exc.retval; + return exc.retval; } diff --git a/src/rtapi/rtapi_math/mathP.h b/src/rtapi/rtapi_math/mathP.h index a9d1e26c7c..727d8dc3cb 100644 --- a/src/rtapi/rtapi_math/mathP.h +++ b/src/rtapi/rtapi_math/mathP.h @@ -4,7 +4,7 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -17,11 +17,7 @@ #ifndef _MATH_PRIVATE_H_ #define _MATH_PRIVATE_H_ -#ifdef MODULE -#include -#else #include -#endif #include "rtapi_byteorder.h" #define __P(args) args @@ -88,10 +84,10 @@ extern double __kernel_standard(double x, double y, int type); #if RTAPI_BIG_ENDIAN -typedef union +typedef union { double value; - struct + struct { u_int32_t msw; u_int32_t lsw; @@ -102,10 +98,10 @@ typedef union #if RTAPI_LITTLE_ENDIAN -typedef union +typedef union { double value; - struct + struct { u_int32_t lsw; u_int32_t msw; @@ -200,13 +196,13 @@ do { \ } while (0) /* ieee style elementary functions */ -extern double __ieee754_sqrt __P((double)); -extern double __ieee754_acos __P((double)); -extern double __ieee754_acosh __P((double)); -extern double __ieee754_log __P((double)); -extern double __ieee754_atanh __P((double)); -extern double __ieee754_asin __P((double)); -extern double __ieee754_atan2 __P((double,double)); +extern double __ieee754_sqrt __P((double)); +extern double __ieee754_acos __P((double)); +extern double __ieee754_acosh __P((double)); +extern double __ieee754_log __P((double)); +extern double __ieee754_atanh __P((double)); +extern double __ieee754_asin __P((double)); +extern double __ieee754_atan2 __P((double,double)); extern double __ieee754_exp __P((double)); extern double __ieee754_cosh __P((double)); extern double __ieee754_fmod __P((double,double)); @@ -233,7 +229,7 @@ extern double __ieee754_scalb __P((double,double)); #endif /* fdlibm kernel function */ -extern double __kernel_standard __P((double,double,int)); +extern double __kernel_standard __P((double,double,int)); extern double __kernel_sin __P((double,double,int)); extern double __kernel_cos __P((double,double)); extern double __kernel_tan __P((double,double,int)); @@ -241,13 +237,13 @@ extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*)); /* ieee style elementary float functions */ -extern float __ieee754_sqrtf __P((float)); -extern float __ieee754_acosf __P((float)); -extern float __ieee754_acoshf __P((float)); -extern float __ieee754_logf __P((float)); -extern float __ieee754_atanhf __P((float)); -extern float __ieee754_asinf __P((float)); -extern float __ieee754_atan2f __P((float,float)); +extern float __ieee754_sqrtf __P((float)); +extern float __ieee754_acosf __P((float)); +extern float __ieee754_acoshf __P((float)); +extern float __ieee754_logf __P((float)); +extern float __ieee754_atanhf __P((float)); +extern float __ieee754_asinf __P((float)); +extern float __ieee754_atan2f __P((float,float)); extern float __ieee754_expf __P((float)); extern float __ieee754_coshf __P((float)); extern float __ieee754_fmodf __P((float,float)); diff --git a/src/rtapi/rtapi_module.c b/src/rtapi/rtapi_module.c deleted file mode 100644 index 72ebafdfc1..0000000000 --- a/src/rtapi/rtapi_module.c +++ /dev/null @@ -1,594 +0,0 @@ -/******************************************************************** -* Description: rtapi_module.c -* -* This file, 'rtapi_module.c', implements the -* init_module(), cleanup_module(), rtapi_init(), -* rtapi_exit() and module_delete() functions for kernel -* space thread systems. -* -* It should not be built for userspace thread systems. -* -* Copyright 2006-2013 Various Authors -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -********************************************************************/ - -#include "config.h" // build configuration -#include "rtapi.h" // these functions -#include "rtapi_common.h" // RTAPI macros and decls -#include "ring.h" -#include "rtapi_heap.h" -#include "shmdrv.h" - - -#ifdef MODULE -#include "rtapi_proc.h" /* proc filesystem decls & code */ - -# if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -# include /* NR_CPUS, cpu_online() */ -# endif -#endif - -extern void init_rtapi_data(rtapi_data_t * data); - -#ifdef RTAPI -MODULE_AUTHOR("Michael Haberler"); -MODULE_DESCRIPTION("RTAPI module support - kernel threads"); -MODULE_LICENSE("GPL"); - -// kernel styles do not support multiple instances -// this just numbers this particular instance to fit with the scheme -int rtapi_instance; - -RTAPI_MP_INT(rtapi_instance, "RTAPI instance id"); -EXPORT_SYMBOL(rtapi_instance); - -global_data_t *global_data = NULL; -EXPORT_SYMBOL(global_data); - -rtapi_switch_t *rtapi_switch = NULL; -EXPORT_SYMBOL(rtapi_switch); - -struct rtapi_heap *global_heap = NULL; -EXPORT_SYMBOL(global_heap); - -ringbuffer_t rtapi_message_buffer; // error ring access strcuture - -/* the following are internal functions that do the real work associated - with deleting tasks, etc. They do not check the mutex that protects - the internal data structures. When someone calls an rtapi_xxx_delete() - function, the rtapi funct gets the mutex before calling one of these - internal functions. When internal code that already has the mutex - needs to delete something, it calls these functions directly. -*/ -static int module_delete(int module_id); -extern void _rtapi_module_cleanup_hook(void); - -/*********************************************************************** -* INIT AND SHUTDOWN FUNCTIONS * -************************************************************************/ - -#ifdef HAVE_RTAPI_MODULE_INIT_HOOK -void _rtapi_module_init_hook(void); -#endif - -#ifdef HAVE_RTAPI_MODULE_EXIT_HOOK -void _rtapi_module_exit_hook(void); -#endif - -int init_module(void) { - int n; - struct shm_status sm; - int retval, gsize; - - rtapi_switch = rtapi_get_handle(); - - // first thing: attach global_data - sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance); - sm.size = 0; - sm.flags = 0; - - if ((retval = shmdrv_attach(&sm, (void **)&global_data)) < 0) { - // cant use the message ringbuffer just yet - printk("RTAPI ERROR: can attach global segment: %d", - retval); - return -EINVAL; - } - gsize = sm.size; - - // fail immediately if the global segment isnt in shape yet - // this catches https://github.com/zultron/linuxcnc/issues/49 early - if (global_data->magic != GLOBAL_READY) { - - printk("RTAPI ERROR: bad global magic: 0x%x", - global_data->magic); - - // TBD: remove once cause identified - printk("halsize=%d\n", global_data->hal_size); - printk("msgd pid=%d\n", global_data->rtapi_msgd_pid); - printk("magic=%x\n", global_data->magic); - printk("flavor=%d\n", global_data->rtapi_thread_flavor); - // fail the insmod - return -EINVAL; - } - - // say hello - this now goes through the message ringbuffer - RTAPIINFO("%s %s init", - rtapi_get_handle()->thread_flavor_name, - GIT_VERSION); - - sm.key = OS_KEY(RTAPI_KEY, rtapi_instance); - sm.size = sizeof(rtapi_data_t); - sm.flags = 0; - if ((retval = shmdrv_create(&sm)) < 0) { - RTAPIERR("can create rtapi segment: %d", retval); - return -EINVAL; - } - if ((retval = shmdrv_attach(&sm, (void **)&rtapi_data)) < 0) { - RTAPIERR("cant attach rtapi segment: %d", retval); - return -EINVAL; - } - // this heap is inited in rtapi_msgd.cc - // make it accessible in RTAPI - global_heap = &global_data->heap; - - // make the message ringbuffer accessible - ringbuffer_init(shm_ptr(global_data, global_data->rtapi_messages_ptr), - &rtapi_message_buffer); - rtapi_message_buffer.header->refcount++; // rtapi is 'attached' - - // tag messages originating from RT proper - rtapi_set_logtag("rt"); - - /* this will take care of any threads flavor hook */ - init_rtapi_data(rtapi_data); - - /* check flavor and serial codes */ - if ((rtapi_data->thread_flavor_id != THREAD_FLAVOR_ID) || - (rtapi_data->serial != RTAPI_SERIAL)) { - - if (rtapi_data->thread_flavor_id != THREAD_FLAVOR_ID) - RTAPIERR("flavor mismatch %d vs %d", - rtapi_data->thread_flavor_id, - THREAD_FLAVOR_ID); - - if (rtapi_data->serial != RTAPI_SERIAL) - RTAPIERR("serial mismatch '%d' vs '%d'", - rtapi_data->serial, RTAPI_SERIAL); - - // release rtapi and global shared memory blocks - sm.key = OS_KEY(RTAPI_KEY, rtapi_instance); - sm.size = sizeof(rtapi_data_t); - sm.flags = 0; - if ((retval = shmdrv_detach(&sm)) < 0) - RTAPIERR("shmdrv_detach(rtapi=0x%x,%zu) returns %d", - sm.key, sm.size, retval); - - sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance); - sm.size = gsize; - sm.flags = 0; - if ((retval = shmdrv_detach(&sm)) < 0) - RTAPIERR("shmdrv_detach(global=0x%x,%zu) returns %d", - sm.key, sm.size, retval); - - return -EINVAL; - } - - /* set up local pointers to global data */ - module_array = rtapi_data->module_array; - task_array = rtapi_data->task_array; - shmem_array = rtapi_data->shmem_array; - - /* perform local init */ - for (n = 0; n <= RTAPI_MAX_TASKS; n++) { - ostask_array[n] = NULL; - } - for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { - shmem_addr_array[n] = NULL; - } - rtapi_data->timer_running = 0; - rtapi_data->timer_period = 0; - max_delay = DEFAULT_MAX_DELAY; - -#ifdef RT_LINUX_USE_FPU - rt_linux_use_fpu(1); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - /* on SMP machines, we want to put RT code on the last CPU */ - n = NR_CPUS-1; - while ( ! cpu_online(n) ) { - n--; - } - rtapi_data->rt_cpu = n; -#else - /* old kernel, the SMP hooks aren't available, so use CPU 0 */ - rtapi_data->rt_cpu = 0; -#endif - - -#ifdef CONFIG_PROC_FS - /* set up /proc/rtapi */ - if (proc_init() != 0) { - RTAPIWARN("Could not activate /proc entries"); - proc_clean(); - } -#endif - -#ifdef HAVE_RTAPI_MODULE_INIT_HOOK - _rtapi_module_init_hook(); -#endif - - RTAPIINFO("Init complete"); - return 0; -} - -/* This cleanup code attempts to fix any messes left by modules -that fail to load properly, or fail to clean up after themselves */ - -void cleanup_module(void) { - int n; - struct shm_status sm; - int retval; - - if (rtapi_data == NULL) { - /* never got inited, nothing to do */ - return; - } - -#ifdef HAVE_RTAPI_MODULE_EXIT_HOOK - _rtapi_module_exit_hook(); -#endif - - /* grab the mutex */ - rtapi_mutex_get(&(rtapi_data->mutex)); - RTAPIINFO("exit"); - - /* clean up leftover modules (start at 1, we don't use ID 0 */ - for (n = 1; n <= RTAPI_MAX_MODULES; n++) { - if (module_array[n].state == REALTIME) { - RTAPIWARN("module '%s' (ID: %02d) did not " - "call rtapi_exit()", - module_array[n].name, n); - module_delete(n); - } - } - - /* cleaning up modules should clean up everything, if not there has - probably been an unrecoverable internal error.... */ - for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { - if (shmem_array[n].rtusers > 0) { - RTAPIERR("shared memory block %02d not deleted, " - "%d RT users left", n, - shmem_array[n].rtusers ); - } - } - for (n = 1; n <= RTAPI_MAX_TASKS; n++) { - if (task_array[n].state != EMPTY) { - RTAPIERR("task %02d not deleted", n); - /* probably un-recoverable, but try anyway */ - _rtapi_task_pause(n); - /* rtapi_task_delete should not grab mutex */ - task_array[n].state = DELETE_LOCKED; - _rtapi_task_delete(n); - } - } - if (rtapi_data->timer_running != 0) { -#ifdef HAVE_RTAPI_MODULE_TIMER_STOP - _rtapi_module_timer_stop(); -#endif - rtapi_data->timer_period = 0; - timer_counts = 0; - rtapi_data->timer_running = 0; - max_delay = DEFAULT_MAX_DELAY; - } - rtapi_mutex_give(&(rtapi_data->mutex)); -#ifdef CONFIG_PROC_FS - proc_clean(); -#endif - - sm.key = OS_KEY(RTAPI_KEY, rtapi_instance); - sm.size = sizeof(rtapi_data_t); - sm.flags = 0; - if ((retval = shmdrv_detach(&sm)) < 0) { - RTAPIERR("shmdrv_detach(rtapi) returns %d", - retval); - } - rtapi_data = NULL; - rtapi_message_buffer.header->refcount--; // detach rtapi end - - sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance); - sm.size = sizeof(global_data_t); - sm.flags = 0; - if ((retval = shmdrv_detach(&sm)) < 0) { - RTAPIERR("shmdrv_detach(global) returns %d", - retval); - } - global_data = NULL; - - RTAPIINFO("Exit complete"); - return; -} - -/*********************************************************************** -* GENERAL PURPOSE FUNCTIONS * -************************************************************************/ - -/* all RTAPI init is done when the rtapi kernel module -is insmoded. The rtapi_init() and rtapi_exit() functions -simply register that another module is using the RTAPI. -For other RTOSes, things might be different, especially -if the RTOS does not use modules. */ - -int _rtapi_init(const char *modname) { - int n, module_id; - module_data *module; - - RTAPIDBG("initing module %s", modname); - - /* get the mutex */ - rtapi_mutex_get(&(rtapi_data->mutex)); - - /* find empty spot in module array */ - n = 1; - while ((n <= RTAPI_MAX_MODULES) && (module_array[n].state != NO_MODULE)) { - n++; - } - if (n > RTAPI_MAX_MODULES) { - /* no room */ - rtapi_mutex_give(&(rtapi_data->mutex)); - RTAPIERR("'%s': reached module limit %d", modname, n); - return -EMFILE; - } - - /* we have space for the module */ - module_id = n; - module = &(module_array[n]); - /* update module data */ - module->state = REALTIME; - if (modname != NULL) { - /* use name supplied by caller, truncating if needed */ - rtapi_snprintf(module->name, RTAPI_NAME_LEN, - "%s", modname); - } else { - /* make up a name */ - rtapi_snprintf(module->name, RTAPI_NAME_LEN, - "RTMOD%03d", module_id); - } - rtapi_data->rt_module_count++; - RTAPIDBG("module '%s' loaded, ID: %d", - module->name, module_id); - rtapi_mutex_give(&(rtapi_data->mutex)); - return module_id; -} - -int _rtapi_exit(int module_id) { - int retval; - - rtapi_mutex_get(&(rtapi_data->mutex)); - retval = module_delete(module_id); - rtapi_mutex_give(&(rtapi_data->mutex)); - return retval; -} - -static int module_delete(int module_id) { - module_data *module; - char name[RTAPI_NAME_LEN + 1]; - int n; - - RTAPIDBG("module %d exiting", module_id); - - /* validate module ID */ - if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { - return -EINVAL; - } - - /* point to the module's data */ - module = &(module_array[module_id]); - - /* check module status */ - if (module->state != REALTIME) { - /* not an active realtime module */ - return -EINVAL; - } - /* clean up any mess left behind by the module */ - for (n = 1; n <= RTAPI_MAX_TASKS; n++) { - if ((task_array[n].state != EMPTY) - && (task_array[n].owner == module_id)) { - RTAPIWARN("module '%s' failed to delete task %02d", - module->name, n); - task_array[n].state = DELETE_LOCKED; - _rtapi_task_delete(n); - } - } - for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { - if (rtapi_test_bit(module_id, shmem_array[n].bitmap)) { - - RTAPIWARN("module '%s' failed to delete shmem %02d rt=%d ul=%d", - module->name, n, - shmem_array[n].rtusers, - shmem_array[n].ulusers); - - // mark block as ready for delete, lock already held - shmem_array[n].magic = SHMEM_MAGIC_DEL_LOCKED; - _rtapi_shmem_delete(n, module_id); - } - } - - rtapi_snprintf(name, RTAPI_NAME_LEN, "%s", module->name); - - /* update module data */ - module->state = NO_MODULE; - module->name[0] = '\0'; - rtapi_data->rt_module_count--; - if (rtapi_data->rt_module_count == 0) { - if (rtapi_data->timer_running != 0) { -#ifdef HAVE_RTAPI_MODULE_TIMER_STOP - _rtapi_module_timer_stop(); -#endif - rtapi_data->timer_period = 0; - timer_counts = 0; - max_delay = DEFAULT_MAX_DELAY; - rtapi_data->timer_running = 0; - } - } - RTAPIDBG("module %d exited, name: '%s'", - module_id, name); - return 0; -} - -#else /* ULAPI */ - -int _rtapi_init(const char *modname) { - int n, module_id; - module_data *module; - struct shm_status sm; - int retval; - - ULAPIDBG("initing module '%s'", modname); - - errno = 0; - - // if not done yet, attach global and rtapi_data segments now - if (global_data == NULL) { - sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance); - sm.size = sizeof(global_data_t); - sm.flags = 0; - if ((retval = shmdrv_attach(&sm, (void **)&global_data)) < 0) { - ULAPIERR(" '%s' - cant attach global segment: %d", - modname, retval); - return -EINVAL; - } - sm.key = OS_KEY(RTAPI_KEY, rtapi_instance); - sm.size = sizeof(rtapi_data_t); - sm.flags = 0; - if ((retval = shmdrv_attach(&sm, (void **)&rtapi_data)) < 0) { - ULAPIERR(" '%s' - cant attach rtapi segment: %d", - modname, retval); - return -EINVAL; - } - } - // I consider this very dubious - there is no reason for ULAPI to start without - // rtapi_data already being inited: -mah - // init_rtapi_data(rtapi_data); - - /* check flavor and serial codes */ - if (rtapi_data->thread_flavor_id != THREAD_FLAVOR_ID) { - /* mismatch - release master shared memory block */ - ULAPIERR(" '%s' - flavor mismatch %d vs %d", - modname, rtapi_data->thread_flavor_id, - THREAD_FLAVOR_ID); - return -EINVAL; - } - if (rtapi_data->serial != RTAPI_SERIAL) { - /* mismatch - release master shared memory block */ - - ULAPIERR("serial mismatch %d vs %d", - rtapi_data->serial, RTAPI_SERIAL); - return -EINVAL; - } - /* set up local pointers to global data */ - module_array = rtapi_data->module_array; - task_array = rtapi_data->task_array; - shmem_array = rtapi_data->shmem_array; - - /* perform local init */ - for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { - shmem_addr_array[n] = NULL; - } - - /* get the mutex */ - rtapi_mutex_get(&(rtapi_data->mutex)); - /* find empty spot in module array */ - n = 1; - while ((n <= RTAPI_MAX_MODULES) && (module_array[n].state != NO_MODULE)) { - n++; - } - if (n > RTAPI_MAX_MODULES) { - /* no room */ - rtapi_mutex_give(&(rtapi_data->mutex)); - ULAPIERR("reached module limit %d",n); - return -EMFILE; - } - /* we have space for the module */ - module_id = n; - module = &(module_array[n]); - /* update module data */ - module->state = USERSPACE; - if (modname != NULL) { - /* use name supplied by caller, truncating if needed */ - rtapi_snprintf(module->name, RTAPI_NAME_LEN, "%s", modname); - } else { - /* make up a name */ - rtapi_snprintf(module->name, RTAPI_NAME_LEN, "ULMOD%03d", module_id); - } - rtapi_data->ul_module_count++; - rtapi_mutex_give(&(rtapi_data->mutex)); - ULAPIDBG("module '%s' inited, ID = %02d", - module->name, module_id); - return module_id; -} - -int _rtapi_exit(int module_id) { - module_data *module; - int n; - - if (rtapi_data == NULL) { - ULAPIERR("exit called before init"); - return -EINVAL; - } - - ULAPIDBG("module %02d exiting", module_id); - - /* validate module ID */ - if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { - ULAPIERR("bad module id %d", module_id); - return -EINVAL; - } - - /* get mutex */ - rtapi_mutex_get(&(rtapi_data->mutex)); - - /* point to the module's data */ - module = &(module_array[module_id]); - /* check module status */ - if (module->state != USERSPACE) { - ULAPIERR("not a userspace module: %d", module_id); - rtapi_mutex_give(&(rtapi_data->mutex)); - return -EINVAL; - } - /* clean up any mess left behind by the module */ - for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { - if (rtapi_test_bit(module_id, shmem_array[n].bitmap)) { - ULAPIWARN("module '%s' failed to delete " - "shmem %02d", module->name, n); - // mark block as ready for delete, lock already held - shmem_array[n].magic = SHMEM_MAGIC_DEL_LOCKED; - _rtapi_shmem_delete(n, module_id); - } - } - /* update module data */ - ULAPIDBG("module %02d exited, name = '%s'", - module_id, module->name); - module->state = NO_MODULE; - module->name[0] = '\0'; - rtapi_data->ul_module_count--; - rtapi_mutex_give(&(rtapi_data->mutex)); - return 0; -} - - -#endif /* ULAPI */ - diff --git a/src/rtapi/rtapi_msgd.cc b/src/rtapi/rtapi_msgd.cc index b2b63888b1..d1c1dda920 100644 --- a/src/rtapi/rtapi_msgd.cc +++ b/src/rtapi/rtapi_msgd.cc @@ -109,7 +109,6 @@ using namespace google::protobuf; int rtapi_instance; global_data_t *global_data; -int shmdrv_loaded; long page_size; // some global defaults are set in msgd, and recorded in the @@ -128,8 +127,6 @@ static int global_heap_flags = RTAPIHEAP_TRIM; static const char *inifile; static int foreground; -static int use_shmdrv; -static flavor_ptr flavor; static const char *instance_name; static int signal_fd; static bool trap_signals = true; @@ -161,8 +158,6 @@ static mk_netopts_t netopts; static mk_socket_t logpub; static int port = -1; // defaults to ephemeral port -static const char *shmdrv_opts; - static ringbuffer_t rtapi_msg_buffer; // ring access strcuture for messages static const char *progname; static char proctitle[20]; @@ -212,33 +207,6 @@ static global_data_t *create_global_segment(const size_t global_size) pid_t msgd_pid = pid_of("msgd:%d", rtapi_instance); - if (rtapi_instance == kernel_instance_id()) { - - // collision with a running kernel instance - not good. - int shmdrv_loaded = is_module_loaded("shmdrv"); - int rtapi_loaded = is_module_loaded("rtapi"); - int hal_loaded = is_module_loaded("hal_lib"); - - fprintf(stderr, "ERROR: found existing kernel " - "instance with the same instance id (%d)\n", - rtapi_instance); - - fprintf(stderr,"kernel modules loaded: %s%s%s\n", - shmdrv_loaded ? "shmdrv " : "", - rtapi_loaded ? "rtapi " : "", - hal_loaded ? "hal_lib " : ""); - - if (msgd_pid > 0) - FAIL_NULL(EEXIST, - "the msgd process msgd:%d is " - "already running, pid: %d\n", - rtapi_instance, msgd_pid); - else - FAIL_NULL(ENOENT, - "msgd:%d not running!\n", - rtapi_instance); - } - // running userthreads instance? pid_t app_pid = pid_of("rtapi:%d", rtapi_instance); @@ -263,45 +231,38 @@ static global_data_t *create_global_segment(const size_t global_size) rtapi_instance); // TBD: might check for other user HAL processes still - // around. This might work with fuser on the HAL segment - // but might be tricky wit shmdrv. + // around. This might work with fuser on the HAL segment. } // leftover shared memory segments were around, but no using // entities (user process or kernel modules). // Remove and keep going: - if (shmdrv_loaded) { - // since neiter rtapi.ko nor hal_lib.ko is loaded - // cause a garbage collect in shmdrv - shmdrv_gc(); - } else { - // Posix shm case. - char segment_name[LINELEN]; - - if (hal_exists) { - sprintf(segment_name, SHM_FMT, rtapi_instance, halkey); - fprintf(stderr,"warning: removing unused HAL shm segment %s\n", - segment_name); - if (shm_unlink(segment_name)) - perror(segment_name); - } - if (rtapi_exists) { - sprintf(segment_name, SHM_FMT, rtapi_instance, rtapikey); - fprintf(stderr,"warning: removing unused RTAPI" - " shm segment %s\n", - segment_name); - if (shm_unlink(segment_name)) - perror(segment_name); - } - if (global_exists) { - sprintf(segment_name, SHM_FMT, rtapi_instance, globalkey); - fprintf(stderr,"warning: removing unused global" - " shm segment %s\n", - segment_name); - if (shm_unlink(segment_name)) - perror(segment_name); - } - } + // Posix shm case. + char segment_name[LINELEN]; + + if (hal_exists) { + sprintf(segment_name, SHM_FMT, rtapi_instance, halkey); + fprintf(stderr,"warning: removing unused HAL shm segment %s\n", + segment_name); + if (shm_unlink(segment_name)) + perror(segment_name); + } + if (rtapi_exists) { + sprintf(segment_name, SHM_FMT, rtapi_instance, rtapikey); + fprintf(stderr,"warning: removing unused RTAPI" + " shm segment %s\n", + segment_name); + if (shm_unlink(segment_name)) + perror(segment_name); + } + if (global_exists) { + sprintf(segment_name, SHM_FMT, rtapi_instance, globalkey); + fprintf(stderr,"warning: removing unused global" + " shm segment %s\n", + segment_name); + if (shm_unlink(segment_name)) + perror(segment_name); + } } // now try again: @@ -351,7 +312,6 @@ static void check_memlock_limit(const char *where) static int init_global_data(global_data_t * data, int actual_global_size, - int flavor, int instance_id, int hal_size, int rt_level, @@ -370,13 +330,11 @@ static int init_global_data(global_data_t * data, rtapi_mutex_try(&(data->mutex)); // lock the global data segment - if (flavor != RTAPI_POSIX_ID) { - if (mlock(data, sizeof(global_data_t))) { - const char *errmsg = strerror(errno); - syslog_async(LOG_ERR, "mlock(global) failed: %d '%s'\n", - errno, errmsg); - check_memlock_limit(errmsg); - } + if (mlock(data, sizeof(global_data_t))) { + const char *errmsg = strerror(errno); + syslog_async(LOG_ERR, "mlock(global) failed: %d '%s'\n", + errno, errmsg); + check_memlock_limit(errmsg); } // report progress data->magic = GLOBAL_INITIALIZING; @@ -394,9 +352,6 @@ static int init_global_data(global_data_t * data, // uthreads use arbitrary ints since those dont use fixed-size arrays data->next_handle = RTAPI_MAX_MODULES + 1; - // tell the others what we determined as the proper flavor - data->rtapi_thread_flavor = flavor; - // record HAL parameters for later data->hal_size = hal_size; data->hal_descriptor_alignment = hal_descriptor_alignment; @@ -415,21 +370,21 @@ static int init_global_data(global_data_t * data, } // init the global heap - _rtapi_heap_init(&data->heap, "global heap"); + rtapi_heap_init(&data->heap, "global heap"); // allocate everything from global->arena to end of egment for global heap size_t global_heap_size = data->global_segment_size - offsetof(global_data_t, arena); DPRINTF("global_heap_size=%zu\n", global_heap_size); - _rtapi_heap_addmem(&data->heap, data->arena, global_heap_size); - _rtapi_heap_setflags(&data->heap, global_heap_flags); + rtapi_heap_addmem(&data->heap, data->arena, global_heap_size); + rtapi_heap_setflags(&data->heap, global_heap_flags); // done with heap // Allocate the message ring buffer from the global heap: size_t rsize = ring_memsize(RINGTYPE_RECORD, message_ring_size, 0); DPRINTF("rsize=%zu message_ring_size=%zu\n", rsize, message_ring_size); - ringheader_t *mring = ( ringheader_t *) _rtapi_calloc(&data->heap, rsize, 1); + ringheader_t *mring = ( ringheader_t *) rtapi_calloc(&data->heap, rsize, 1); if (mring == NULL) FAIL_RC(ENOMEM, "failed to allocate message ring size=%zu\n", rsize); @@ -452,46 +407,6 @@ static int init_global_data(global_data_t * data, return retval; } -// determine if we can run this flavor on the current kernel -static int flavor_and_kernel_compatible(flavor_ptr f) -{ - int retval = 1; - - if (f->flavor_id == RTAPI_POSIX_ID) - return 1; // no prerequisites - - if (kernel_is_xenomai()) { - if (f->flavor_id == RTAPI_RT_PREEMPT_ID) { - fprintf(stderr, - "MSGD:%d Warning: starting %s RTAPI on a Xenomai kernel\n", - rtapi_instance, f->name); - return 1; - } - if ((f->flavor_id != RTAPI_XENOMAI_ID) && - (f->flavor_id != RTAPI_XENOMAI_KERNEL_ID)) { - fprintf(stderr, - "MSGD:%d ERROR: trying to start %s RTAPI on a Xenomai kernel\n", - rtapi_instance, f->name); - return 0; - } - } - - if (kernel_is_rtai() && - (f->flavor_id != RTAPI_RTAI_KERNEL_ID)) { - fprintf(stderr, "MSGD:%d ERROR: trying to start %s RTAPI on an RTAI kernel\n", - rtapi_instance, f->name); - return 0; - } - - if (kernel_is_rtpreempt() && - (f->flavor_id != RTAPI_RT_PREEMPT_ID)) { - fprintf(stderr, "MSGD:%d ERROR: trying to start %s RTAPI on an RT PREEMPT kernel\n", - rtapi_instance, f->name); - return 0; - } - return retval; -} - // actions common to sigaction and signalfd() static void start_shutdown(int signal) { @@ -741,14 +656,11 @@ static struct option long_options[] = { { "instance", required_argument, 0, 'I'}, { "instance_name", required_argument, 0, 'i'}, { "ini", required_argument, 0, 'M'}, // default: getenv(INI_FILE_NAME) - { "flavor", required_argument, 0, 'f'}, { "halsize", required_argument, 0, 'H'}, { "halstacksize", required_argument, 0, 'T'}, - { "shmdrv", no_argument, 0, 'S'}, { "port", required_argument, NULL, 'p' }, { "svcuuid", required_argument, 0, 'R'}, { "interfaces", required_argument, 0, 'n'}, - { "shmdrv_opts", required_argument, 0, 'o'}, { "nosighdlr", no_argument, 0, 'G'}, { "heapdebug", no_argument, 0, 'P'}, { "debug", required_argument, 0, 'd'}, @@ -815,17 +727,6 @@ int main(int argc, char **argv) case 'M': inifile = strdup(optarg); break; - case 'f': - if ((flavor = flavor_byname(optarg)) == NULL) { - fprintf(stderr, "no such flavor: '%s' -- valid flavors are:\n", optarg); - flavor_ptr f = flavors; - while (f->name) { - fprintf(stderr, "\t%s\n", f->name); - f++; - } - exit(1); - } - break; case 'u': usr_msglevel = atoi(optarg); break; @@ -838,12 +739,6 @@ int main(int argc, char **argv) case 'H': halsize = atoi(optarg); break; - case 'S': - use_shmdrv++; - break; - case 'o': - shmdrv_opts = strdup(optarg); - break; case 'P': hal_heap_flags |= (RTAPIHEAP_TRACE_MALLOC|RTAPIHEAP_TRACE_FREE); global_heap_flags |= (RTAPIHEAP_TRACE_MALLOC|RTAPIHEAP_TRACE_FREE); @@ -886,66 +781,6 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if (flavor == NULL) - flavor = default_flavor(); - - if (flavor == NULL) { - fprintf(stderr, "%s: FATAL - failed to detect thread flavor\n", progname); - exit(EXIT_FAILURE); - } - - // can we actually run what's being suggested? - if (!flavor_and_kernel_compatible(flavor)) { - fprintf(stderr, "%s: FATAL - cant run the %s flavor on this kernel\n", - progname, flavor->name); - exit(EXIT_FAILURE); - } - - // catch installation error: user not in xenomai group - if (flavor->flavor_id == RTAPI_XENOMAI_ID) { - int retval = user_in_xenomai_group(); - - switch (retval) { - case 1: // yes - break; - case 0: - fprintf(stderr, "this user is not member of group xenomai\n"); - fprintf(stderr, "please 'sudo adduser xenomai'," - " logout and login again\n"); - exit(EXIT_FAILURE); - - default: - fprintf(stderr, "cannot determine if this user " - "is a member of group xenomai: %s\n", - strerror(-retval)); - exit(EXIT_FAILURE); - } - } - - // do we need the shmdrv module? - if (((flavor->flags & FLAVOR_KERNEL_BUILD) || - use_shmdrv) && - !shmdrv_available()) { - - if (shmdrv_opts == NULL) - shmdrv_opts = getenv("SHMDRV_OPTS"); - if (shmdrv_opts == NULL) - shmdrv_opts = ""; - - if (run_module_helper("insert shmdrv %s",shmdrv_opts)) { - fprintf(stderr, "%s: cant insert shmdrv module - needed by %s\n", - progname, use_shmdrv ? "--shmdrv" : flavor->name); - exit(EXIT_FAILURE); - } - - shm_common_init(); - if (!shmdrv_available()) { - fprintf(stderr, "%s: BUG: shmdrv module not detected\n", - progname); - exit(EXIT_FAILURE); - } - } - // the global segment every entity in HAL/RTAPI land attaches to if ((global_data = create_global_segment(global_segment_size)) == NULL) { // must be a new shm segment @@ -1013,7 +848,6 @@ int main(int argc, char **argv) // gets initialized - no reinitialization from elsewhere if (init_global_data(global_data, actual_global_size, - flavor->flavor_id, rtapi_instance, halsize, rt_msglevel, @@ -1030,14 +864,12 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } else { syslog_async(LOG_INFO, - "startup pid=%d flavor=%s " - "rtlevel=%d usrlevel=%d halsize=%d shm=%s cc=%s %s version=%s", + "startup pid=%d " + "rtlevel=%d usrlevel=%d halsize=%d cc=%s %s version=%s", getpid(), - flavor->name, global_data->rt_msg_level, global_data->user_msg_level, global_data->hal_size, - shmdrv_loaded ? "shmdrv" : "Posix", #ifdef __clang__ "clang", __clang_version__, #endif diff --git a/src/rtapi/rtapi_pci.c b/src/rtapi/rtapi_pci.c index 4a8df67df8..9d499f0cf8 100644 --- a/src/rtapi/rtapi_pci.c +++ b/src/rtapi/rtapi_pci.c @@ -1,10 +1,10 @@ /******************************************************************** * Description: rtapi_pci.c -* This file, 'rtapi_pci.c', implements the -* usermode PCI functions +* This file, 'rtapi_pci.c', implements the +* usermode PCI functions * * -* Copyright (C) 2009 - 2013 Michael Büsch , +* Copyright (C) 2009 - 2013 Michael Büsch , * Charles Steinkuehler * John Morris * Michael Haberler @@ -29,7 +29,6 @@ #endif #include "config.h" -#if defined(USERMODE_PCI) && defined(BUILD_SYS_USER_DSO) #include #include /* vprintf() */ @@ -362,7 +361,7 @@ void * rtapi_pci_ioremap(struct rtapi_pcidev *dev, int bar, size_t size) return NULL; } -// rtapi_print_msg(RTAPI_MSG_ERR, "%i: %lx.%lx %lx.%lx\n", i, +// rtapi_print_msg(RTAPI_MSG_ERR, "%i: %lx.%lx %lx.%lx\n", i, // *((unsigned long *) (mmio + 0xff0)), // *((unsigned long *) (mmio + 0xff4)), // *((unsigned long *) (mmio + 0xff8)), @@ -486,8 +485,8 @@ int pci_register_driver(struct pci_driver *driver) } for (i=0; driver->id_table[i].vendor != 0; i++) { - snprintf(buf, sizeof(buf), "%04X:%04X", - driver->id_table[i].vendor, + snprintf(buf, sizeof(buf), "%04X:%04X", + driver->id_table[i].vendor, driver->id_table[i].device); err = udev_enumerate_add_match_property(enumerate, "PCI_ID", buf); @@ -668,7 +667,7 @@ int pci_enable_device(struct pci_dev *dev) } fprintf(stream, "1"); fclose(stream); - + /* Open the resource file... */ snprintf(path, sizeof(path), "%s/resource", dev->sys_path); stream = fopen(path, "r"); @@ -678,7 +677,7 @@ int pci_enable_device(struct pci_dev *dev) path, strerror(errno)); return -1; } - + /* ...and read in the data */ for (i=0; i < 6; i++) { r=fscanf(stream, "%p %p %lx", @@ -743,5 +742,3 @@ EXPORT_SYMBOL(pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); EXPORT_SYMBOL(pci_ioremap_bar); - -#endif // USERMODE_PCI diff --git a/src/rtapi/rtapi_pci.h b/src/rtapi/rtapi_pci.h index 9590058203..39438016cd 100644 --- a/src/rtapi/rtapi_pci.h +++ b/src/rtapi/rtapi_pci.h @@ -1,7 +1,7 @@ /******************************************************************** * Description: rtapi_pci.h -* This file, 'rtapi_pci.h', exports the -* usermode PCI functions +* This file, 'rtapi_pci.h', exports the +* usermode PCI functions * * * Copyright (C) 2012 - 2013 Charles Steinkuehler @@ -31,7 +31,6 @@ /*********************************************************************** * PCI DEVICE SUPPORT * ************************************************************************/ -#if defined(BUILD_SYS_USER_DSO) /*---------------------------------------------------------------------** ** Structures and defines that should be pulled in from ** @@ -61,8 +60,8 @@ struct pci_dev { unsigned short subsystem_vendor; unsigned short subsystem_device; unsigned int t_class; /* 3 bytes: (base,sub,prog-if) */ - struct pci_resource - resource[6]; /* Device BARs */ + struct pci_resource + resource[6]; /* Device BARs */ void *driver_data; /* Data private to the driver */ }; @@ -148,76 +147,40 @@ void __iomem * rtapi_pci_ioremap(struct rtapi_pcidev *dev, int bar, size_t size) extern void rtapi_pci_iounmap(struct rtapi_pcidev *dev, void __iomem *mmio); -#endif /* BUILD_SYS_USER_DSO */ - static inline __u8 rtapi_pci_readb(const void __iomem *mmio) { -#ifdef BUILD_SYS_USER_DSO return *((volatile const __u8 __iomem *)mmio); -#else - return readb(mmio); -#endif } static inline __u16 rtapi_pci_readw(const void __iomem *mmio) { -#ifdef BUILD_SYS_USER_DSO return *((volatile const __u16 __iomem *)mmio); -#else - return readw(mmio); -#endif } static inline __u32 rtapi_pci_readl(const void __iomem *mmio) { -#ifdef BUILD_SYS_USER_DSO return *((volatile const __u32 __iomem *)mmio); -#else - return readl(mmio); -#endif } static inline void rtapi_pci_writeb(void __iomem *mmio, unsigned int offset, __u8 value) { -#ifdef BUILD_SYS_USER_DSO *((volatile __u8 __iomem *)mmio) = value; -#else - writeb(value, mmio); -#endif } static inline void rtapi_pci_writew(void __iomem *mmio, unsigned int offset, __u16 value) { -#ifdef BUILD_SYS_USER_DSO *((volatile __u16 __iomem *)mmio) = value; -#else - writew(value, mmio); -#endif } static inline void rtapi_pci_writel(void __iomem *mmio, unsigned int offset, __u32 value) { -#ifdef BUILD_SYS_USER_DSO *((volatile __u32 __iomem *)mmio) = value; -#else - writel(value, mmio); -#endif -} - -/* Some kernels don't have pci_ioremap_bar */ -#ifndef BUILD_SYS_USER_DSO -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) -void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) -{ - return ioremap_nocache(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)); } -#endif -#endif #endif // RTAPI_PCI_H diff --git a/src/rtapi/rtapi_proc.h b/src/rtapi/rtapi_proc.h deleted file mode 100644 index 9730c87900..0000000000 --- a/src/rtapi/rtapi_proc.h +++ /dev/null @@ -1,366 +0,0 @@ -#ifndef RTAPI_PROC_H -#define RTAPI_PROC_H - -/** RTAPI is a library providing a uniform API for several real time - operating systems. As of ver 2.0, RTLinux and RTAI are supported. -*/ -/******************************************************************** -* Description: rtai_proc.h -* This file, 'rtapi_proc.h', contains code that -* implements several /proc filesystem entries that can -* display the status of the RTAPI. -* -* Author: John Kasunich, Paul Corner -* License: LGPL Version 2 -* -* Copyright (c) 2004 All rights reserved. -* -* Last change: -********************************************************************/ - -/** This file, 'rtapi_proc.h', contains code that implements several - /proc filesystem entries that can display the status of the RTAPI. - This code is common to both the RTAI and RTLinux implementations, - and most likely to any other implementations under Linux. This - data is INTERNAL to the RTAPI implementation, and should not be - included in any application modules. This data also applies - only to kernel modules, and should be included only in the - real-time portion of the implementation. Items that are common - to both the realtime and user-space portions of the implementation - are in rtapi_common.h. -*/ - -/** Copyright (C) 2003 John Kasunich - - Copyright (C) 2003 Paul Corner - - - This library is based on version 1.0, which was released into - the public domain by its author, Fred Proctor. Thanks Fred! -*/ - -/* This library is free software; you can redistribute it and/or - modify it under the terms of version 2.1 of the GNU Lesser General - Public License as published by the Free Software Foundation. - This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA -*/ - -/** THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR - ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE - TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of - harming persons must have provisions for completely removing power - from all motors, etc, before persons enter any danger area. All - machinery must be designed to comply with local and national safety - codes, and the authors of this software can not, and do not, take - any responsibility for such compliance. -*/ - -/** This code was written as part of the EMC HAL project. For more - information, go to www.linuxcnc.org. -*/ - -/* Internal function for the proc_fs system. */ - -/* The proc file system is available in 2.2 and 2.4 kernels with - minor differences - The 2.4 kernels have a usefull helper function - for creating the proc_fs entries. - It is unlikely that the following implimentaion will work on a 2.0 - series kernel.. -*/ -#ifdef CONFIG_PROC_FS - -#include /* isdigit */ -#include "procfs_macros.h" /* macros for read functions */ -#include /* copy_from_user() */ - -struct proc_dir_entry *rtapi_dir = 0; /* /proc/rtapi directory */ -static struct proc_dir_entry *status_file = 0; /* /proc/rtapi/status */ -static struct proc_dir_entry *modules_file = 0; /* /proc/rtapi/modules */ -static struct proc_dir_entry *tasks_file = 0; /* /proc/rtapi/tasks */ -static struct proc_dir_entry *shmem_file = 0; /* /proc/rtapi/shmem */ -static struct proc_dir_entry *debug_file = 0; /* /proc/rtapi/debug */ -static struct proc_dir_entry *instance_file = 0; /* /proc/rtapi/instance */ - -/** The following are callback functions for the /proc filesystem - When someone reads a /proc file, the appropriate function below - is called, and it must generate output for the reader on the fly. - These functions use the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT - macros to make sure the RTAPI module is not removed while servicing - a /proc request. -*/ - - -// thread flavors may provide a function to make extra data available -// in procfs -#ifdef HAVE_RTAPI_READ_STATUS_HOOK -void rtapi_proc_read_status_hook(char *page, char **start, off_t off, - int count, int *eof, void *data); -#endif - -PROC_READ_FUN(proc_read_status) -{ - PROC_PRINT_VARS; - PROC_PRINT("******* RTAPI STATUS ********\n"); - PROC_PRINT(" RT Modules = %i\n", rtapi_data->rt_module_count); - PROC_PRINT(" UL Modules = %i\n", rtapi_data->ul_module_count); - PROC_PRINT(" Tasks = %i/%i\n", rtapi_data->task_count, - RTAPI_MAX_TASKS); - PROC_PRINT("Shared memory = %i/%i\n", rtapi_data->shmem_count, - RTAPI_MAX_SHMEMS); - PROC_PRINT("default RT task CPU = %i\n", rtapi_data->rt_cpu); - if (rtapi_data->timer_running) { - PROC_PRINT(" Timer status = Running\n"); - PROC_PRINT(" Timer period = %li nSec\n", rtapi_data->timer_period); - } else { - PROC_PRINT(" Timer status = Stopped\n"); - } - PROC_PRINT("\n"); - PROC_PRINT_DONE; -} -PROC_READ_OPEN_OPS(status_file_fops, proc_read_status); - -PROC_READ_FUN(proc_read_modules) -{ - int n; - char *state_str; - - PROC_PRINT_VARS; - PROC_PRINT("******* RTAPI MODULES *******\n"); - PROC_PRINT("ID Type Name\n"); - for (n = 1; n <= RTAPI_MAX_MODULES; n++) { - if (module_array[n].state != NO_MODULE) { - switch (module_array[n].state) { - case REALTIME: - state_str = "RT "; - break; - case USERSPACE: - state_str = "USER"; - break; - default: - state_str = "????"; - break; - } - PROC_PRINT("%02d %s %s\n", n, state_str, module_array[n].name); - } - } - PROC_PRINT("\n"); - PROC_PRINT_DONE; -} -PROC_READ_OPEN_OPS(modules_file_fops, proc_read_modules); - -PROC_READ_FUN(proc_read_tasks) -{ - int n; - char *state_str; - - PROC_PRINT_VARS; - PROC_PRINT("******** RTAPI TASKS ********\n"); - PROC_PRINT("ID CPU Own Prio State Code\n"); - for (n = 1; n <= RTAPI_MAX_TASKS; n++) { - if (task_array[n].state != EMPTY) { - switch (task_array[n].state) { - case PAUSED: - state_str = "PAUSED "; - break; - case PERIODIC: - state_str = "PERIODIC"; - break; - case FREERUN: - state_str = "FREE RUN"; - break; - case ENDED: - state_str = "ENDED "; - break; - default: - state_str = "UNKNOWN "; - break; - } - PROC_PRINT("%02d %2d %02d %3d %s %p\n", - n, - task_array[n].cpu, - task_array[n].owner, - task_array[n].prio, - state_str, - task_array[n].taskcode); - } - } - PROC_PRINT("\n"); - PROC_PRINT_DONE; -} -PROC_READ_OPEN_OPS(tasks_file_fops, proc_read_tasks); - -PROC_READ_FUN(proc_read_shmem) -{ - int n; - - PROC_PRINT_VARS; - PROC_PRINT("**** RTAPI SHARED MEMORY ****\n"); - PROC_PRINT("ID Users Key Size\n"); - PROC_PRINT(" RT/UL \n"); - for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { - if (shmem_array[n].key != 0) { - PROC_PRINT("%02d %2d/%-2d %-10d %-10lu\n", - n, shmem_array[n].rtusers, shmem_array[n].ulusers, - shmem_array[n].key, shmem_array[n].size); - } - } - PROC_PRINT("\n"); - PROC_PRINT_DONE; -} -PROC_READ_OPEN_OPS(shmem_file_fops, proc_read_shmem); - -PROC_READ_FUN(proc_read_debug) -{ - PROC_PRINT_VARS; - PROC_PRINT("******* RTAPI MESSAGES ******\n"); - PROC_PRINT(" Message Level = RT:%i User:%i\n", - global_data->rt_msg_level,global_data->user_msg_level); - PROC_PRINT("RT ERROR messages = %s\n", - global_data->rt_msg_level >= RTAPI_MSG_ERR ? "ON" : "OFF"); - PROC_PRINT("WARNING messages = %s\n", - global_data->rt_msg_level >= RTAPI_MSG_WARN ? "ON" : "OFF"); - PROC_PRINT(" INFO messages = %s\n", - global_data->rt_msg_level >= RTAPI_MSG_INFO ? "ON" : "OFF"); - PROC_PRINT(" DEBUG messages = %s\n", - global_data->rt_msg_level >= RTAPI_MSG_DBG ? "ON" : "OFF"); - - PROC_PRINT("User ERROR messages = %s\n", - global_data->user_msg_level >= RTAPI_MSG_ERR ? "ON" : "OFF"); - PROC_PRINT("WARNING messages = %s\n", - global_data->user_msg_level >= RTAPI_MSG_WARN ? "ON" : "OFF"); - PROC_PRINT(" INFO messages = %s\n", - global_data->user_msg_level >= RTAPI_MSG_INFO ? "ON" : "OFF"); - PROC_PRINT(" DEBUG messages = %s\n", - global_data->user_msg_level >= RTAPI_MSG_DBG ? "ON" : "OFF"); - PROC_PRINT("\n"); - PROC_PRINT_DONE; -} - -static ssize_t proc_write_debug(struct file *file, - const char __user *buffer, size_t count, - loff_t *data) -{ - char c; - int msg_level; - - /* copy 1 byte from user space */ - if (copy_from_user(&c, buffer, 1)) { - return -1; - } - /* check it is a digit */ - if (isdigit(c)) { - /* convert to a number */ - msg_level = (int) (c - '0'); - /* cap the value if it is outside the valid range */ - if (msg_level < RTAPI_MSG_NONE) { - msg_level = RTAPI_MSG_NONE; - } - if (msg_level > RTAPI_MSG_ALL) { - msg_level = RTAPI_MSG_ALL; - } - global_data-> rt_msg_level = msg_level; - } - /* tell whoever called us that we used all the data, even though we - really only used the first byte */ - return count; -} -PROC_READ_WRITE_OPEN_OPS(debug_file_fops, proc_read_debug, proc_write_debug) - -PROC_READ_FUN(proc_read_instance) -{ - PROC_PRINT_VARS; - PROC_PRINT("%i\n", rtapi_instance); - PROC_PRINT_DONE; -} -PROC_READ_OPEN_OPS(instance_file_fops, proc_read_instance); - -/** proc_init() initializes the /proc filesystem entries, - creating the directory and files, and linking them - to the appropriate callback functions. This function - is called from the init_module() function of the - RTAPI implementation. -*/ - -static int proc_init(void) -{ - /* create the rtapi directory "/proc/rtapi" */ - rtapi_dir = CREATE_PROC_ENTRY("rtapi",S_IFDIR,NULL,NULL); - if (rtapi_dir == 0) - return -1; - - /* create read only file "/proc/rtapi/status" */ - status_file = \ - CREATE_PROC_ENTRY("status",S_IRUGO,rtapi_dir,&status_file_fops); - - /* create read only file "/proc/rtapi/modules" */ - modules_file = \ - CREATE_PROC_ENTRY("modules",S_IRUGO,rtapi_dir,&modules_file_fops); - - /* create read only file "/proc/rtapi/tasks" */ - tasks_file = \ - CREATE_PROC_ENTRY("tasks",S_IRUGO,rtapi_dir,&tasks_file_fops); - - /* create read only file "/proc/rtapi/shmem" */ - shmem_file = \ - CREATE_PROC_ENTRY("shmem",S_IRUGO,rtapi_dir,&shmem_file_fops); - - /* create read/write file "/proc/rtapi/debug" */ - debug_file = \ - CREATE_PROC_ENTRY("debug",S_IRUGO|S_IWUGO,rtapi_dir,&debug_file_fops); - - /* create read only file "/proc/rtapi/instance" */ - instance_file = \ - CREATE_PROC_ENTRY("instance",S_IRUGO,rtapi_dir,&instance_file_fops); - - return 0; -} - -/** proc_clean() is called from the cleanup_module function of - of the RTAPI implementation. It removes the rtapi entries - from the /proc filesystem. Failing to remove a /proc - entry before the module is removed may cause kernel panics. -*/ - -static void proc_clean(void) -{ - /* remove /proc entries, only if they exist */ - if (rtapi_dir != NULL) { - if (status_file != NULL) { - remove_proc_entry("status", rtapi_dir); - status_file = NULL; - } - if (modules_file != NULL) { - remove_proc_entry("modules", rtapi_dir); - modules_file = NULL; - } - if (tasks_file != NULL) { - remove_proc_entry("tasks", rtapi_dir); - tasks_file = NULL; - } - if (shmem_file != NULL) { - remove_proc_entry("shmem", rtapi_dir); - shmem_file = NULL; - } - if (debug_file != NULL) { - remove_proc_entry("debug", rtapi_dir); - debug_file = NULL; - } - if (instance_file != NULL) { - remove_proc_entry("instance", rtapi_dir); - instance_file = NULL; - } - remove_proc_entry("rtapi", NULL); - } -} - -EXPORT_SYMBOL(rtapi_dir); - -#endif /* CONFIG_PROC_FS */ -#endif /* RTAPI_PROC_H */ diff --git a/src/rtapi/rtapi_shmem.c b/src/rtapi/rtapi_shmem.c index 349beee125..f480c1efea 100644 --- a/src/rtapi/rtapi_shmem.c +++ b/src/rtapi/rtapi_shmem.c @@ -6,17 +6,17 @@ * rtapi.h for more info. * * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -27,7 +27,6 @@ #include "rtapi_common.h" #include "shmdrv.h" -#ifdef BUILD_SYS_USER_DSO #include #include #include @@ -36,44 +35,15 @@ #include /* rand_r() */ #include /* getuid(), getgid(), sysconf(), ssize_t, _SC_PAGESIZE */ - -#else /* BUILD_SYS_KBUILD */ -# ifdef ULAPI -# include // perror -# include -# include -# include "rtapi/shmdrv/shmdrv.h" -# endif -#endif +#include // memset() #define SHM_PERMISSIONS 0666 -#ifdef BUILD_SYS_KBUILD -# ifdef RTAPI -# define MODULE_STATE REALTIME -# define OUR_API "RTAPI" -# else -# define MODULE_STATE USERSPACE -# define OUR_API "ULAPI" -# endif -#endif - -#if defined(BUILD_SYS_KBUILD) && defined(ULAPI) -static void check_memlock_limit(const char *where); -#endif - - -#ifdef BUILD_SYS_KBUILD -void *shmem_addr_array[RTAPI_MAX_SHMEMS + 1]; -#endif - - -#ifdef BUILD_SYS_USER_DSO /*********************************************************************** * USERLAND THREADS * ************************************************************************/ -int _rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned long int size) { +int rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned long int size) { shmem_data *shmem; int i, ret, actual_size; int is_new = 0; @@ -151,7 +121,7 @@ int _rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned lon return i; } -int _rtapi_shmem_getptr_inst(int handle, int instance, void **ptr, unsigned long *size) { +int rtapi_shmem_getptr_inst(int handle, int instance, void **ptr, unsigned long *size) { shmem_data *shmem; if (handle < 1 || handle >= RTAPI_MAX_SHMEMS) return -EINVAL; @@ -169,7 +139,7 @@ int _rtapi_shmem_getptr_inst(int handle, int instance, void **ptr, unsigned long return 0; } -int _rtapi_shmem_delete_inst(int handle, int instance, int module_id) { +int rtapi_shmem_delete_inst(int handle, int instance, int module_id) { shmem_data *shmem; int retval = 0; @@ -211,350 +181,31 @@ int _rtapi_shmem_delete_inst(int handle, int instance, int module_id) { return retval; } -int _rtapi_shmem_exists(int userkey) { +int rtapi_shmem_exists(int userkey) { return shm_common_exists(userkey); } -#else /* BUILD_SYS_KBUILD */ -/*********************************************************************** -* KERNEL THREADS * -************************************************************************/ - -int _rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned long int size) { - int n, retval; - int shmem_id; - shmem_data *shmem; - struct shm_status sm; - - int key = OS_KEY(userkey, instance); - - /* key must be non-zero, and also cannot match the key that RTAPI uses */ - if ((key == 0) || (key == OS_KEY(RTAPI_KEY, instance))) { - rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad shmem key: 0x%x\n", - key); - return -EINVAL; - } - /* get the mutex */ - rtapi_mutex_get(&(rtapi_data->mutex)); - /* validate module_id */ - if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad module ID: %d\n", - module_id); - return -EINVAL; - } - if (module_array[module_id].state != MODULE_STATE) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: ERROR: not a " OUR_API " module ID: %d\n", - module_id); - rtapi_mutex_give(&(rtapi_data->mutex)); - return -EINVAL; - } - - /* check if a block is already open for this key */ - for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { - if (shmem_array[n].key == key) { - /* found a match */ - shmem_id = n; - shmem = &(shmem_array[n]); - /* is it big enough? */ - if (shmem->size < size) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: ERROR: shmem size mismatch: request: %ld actual: %ld\n", - size, shmem->size); - return -EINVAL; - } - /* is this module already using it? */ - // redefine size == 0 to mean 'attach only, dont create' - if (rtapi_test_bit(module_id, shmem->bitmap) && (size > 0)) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_WARN, - "RTAPI: Warning: shmem %d key 0x%x already mapped\n", - n, key); - return -EEXIST; - } - /* yes, has it been mapped into kernel space? */ -#ifdef RTAPI - if (shmem->rtusers == 0) { -#endif - /* no, map it and save the address */ - sm.key = key; - sm.size = size; - sm.flags = 0; -#ifdef ULAPI - sm.driver_fd = shmdrv_driver_fd(); -#endif - retval = shmdrv_attach(&sm, &shmem_addr_array[shmem_id]); - if (retval < 0) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, - "shmdrv attached failed key=0x%x size=%ld\n", key, size); - return retval; - } - if (shmem_addr_array[shmem_id] == NULL) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: ERROR: failed to map shmem %d\n", shmem_id); - rtapi_mutex_give(&(rtapi_data->mutex)); -#ifdef ULAPI - check_memlock_limit("failed to map shmem"); -#endif - return -ENOMEM; - } -#ifdef RTAPI - } -#endif - - // increase refcount only if not already used - if (!rtapi_test_bit(module_id, shmem->bitmap)) { -#ifdef ULAPI - shmem->ulusers++; -#else /* RTAPI */ - shmem->rtusers++; -#endif /* RTAPI */ - } - /* update usage data */ - rtapi_set_bit(module_id, shmem->bitmap); - - /* announce another user for this shmem */ - rtapi_print_msg(RTAPI_MSG_DBG, - "RTAPI: shmem %02d 0x%x opened by module %02d\n", - shmem_id, key, module_id); - /* done */ - rtapi_mutex_give(&(rtapi_data->mutex)); - return shmem_id; - } - } - /* find empty spot in shmem array */ - n = 1; - while ((n <= RTAPI_MAX_SHMEMS) && (shmem_array[n].key != 0)) { - rtapi_print_msg(RTAPI_MSG_DBG, OUR_API ": shmem %d occupied \n",n); - n++; - } - if (n > RTAPI_MAX_SHMEMS) { - /* no room */ - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: reached shmem limit %d\n", - n); - return -EMFILE; - } - /* we have space for the block data */ - rtapi_print_msg(RTAPI_MSG_DBG, OUR_API ": using new shmem %d key 0x%x\n", - n,key); - shmem_id = n; - shmem = &(shmem_array[n]); - - /* get shared memory block from OS and save its address */ - sm.key = key; - sm.size = size; - sm.flags = 0; -#ifdef ULAPI - sm.driver_fd = shmdrv_driver_fd(); -#endif - retval = shmdrv_create(&sm); - if (retval < 0) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR,"shmdrv create failed key=0x%x size=%ld\n", key, size); - return retval; - } - retval = shmdrv_attach(&sm, &shmem_addr_array[shmem_id]); - if (retval < 0) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR,"shmdrv attached failed key=0x%x size=%ld\n", key, size); - return retval; - } - if (shmem_addr_array[shmem_id] == NULL) { - rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: ERROR: could not create shmem %d key 0x%x\n", - n, key); - return -ENOMEM; - } - /* the block has been created, update data */ - rtapi_set_bit(module_id, shmem->bitmap); - shmem->key = key; -#ifdef RTAPI - shmem->rtusers = 1; - shmem->ulusers = 0; -#else /* ULAPI */ - shmem->rtusers = 0; - shmem->ulusers = 1; -#endif /* ULAPI */ - shmem->size = size; - shmem->magic = SHMEM_MAGIC; - shmem->instance = instance; - rtapi_data->shmem_count++; - /* zero the first word of the shmem area */ - *((long int *) (shmem_addr_array[shmem_id])) = 0; - /* announce the birth of a brand new baby shmem */ - rtapi_print_msg(RTAPI_MSG_DBG, - "RTAPI: shmem %02d created by module %02d key: 0x%x size: %lu\n", - shmem_id, module_id, key, size); +// implement rtapi_shmem_* calls in terms of rtapi_shmem_*_inst() - /* and return the ID to the proud parent */ - rtapi_mutex_give(&(rtapi_data->mutex)); - return shmem_id; +int rtapi_shmem_new(int userkey, int module_id, unsigned long int size) { + return rtapi_shmem_new_inst(userkey, rtapi_instance, module_id, size); } -#ifdef ULAPI -static void check_memlock_limit(const char *where) { - static int checked=0; - struct rlimit lim; - int result; - if(checked) return; - checked=1; - - result = getrlimit(RLIMIT_MEMLOCK, &lim); - if(result < 0) { perror("getrlimit"); return; } - if(lim.rlim_cur == (rlim_t)-1) return; // unlimited - if(lim.rlim_cur >= RLIMIT_MEMLOCK_RECOMMENDED) return; // limit is at least recommended - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: Locked memory limit is %luKiB, recommended at least %luKiB.\n" - "This can cause the error '%s'.\n" - "For more information, see\n" - "\thttp://wiki.linuxcnc.org/cgi-bin/emcinfo.pl?LockedMemory\n", - (unsigned long)lim.rlim_cur/1024, RLIMIT_MEMLOCK_RECOMMENDED/1024, where); - return; +int rtapi_shmem_getptr(int handle, void **ptr, unsigned long int *size) { + return rtapi_shmem_getptr_inst(handle, rtapi_instance, ptr, size); } -#endif /* ULAPI */ +int rtapi_shmem_delete(int handle, int module_id) { + return rtapi_shmem_delete_inst(handle, rtapi_instance, module_id); +} -int _rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id) { - shmem_data *shmem; - int manage_lock, retval; #ifdef RTAPI - struct shm_status sm; +EXPORT_SYMBOL(rtapi_shmem_new_inst); +EXPORT_SYMBOL(rtapi_shmem_getptr_inst); +EXPORT_SYMBOL(rtapi_shmem_delete_inst); +EXPORT_SYMBOL(rtapi_shmem_exists); +EXPORT_SYMBOL(rtapi_shmem_new); +EXPORT_SYMBOL(rtapi_shmem_getptr); +EXPORT_SYMBOL(rtapi_shmem_delete); #endif - - /* validate shmem ID */ - if ((shmem_id < 1) || (shmem_id > RTAPI_MAX_SHMEMS)) { - return -EINVAL; - } - /* point to the shmem's data */ - shmem = &(shmem_array[shmem_id]); - /* is the block valid? */ - if (shmem->key == 0) { - return -EINVAL; - } - /* validate module_id */ - if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { - return -EINVAL; - } - if (module_array[module_id].state != MODULE_STATE) { - return -EINVAL; - } - /* is this module using the block? */ - if (rtapi_test_bit(module_id, shmem->bitmap) == 0) { - return -EINVAL; - } - /* check if we need to manage the mutex */ - manage_lock = (shmem->magic != SHMEM_MAGIC_DEL_LOCKED); - /* if no magic delete lock held is set, get the mutex */ - if (manage_lock) rtapi_mutex_get(&(rtapi_data->mutex)); - /* OK, we're no longer using it */ - rtapi_clear_bit(module_id, shmem->bitmap); -#ifdef ULAPI - shmem->ulusers--; - - if ((shmem->ulusers == 0) && (shmem->rtusers == 0)) { - // shmdrv can detach unused shared memory from userland too - // this will munmap() the segment causing a drop in uattach refcount - // and eventual free by garbage collect in shmdrv - retval = shm_common_detach(shmem->size, shmem_addr_array[shmem_id]); - if (retval) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: shm_common_detach(%02d) failed: %d\n", - rtapi_instance, shmem_id, retval); - } - } - /* unmap the block */ - shmem_addr_array[shmem_id] = NULL; -#else /* RTAPI */ - shmem->rtusers--; -#endif /* RTAPI */ - /* is somebody else still using the block? */ - if ((shmem->ulusers > 0) || (shmem->rtusers > 0)) { - /* yes, we're done for now */ - rtapi_print_msg(RTAPI_MSG_DBG, - "RTAPI: shmem %02d key 0x%x closed by module %02d\n", - shmem_id, shmem->key, module_id); - if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); - return 0; - } - -#ifdef RTAPI - /* no other realtime users, free the shared memory from kernel space */ - shmem_addr_array[shmem_id] = NULL; - shmem->rtusers = 0; - /* are any user processes using the block? */ - if (shmem->ulusers > 0) { - /* yes, we're done for now */ - rtapi_print_msg(RTAPI_MSG_DBG, - "RTAPI: shmem %02d key 0x%x unmapped by module %02d\n", - shmem_id,shmem->key, module_id); - if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); - return 0; - } - - /* no other users at all, this ID is now free */ - sm.key = shmem->key; - sm.size = shmem->size; - sm.flags = 0; - if ((retval = shmdrv_detach(&sm)) < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI:%d ERROR: shmdrv_detach(%x,%d) fail: %d\n", - rtapi_instance, sm.key, sm.size, retval); - } -#endif /* RTAPI */ - - - /* update the data array and usage count */ - shmem->size = 0; - rtapi_data->shmem_count--; - /* release the lock if needed, print a debug message and return */ - if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); - rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d key 0x%x freed by module %02d\n", - shmem_id, shmem->key, module_id); - shmem->key = 0; - return 0; -} - -int _rtapi_shmem_getptr_inst(int shmem_id, int instance, void **ptr, - unsigned long int *size) { - /* validate shmem ID */ - if ((shmem_id < 1) || (shmem_id > RTAPI_MAX_SHMEMS)) { - return -EINVAL; - } - /* is the block mapped? */ - if (shmem_addr_array[shmem_id] == NULL) { - return -ENOENT; - } - /* pass memory address back to caller */ - *ptr = shmem_addr_array[shmem_id]; - return 0; -} - -int _rtapi_shmem_exists(int userkey) { - struct shm_status sm; - sm.key = userkey; - - return !shmdrv_status(&sm); -} - -#endif /* BUILD_SYS_KBUILD */ - - -// implement rtapi_shmem_* calls in terms of _rtapi_shmem_*_inst() - -int _rtapi_shmem_new(int userkey, int module_id, unsigned long int size) { - return _rtapi_shmem_new_inst(userkey, rtapi_instance, module_id, size); -} - -int _rtapi_shmem_getptr(int handle, void **ptr, unsigned long int *size) { - return _rtapi_shmem_getptr_inst(handle, rtapi_instance, ptr, size); -} - -int _rtapi_shmem_delete(int handle, int module_id) { - return _rtapi_shmem_delete_inst(handle, rtapi_instance, module_id); -} diff --git a/src/rtapi/rtapi_string.h b/src/rtapi/rtapi_string.h index 829ec99063..9bc44f0916 100644 --- a/src/rtapi/rtapi_string.h +++ b/src/rtapi/rtapi_string.h @@ -13,28 +13,4 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#ifdef MODULE -/* Suspect only very early kernels are missing the basic string functions. - To be sure, see what has been implemented by looking in linux/string.h - and {linux_src_dir}/lib/string.c */ -#include -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#ifndef __HAVE_ARCH_STRCMP /* This flag will be defined if we do */ -#define __HAVE_ARCH_STRCMP /* have strcmp */ -/* some kernels don't have strcmp */ -static int strcmp(const char *cs, const char *ct) -{ - signed char __res; - while (1) { - if ((__res = *cs - *ct++) != 0 || !*cs++) { - break; - } - } - return __res; -} -#endif /* __HAVE_ARCH_STRCMP */ -#endif /* linux 2.4 */ -#else #include -#endif diff --git a/src/rtapi/rtapi_support.c b/src/rtapi/rtapi_support.c index 512b03dc45..d6551175f9 100644 --- a/src/rtapi/rtapi_support.c +++ b/src/rtapi/rtapi_support.c @@ -10,17 +10,17 @@ * RTAPI starts up * * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -31,24 +31,12 @@ #include "rtapi.h" #include "shmdrv.h" #include "ring.h" -#if defined(BUILD_SYS_USER_DSO) || defined(ULAPI) #include "syslog_async.h" #ifndef SYSLOG_FACILITY #define SYSLOG_FACILITY LOG_LOCAL1 // where all rtapi/ulapi logging goes #endif -#endif #define RTPRINTBUFFERLEN 256 -#ifdef MODULE -#include "rtapi_app.h" - -#include /* va_* */ -#include /* kernel's vsnprintf */ - -#define MSG_ORIGIN MSG_KERNEL - -#else /* user land */ - #include /* libc's vsnprintf() */ #include #include @@ -58,7 +46,6 @@ #else #define MSG_ORIGIN MSG_ULAPI #endif -#endif static int get_msg_level(void); @@ -121,9 +108,8 @@ int vs_ringlogfv(const msg_level_t level, rtapi_mutex_give(&rtapi_message_buffer.header->wmutex); } else { // early startup, global_data & log ring not yet initialized - // depending on context, log the message in an appropriate way: + // log the message to both stderr and syslog -#if defined(BUILD_SYS_USER_DSO) || defined(ULAPI) static int log_opened; if (!log_opened) { log_opened = async_log_open(); @@ -132,17 +118,17 @@ int vs_ringlogfv(const msg_level_t level, log_opened = 1; } } -#ifdef USE_STDERR + if (!strchr(msg.buf, '\n')) strcat(msg.buf,"\n"); fprintf(stderr, -#else + "%d:%s:%d:%s %s", + level, + tag, + pid, + origins[origin & 3], + msg.buf); syslog_async(rtapi2syslog(level), -#endif -#endif -#if defined(RTAPI) && defined(BUILD_SYS_KBUILD) - printk( -#endif "%d:%s:%d:%s %s", level, tag, @@ -157,10 +143,8 @@ void default_rtapi_msg_handler(msg_level_t level, const char *fmt, va_list ap) { static pid_t rtapi_pid; -#if !defined(BUILD_SYS_KBUILD) && !defined(MODULE) if (rtapi_pid == 0) rtapi_pid = getpid(); -#endif vs_ringlogfv(level, rtapi_pid, MSG_ORIGIN, logtag, fmt, ap); } @@ -178,7 +162,7 @@ void rtapi_set_msg_handler(rtapi_msg_handler_t handler) { } // rtapi_get_msg_level and rtapi_set_msg_level moved here -// since they access the global segment +// since they access the global segment // which might not exist during first use // assure we can use message levels before global_data is set up @@ -246,7 +230,7 @@ void rtapi_print(const char *fmt, ...) { void rtapi_print_msg(int level, const char *fmt, ...) { va_list args; - if ((level <= rtapi_get_msg_level()) && + if ((level <= rtapi_get_msg_level()) && (rtapi_get_msg_level() != RTAPI_MSG_NONE)) { va_start(args, fmt); rtapi_msg_handler(level, fmt, args); diff --git a/src/rtapi/rtapi_task.c b/src/rtapi/rtapi_task.c index 0f009b1cf2..e93142109e 100644 --- a/src/rtapi/rtapi_task.c +++ b/src/rtapi/rtapi_task.c @@ -12,17 +12,17 @@ * function. * * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -31,73 +31,50 @@ #include "config.h" // build configuration #include "rtapi.h" // these functions #include "rtapi_common.h" // RTAPI macros and decls - -#ifdef MODULE -#include /* kmalloc() */ -#endif +#include "rtapi_flavor.h" // flavor_* /* These functions are completely different between each userland thread system, so these are defined in rtapi_module.c for kernel threads systems and $THREADS.c for the userland thread systems - int _rtapi_init(const char *modname) - int _rtapi_exit(int id) + int rtapi_init(const char *modname) + int rtapi_exit(int id) */ -#ifdef MODULE -/* resource data unique to kernel space */ -RT_TASK *ostask_array[RTAPI_MAX_TASKS + 1]; -#endif - - /* priority functions */ -/* Some RT systems (well, just RTAI) define lower values as higher - priority */ -#ifdef INVERSE_PRIO -# define PRIO_INCR -- -# define PRIO_DECR ++ -# define PRIO_GT(a,b) (ab) -#else // normal priorities -# define PRIO_INCR ++ -# define PRIO_DECR -- -# define PRIO_GT(a,b) (a>b) -# define PRIO_LT(a,b) (a rtapi_prio_highest()) + return rtapi_prio_highest(); + if (prio < rtapi_prio_lowest()) + return rtapi_prio_lowest(); return prio; } -int _rtapi_prio_next_lower(int prio) { +int rtapi_prio_next_lower(int prio) { /* next lower priority for arg */ - prio PRIO_DECR; + prio--; /* return a valid priority for out of range arg */ - if (PRIO_GT(prio,_rtapi_prio_highest())) - return _rtapi_prio_highest(); - if (PRIO_GT(_rtapi_prio_lowest(),prio)) - return _rtapi_prio_lowest(); + if (prio > rtapi_prio_highest()) + return rtapi_prio_highest(); + if (prio < rtapi_prio_lowest()) + return rtapi_prio_lowest(); return prio; } @@ -106,12 +83,7 @@ int _rtapi_prio_next_lower(int prio) { #ifdef RTAPI /* below functions not available to user programs */ /* task setup and teardown functions */ -#ifdef HAVE_RTAPI_TASK_NEW_HOOK -int _rtapi_task_new_hook(task_data *task, int task_id); -#endif - - -int _rtapi_task_new(const rtapi_task_args_t *args) { +int rtapi_task_new(const rtapi_task_args_t *args) { int task_id; int __attribute__((__unused__)) retval = 0; task_data *task; @@ -119,25 +91,6 @@ int _rtapi_task_new(const rtapi_task_args_t *args) { /* get the mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); -#ifdef MODULE - /* validate owner */ - if ((args->owner < 1) || (args->owner > RTAPI_MAX_MODULES)) { - rtapi_mutex_give(&(rtapi_data->mutex)); - return -EINVAL; - } - if (module_array[args->owner].state != REALTIME) { - rtapi_mutex_give(&(rtapi_data->mutex)); - return -EINVAL; - } - if ((args->flags & (TF_NONRT|TF_NOWAIT)) != 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "task '%s' : nowait/posix flags not supported with kthreads\n", - args->name); - rtapi_mutex_give(&(rtapi_data->mutex)); - return -EINVAL; - } -#endif - /* find an empty entry in the task array */ task_id = 1; // tasks start at one! // go through task_array until an empty task slot is found @@ -153,14 +106,14 @@ int _rtapi_task_new(const rtapi_task_args_t *args) { // if requested priority is invalid, release lock and return error - if (PRIO_LT(args->prio,_rtapi_prio_lowest()) || - PRIO_GT(args->prio,_rtapi_prio_highest())) { + if (args->prio < rtapi_prio_lowest() || + args->prio > rtapi_prio_highest()) { rtapi_print_msg(RTAPI_MSG_ERR, "New task %d '%s:%d': invalid priority %d " "(highest=%d lowest=%d)\n", task_id, args->name, rtapi_instance, args->prio, - _rtapi_prio_highest(), - _rtapi_prio_lowest()); + rtapi_prio_highest(), + rtapi_prio_lowest()); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } @@ -181,8 +134,8 @@ int _rtapi_task_new(const rtapi_task_args_t *args) { "req prio %d (highest=%d lowest=%d) stack=%lu fp=%d flags=%d " "cgname=%s\n", task_id, args->name, rtapi_instance, args->prio, - _rtapi_prio_highest(), - _rtapi_prio_lowest(), + rtapi_prio_highest(), + rtapi_prio_lowest(), args->stacksize, args->uses_fp, args->flags, args->cgname); task->magic = TASK_MAGIC; @@ -199,57 +152,19 @@ int _rtapi_task_new(const rtapi_task_args_t *args) { rtapi_print_msg(RTAPI_MSG_DBG, "Task CPU: %d\n", task->cpu); - rtapi_snprintf(task->name, sizeof(task->name), + rtapi_snprintf(task->name, sizeof(task->name), "%s:%d", args->name, rtapi_instance); task->name[sizeof(task->name) - 1] = '\0'; -#ifdef MODULE - /* get space for the OS's task data - this is around 900 bytes, */ - /* so we don't want to statically allocate it for unused tasks. */ - ostask_array[task_id] = kmalloc(sizeof(RT_TASK), GFP_USER); - if (ostask_array[task_id] == NULL) { - rtapi_mutex_give(&(rtapi_data->mutex)); - return -ENOMEM; - } - -#ifdef HAVE_RTAPI_TASK_NEW_HOOK - /* kernel threads: rtapi_task_new_hook() should call OS to - initialize the task - use predetermined or explicitly assigned - CPU */ - retval = _rtapi_task_new_hook(task, task_id); - - if (retval) { - rtapi_print_msg(RTAPI_MSG_ERR, - "rt_task_create failed, rc = %d\n", retval ); - - /* couldn't create task, free task data memory */ - kfree(ostask_array[task_id]); - rtapi_mutex_give(&(rtapi_data->mutex)); - if (retval == ENOMEM) { - /* not enough space for stack */ - return -ENOMEM; - } - /* unknown error */ - return -EINVAL; - } -#endif - - /* the task has been created, update data */ - task->state = PAUSED; - retval = task_id; -#else /* userland thread */ - /* userland threads: rtapi_task_new_hook() should perform any - thread system-specific tasks, and return task_id or an error - code back to the caller (how do we know the diff between an - error and a task_id???). */ + /* userland threads: flavor_task_new_hook() should perform any + thread system-specific tasks, and return task_id or an error code back to + the caller (how do we know the diff between an error and a + task_id???). */ task->state = USERLAND; // userland threads don't track this -# ifdef HAVE_RTAPI_TASK_NEW_HOOK - retval = _rtapi_task_new_hook(task,task_id); -# else - retval = task_id; -# endif -#endif /* userland thread */ + retval = flavor_task_new_hook(NULL, task, task_id); + if (retval == -ENOSYS) // Unimplemented + retval = task_id; rtapi_data->task_count++; @@ -264,11 +179,7 @@ int _rtapi_task_new(const rtapi_task_args_t *args) { } -#ifdef HAVE_RTAPI_TASK_DELETE_HOOK -int _rtapi_task_delete_hook(task_data *task, int task_id); -#endif - -int _rtapi_task_delete(int task_id) { +int rtapi_task_delete(int task_id) { task_data *task; int retval = 0; @@ -282,47 +193,14 @@ int _rtapi_task_delete(int task_id) { if (task->state != DELETE_LOCKED) // we don't already hold mutex rtapi_mutex_get(&(rtapi_data->mutex)); -#ifdef MODULE - if ((task->state == PERIODIC) || (task->state == FREERUN)) { - /* task is running, need to stop it */ - rtapi_print_msg(RTAPI_MSG_WARN, - "RTAPI: WARNING: tried to delete task %02d while running\n", - task_id); - _rtapi_task_pause(task_id); - } - /* get rid of it */ - rt_task_delete(ostask_array[task_id]); - /* free kernel memory */ - kfree(ostask_array[task_id]); - /* update data */ - task->prio = 0; - task->owner = 0; - task->taskcode = NULL; - ostask_array[task_id] = NULL; - rtapi_data->task_count--; - /* if no more tasks, stop the timer */ - if (rtapi_data->task_count == 0) { - if (rtapi_data->timer_running != 0) { -# ifdef HAVE_RTAPI_MODULE_TIMER_STOP - _rtapi_module_timer_stop(); -# endif - rtapi_data->timer_period = 0; - max_delay = DEFAULT_MAX_DELAY; - rtapi_data->timer_running = 0; - } - } -#endif /* MODULE */ - -#ifdef HAVE_RTAPI_TASK_DELETE_HOOK - retval = _rtapi_task_delete_hook(task,task_id); -#endif + flavor_task_delete_hook(NULL, task,task_id); if (task->state != DELETE_LOCKED) // we don't already hold mutex rtapi_mutex_give(&(rtapi_data->mutex)); task->state = EMPTY; task->magic = 0; - rtapi_print_msg(RTAPI_MSG_DBG, "rt_task_delete %d \"%s\"\n", task_id, + rtapi_print_msg(RTAPI_MSG_DBG, "rt_task_delete %d \"%s\"\n", task_id, task->name ); return retval; @@ -330,15 +208,11 @@ int _rtapi_task_delete(int task_id) { /* all threads systems must define this hook */ -int _rtapi_task_start_hook(task_data *task, int task_id, - unsigned long int period_nsec); - -#ifndef MODULE /* userspace RTAPI */ -int _rtapi_task_start(int task_id, unsigned long int period_nsec) { +int rtapi_task_start(int task_id, unsigned long int period_nsec) { task_data *task; if (task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL; - + task = &task_array[task_id]; /* validate task handle */ @@ -358,200 +232,87 @@ int _rtapi_task_start(int task_id, unsigned long int period_nsec) { task_id, task->name); rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: period_nsec: %ld\n", period_nsec); - return _rtapi_task_start_hook(task,task_id,0); + return flavor_task_start_hook(NULL, task,task_id); } -#else /* kernel RTAPI */ -int _rtapi_task_start(int task_id, unsigned long int period_nsec) { - int retval; - task_data *task; - - /* validate task ID */ - if ((task_id < 1) || (task_id > RTAPI_MAX_TASKS)) { - return -EINVAL; - } - /* point to the task's data */ - task = &(task_array[task_id]); - /* is task ready to be started? */ - if (task->state != PAUSED) { - return -EINVAL; - } - /* can't start periodic tasks if timer isn't running */ - if ((rtapi_data->timer_running == 0) || (rtapi_data->timer_period == 0)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: could not start task: timer isn't running\n"); - return -EINVAL; - } - - if ((retval = _rtapi_task_start_hook(task, task_id, period_nsec))) - return retval; - - /* ok, task is started */ - task->state = PERIODIC; - rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: start_task id: %02d\n", task_id); - rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: period_nsec: %ld\n", period_nsec); - return retval; -} -#endif /* kernel threads */ - - -#ifdef HAVE_RTAPI_TASK_STOP_HOOK -int _rtapi_task_stop_hook(task_data *task, int task_id); -#endif - -int _rtapi_task_stop(int task_id) { +int rtapi_task_stop(int task_id) { task_data *task; if(task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL; - + task = &task_array[task_id]; /* validate task handle */ if (task->magic != TASK_MAGIC) return -EINVAL; -#ifdef HAVE_RTAPI_TASK_STOP_HOOK - _rtapi_task_stop_hook(task,task_id); -#endif + flavor_task_stop_hook(NULL, task,task_id); return 0; } -#ifdef HAVE_RTAPI_TASK_PAUSE_HOOK -int _rtapi_task_pause_hook(task_data *task, int task_id); -#endif - -int _rtapi_task_pause(int task_id) { +int rtapi_task_pause(int task_id) { task_data *task; -#ifdef MODULE - task_state_t oldstate; - int retval; -#endif if(task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL; - + task = &task_array[task_id]; - + /* validate task handle */ if (task->magic != TASK_MAGIC) return -EINVAL; -#ifdef MODULE - if ((task->state != PERIODIC) && (task->state != FREERUN)) { - return -EINVAL; - } - /* pause the task */ - oldstate = task->state; - task->state = PAUSED; - // ok for both RTAI and Xenomai - retval = rt_task_suspend(ostask_array[task_id]); - if (retval != 0) { - task->state = oldstate; - return -EINVAL; - } - /* update task data */ - return 0; -#endif - -#ifdef HAVE_RTAPI_TASK_PAUSE_HOOK - return _rtapi_task_pause_hook(task,task_id); -#else - return -ENOSYS; -#endif - + return flavor_task_pause_hook(NULL, task, task_id); } -#ifdef HAVE_RTAPI_WAIT_HOOK -extern int _rtapi_wait_hook(int); -#endif - -int _rtapi_wait(const int flag) { -#ifdef HAVE_RTAPI_WAIT_HOOK - return _rtapi_wait_hook(flag); -#else - return 0; -#endif +int rtapi_wait(const int flag) { + return flavor_task_wait_hook(NULL, flag); } -#ifdef HAVE_RTAPI_TASK_RESUME_HOOK -int _rtapi_task_resume_hook(task_data *task, int task_id); -#endif - -int _rtapi_task_resume(int task_id) { +int rtapi_task_resume(int task_id) { task_data *task; -#ifdef MODULE - int retval; -#endif if(task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL; - + task = &task_array[task_id]; - + /* validate task handle */ if (task->magic != TASK_MAGIC) return -EINVAL; -#ifdef MODULE - if (task->state != PAUSED) { - return -EINVAL; - } - /* start the task */ - // ok for both RTAI and Xenomai - retval = rt_task_resume(ostask_array[task_id]); - if (retval != 0) { - return -EINVAL; - } - /* update task data */ - task->state = FREERUN; - - return 0; -#endif - -#ifdef HAVE_RTAPI_TASK_RESUME_HOOK - return _rtapi_task_resume_hook(task,task_id); -#else - return -ENOSYS; -#endif + return flavor_task_resume_hook(NULL, task, task_id); } -#ifdef HAVE_RTAPI_TASK_SELF_HOOK -int _rtapi_task_self_hook(void); -#endif - -int _rtapi_task_self(void) { -#ifdef HAVE_RTAPI_TASK_SELF_HOOK - return _rtapi_task_self_hook(); -#else - /* not implemented */ - return -EINVAL; -#endif +int rtapi_task_self(void) { + return flavor_task_self_hook(NULL); } -#ifdef HAVE_RTAPI_TASK_PLL_GET_REFERENCE_HOOK -long long _rtapi_task_pll_get_reference_hook(void); -#endif - -long long _rtapi_task_pll_get_reference(void) { -#ifdef HAVE_RTAPI_TASK_PLL_GET_REFERENCE_HOOK - return _rtapi_task_pll_get_reference_hook(); -#else - return 0; -#endif +long long rtapi_task_pll_get_reference(void) { + return flavor_task_pll_get_reference_hook(NULL); } -#ifdef HAVE_RTAPI_TASK_PLL_SET_CORRECTION_HOOK -int _rtapi_task_pll_set_correction_hook(long); -#endif - -int _rtapi_task_pll_set_correction(long value) { -#ifdef HAVE_RTAPI_TASK_PLL_SET_CORRECTION_HOOK - return _rtapi_task_pll_set_correction_hook(value); -#else - return 0; -#endif +int rtapi_task_pll_set_correction(long value) { + return flavor_task_pll_set_correction_hook(NULL, value); } #endif /* RTAPI */ + +#ifdef RTAPI +EXPORT_SYMBOL(rtapi_prio_highest); +EXPORT_SYMBOL(rtapi_prio_lowest); +EXPORT_SYMBOL(rtapi_prio_next_higher); +EXPORT_SYMBOL(rtapi_prio_next_lower); +EXPORT_SYMBOL(rtapi_task_new); +EXPORT_SYMBOL(rtapi_task_delete); +EXPORT_SYMBOL(rtapi_task_start); +EXPORT_SYMBOL(rtapi_task_stop); +EXPORT_SYMBOL(rtapi_task_pause); +EXPORT_SYMBOL(rtapi_wait); +EXPORT_SYMBOL(rtapi_task_resume); +EXPORT_SYMBOL(rtapi_task_self); +EXPORT_SYMBOL(rtapi_task_pll_get_reference); +EXPORT_SYMBOL(rtapi_task_pll_set_correction); +#endif diff --git a/src/rtapi/rtapi_time.c b/src/rtapi/rtapi_time.c index 4a2e4d6a76..4871debf18 100644 --- a/src/rtapi/rtapi_time.c +++ b/src/rtapi/rtapi_time.c @@ -5,17 +5,17 @@ * for more info. * * Copyright 2006-2013 Various Authors -* +* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -24,51 +24,28 @@ #include "config.h" // build configuration #include "rtapi.h" // these functions #include "rtapi_common.h" // these functions +#include "rtapi_flavor.h" // flavor_* -#ifndef MODULE // kernel threads systems have own timer functions -# include // clock_getres(), clock_gettime() -#endif +#include // clock_getres(), clock_gettime() -#ifndef HAVE_RTAPI_GET_CLOCKS_HOOK // find a useable time stamp counter -#ifndef MODULE /* kernel has rdtscll in - arch/x86/include/msr.h; does this - apply to other arches? */ #ifdef MSR_H_USABLE #include -#elif defined(__i386__) || defined(__x86_64__) -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) -#else -#error No implementation of rtapi_get_clocks available -#define rdtscll(val) (val)=0 #endif -#endif -#endif /* HAVE_RTAPI_GET_CLOCKS_HOOK */ long int max_delay = DEFAULT_MAX_DELAY; #ifdef RTAPI /* hide most functions from ULAPI */ -#ifdef BUILD_SYS_USER_DSO int period = 0; -#endif // Actual number of counts of the periodic timer unsigned long timer_counts; -#ifdef HAVE_RTAPI_CLOCK_SET_PERIOD_HOOK -void _rtapi_clock_set_period_hook(long int nsecs, RTIME *counts, - RTIME *got_counts); -#endif - -#ifdef BUILD_SYS_USER_DSO -long int _rtapi_clock_set_period(long int nsecs) { -#ifndef RTAPI_TIME_NO_CLOCK_MONOTONIC - struct timespec res = { 0, 0 }; -#endif +long int rtapi_clock_set_period(long int nsecs) { + struct timespec res = { 0, 0}; if (nsecs == 0) return period; @@ -77,73 +54,32 @@ long int _rtapi_clock_set_period(long int nsecs) { return -EINVAL; } -#ifdef RTAPI_TIME_NO_CLOCK_MONOTONIC - period = nsecs; -#else - clock_getres(CLOCK_MONOTONIC, &res); - period = (nsecs / res.tv_nsec) * res.tv_nsec; - if (period < 1) - period = res.tv_nsec; - - rtapi_print_msg(RTAPI_MSG_DBG, - "rtapi_clock_set_period (res=%ld) -> %d\n", res.tv_nsec, - period); -#endif /* ! RTAPI_TIME_NO_CLOCK_MONOTONIC */ - - return period; -} -#else /* BUILD_SYS_KBUILD */ -long int _rtapi_clock_set_period(long int nsecs) { - RTIME counts, got_counts; - - if (nsecs == 0) { - /* it's a query, not a command */ - return rtapi_data->timer_period; - } - if (rtapi_data->timer_running) { - /* already started, can't restart */ - return -EINVAL; + if (flavor_feature(NULL, FLAVOR_TIME_NO_CLOCK_MONOTONIC)) + period = nsecs; + else { + clock_getres(CLOCK_MONOTONIC, &res); + period = (nsecs / res.tv_nsec) * res.tv_nsec; + if (period < 1) + period = res.tv_nsec; + + rtapi_print_msg(RTAPI_MSG_DBG, + "rtapi_clock_set_period (res=%ld) -> %d\n", res.tv_nsec, + period); } - /* limit period to 2 micro-seconds min, 1 second max */ - if ((nsecs < 2000) || (nsecs > 1000000000L)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: ERR: clock_set_period: %ld nsecs, out of range\n", - nsecs); - return -EINVAL; - } - - /* kernel thread systems should init counts and - rtapi_data->timer_period using their own timer functions */ -#ifdef HAVE_RTAPI_CLOCK_SET_PERIOD_HOOK - _rtapi_clock_set_period_hook(nsecs, &counts, &got_counts); - timer_counts = got_counts; -#endif - rtapi_print_msg(RTAPI_MSG_DBG, - "RTAPI: clock_set_period requested: %ld actual: %ld " - "counts requested: %llu actual: %d\n", - nsecs, rtapi_data->timer_period, - (unsigned long long)counts, (int)got_counts); - - rtapi_data->timer_running = 1; - max_delay = rtapi_data->timer_period / 4; - return rtapi_data->timer_period; + return period; } -#endif /* BUILD_SYS_KBUILD */ -// rtapi_delay_hook MUST be implemented by all threads systems -void _rtapi_delay_hook(long int nsec); - -void _rtapi_delay(long int nsec) +void rtapi_delay(long int nsec) { if (nsec > max_delay) { nsec = max_delay; } - _rtapi_delay_hook(nsec); + flavor_task_delay_hook(NULL, nsec); } -long int _rtapi_delay_max(void) +long int rtapi_delay_max(void) { return max_delay; } @@ -152,39 +88,45 @@ long int _rtapi_delay_max(void) /* The following functions are common to both RTAPI and ULAPI */ -#ifdef HAVE_RTAPI_GET_TIME_HOOK -long long int _rtapi_get_time_hook(void); +long long int rtapi_get_time(void) { + long long int res; -long long int _rtapi_get_time(void) { - return _rtapi_get_time_hook(); + res = flavor_get_time_hook(NULL); + if (res == -ENOSYS) { // Unimplemented + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + res = ts.tv_sec * 1000000000LL + ts.tv_nsec; + } + return res; } -#else -long long int _rtapi_get_time(void) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000LL + ts.tv_nsec; +long long int rtapi_get_clocks(void) { + long long int res; + res = flavor_get_clocks_hook(NULL); + if (res == -ENOSYS) { // Unimplemented + +# ifdef MSR_H_USABLE + /* This returns a result in clocks instead of nS, and needs to be + used with care around CPUs that change the clock speed to save + power and other disgusting, non-realtime oriented behavior. + But at least it doesn't take a week every time you call it. */ + rdtscll(res); +# elif defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__("rdtsc" : "=A" (res)); +# else + // Needed for e.g. ARM + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + res = ts.tv_sec * 1000000000LL + ts.tv_nsec; +# endif + } + return res; } -#endif /* HAVE_RTAPI_GET_TIME_HOOK */ -#ifdef HAVE_RTAPI_GET_CLOCKS_HOOK -long long int _rtapi_get_clocks_hook(void); +#ifdef RTAPI +EXPORT_SYMBOL(rtapi_clock_set_period); +EXPORT_SYMBOL(rtapi_delay); +EXPORT_SYMBOL(rtapi_delay_max); +EXPORT_SYMBOL(rtapi_get_time); +EXPORT_SYMBOL(rtapi_get_clocks); #endif - -long long int _rtapi_get_clocks(void) { -#ifndef HAVE_RTAPI_GET_CLOCKS_HOOK - long long int retval; - - /* This returns a result in clocks instead of nS, and needs to be - used with care around CPUs that change the clock speed to save - power and other disgusting, non-realtime oriented behavior. - But at least it doesn't take a week every time you call it. */ - - rdtscll(retval); - return retval; -#else - return _rtapi_get_clocks_hook(); -#endif /* HAVE_RTAPI_GET_CLOCKS_HOOK */ -} - - diff --git a/src/rtapi/shmdrv/Submakefile b/src/rtapi/shmdrv/Submakefile index 3948c947c5..fc785e9b76 100644 --- a/src/rtapi/shmdrv/Submakefile +++ b/src/rtapi/shmdrv/Submakefile @@ -1,54 +1,11 @@ ################################################################## # the shmdrv shared memory allocator module # -# loosely based on: http://www.embrisk.com/notes/shmem.html +# loosely based on: http://www.embrisk.com/notes/shmem.html # Status: public domain # ################################################################## -#------------------------------ -# shmdrv module -# -# build for kthreads flavors -ifeq ($(BUILD_SYS),kbuild) -obj-m += shmdrv.o -shmdrv-objs := rtapi/shmdrv/shmdrv.o - -$(RTLIBDIR)/shmdrv$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(shmdrv-objs)) - -INCLUDES += rtapi/shmdrv -endif # BUILD_SYS = kbuild - -#------------------------------ -# shmdrv module -# -# build for all kernels in SHMDRV_KERNEL_DIRS -ifeq ($(BUILD_ALL_FLAVORS)+$(USE_SHMDRV),yes+yes) -# we have no mapping of kver to kdir, so use a timestamp and do the -# whole thing in a big ugly non-Makefile-thonic shell script -SHMDRV_SRCS = rtapi/shmdrv/shmdrv.c \ - rtapi/shmdrv/shmdrv.h \ - rtapi/shmdrv/Makefile -objects/.shmdrv-built: $(SHMDRV_SRCS) - for kdir in $(SHMDRV_KERNEL_DIRS); do \ - kver=`../scripts/kernel-vers.sh $$kdir`; \ - mkdir -p objects/userland/$$kver; \ - cp $(SHMDRV_SRCS) objects/userland/$$kver; \ - echo "Building userland shmdrv module for kernel version $$kver"; \ - $(MAKE) \ - -C $$kdir \ - M=$(BASEPWD)/objects/userland/$$kver \ - CC=$(CC) KBUILD_VERBOSE=$(BUILD_VERBOSE); \ - mkdir -p ../rtlib/userland/$$kver; \ - cp objects/userland/$$kver/Module.symvers \ - objects/userland/$$kver/shmdrv.ko \ - ../rtlib/userland/$$kver; \ - done - touch $@ - -modules: objects/.shmdrv-built -endif # BUILD_ALL_FLAVORS && USE_SHMDRV - #------------------------------ # liblinuxcncshm.so shared lib @@ -65,7 +22,7 @@ $(SHMDRVLIB).0: $(call TOOBJS, $(SHMDRVAPISRCS)) @rm -f $@ $(Q)$(CC) $(LDFLAGS) -Wl,-soname,$(notdir $@) -shared \ -o $@ $^ -lrt -USERSRCS += $(SHMDRVAPISRCS) +USERSRCS += $(SHMDRVAPISRCS) TARGETS += $(SHMDRVLIB) $(SHMDRVLIB).0 ifeq ($(BUILD_EXAMPLES),yes) @@ -75,9 +32,6 @@ ifeq ($(BUILD_EXAMPLES),yes) # lock debugging help plus a bit of API example MUTEXWATCH_SRCS = rtapi/shmdrv/mutexwatch.c -$(call TOOBJSDEPS, $(MUTEXWATCH_SRCS)): \ - EXTRAFLAGS += $(THREADS_RTFLAGS) - ../bin/mutexwatch: ../lib/liblinuxcncshm.so $(call TOOBJS, $(MUTEXWATCH_SRCS)) $(ECHO) Linking $(notdir $@) $(Q)$(CC) $(LDFLAGS) -o $@ $^ ../lib/liblinuxcncshm.so -lrt diff --git a/src/rtapi/shmdrv/mutexwatch.c b/src/rtapi/shmdrv/mutexwatch.c index b14d640ef1..c4f97d4e36 100644 --- a/src/rtapi/shmdrv/mutexwatch.c +++ b/src/rtapi/shmdrv/mutexwatch.c @@ -1,136 +1,134 @@ -/******************************************************************** - * Copyright (C) 2012, 2013 Michael Haberler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ********************************************************************/ - -// helper to watch mutexes - -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "rtapi.h" -#include "rtapi_common.h" -#include "rtapi_global.h" -#include "rtapi/shmdrv/shmdrv.h" -#include "hal.h" -#include "hal_priv.h" - -global_data_t *global_data; -rtapi_data_t *rtapi_data; -hal_data_t *hal_data; - -int shmdrv_loaded; -long page_size; - -int gm = -1; -int rm = -1; -int rrm = -1; -int hm = -1; - -int rtapi_instance = 0; - -struct timespec looptime = { - .tv_sec = 0, - .tv_nsec = 1000 * 1000 * 100, -}; - -int main(int argc, char **argv) -{ - int globalkey,rtapikey,halkey,retval; - int size; - - page_size = sysconf(_SC_PAGESIZE); - shmdrv_loaded = shmdrv_available(); - - if (argc > 1) - rtapi_instance = atoi(argv[1]); - - globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance); - rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance); - halkey = OS_KEY(HAL_KEY, rtapi_instance); - - size = sizeof(global_data_t); - retval = shm_common_new(globalkey, &size, - rtapi_instance, (void **) &global_data, 0); - if (retval < 0) - fprintf(stderr, "cannot attach global segment key=0x%x %s\n", - globalkey, strerror(-retval)); - - if (MMAP_OK(global_data) && (global_data->magic != GLOBAL_READY)) { - printf("global_data MAGIC wrong: %x %x\n", global_data->magic, GLOBAL_READY); - } - - size = sizeof(rtapi_data_t); - retval = shm_common_new(rtapikey, &size, - rtapi_instance, (void **) &rtapi_data, 0); - if (retval < 0) - fprintf(stderr, "cannot attach rtapi segment key=0x%x %s\n", - rtapikey, strerror(-retval)); - - if (MMAP_OK(rtapi_data) && (rtapi_data->magic != RTAPI_MAGIC)) { - printf("rtapi_data MAGIC wrong: %x\n", rtapi_data->magic); - } - - if (MMAP_OK(global_data)) { - size = global_data->hal_size; - // global_data is needed for actual size of the HAL data segment - retval = shm_common_new(halkey, &size, - rtapi_instance, (void **) &hal_data, 0); - if (retval < 0) - fprintf(stderr, "cannot attach hal segment key=0x%x %s\n", - halkey, strerror(-retval)); - - if (MMAP_OK(hal_data) && (hal_data->version != HAL_VER)) { - printf("hal_data HAL_VER wrong: %x\n", hal_data->version); - } - } - - if (!(MMAP_OK(global_data) || MMAP_OK(rtapi_data) || MMAP_OK(hal_data))) { - printf("nothing to attach to!\n"); - exit(1); - } - - do { - if (nanosleep(&looptime, &looptime)) - break; - - if (MMAP_OK(global_data) && (global_data->mutex != gm)) { - printf("global_data->mutex: %ld\n", global_data->mutex); - gm = global_data->mutex; - } - if (MMAP_OK(rtapi_data) && (rtapi_data->ring_mutex != rrm)) { - printf("rtapi_data->ring_mutex: %ld\n", rtapi_data->ring_mutex); - rrm = rtapi_data->ring_mutex; - } - if (MMAP_OK(rtapi_data) && (rtapi_data->mutex != rm)) { - printf("rtapi_data->mutex: %ld\n", rtapi_data->mutex); - rm = rtapi_data->mutex; - } - if (MMAP_OK(hal_data) && (hal_data->mutex != hm)) { - printf("hal_data->mutex: %ld\n", hal_data->mutex); - hm = hal_data->mutex; - } - - } while (1); - - exit(0); -} +/******************************************************************** + * Copyright (C) 2012, 2013 Michael Haberler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ********************************************************************/ + +// helper to watch mutexes + +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "rtapi.h" +#include "rtapi_common.h" +#include "rtapi_global.h" +#include "rtapi/shmdrv/shmdrv.h" +#include "hal.h" +#include "hal_priv.h" + +hal_data_t *hal_data; + +int shmdrv_loaded; +long page_size; + +int gm = -1; +int rm = -1; +int rrm = -1; +int hm = -1; + +int rtapi_instance = 0; + +struct timespec looptime = { + .tv_sec = 0, + .tv_nsec = 1000 * 1000 * 100, +}; + +int main(int argc, char **argv) +{ + int globalkey,rtapikey,halkey,retval; + int size; + + page_size = sysconf(_SC_PAGESIZE); + shmdrv_loaded = shmdrv_available(); + + if (argc > 1) + rtapi_instance = atoi(argv[1]); + + globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance); + rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance); + halkey = OS_KEY(HAL_KEY, rtapi_instance); + + size = sizeof(global_data_t); + retval = shm_common_new(globalkey, &size, + rtapi_instance, (void **) &global_data, 0); + if (retval < 0) + fprintf(stderr, "cannot attach global segment key=0x%x %s\n", + globalkey, strerror(-retval)); + + if (MMAP_OK(global_data) && (global_data->magic != GLOBAL_READY)) { + printf("global_data MAGIC wrong: %x %x\n", global_data->magic, GLOBAL_READY); + } + + size = sizeof(rtapi_data_t); + retval = shm_common_new(rtapikey, &size, + rtapi_instance, (void **) &rtapi_data, 0); + if (retval < 0) + fprintf(stderr, "cannot attach rtapi segment key=0x%x %s\n", + rtapikey, strerror(-retval)); + + if (MMAP_OK(rtapi_data) && (rtapi_data->magic != RTAPI_MAGIC)) { + printf("rtapi_data MAGIC wrong: %x\n", rtapi_data->magic); + } + + if (MMAP_OK(global_data)) { + size = global_data->hal_size; + // global_data is needed for actual size of the HAL data segment + retval = shm_common_new(halkey, &size, + rtapi_instance, (void **) &hal_data, 0); + if (retval < 0) + fprintf(stderr, "cannot attach hal segment key=0x%x %s\n", + halkey, strerror(-retval)); + + if (MMAP_OK(hal_data) && (hal_data->version != HAL_VER)) { + printf("hal_data HAL_VER wrong: %x\n", hal_data->version); + } + } + + if (!(MMAP_OK(global_data) || MMAP_OK(rtapi_data) || MMAP_OK(hal_data))) { + printf("nothing to attach to!\n"); + exit(1); + } + + do { + if (nanosleep(&looptime, &looptime)) + break; + + if (MMAP_OK(global_data) && (global_data->mutex != gm)) { + printf("global_data->mutex: %ld\n", global_data->mutex); + gm = global_data->mutex; + } + if (MMAP_OK(rtapi_data) && (rtapi_data->ring_mutex != rrm)) { + printf("rtapi_data->ring_mutex: %ld\n", rtapi_data->ring_mutex); + rrm = rtapi_data->ring_mutex; + } + if (MMAP_OK(rtapi_data) && (rtapi_data->mutex != rm)) { + printf("rtapi_data->mutex: %ld\n", rtapi_data->mutex); + rm = rtapi_data->mutex; + } + if (MMAP_OK(hal_data) && (hal_data->mutex != hm)) { + printf("hal_data->mutex: %ld\n", hal_data->mutex); + hm = hal_data->mutex; + } + + } while (1); + + exit(0); +} diff --git a/src/rtapi/shmdrv/shmdrv.rules b/src/rtapi/shmdrv/shmdrv.rules deleted file mode 100644 index acacc38b97..0000000000 --- a/src/rtapi/shmdrv/shmdrv.rules +++ /dev/null @@ -1,2 +0,0 @@ -# make the shared memory allocator publically accessible -KERNEL=="shmdrv", MODE="0666" diff --git a/src/rtapi/tests/rtapi_flavor.c b/src/rtapi/tests/rtapi_flavor.c new file mode 100644 index 0000000000..d950ba625e --- /dev/null +++ b/src/rtapi/tests/rtapi_flavor.c @@ -0,0 +1,409 @@ +#include "rtapi_flavor.h" +#include +#include +#include + +// Set this to print verbose debug messages +int debug_tests = 0; +#define DEBUG(args...) \ + do { if (debug_tests) fprintf(stderr, args); } while (0) + +/******************************************************************/ +// Mock functions + +int __wrap_flavor_can_run_flavor(flavor_descriptor_ptr f) +{ + int ret = mock(); + if (f == NULL) + DEBUG("mock: flavor_can_run_flavor(NULL) = %d\n", ret); + else + DEBUG("mock: flavor_can_run_flavor('%s') = %d\n", f->name, ret); + function_called(); + /* check_expected(f->flavor_id); */ + check_expected_ptr(f); + return ret; +} + +char *__wrap_getenv(const char *name) +{ + // From + function_called(); + check_expected_ptr(name); + char* ret = mock_ptr_type(char *); + DEBUG("mock: getenv(%s) = '%s'\n", name, ret); + return ret; +} + +/******************************************************************/ +// Tests for flavor_names + +// Number of flavors +#ifdef RTAPI +# ifdef HAVE_XENOMAI_THREADS +# define FLAVOR_NAMES_COUNT 3 +static char* expected_flavor_names[] = { "posix", "rt-preempt", "xenomai" }; +# else +# define FLAVOR_NAMES_COUNT 2 +static char* expected_flavor_names[] = { "posix", "rt-preempt" }; +# endif +#else // ULAPI +# define FLAVOR_NAMES_COUNT 1 +static char* expected_flavor_names[] = { "ulapi" }; +#endif + +static void test_flavor_names(void **state) +{ + flavor_descriptor_ptr * f = NULL; + char** expected_name_ptr = expected_flavor_names; + const char* fname; + int count = 0; + + // Set up mock calls to flavor_can_run_flavor(): all runnable + expect_function_calls(__wrap_flavor_can_run_flavor, FLAVOR_NAMES_COUNT); + will_return_count(__wrap_flavor_can_run_flavor, 1, FLAVOR_NAMES_COUNT); + for (count = 0; count < FLAVOR_NAMES_COUNT; count++) + expect_value(__wrap_flavor_can_run_flavor, f, + flavor_byname(expected_flavor_names[count])); + + for (count=0; (fname=flavor_names(&f)); count++) + assert_string_equal(fname, *(expected_name_ptr++)); + assert_int_equal(count, FLAVOR_NAMES_COUNT); +} + +static void test_flavor_names_unrunnable(void **state) +{ + flavor_descriptor_ptr * f = NULL; + int count = 0; + + // Set up mock calls to flavor_can_run_flavor(): all unrunnable + expect_function_calls(__wrap_flavor_can_run_flavor, FLAVOR_NAMES_COUNT); + will_return_count(__wrap_flavor_can_run_flavor, 0, FLAVOR_NAMES_COUNT); + for (count = 0; count < FLAVOR_NAMES_COUNT; count++) + expect_value(__wrap_flavor_can_run_flavor, f, + flavor_byname(expected_flavor_names[count])); + + // Shouldn't get any names + for (count=0; flavor_names(&f); count++) + fail(); + assert_int_equal(count, 0); +} + +/******************************************************************/ +// Tests for flavor_byname, flavor_byid + +// Test inputs +typedef struct { char* name; int id; } flavor_by_test_data_t; +#ifdef RTAPI +static flavor_by_test_data_t flavor_by_test_data[] = { + {"posix", 2}, + {"rt-preempt", 3}, +# ifdef HAVE_XENOMAI_THREADS + {"xenomai", 4}, +# else + {"xenomai", 0}, + {"bogus", 4}, +# endif + {"ulapi", 0}, + {"bogus", 0}, + {"bogus", -10000}, + {"END OF TESTS", -1}, +}; +#endif +#ifdef ULAPI +static flavor_by_test_data_t flavor_by_test_data[] = { + {"ulapi", 1}, + {"posix", 0}, + {"rt-preempt", 0}, + {"bogus", 2}, + {"bogus", 3}, + {"bogus", 4}, + {"bogus", 10000}, + {"END OF TESTS", -1}, +}; +#endif + +static void test_flavor_byname(void **state) +{ + flavor_descriptor_ptr flavor; + flavor_by_test_data_t * td_ptr = flavor_by_test_data; + for (; td_ptr->id >= 0; td_ptr++) { + DEBUG("name=%s; id=%d\n", td_ptr->name, td_ptr->id); + flavor = flavor_byname(td_ptr->name); + + if (td_ptr->id == 0 || strcmp(td_ptr->name, "bogus") == 0) { + // Bogus name, or not compiled in + assert_null(flavor); + continue; + } + + assert_non_null(flavor); + if (td_ptr->id > 0 && strcmp(td_ptr->name,"bogus") != 0) + assert_int_equal(flavor->flavor_id, td_ptr->id); + else + assert_int_equal(flavor->flavor_id, 0); + } +} + +static void test_flavor_byid(void **state) +{ + flavor_descriptor_ptr f; + flavor_by_test_data_t * td_ptr = flavor_by_test_data; + for (; td_ptr->id >= 0; td_ptr++) { + f = flavor_byid(td_ptr->id); + if (td_ptr->id > 0 && strcmp(td_ptr->name,"bogus") != 0) { + assert_non_null(f); + assert_int_equal(f->flavor_id, td_ptr->id); + assert_string_equal(f->name, td_ptr->name); + } else + // Bogus tests + assert_null(f); + } +} + +/******************************************************************/ +// Tests for flavor_default + +// Test inputs +typedef struct { + char* getenv_ret; // Return value of getenv("FLAVOR") + int ret; // Returned flavor ID + int exit; // Exit error code + // Return values of flavor_can_run_flavor(flavor) functions + int ulapi_cannot_run; // Just to test the flow + int posix_cannot_run; // Just to test the flow + int rtpreempt_can_run; + int xenomai_can_run; +} flavor_default_test_data_t; + +static flavor_default_test_data_t flavor_default_test_data[] = { +#ifdef RTAPI + // Flavor from environment variable: Success + { .getenv_ret = "posix", .ret = 2 }, + { .getenv_ret = "rt-preempt", .rtpreempt_can_run = 1, .ret = 3 }, + // Flavor from environment variable: No such flavor exit 100 + { .getenv_ret = "ulapi", .exit = 100 }, // No such flavor + { .getenv_ret = "bogus", .exit = 100 }, + // Flavor from environment variable: Cannot run exit 101 + { .getenv_ret = "rt-preempt", .rtpreempt_can_run = 0, .exit = 101 }, + { .getenv_ret = "posix", .posix_cannot_run = 1, .exit = 101 }, + // Choose best default: Success + { .ret = 2 }, // Worst case scenario: posix + { .getenv_ret = "", .ret = 2 }, // $FLAVOR set to empty + { .rtpreempt_can_run = 1, .ret = 3 }, // RT_PREEMPT can_run +# ifdef HAVE_XENOMAI_THREADS + { .xenomai_can_run = 1, .ret = 4 }, // Xenomai can_run + { .rtpreempt_can_run = 1, .xenomai_can_run = 1, .ret = 4 }, // Both can_run +# endif + // Choose best default: No runnable flavors exit 102 + { .posix_cannot_run = 1, .exit = 102 }, // Impossible + +#else // ULAPI + // Flavor from environment variable: Success + { .getenv_ret = "ulapi", .ret = 1 }, + // Flavor from environment variable: No such flavor exit 100 + { .getenv_ret = "posix", .exit = 100 }, + { .getenv_ret = "bogus", .exit = 100 }, + // Flavor from environment variable: Cannot run exit 101 + { .getenv_ret = "ulapi", .ulapi_cannot_run = 1, .exit = 101 }, + // Choose best default: Success + { .ret = 1 }, + { .getenv_ret = "", .ret = 1 }, // $FLAVOR set to empty + // Choose best default: No runnable flavors exit 102 + { .ulapi_cannot_run = 1, .exit = 102 }, +#endif + { .getenv_ret = "END" }, // Marks end of tests +}; + +static void test_flavor_default_runner(flavor_default_test_data_t *td) +{ + flavor_descriptor_ptr flavor; + DEBUG("test: Setting up ret = %d, exit = %d\n", td->ret, td->exit); + + // getenv("FLAVOR") should always be called; returns test data + DEBUG("test: mock getenv(FLAVOR) = '%s'\n", td->getenv_ret); + expect_function_call(__wrap_getenv); + expect_string(__wrap_getenv, name, "FLAVOR"); + will_return(__wrap_getenv, td->getenv_ret); + + if (td->getenv_ret && td->getenv_ret[0]) { + // $FLAVOR is set in environment + if (td->ret > 0 || td->exit == 101) + // Get flavor_descriptor for tests where $FLAVOR is valid + flavor = flavor_byname(td->getenv_ret); + + if (td->ret > 0) { + DEBUG("test: mock flavor_can_run_flavor(%s) = 1\n", flavor->name); + expect_function_call(__wrap_flavor_can_run_flavor); + expect_value(__wrap_flavor_can_run_flavor, f, flavor); + will_return(__wrap_flavor_can_run_flavor, 1); + } + if (td->exit == 100) { + // We don't care about these calls, for printing valid flavors + // before exit; not critical to function and hard to mock + DEBUG("test: mock flavor_can_run_flavor('%s') = 0 (any)\n", + td->getenv_ret); + expect_function_call_any(__wrap_flavor_can_run_flavor); + expect_any_count(__wrap_flavor_can_run_flavor, f, + FLAVOR_NAMES_COUNT); + will_return_always(__wrap_flavor_can_run_flavor, 1); + } + if (td->exit == 101) { + DEBUG("test: mock flavor_can_run_flavor('%s') = 0\n", + td->getenv_ret); + expect_function_call(__wrap_flavor_can_run_flavor); + expect_value(__wrap_flavor_can_run_flavor, f, flavor); + will_return(__wrap_flavor_can_run_flavor, 0); + } + } else { + // No $FLAVOR set; pick best available +# ifdef ULAPI + expect_function_call(__wrap_flavor_can_run_flavor); + DEBUG("test: mock flavor_can_run_flavor('ulapi') = %d\n", + !td->ulapi_cannot_run); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname("ulapi")); + will_return(__wrap_flavor_can_run_flavor, !td->ulapi_cannot_run); +# else // RTAPI + expect_function_calls(__wrap_flavor_can_run_flavor, 2); + DEBUG("test: mock flavor_can_run_flavor('posix') = %d\n", + !td->posix_cannot_run); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname("posix")); + will_return(__wrap_flavor_can_run_flavor, !td->posix_cannot_run); + DEBUG("test: mock flavor_can_run_flavor('rt-preempt') = %d\n", + td->rtpreempt_can_run); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname("rt-preempt")); + will_return(__wrap_flavor_can_run_flavor, td->rtpreempt_can_run); +# ifdef HAVE_XENOMAI_THREADS + expect_function_call(__wrap_flavor_can_run_flavor); + DEBUG("test: mock flavor_can_run_flavor('xenomai') = %d\n", + td->xenomai_can_run); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname("xenomai")); + will_return(__wrap_flavor_can_run_flavor, td->xenomai_can_run); +# endif +# endif + } + + // Run the function + flavor = flavor_default(); + + // Check result + if (flavor) // Success + assert_int_equal(flavor->flavor_id, td->ret); + else // Failure + assert_int_equal(flavor_mocking_err, td->exit); +} + +// This increments over the tests +typedef flavor_default_test_data_t * flavor_default_test_data_ptr; +flavor_default_test_data_ptr td = flavor_default_test_data; + +static void test_flavor_default(void **state) +{ + // Walk through the list of tests and call runner + if (td->getenv_ret != NULL && strcmp(td->getenv_ret, "END") == 0) + // End of tests + skip(); + else + // Run the next test & increment test case + test_flavor_default_runner(td++); +} + +/******************************************************************/ +// Tests for flavor_install + +#ifdef RTAPI +char * flav_req = "posix"; +#else // ULAPI +char * flav_req = "ulapi"; +#endif + +static void test_flavor_install_already_configured(void **state) +{ + // Simulate flavor already configured + flavor_descriptor = flavor_byname(flav_req); + + // Request to install a flavor + flavor_install(flavor_byname(flav_req)); + + // Check error + assert_int_equal(flavor_mocking_err, 103); +} + +static void test_flavor_install_unrunnable(void **state) +{ + // Simulate unconfigured flavor + flavor_descriptor = NULL; + + // Mock can_run_flavor() return value + expect_function_call(__wrap_flavor_can_run_flavor); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname(flav_req)); + will_return(__wrap_flavor_can_run_flavor, 0); + + // Request unrunnable flavor + flavor_install(flavor_byname(flav_req)); + + // Check error + assert_int_equal(flavor_mocking_err, 104); +} + +static void test_flavor_install_success(void **state) +{ + // Simulate unconfigured flavor + flavor_descriptor = NULL; + + // Mock can_run_flavor() return value + expect_function_call(__wrap_flavor_can_run_flavor); + expect_value(__wrap_flavor_can_run_flavor, f, flavor_byname(flav_req)); + will_return(__wrap_flavor_can_run_flavor, 1); + + // Request runnable flavor + flavor_install(flavor_byname(flav_req)); + + // Check flavor + assert_non_null(flavor_descriptor); + assert_int_equal(strcmp(flavor_descriptor->name, flav_req), 0); +} + +/******************************************************************/ +// Test runner + +int main(void) +{ + // Tell functions we're in test mode + flavor_mocking = 1; + + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_flavor_names), + cmocka_unit_test(test_flavor_names_unrunnable), + cmocka_unit_test(test_flavor_byname), + cmocka_unit_test(test_flavor_byid), +# ifdef RTAPI // Ugh + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), +# ifdef HAVE_XENOMAI_THREADS + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), +# endif + cmocka_unit_test(test_flavor_default), +# else // ULAPI + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), + cmocka_unit_test(test_flavor_default), +# endif + cmocka_unit_test(test_flavor_install_already_configured), + cmocka_unit_test(test_flavor_install_unrunnable), + cmocka_unit_test(test_flavor_install_success), + }; + + return cmocka_run_group_tests_name("rtapi_flavor tests", tests, NULL, NULL); +} diff --git a/src/rtapi/ulapi_autoload.c b/src/rtapi/ulapi_autoload.c deleted file mode 100644 index 7de2fee0af..0000000000 --- a/src/rtapi/ulapi_autoload.c +++ /dev/null @@ -1,375 +0,0 @@ -/******************************************************************** - * Copyright (C) 2012, 2013 Michael Haberler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ********************************************************************/ - - -// ULAPI autoloading support -// -// this postpones binding to the flavor-specific ULAPI -// by intercepting the first call to rtapi_init() - -// other than the previous code which assumed realtime is started -// and failed during loading of the HAL library, this code makes the -// HAL library load fine regardless of realtime started or stopped -// however, any calls to hal_init() (which cause a call to rtapi_init()) -// will fail if realtime stopped; or succeed after loading the -// ulapi shared object for the current flavor. - -// Michael Haberler 7/2013 - -#include // snprintf -#include // for dlopen/dlsym ulapi-$THREADSTYLE.so -#include -#include // PATH_MAX -#include // exit() - -#include "rtapi.h" // RTAPI realtime OS API -#include "ring.h" // RTAPI realtime OS API -#include "shmdrv.h" // common shared memory API -#include "rtapi_compat.h" // flavor support - -#ifdef ULAPI - -static rtapi_switch_t dummy_ulapi_switch_struct; - -// exported symbols -// since this is normal userland linking, not RT loading, no need to -// EXPORT_SYMBOL() any of those - -rtapi_switch_t *rtapi_switch = &dummy_ulapi_switch_struct; -global_data_t *global_data; -struct rtapi_heap *global_heap; -extern ringbuffer_t rtapi_message_buffer; // error ring access strcuture -int rtapi_instance; -flavor_ptr flavor; -// end exported symbols: - -static void *ulapi_so; // dlopen handle for ULAPI .so -static char *ulapi_lib = "ulapi"; - -static ulapi_main_t ulapi_main_ref; -static ulapi_exit_t ulapi_exit_ref; - -// use 'ULAPI_DEBUG= ' to trace ulapi loading -static int ulapi_debug = RTAPI_MSG_NONE; - -static int ulapi_load(rtapi_switch_t **ulapi_switch); - -static int _ulapi_dummy(void) __attribute__((noreturn)); - -static int _ulapi_dummy(void) { - // API abuse trap: rtapi_init() must be first, and succeed - // for any other _subsequent_ rtapi_* calls to succeed - - rtapi_print_msg(RTAPI_MSG_ERR, - "Error: _ulapi_dummy function called from rtapi_switch; " - "this should never happen!"); - assert("API Abuse - check your code" == NULL); -} - -int _ulapi_init(const char *modname) { - if (ulapi_load(&rtapi_switch) < 0) { - return -ENOSYS; - } - rtapi_print_msg(RTAPI_MSG_DBG, - "_ulapi_init(): ulapi %s %s loaded\n", - flavor->name, rtapi_switch->git_version); - - // switch logging level to what was set in global via msgd: - rtapi_set_msg_level(global_data->user_msg_level); - - // and return what was intended to start with - return rtapi_init(modname); -} - -// NB: must be kept in sync with rtapi_switch_t in rtapi.h - -static rtapi_switch_t dummy_ulapi_switch_struct = { - .git_version = GIT_VERSION, - .thread_flavor_name = RTAPI_NOTLOADED_NAME, - .thread_flavor_id = RTAPI_NOTLOADED_ID, - - // the only "working" method is _ulapi_init() - // which will detect and load the proper ulapi - .rtapi_init = &_ulapi_init, - - // everything else is supposed to fail miserably - // since it violates the API contract: rtapi_init() - // must be first - .rtapi_exit = (rtapi_exit_t) &_ulapi_dummy, - .rtapi_next_handle = &_ulapi_dummy, - - .rtapi_clock_set_period = &_ulapi_dummy, - .rtapi_delay = &_ulapi_dummy, - .rtapi_delay_max = &_ulapi_dummy, - .rtapi_task_pll_get_reference = &_ulapi_dummy, - .rtapi_task_pll_set_correction = &_ulapi_dummy, - - .rtapi_get_time = (rtapi_get_time_t) &_ulapi_dummy, - .rtapi_get_clocks = (rtapi_get_clocks_t) &_ulapi_dummy, - - .rtapi_prio_highest = &_ulapi_dummy, - .rtapi_prio_lowest = &_ulapi_dummy, - - .rtapi_prio_next_higher = (rtapi_prio_next_higher_lower_t) &_ulapi_dummy, - .rtapi_prio_next_lower = (rtapi_prio_next_higher_lower_t) &_ulapi_dummy, - - .rtapi_task_new = &_ulapi_dummy, - .rtapi_task_delete = &_ulapi_dummy, - .rtapi_task_start = &_ulapi_dummy, - .rtapi_wait = &_ulapi_dummy, - .rtapi_task_resume = &_ulapi_dummy, - .rtapi_task_pause = &_ulapi_dummy, - .rtapi_task_self = &_ulapi_dummy, - - .rtapi_shmem_new = (rtapi_shmem_new_t) &_ulapi_dummy, - .rtapi_shmem_new_inst = (rtapi_shmem_new_inst_t) &_ulapi_dummy, - - .rtapi_shmem_delete = (rtapi_shmem_delete_t) &_ulapi_dummy, - .rtapi_shmem_delete_inst =(rtapi_shmem_delete_inst_t)&_ulapi_dummy, - - .rtapi_shmem_getptr = (rtapi_shmem_getptr_t) &_ulapi_dummy, - .rtapi_shmem_getptr_inst = (rtapi_shmem_getptr_inst_t) &_ulapi_dummy, - - .rtapi_set_exception = &_ulapi_dummy, - .rtapi_task_update_stats = &_ulapi_dummy, - - .rtapi_malloc = (rtapi_malloc_t)&_ulapi_dummy, - .rtapi_malloc_aligned = (rtapi_malloc_aligned_t)&_ulapi_dummy, - .rtapi_calloc = (rtapi_calloc_t)&_ulapi_dummy, - .rtapi_realloc = (rtapi_realloc_t)&_ulapi_dummy, - .rtapi_free = (rtapi_free_t)&_ulapi_dummy, - .rtapi_allocsize = (rtapi_allocsize_t)&_ulapi_dummy, - .rtapi_heap_init = (rtapi_heap_init_t)&_ulapi_dummy, - .rtapi_heap_addmem = (rtapi_heap_addmem_t)&_ulapi_dummy, - .rtapi_heap_status = (rtapi_heap_status_t)&_ulapi_dummy, - .rtapi_heap_setflags = (rtapi_heap_setflags_t)&_ulapi_dummy, - .rtapi_heap_walk_freelist = (rtapi_heap_walk_freelist_t)&_ulapi_dummy, -}; - - -static int ulapi_load(rtapi_switch_t **ulapi_switch) -{ - int retval; - const char *errmsg; - rtapi_get_handle_t rtapi_get_handle; - char ulapi_lib_fname[PATH_MAX]; - char *instance = getenv("MK_INSTANCE"); - char *debug_env = getenv("ULAPI_DEBUG"); - int size = 0; - int globalkey; - - // set the rtapi_instance global for this hal library instance - if (instance != NULL) - rtapi_instance = atoi(instance); - - if (debug_env) - ulapi_debug = atoi(debug_env); - - rtapi_set_msg_level(ulapi_debug); - - // tag message origin field - rtapi_set_logtag("ulapi"); - - // first thing is to attach the global segment, based on - // the RTAPI instance id. This will contain the flavor - // this ULAPI HAL instance is to run with. - - // Also, it's the prerequisite for common error message - // handling through the message ringbuffer; unless then - // error messages will go to stderr. - - // the global segment is attached once here per ULAPI instance; - // it's address is passed to the ulapi-.so module once loaded. - - // init the common shared memory driver APU - shm_common_init(); - - globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance); - retval = shm_common_new(globalkey, &size, - rtapi_instance, (void **) &global_data, 0); - - if (retval == -ENOENT) { - // the global_data segment does not exist. Happens if the realtime - // script was not started - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: realtime not started\n", - rtapi_instance); - return retval; - } - - if (retval < 0) { - // some other error attaching global - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: shm_common_new() failed key=0x%x %s\n", - rtapi_instance, globalkey, strerror(-retval)); - return retval; - } - - if (size < sizeof(global_data_t)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: global segment size mismatch," - " expected: %zd, actual:%d\n", - rtapi_instance, sizeof(global_data_t), size); - return -EINVAL; - } - - if (global_data->magic != GLOBAL_READY) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: global segment invalid magic:" - " expected: 0x%x, actual: 0x%x\n", - rtapi_instance, GLOBAL_READY, - global_data->magic); - return -EINVAL; - } - - // global data set up ok - - // make the message ringbuffer accessible - ringbuffer_init(shm_ptr(global_data, global_data->rtapi_messages_ptr), - &rtapi_message_buffer); - - // this heap is inited in rtapi_msgd.cc - // make it accessible in HAL - global_heap = &global_data->heap; - - // obtain handle on flavor descriptor as detected by rtapi_msgd - flavor = flavor_byid(global_data->rtapi_thread_flavor); - if (flavor == NULL) { - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB:%d BUG - invalid flavor id: %d\n", - rtapi_instance, global_data->rtapi_thread_flavor); - return -EINVAL; - } - - snprintf(ulapi_lib_fname,PATH_MAX,"%s/%s-%s%s", - EMC2_RTLIB_DIR, ulapi_lib, flavor->name, flavor->so_ext); - - // dynload the proper ulapi.so: - if ((ulapi_so = dlopen(ulapi_lib_fname, RTLD_GLOBAL|RTLD_NOW)) == NULL) { - errmsg = dlerror(); - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB:%d FATAL - dlopen(%s) failed: %s\n", - rtapi_instance, ulapi_lib_fname, - errmsg ? errmsg : "NULL"); - return -ENOENT; - } - - // resolve rtapi_switch getter function - dlerror(); - if ((rtapi_get_handle = (rtapi_get_handle_t) - dlsym(ulapi_so, "rtapi_get_handle")) == NULL) { - errmsg = dlerror(); - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB:%d FATAL - resolving %s: cant" - " dlsym(rtapi_get_handle): %s\n", - rtapi_instance, ulapi_lib, errmsg ? errmsg : "NULL"); - return -ENOENT; - } - - assert(rtapi_get_handle != NULL); - - // this redirects calls to rtapi through the just-loaded ulapi - *ulapi_switch = rtapi_get_handle(); - - // from here on it is safe to call all RTAPI functions (i.e. including those - // which go through rtapi_switch) - - // resolve main function - dlerror(); - if ((ulapi_main_ref = (ulapi_main_t) - dlsym(ulapi_so, "ulapi_main")) == NULL) { - errmsg = dlerror(); - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB:%d FATAL - resolving %s: " - "cant dlsym(ulapi_main): %s\n", - rtapi_instance, ulapi_lib, errmsg ? errmsg : "NULL"); - return -ENOENT; - } - // resolve exit function - dlerror(); - if ((ulapi_exit_ref = (ulapi_exit_t) - dlsym(ulapi_so, "ulapi_exit")) == NULL) { - errmsg = dlerror(); - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB: FATAL - resolving %s:" - " cant dlsym(ulapi_exit): %s\n", - ulapi_lib, errmsg ? errmsg : "NULL"); - return -ENOENT; - } - - assert(ulapi_main_ref != NULL); - assert(ulapi_exit_ref != NULL); - - // call the ulapi init method, passing in the global segment - if ((retval = ulapi_main_ref(rtapi_instance, - flavor->flavor_id, global_data)) < 0) { - // check shmdrv, permissions - rtapi_print_msg(RTAPI_MSG_ERR, - "HAL_LIB: FATAL - cannot attach to instance %d" - " - realtime not started?\n", - rtapi_instance); - return -ENOENT; - } - - // pretty bad - we loaded the wrong ulapi.so - if (flavor->flavor_id != rtapi_switch->thread_flavor_id) { - rtapi_print_msg(RTAPI_MSG_ERR, "HAL_LIB: BUG: thread flavors disagree:" - " hal_lib.c=%d rtapi=%d\n", - flavor->flavor_id, rtapi_switch->thread_flavor_id); - } - - // sanity check - may be harmless - if (strcmp(GIT_VERSION, rtapi_switch->git_version)) { - rtapi_print_msg(RTAPI_MSG_WARN, - "HAL_LIB: UP API warning - git versions disagree:" - " hal_lib.c=%s %s=%s\n", - GIT_VERSION, ulapi_lib, rtapi_switch->git_version); - } - - // declare victory - return 0; -} - -// determine if ulapi.so loaded -int ulapi_loaded(void) { - return (rtapi_switch->thread_flavor_id != RTAPI_NOTLOADED_ID); -} - -// ULAPI cleanup. Call the exit handler and unload ulapi-.so. -void ulapi_cleanup(void) -{ - // call the ulapi exit handler - // detach the rtapi shm segment as needed - // (some flavors do not employ an rtapi shm segment) - if (ulapi_exit_ref) { - ulapi_exit_ref(rtapi_instance); - ulapi_exit_ref = NULL; - } - // NB: we do not detach the global segment - - // unload ulapi shared object. - if (ulapi_so){ - dlclose(ulapi_so); - ulapi_so = NULL; - } - // reset rtapi_switch to make the code - // serially reusable - rtapi_switch = &dummy_ulapi_switch_struct; -} - -#endif // ULAPI diff --git a/src/rtapi/ulapi_main.c b/src/rtapi/ulapi_main.c deleted file mode 100644 index a9f1a0b255..0000000000 --- a/src/rtapi/ulapi_main.c +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************** -* Description: ulapi_main.c -* -* purpose: -* - attach to the rtapi data segment within the ULAPI -* symbol namespace -* - pass in the global_data shm pointer -* - set the rtapi_instance variable -* -* Copyright (C) 2012, 2013 Michael Haberler -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -#if defined(ULAPI) - -#include "config.h" -#include "rtapi.h" /* RTAPI realtime OS API */ -#include "rtapi_global.h" /* global_data_t */ -#include "rtapi_common.h" -#include "rtapi_compat.h" -#include "shmdrv.h" - -#include -#include -#include -#include -#include //shm_open -#include -#include -#include - -int ulapi_main(int instance, int flavor, global_data_t *global) -{ - int retval = 0; - int rtapikey; - int size = 0; - - rtapi_instance = instance; // from here on global within ulapi.so - - // shm_common_init(); // common shared memory API needs this - - // the HAL library constructor already has the global - // shm segment attached, so no need to do it again here - // since we're not using the rtapi_app_init()/rtapi_app_exit() - // calling conventions might as well pass it it - - // this sets global_data for use within ulapi.so which - // has a disjoint symbol namespace from hal_lib - global_data = global; - - /* rtapi_print_msg(RTAPI_MSG_DBG,"ULAPI:%d %s %s init\n", */ - /* rtapi_instance, */ - /* rtapi_get_handle()->thread_flavor_name, */ - /* GIT_VERSION); */ - - - if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) { - - rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance); - - // attach to existing RTAPI segment - // not all thread flavors actuall might use it - if ((retval = shm_common_new(rtapikey, &size, - rtapi_instance, (void **) &rtapi_data, 0))) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: cannot attach rtapi" - " segment key=0x%x %d\n", - rtapi_instance, rtapikey, retval); - } - if (size != sizeof(rtapi_data_t)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: unexpected rtapi shm size:" - " expected: %zu actual: %d\n", - rtapi_instance, sizeof(rtapi_data_t), size); - return -EINVAL; - } - - if (MMAP_OK(global_data) && MMAP_OK(rtapi_data)) { - rtapi_print_msg(RTAPI_MSG_DBG, - "ULAPI:%d msglevel=%d/%d halsize=%d" - " %s startup %s\n", - rtapi_instance, - global_data->rt_msg_level, - global_data->user_msg_level, - global_data->hal_size, - GIT_VERSION, retval ? "FAILED" : "OK"); - } else { - rtapi_print_msg(RTAPI_MSG_DBG, - "ULAPI:%d init failed, realtime not running?" - " global=%p rtapi=%p\n", - rtapi_instance, global_data, rtapi_data); - } - } - return retval; -} - -int ulapi_exit(int instance) -{ - /* rtapi_print_msg(RTAPI_MSG_DBG, "ULAPI:%d %s exit\n", */ - /* instance, */ - /* GIT_VERSION); */ - - if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) { - // detach RTAPI segment - int retval = shm_common_detach(sizeof(rtapi_data_t), rtapi_data); - if (retval) { - rtapi_print_msg(RTAPI_MSG_ERR, - "ULAPI:%d ERROR: shm_common_detach(rtapi_data)" - " failed: %d\n", - rtapi_instance, retval); - } - rtapi_data = NULL; - } - return 0; -} - -#endif // ULAPI diff --git a/src/rtapi/userpci/Submakefile b/src/rtapi/userpci/Submakefile index 17617835ad..3af768bdb5 100644 --- a/src/rtapi/userpci/Submakefile +++ b/src/rtapi/userpci/Submakefile @@ -12,11 +12,8 @@ $(USERPCI_HEADERS): ../include/userpci/%.h: rtapi/userpci/%.h @mkdir -p ../include/userpci cp $^ $@ -ifeq ($(BUILD_DRIVERS),yes) # These headers need to remain in the 'userpci' subdirectory SUBDIRECTORY_HEADERS += $(USERPCI_HEADERS) -INSTALL_DIRS += ../include/userpci -endif clean: userpci-clean userpci-clean: diff --git a/src/rtapi/xenomai-common.h b/src/rtapi/xenomai-common.h deleted file mode 100644 index 16e7021b69..0000000000 --- a/src/rtapi/xenomai-common.h +++ /dev/null @@ -1 +0,0 @@ -#define XENOMAI_INCLUDE(header) diff --git a/src/rtapi/xenomai-kernel.c b/src/rtapi/xenomai-kernel.c deleted file mode 100644 index 7a3129933a..0000000000 --- a/src/rtapi/xenomai-kernel.c +++ /dev/null @@ -1,330 +0,0 @@ -/******************************************************************** -* Copyright (C) 2012 - 2013 John Morris -* Michael Haberler -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -#include "config.h" -#include "rtapi.h" -#include "rtapi_common.h" -#include "xenomai-common.h" - -#include XENOMAI_INCLUDE(heap.h) // RT_HEAP, H_SHARED, rt_heap_* -#include XENOMAI_INCLUDE(task.h) // RT_TASK, rt_task_*() - -#ifdef RTAPI /* In kernel land, this is equiv. to MODULE */ -#include // kfree -#include XENOMAI_INCLUDE(timer.h) // rt_timer_*() -#include "procfs_macros.h" // PROC_PRINT() - -#else /* ULAPI */ -#include /* errno */ -#include // getpid() - -#endif - -#define MAX_ERRORS 3 - -#ifdef RTAPI -static rthal_trap_handler_t old_trap_handler; -static int _rtapi_trap_handler(unsigned event, unsigned domid, void *data); - -#endif /* RTAPI */ - -/*********************************************************************** -* RT thread statistics update * -************************************************************************/ -#ifdef RTAPI -int _rtapi_task_update_stats_hook(void) -{ - int task_id = _rtapi_task_self(); - - // paranoia - if ((task_id < 0) || (task_id > RTAPI_MAX_TASKS)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_task_update_stats_hook: BUG -" - " task_id out of range: %d\n", - task_id); - return -ENOENT; - } - - RT_TASK_INFO rtinfo; - int retval = rt_task_inquire(ostask_array[task_id], &rtinfo); - if (retval) { - rtapi_print_msg(RTAPI_MSG_ERR, - "rt_task_inquire() failed: %d\n", - retval); - return -ESRCH; - } - - rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; - - ts->flavor.xeno.modeswitches = rtinfo.modeswitches; - ts->flavor.xeno.ctxswitches = rtinfo.ctxswitches; - ts->flavor.xeno.pagefaults = rtinfo.pagefaults; - ts->flavor.xeno.exectime = rtinfo.exectime; - ts->flavor.xeno.modeswitches = rtinfo.modeswitches; - ts->flavor.xeno.status = rtinfo.status; - - ts->num_updates++; - - return task_id; -} -#endif - - -/*********************************************************************** -* rtapi_module.c * -************************************************************************/ - -#ifdef RTAPI - -void _rtapi_module_init_hook(void) { - old_trap_handler = \ - rthal_trap_catch((rthal_trap_handler_t) _rtapi_trap_handler); -} - -void _rtapi_module_cleanup_hook(void) { - /* release master shared memory block */ - rthal_trap_catch(old_trap_handler); -} -#endif /* RTAPI */ - - -/*********************************************************************** -* rtapi_time.c * -************************************************************************/ - -#ifdef RTAPI -/* RTAPI time functions */ -long long int _rtapi_get_time_hook(void) { - /* The value returned will represent a count of jiffies if the - native skin is bound to a periodic time base (see - CONFIG_XENO_OPT_NATIVE_PERIOD), or nanoseconds otherwise. */ - return rt_timer_read(); -} - -/* This returns a result in clocks instead of nS, and needs to be used - with care around CPUs that change the clock speed to save power and - other disgusting, non-realtime oriented behavior. But at least it - doesn't take a week every time you call it. -*/ -long long int _rtapi_get_clocks_hook(void) { - return rt_timer_read(); -} - -void _rtapi_clock_set_period_hook(long int nsecs, RTIME *counts, - RTIME *got_counts) { - rtapi_data->timer_period = *got_counts = (RTIME) nsecs; -} - - -void _rtapi_delay_hook(long int nsec) -{ - long long int release = rt_timer_read() + nsec; - while (rt_timer_read() < release); -} -#endif /* RTAPI */ - - -/*********************************************************************** -* rtapi_task.c * -************************************************************************/ - -#ifdef RTAPI -extern int _rtapi_task_self_hook(void); - -extern rtapi_exception_handler_t rt_exception_handler; - -// not better than the builtin Xenomai handler, but at least -// hook into to rtapi_exception_handler - -int _rtapi_trap_handler(unsigned event, unsigned domid, void *data) { - struct pt_regs *regs = data; - xnthread_t *thread = xnpod_current_thread(); ; - - int task_id = _rtapi_task_self_hook(); - - rtapi_exception_detail_t detail = {0}; - - detail.task_id = task_id; - detail.error_code = thread->errcode; - - detail.flavor.xeno.event = event; - detail.flavor.xeno.domid = domid; - detail.flavor.xeno.ip = (exc_register_t) regs->ip; - detail.flavor.xeno.sp = (exc_register_t) regs->sp; - - if (rt_exception_handler) - rt_exception_handler(XK_TRAP, &detail, - (task_id > -1) ? - &global_data->thread_status[task_id] : NULL); - - // forward to default Xenomai trap handler - return ((rthal_trap_handler_t) old_trap_handler)(event, domid, data); -} - -int _rtapi_task_self_hook(void) { - RT_TASK *ptr; - int n; - - /* ask OS for pointer to its data for the current task */ - ptr = rt_task_self(); - - if (ptr == NULL) { - /* called from outside a task? */ - return -EINVAL; - } - /* find matching entry in task array */ - n = 1; - while (n <= RTAPI_MAX_TASKS) { - if (ostask_array[n] == ptr) { - /* found a match */ - return n; - } - n++; - } - return -EINVAL; -} - -int _rtapi_wait_hook(const int flags) { - - if (flags & TF_NOWAIT) - return 0; - - unsigned long overruns = 0; - int result = rt_task_wait_period(&overruns); - - if (result) { - // something went wrong: - - // update stats counters in thread status - _rtapi_task_update_stats_hook(); - - // inquire, fill in - // exception descriptor, and call exception handler - - int task_id = _rtapi_task_self(); - - // paranoid, but you never know; this index off and - // things will go haywire really fast - if ((task_id < 0) || (task_id > RTAPI_MAX_TASKS)) { - rtapi_print_msg(RTAPI_MSG_ERR, - "_rtapi_wait_hook: BUG - task_id out of range: %d\n", - task_id); - // maybe should call a BUG exception here - return; - } - - // task_data *task = &(task_array[task_id]); - rtapi_exception_detail_t detail = {0}; - rtapi_threadstatus_t *ts = &global_data->thread_status[task_id]; - rtapi_exception_t type; - - // exception descriptor - detail.task_id = task_id; - detail.error_code = result; - - switch (result) { - - case -ETIMEDOUT: - // release point was missed - detail.flavor.xeno.overruns = overruns; - - // update thread status in global_data - ts->flavor.xeno.wait_errors++; - ts->flavor.xeno.total_overruns += overruns; - type = XK_ETIMEDOUT; - break; - - case -EWOULDBLOCK: - // returned if rt_task_set_periodic() has not previously - // been called for the calling task. This is clearly - // a Xenomai API usage error. - ts->api_errors++; - type = XK_EWOULDBLOCK; - break; - - case -EINTR: - // returned if rt_task_unblock() has been called for - // the waiting task before the next periodic release - // point has been reached. In this case, the overrun - // counter is reset too. - // a Xenomai API usage error. - ts->api_errors++; - type = XK_EINTR; - break; - - case -EPERM: - // returned if this service was called from a - // context which cannot sleep (e.g. interrupt, - // non-realtime or scheduler locked). - // a Xenomai API usage error. - ts->api_errors++; - type = XK_EPERM; - break; - - default: - // the above should handle all possible returns - // as per manual, so at least leave a scent - // (or what Jeff calls a 'canary value') - ts->other_errors++; - type = XK_UNDOCUMENTED; - } - if (rt_exception_handler) - rt_exception_handler(type, &detail, ts); - } // else: ok - no overruns; -} - - - -int _rtapi_task_new_hook(task_data *task, int task_id) { - rtapi_print_msg(RTAPI_MSG_DBG, - "rt_task_create %d \"%s\" cpu=%d fpu=%d prio=%d\n", - task_id, task->name, task->cpu, task->uses_fp, - task->prio ); - - return rt_task_create(ostask_array[task_id], task->name, task->stacksize, - task->prio, - (task->uses_fp ? T_FPU : 0) | T_CPU(task->cpu)); -} - - -int _rtapi_task_start_hook(task_data *task, int task_id, - unsigned long int period_nsec) { - int retval; - - if ((retval = rt_task_set_periodic(ostask_array[task_id], TM_NOW, - period_nsec)) != 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: rt_task_set_periodic() task_id %d " - "periodns=%ld returns %d\n", - task_id, period_nsec, retval); - return -EINVAL; - } - if ((retval = rt_task_start(ostask_array[task_id], task->taskcode, - (void*)task->arg )) != 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "RTAPI: rt_task_start() task_id %d returns %d\n", - task_id, retval); - return -EINVAL; - } - - return 0; -} - - -#endif /* ULAPI */ diff --git a/src/rtapi/xenomai-kernel.h b/src/rtapi/xenomai-kernel.h deleted file mode 100644 index 42cf6885a8..0000000000 --- a/src/rtapi/xenomai-kernel.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************** -* Description: xenomai-kernel.h -* This file defines the differences specific to the -* the Xenomai kernel thread system -* -* Copyright (C) 2012 - 2013 John Morris -* Michael Haberler -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -#define FLAVOR_FLAGS XENOMAI_KERNEL_FLAVOR_FLAGS // see rtapi_compat.h - -#include "xenomai-common.h" -#include XENOMAI_INCLUDE(task.h) /* RT_TASK, rt_task_*() */ - -/* rtapi_common.c */ - -/* Priority functions settings */ - -// Xenomai rt_task priorities are 0: lowest .. 99: highest -#define PRIO_LOWEST 0 -#define PRIO_HIGHEST 99 - - -/* rtapi_module.c */ -#define HAVE_RTAPI_MODULE_INIT_HOOK - -/* rtapi_task.c */ -#define HAVE_RTAPI_TASK_NEW_HOOK -#define HAVE_RTAPI_WAIT_HOOK -#define HAVE_RTAPI_TASK_SELF_HOOK -#define HAVE_RTAPI_TASK_UPDATE_STATS_HOOK - - -/* rtapi_io hooks */ - - -/* rtapi_time.c */ -#ifdef RTAPI -#define HAVE_RTAPI_CLOCK_SET_PERIOD_HOOK -#define HAVE_RTAPI_GET_TIME_HOOK -#define HAVE_RTAPI_GET_CLOCKS_HOOK -#endif - diff --git a/src/rtapi/xenomai.h b/src/rtapi/xenomai.h deleted file mode 100644 index 0c30c4f594..0000000000 --- a/src/rtapi/xenomai.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************** -* Description: xenomai.h -* This file defines the differences specific to the -* the Xenomai user land thread system -* -* Copyright (C) 2012 - 2013 John Morris -* Michael Haberler -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -********************************************************************/ - -#define FLAVOR_FLAGS XENOMAI_FLAVOR_FLAGS // see rtapi_compat.h - -/* rtapi_proc */ -#ifdef RTAPI -#define HAVE_RTAPI_READ_STATUS_HOOK -#endif - - -/* rtapi_task.c */ -// Xenomai rt_task priorities are 0: lowest .. 99: highest -#define PRIO_LOWEST 0 -#define PRIO_HIGHEST 99 - -#define HAVE_RTAPI_TASK_DELETE_HOOK -#define HAVE_RTAPI_TASK_STOP_HOOK -#define HAVE_RTAPI_TASK_PAUSE_HOOK -#define HAVE_RTAPI_WAIT_HOOK -#define HAVE_RTAPI_TASK_RESUME_HOOK -#define HAVE_RTAPI_TASK_SELF_HOOK -#define HAVE_RTAPI_TASK_UPDATE_STATS_HOOK - -/* rtapi_time.c */ -#define RTAPI_TIME_NO_CLOCK_MONOTONIC // Xenomai has its own time features -#define HAVE_RTAPI_GET_TIME_HOOK -#define HAVE_RTAPI_GET_CLOCKS_HOOK - -/* rtapi_main.c */ -#define HAVE_RTAPI_MODULE_INIT_HOOK // arm SGXCPU handler -#define HAVE_RTAPI_MODULE_EXIT_HOOK // disarm SGXCPU handler - -/* misc */ - diff --git a/src/workaround/hardy-amd64/asm/rtai_lxrt.h b/src/workaround/hardy-amd64/asm/rtai_lxrt.h deleted file mode 100644 index 16c316a7f8..0000000000 --- a/src/workaround/hardy-amd64/asm/rtai_lxrt.h +++ /dev/null @@ -1,286 +0,0 @@ -#warning "manually modified header /usr/realtime-2.6.24-16-rtai/include/asm-x86_64/rtai_lxrt.h" - -#ifdef BROKEN_RTAI_LXRT - -/* Copyright (C) 1999-2003 Paolo Mantegazza - * extensions for user space modules are jointly copyrighted (2000) with: - * Pierre Cloutier , - * Steve Papacharalambous . - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _RTAI_ASM_X8664_LXRT_H -#define _RTAI_ASM_X8664_LXRT_H - -#include - -// the following include is in error, see https://gna.org/bugs/?19185 -// #include - -#include - -#ifdef CONFIG_RTAI_LXRT_USE_LINUX_SYSCALL -#define USE_LINUX_SYSCALL -#else -#undef USE_LINUX_SYSCALL -#endif - -#define RTAI_SYSCALL_NR 0x70000000 -#define RTAI_SYSCALL_CODE rdi -#define RTAI_SYSCALL_ARGS rsi -#define RTAI_SYSCALL_RETPNT rdx - -#define RTAI_FAKE_LINUX_SYSCALL 39 - -#ifndef NR_syscalls -#define NR_syscalls __NR_syscall_max -#endif - -#define LINUX_SYSCALL_NR orig_rax -#define LINUX_SYSCALL_REG1 rdi -#define LINUX_SYSCALL_REG2 rsi -#define LINUX_SYSCALL_REG3 rdx -#define LINUX_SYSCALL_REG4 r10 -#define LINUX_SYSCALL_REG5 r8 -#define LINUX_SYSCALL_REG6 r9 -#define LINUX_SYSCALL_RETREG rax -#define LINUX_SYSCALL_FLAGS eflags - -#define LXRT_DO_IMMEDIATE_LINUX_SYSCALL(regs) \ - do { \ - regs->rcx = regs->r10; \ - regs->LINUX_SYSCALL_RETREG = ((asmlinkage int (*)(long, ...))sys_call_table[regs->rax])(regs->rdi, regs->rsi, regs->rdx, regs->rcx, regs->rax, regs->r8, regs->r9, regs->r10, regs->r11, regs->rbx, regs->rbp, regs->r12, regs->r13, regs->r14, regs->r15); \ - } while (0) - -#define SET_LXRT_RETVAL_IN_SYSCALL(regs, retval) \ - do { \ - if (regs->RTAI_SYSCALL_RETPNT) { \ - rt_copy_to_user((void *)regs->RTAI_SYSCALL_RETPNT, &retval, sizeof(retval)); \ - } \ - } while (0) - -#define LOW 0 -#define HIGH 1 - -#if defined(CONFIG_RTAI_RTC_FREQ) && CONFIG_RTAI_RTC_FREQ >= 2 - -#define TIMER_NAME "RTC" -#define TIMER_FREQ CONFIG_RTAI_RTC_FREQ -#define TIMER_LATENCY 0 -#define TIMER_SETUP_TIME 0 -#define ONESHOT_SPAN 0 - -#else /* CONFIG_RTAI_RTC_FREQ == 0 */ - -#ifdef CONFIG_X86_LOCAL_APIC - -#define TIMER_NAME "APIC" -#define TIMER_TYPE 1 -#define HRT_LINUX_TIMER_NAME "lapic" -#define FAST_TO_READ_TSC -#define TIMER_FREQ RTAI_FREQ_APIC -#define TIMER_LATENCY RTAI_LATENCY_APIC -#define TIMER_SETUP_TIME RTAI_SETUP_TIME_APIC -#define ONESHOT_SPAN (CPU_FREQ/(CONFIG_RTAI_CAL_FREQS_FACT + 2)) //(0x7FFFFFFFLL*(CPU_FREQ/TIMER_FREQ)) -#ifdef CONFIG_GENERIC_CLOCKEVENTS -#define USE_LINUX_TIMER -#define update_linux_timer(cpuid) \ - do { hal_pend_uncond(LOCAL_TIMER_IPI, cpuid); } while (0) -#else /* !CONFIG_GENERIC_CLOCKEVENTS */ -#define update_linux_timer(cpuid) -#endif /* CONFIG_GENERIC_CLOCKEVENTS */ - -#else /* !CONFIG_X86_LOCAL_APIC */ - -#define USE_LINUX_TIMER -#define TIMER_NAME "8254-PIT" -#define TIMER_TYPE 0 -#define HRT_LINUX_TIMER_NAME "pit" -#define TIMER_FREQ RTAI_FREQ_8254 -#define TIMER_LATENCY RTAI_LATENCY_8254 -#define TIMER_SETUP_TIME RTAI_SETUP_TIME_8254 -#define ONESHOT_SPAN ((0x7FFF*(CPU_FREQ/TIMER_FREQ))/(CONFIG_RTAI_CAL_FREQS_FACT + 1)) //(0x7FFF*(CPU_FREQ/TIMER_FREQ)) -#define update_linux_timer(cpuid) hal_pend_uncond(TIMER_8254_IRQ, cpuid) - -#endif /* CONFIG_X86_LOCAL_APIC */ - -#endif /* CONFIG_RTAI_RTC_FREQ != 0 */ - -union rtai_lxrt_t { - RTIME rt; - long i[1]; - void *v[1]; -}; - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef __KERNEL__ - -#include -#include - -static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid) -{ - extern void *context_switch(void *, void *, void *); -/* REMARK: the line below is not needed in i386, why should it be so if both - math_restore do a "clts" before orring TS_USEDFPU in status ????? */ - if (task_thread_info(prev)->status & TS_USEDFPU) clts(); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) - prev->fpu_counter = 0; -#endif - context_switch(NULL, prev, next); -} - -#if 0 -#define IN_INTERCEPT_IRQ_ENABLE() do { rtai_hw_sti(); } while (0) -#define IN_INTERCEPT_IRQ_DISABLE() do { rtai_hw_cli(); } while (0) -#else -#define IN_INTERCEPT_IRQ_ENABLE() do { } while (0) -#define IN_INTERCEPT_IRQ_DISABLE() do { } while (0) -#endif - -#if 0 // optimised (?) -static inline void kthread_fun_set_jump(struct task_struct *lnxtsk) -{ - lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/ + (lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.rsp, GFP_KERNEL); - *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread; -// memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)), sizeof(struct thread_info)); - memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (void *)(lnxtsk->thread.rsp), (lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.rsp); -} - -static inline void kthread_fun_long_jump(struct task_struct *lnxtsk) -{ - lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)); -// memcpy((void *)(lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), sizeof(struct thread_info)); - memcpy((void *)lnxtsk->thread.rsp, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.rsp); -} -#else // brute force -static inline void kthread_fun_set_jump(struct task_struct *lnxtsk) -{ - lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + THREAD_SIZE, GFP_KERNEL); - *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread; - memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)), THREAD_SIZE); -} - -static inline void kthread_fun_long_jump(struct task_struct *lnxtsk) -{ - lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)); - memcpy((void *)(lnxtsk->thread.rsp & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), THREAD_SIZE); -} -#endif - -#define rt_copy_from_user(a, b, c) \ - ( { int ret = __copy_from_user_inatomic(a, b, c); ret; } ) - -#define rt_copy_to_user(a, b, c) \ - ( { int ret = __copy_to_user_inatomic(a, b, c); ret; } ) - -#define rt_put_user __put_user -#define rt_get_user __get_user - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - -#define rt_strncpy_from_user(a, b, c) \ - ( { int ret = strncpy_from_user(a, b, c); ret; } ) - -#else - -/* - * From Linux lib/usercopy.c. - */ - -#define __do_strncpy_from_user(dst,src,count,res) \ -do { \ - long __d0, __d1, __d2; \ - __asm__ __volatile__( \ - " testq %1,%1\n" \ - " jz 2f\n" \ - "0: lodsb\n" \ - " stosb\n" \ - " testb %%al,%%al\n" \ - " jz 1f\n" \ - " decq %1\n" \ - " jnz 0b\n" \ - "1: subq %1,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movq %5,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 8\n" \ - " .quad 0b,3b\n" \ - ".previous" \ - : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \ - "=&D" (__d2) \ - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ - : "memory"); \ -} while (0) - -static inline long rt_strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res; - __do_strncpy_from_user(dst, src, count, res); - return res; -} - -#endif - -//#define RTAI_DO_LINUX_SIGNAL -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); -#define RT_DO_SIGNAL(regs) do_signal(regs, NULL) -#else -__attribute__((regparm(3))) void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags); -#define RT_DO_SIGNAL(regs) do_notify_resume(regs, NULL, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)); -#endif - -#else /* !__KERNEL__ */ - -/* NOTE: Keep the following routines unfold: this is a compiler - compatibility issue. */ - -#include -#include - -static union rtai_lxrt_t _rtai_lxrt(long srq, void *arg) -{ - union rtai_lxrt_t retval; -#if 1 //def USE_LINUX_SYSCALL - syscall(RTAI_SYSCALL_NR, srq, arg, &retval); -#else - RTAI_DO_TRAP(RTAI_SYS_VECTOR, retval, srq, arg); -#endif - return retval; -} - -static inline union rtai_lxrt_t rtai_lxrt(long dynx, long lsize, long srq, void *arg) -{ - return _rtai_lxrt(ENCODE_LXRT_REQ(dynx, srq, lsize), arg); -} - -#define rtai_iopl() do { extern int iopl(int); iopl(3); } while (0) - -#endif /* __KERNEL__ */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* !_RTAI_ASM_X8664_LXRT_H */ -#endif // BROKEN_RTAI_LXRT - diff --git a/tests/cpusets/skip b/tests/cpusets/skip index c638dc2ce7..49cd71d143 100755 --- a/tests/cpusets/skip +++ b/tests/cpusets/skip @@ -10,8 +10,8 @@ set -e # Assert the cgtools are available which cgcreate >&/dev/null -# Assert we're running POSIX threads -test "$(flavor)" = posix -o "$(flavor)" = rt-preempt +# Assert we're not running Xenomai threads +test ! -e /sys/module/xeno_nucleus # Attempt to set up a cgroup with cpuset controller # diff --git a/tests/hm2-idrom/skip b/tests/hm2-idrom/skip index 8c7c821e0d..9977fbafea 100755 --- a/tests/hm2-idrom/skip +++ b/tests/hm2-idrom/skip @@ -4,4 +4,4 @@ # Skip the hm2-idrom test if not running kernel threads and the # hostmot2.so module doesn't exist for this flavor -test "$(flavor -b)" = kbuild -o -f $EMC2_HOME/rtlib/$(flavor)/hostmot2.so +test -f $EMC2_HOME/rtlib/modules/hostmot2.so diff --git a/tests/rtapi.0/expected b/tests/rtapi.0/expected index 373e7855f4..fd56d47343 100644 --- a/tests/rtapi.0/expected +++ b/tests/rtapi.0/expected @@ -1,2 +1,2 @@ -rtapi_init() failed: -38 +rtapi_init() failed: -EBUSY rtapi_init() succeeded diff --git a/tests/rtapi.0/rtapi_test.c b/tests/rtapi.0/rtapi_test.c index 62b33e6ba4..3e30f629ec 100644 --- a/tests/rtapi.0/rtapi_test.c +++ b/tests/rtapi.0/rtapi_test.c @@ -21,11 +21,16 @@ #include #include "rtapi.h" #include "syslog_async.h" +#include int main() { int comp_id = rtapi_init("testmod"); + if (comp_id == -EBUSY) { + printf("rtapi_init() failed: -EBUSY\n"); + exit(1); + } if (comp_id < 0) { printf("rtapi_init() failed: %d\n", comp_id); exit(1);