Module: xenomai-head
Branch: master
Commit: d9f6585b00ccfe952cc1e7aabea77427ff8065b2
URL:    
http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=d9f6585b00ccfe952cc1e7aabea77427ff8065b2

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Sun Jan  2 01:32:55 2011 +0100

xeno-test: simplify

---

 configure.in                                  |    5 +-
 doc/man/Makefile.am                           |    2 +-
 doc/man/xeno-test.man.in                      |  136 ------
 scripts/Makefile.am                           |    4 +-
 scripts/xeno-test.in                          |  458 --------------------
 src/testsuite/Makefile.am                     |   11 +-
 src/testsuite/xeno-test/Makefile.am           |    9 +
 src/testsuite/xeno-test/dohell                |   96 +++++
 src/testsuite/xeno-test/xeno-test-run-wrapper |   20 +
 src/testsuite/xeno-test/xeno-test-run.c       |  567 +++++++++++++++++++++++++
 src/testsuite/xeno-test/xeno-test.in          |   17 +
 11 files changed, 723 insertions(+), 602 deletions(-)

diff --git a/configure.in b/configure.in
index 38f9a53..35809f6 100644
--- a/configure.in
+++ b/configure.in
@@ -936,7 +936,6 @@ AC_CONFIG_FILES([ \
        scripts/Makefile \
        scripts/xeno-config \
        scripts/xeno-load \
-       scripts/xeno-test \
        scripts/xeno \
        src/Makefile \
        src/rtdk/Makefile \
@@ -961,6 +960,8 @@ AC_CONFIG_FILES([ \
        src/testsuite/klatency/Makefile \
        src/testsuite/unit/Makefile \
        src/testsuite/sigtest/Makefile \
+       src/testsuite/xeno-test/Makefile \
+       src/testsuite/xeno-test/xeno-test \
        src/utils/Makefile \
        src/utils/can/Makefile \
        src/utils/analogy/Makefile \
@@ -1011,9 +1012,7 @@ if test \! x$XENO_MAYBE_DOCDIR = x ; then
        doc/man/runinfo.man \
        doc/man/xeno.man \
        doc/man/xeno-config.man \
-       doc/man/xeno-info.man \
        doc/man/xeno-load.man \
-       doc/man/xeno-test.man \
        doc/doxygen/Makefile \
        doc/doxygen/Doxyfile-common \
        doc/doxygen/Doxyfile \
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 493c861..3bbe198 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -1,4 +1,4 @@
-man1_MANS = xeno-config.man xeno-info.man xeno-load.man xeno-test.man \
+man1_MANS = xeno-config.man \
            clocktest.man cyclictest.man irqbench.man irqloop.man \
            klatency.man latency.man rtcanconfig.man \
            rtcanrecv.man rtcansend.man switchbench.man \
diff --git a/doc/man/xeno-test.man.in b/doc/man/xeno-test.man.in
deleted file mode 100644
index 91befea..0000000
--- a/doc/man/xeno-test.man.in
+++ /dev/null
@@ -1,136 +0,0 @@
-'\" t
-.\" ** The above line should force tbl to be a preprocessor **
-.\" Man page for xeno-test
-.\"
-.\" Copyright (C) 2005, 2006 Romain Lenglet 
<rleng...@users.forge.objectweb.org>
-.\"
-.\" You may distribute under the terms of the GNU General Public
-.\" License as specified in the file COPYING that comes with the
-.\" Xenomai distribution.
-.\"
-.pc
-.TH XENO-TEST 1 "2006-04-29" "@PACKAGE_VERSION@" "Xenomai"
-.SH NAME
-xeno\-test \- Tests and measures the performance of a Xenomai installation
-.SH SYNOPSIS
-\fBxeno\-test\fP [\fB\-v\fP] [\fB\-w\fP \fIworkloads\fP] [\fB\-d\fP 
\fIdevice\fP] [\fB\-W\fP \fIcommand\fP] [\fB\-p\fP \fIcommand\fP] [\fB\-L\fP] 
[\fB\-N\fP \fIprefix\fP] [\fB\-m\fP | \fB\-M\fP \fIemail\fP | \fB\-U\fP 
\fIurl\fP] [\fB\-s\fP] [\fB\-l\fP \fIsamples\fP] [\fB\-h\fP [\fB\-H\fP 
\fIcategories\fP] [\fB\-B\fP \fIgranularity\fP]] [\fB\-T\fP \fIseconds\fP 
[\fB\-q\fP]] [\fB\-\-\fP] [\fIargs\fP] ...
-.SH DESCRIPTION
-\fBxeno\-test\fP measures the performance of Xenomai, by executing Xenomai's 
\fBlatency\fP tests while generating a high workload on the system.
-The default command that is executed to simulate workload (if no alternate 
command is specified with a \fB-W\fP \fIcommand\fP option) is:
-.RS
-.sp
-.B dd if=/dev/zero of=/dev/null
-.sp
-.RE
-The executed \fBlatency\fP tests periodically (every second) sample and print 
out the minimum, average, and maximum latency.
-However, by default, if no option is specified to \fBxeno\-test\fP, those 
tests are executed with the \fB\-q\fP option (see below), which disables the 
printing of samples.
-If the \fB\-q\fP option is not specified, samples are printed in groups 
separated by headers.
-In addition, \fBlatency\fP print statistics for all samples before 
terminating, and can also optionally print statistics for every group of 
samples (see the \fB\-s\fP option), and distribution histograms (see the 
\fB\-h\fP option).
-
-.SH OPTIONS
-If an invalid option is specified, \fBxeno\-test\fP prints out an usage help 
message and exits.
-
-You are strongly encouraged to use the \fB\-m\fP option, to anonymously help 
the Xenomai team collecting statistics about Xenomai's performance on the 
widest range of systems.
-
-The following options are specific to \fBxeno\-test\fP:
-.TP
-\fB\-v\fP
-Produces more verbose tests results.
-.TP
-\fB\-w\fP \fIworkloads\fP
-The number of workload commands to execute simultaneously. By default, this 
number is \fB1\fP.
-.TP
-\fB\-d\fP \fIdevice\fP
-If the default workload command is to be executed, sets the input device to be 
read by \fBdd\fP to \fIdevice\fP instead of \fB/dev/zero\fP.
-For instance, specifying the device of a real hard-drive (e.g. 
\fB/dev/hda1\fP) is useful for generating interrupts with I/O.
-The specified \fIdevice\fP must be mounted, and cannot be an NFS mount.
-.TP
-\fB\-W\fP \fIcommand\fP
-Executes the specified \fIcommand\fP to generate workload, instead of the 
default \fBdd if=/dev/zero of=/dev/null\fP command.
-If the command requires arguments, the command and its arguments must be 
quoted and passed as a single \fIcommand\fP argument.
-In addition to such static arguments, the \fIargs\fP optional arguments passed 
to \fBxeno\-test\fP are appended to \fIcommand\fP to execute it. 
-.TP
-\fB\-p\fP \fIcommand\fP
-Makes \fBxeno\-test\fP execute the specified \fIcommand\fP before and after 
all the \fBlatency\fP executions. 
-.TP
-\fB\-L\fP
-Activates logging of the tests results.
-The log file is created in the \fB/tmp/\fP directory, and is named 
\fBtest\-\fP\fIkernel_release\fP\fB\-\fP\fItimestamp\fP, where 
\fIkernel_release\fP is the release number of the running Linux kernel (as 
determined by executing \fBuname \-r\fP), and \fItimestamp\fP is a textual 
representation of the current date and time (as determined by executing 
\fBdate\fP) used to reduce the risk of file name collisions.
-The log file name can be customized by using the \fB\-N\fP option instead of, 
or in conjunction with this option.
-.TP
-\fB\-N\fP \fIprefix\fP
-Activates logging of the tests results.
-If the \fB\-L\fP option is also specified, prepends \fIprefix\fP to the log 
file name, hence the log file name is 
\fIprefix\fP\fBtest\-\fP\fIkernel_release\fP\fB\-\fP\fItimestamp\fP.
-If the \fB\-L\fP option is not specified, the log file name is 
\fIprefix\fP\fB\-\fP\fItimestamp\fP.
-This option is useful to create the log file in a different directory than 
\fB/tmp/\fP (default prefix when using the \fB\-L\fP option), by specifying a 
\fIprefix\fP which starts with an absolute directory path or a directory path 
relative to the working directory.
-.TP
-\fB\-m\fP
-Sends the tests results to the Xenomai team's email address 
(\fbxenotest.out...@gmail.com\fp), to help collecting statistics about 
Xenomai's performance. The email is sent using the system's \fBmail\fP command. 
The email's sender address is \fbxenotest.sen...@xenomai.org\fp, and the 
email's subject is \fB"xeno-test results"\fP.
-.TP
-\fB\-M\fP \fIemail\fP
-Similar to the \fB\-m\fP option, but sends the tests results to the specified 
email address instead of the default one.
-.TP
-\fB\-U\fP \fIurl\fP
-Uploads the tests results to the specified URL.
-If there is no file part in the specified \fIurl\fP, and the \fB\-L\fP or 
\fB\-N\fP option is also specified, the log file name is appended to it to form 
the URL used for upload.
-The tests results are transmitted as the contents of an HTTP request using the 
PUT method.
-The upload is performed using the \fBcurl\fP command.
-This option fails silently (i.e. the tests results are not sent) if \fBcurl\fP 
is not available.
-.PP
-The following options are directly passed to the \fBlatency\fP test command 
executed by \fBxeno\-test\fP.
-If no such options are specified, the \fB\-s \-T 120 \-q\fP options are 
implicitly passed by default by \fBxeno\-test\fP.
-Any user-specified set of options overrides this default set of options.
-.TP
-\fB\-s\fP
-Displays statistics (minimum, average, and maximum latencies) for every group 
of samples.
-The number of samples in each group is determined by the \fB\-l\fP 
\fIsamples\fP option (default is \fB21\fP samples).
-.TP
-\fB\-l\fP \fIsamples\fP
-The number of samples in every group of samples.
-This number is the number of sample lines displayed between every header line, 
and is the number of samples used to calculate intermediate statistics if the 
\fB\-s\fP option is specified.
-By default, this number is \fB21\fP.
-.TP
-\fB\-h\fP
-Displays histograms of all sampled data, at the end of tests.
-The number of categories - or value intervals - of each histogram is 
determined by the \fB\-H\fP \fIcategories\fP option (default is \fB100\fP 
categories).
-The granularity - or bucket size -, used to separate latency samples into 
categories, is determined by the \fB\-B\fP \fIgranularity\fP option (default is 
\fB1000\fP ns).
-This option implies \fB\-s\fP.
-.TP
-\fB\-H\fP \fIcategories\fP
-The number of categories - or value intervals - of histograms to display if 
the \fB\-h\fP option is specified.
-By default, this number is \fB100\fP. 
-.TP
-\fB\-B\fP \fIgranularity\fP
-The granularity - or bucket size -, in nanoseconds, used to discriminate 
between the categories of latency samples in histograms (to be printed if the 
\fB\-h\fP option is specified).
-By default, this number is \fB1000\fP ns.
-.TP
-\fB\-T\fP \fIseconds\fP
-The period, in seconds, during which \fBlatency\fP tests are executed.
-If that option is not specified, the tests execute infinitely until the user 
types \fBCONTROL-C\fP (i.e. sends a SIGINT signal to them).
-.TP
-\fB\-q\fP
-Disables the printing of samples and sample group statistics (hence this 
overrides the \fB\-s\fP option), and only global statistics and histograms are 
being printed.
-The default behaviour, if this option is not specified, is to display every 
sample (measured minimum, average, and maximum latency) and optionally sample 
group statistics (if \fB\-s\fP is specified).
-.TP
-.B \-\-
-Indicates the end of options.
-This must be specified before \fIargs\fP arguments if the first argument 
starts with \fB\-\fP, so that it is not considered as an option.
-.PP
-.SH "RETURN CODES"
-.TP
-.B 0
-The tests executed successfully.
-.TP
-.B 1
-An invalid option was specified.
-.SH KNOWN BUGS
-\fBlatency\fP allows to specify the \fB\-H\fP \fIcategories\fP and \fB\-B\fP 
\fIgranularity\fP options without the \fB\-h\fP option, in which case they have 
no effect.
-
-It is possible to specify the period between samples (default is \fB1 
second\fP) using the \fBlatency\fP command's \fB\-p\fP option, but this option 
cannot be passed through \fBxeno-test\fP (this conflicts with \fBxeno-test\fP's 
own \fB\-p\fP option).
-
-The workload generation task (e.g., the default \fBdd if=/dev/zero 
of=/dev/null\fP command) may terminate before the tests are finished, which may 
produce inaccurate tests results. It may be necessary to specify an alternate 
command which lasts longer, using the \fB-W\fP \fIcommand\fP option.
-
-Workload processes may not be properly killed when \fBxeno-test\fP terminate.
-.SH "SEE ALSO"
-.BR xeno\-load (1),
-.BR uname (1)
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 74d1f66..2dac697 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -1,4 +1,4 @@
-bin_SCRIPTS=xeno-config xeno-load xeno-test xeno-info xeno wrap-link.sh
+bin_SCRIPTS=xeno-config xeno-load xeno wrap-link.sh
 
 install-exec-local:
        @if test -r $(srcdir)/postinstall.sh ; then \
@@ -10,11 +10,9 @@ EXTRA_DIST = \
        bootstrap \
        prepare-kernel.sh \
        prepare-patch.sh \
-       xeno-info \
        wrap-link.sh \
        Kconfig.frag \
        Modules.frag \
        defconfig.frag \
        help_from_kconfig.pl \
        $(wildcard postinstall.sh)
-
diff --git a/scripts/xeno-test.in b/scripts/xeno-test.in
deleted file mode 100644
index e5b71b0..0000000
--- a/scripts/xeno-test.in
+++ /dev/null
@@ -1,458 +0,0 @@
-#! /bin/sh
-
-# Adapted to be run also under the BusyBox. 
-# If you want to test it this way, do: sh xeno-test
-# BusyBox >= 1.1.3 with a make defconfig should provide all needed applets.
-
-prefix="@prefix@"
-pkgdatadir="@exec_prefix@/share/xenomai"
-
-myusage() {
-    cat >&1 <<EOF
-xeno-test [options]
-  runs latency test in all 3 test-modes
-  -w <number>  spawn N workloads (dd if=/dev/zero of=/dev/null) default=1
-  -d <device>  used as alternate src in workload (dd if=$device ..)
-               The device must be mounted, and (unfortunately) cannot
-               be an NFS mount a real device (ex /dev/hda) will
-               generate interrupts
-  -W <script>   script is an alternate workload.  If you need to pass args
-               to your program, use quotes.  The program must clean
-               up its children when it gets a SIGTERM
-  -P <cmd>     cmd is run before and after rt-tests
-               (forex: 'ntpdate -b <host>' or 'ntpq -p')
-  -L           writes logs to /tmp/test-`uname -r`-<timestamp>
-  -N <name>    like -L, but writes to name-<timestamp> (in PWD)
-               name can be full or relative pathname
-  -v           verbose
-  -M <email>   sends output to given addr
-  -m           sends output to xenomai-d...@gna.org
-  -U <url>     uploads output to given URL
-  -D <datefmt> alternate options to date, for timestamp (dflt: 
-
-  # following options are passed thru to latency
-  -s   print statistics of sampled data (default on)
-  -h   print histogram of sampled data (default on, implies -s)
-  -q   quiet, dont print 1 sec sampled data (default on, off if !-T)
-  -T <sec test>                 (default: 120 sec)
-  -l <data/header lines> (default 21)
-  -H <bucketcount>      (default 100)
-  -B <bucketsize ns>    (default 1000 ns)
-  -p <sample_period_us>         (default 100 us)
-EOF
-    # NB: many defaults are coded in latency
-    exit 1
-}
-
-echo "xeno-test: started $*"
-#set -e        # ctrl-C's should end everything, not just subshells. 
-       # commenting it out may help to debug stuff.
-
-set -o notify  # see dd's finish immediately.(or not!)
-
-withBusybox=0
-if sh --help 2>&1| grep -q BusyBox; then
-    withBusybox=1;
-# else running a real /bin/sh (bash) shell
-fi
-echo withBusybox is $withBusybox
-pidFile=/var/lock/`basename $0.$$`.pids
-
-checkUtilities() {
-  # Check for needed helper utilities
-  neededApplets="awk basename cut date dd dirname egrep grep head
-                      kill md5sum mount sleep test top uname zcat"
-  foundAll=1
-  for  _j in $neededApplets
-  do
-    if test -z "`which $_j`"; then
-      echo "Please build busybox with support for applet $_j"
-      foundAll=0
-    fi
-  done
-  if ! type getopts 2>&1 >/dev/null; then
-    echo "Please build busybox's ash with support for getopts"
-    foundAll=0
-  fi
-  if test $foundAll -eq 0 ; then 
-      needApplets=""
-      foundAll=""
-      exit 3
-  fi
-  needApplets=""
-  foundAll=""
-}
-
-checkHelpers() {
-  foundAll=1
-  if test -z "`which script`" -a -n "$logging"; then
-      echo "You will not be able to log (-L option) as script is missing"
-      foundAll=0
-  fi
-  if test -z "`which mail`" -a "$sendit" = 'm' ; then
-      echo "You will not be able send mail (-m/-M options) as mail is missing"
-      foundAll=0
-  fi
-  if test -z "`which curl`" -a "$sendit" = 'm' ; then
-      echo "You will not be able to upload (-U option) as curl is missing"
-      foundAll=0
-  fi
-  if test $foundAll -eq 0 ; then 
-      foundAll=""
-      exit 3
-  fi
-  foundAll=""
-}
-
-loudly() {
-    [ "$1" = "" ] && return
-    # run task after announcing it
-    echo; date;
-    echo running: $*
-    eval $* &                  # eval helps w complex cmds, like zegrep -E
-    wait $!
-}
-
-# defaults for cpu workload 
-device=/dev/zero       
-dd_jobs=
-
-# used in generate-loads
-mkload() { dd if=$device of=/dev/null $* & }
-
-generate_loads() {
-    jobsct=$1;
-    # if test -z "$1"; then echo Skipping generate_loads; return; fi
-    shift 1
-    if test 0 -eq $withBusybox ; then
-       reaper() { echo something died a $! or $* ; sleep 1;  }
-       trap reaper CHLD
-       trap cleanup_load EXIT  # under all exit conditions
-    fi
-    while test $jobsct -ge 1; do 
-        jobsct=$(($jobsct-1));
-        mkload
-        dd_jobs="$dd_jobs $!" ;
-    done
-
-    echo dd workload started, pids $dd_jobs stored in $pidFile
-    echo  $dd_jobs > $pidFile
-    jobsct=""
-}
-
-cleanup_load() {
-    # kill the workload
-    if test -z "$dd_jobs" -a -r $pidFile; then
-      dd_jobs=`cat $pidFile`
-      rm -f $pidFile
-    fi
-
-    if test -z "$dd_jobs" ; then
-        echo "cleanup_load: no dd_jobs found"
-    else
-       for _j in $dd_jobs
-       do
-         ps | grep $_j
-         kill $_j
-       done
-    fi
-    unset dd_jobs;
-}
-
-whatconf="XENO|IPIPE|PREEMPT|CONFIG_ACPI|CONFIG_PM|CPU_FREQ|CONFIG_DEBUG_SPINLOCK|CONFIG_FRAME_POINTER"
-
-
-boxinfo() { # static info, show once
-    loudly `dirname $0`/xeno-config --verbose
-    loudly `dirname $0`/xeno-info
-
-    loudly cat /proc/cpuinfo   # bogomips changes under CPU_FREQ
-    loudly md5sum /proc/cpuinfo        '# cpuinfo fingerprint'
-
-    # how much of the config do we want ?
-    filter=" grep -E '$whatconf'"
-    [ "$verbose" = 1 ] && filter=
-    if test -f /proc/config.gz; then # get the config
-         loudly zcat /proc/config.gz | $filter
-    elif test -f /lib/modules/`uname -r`/build/.config
-    then
-       loudly cat /lib/modules/`uname -r`/build/.config | $filter
-    fi
-
-    [ -d /proc/adeos ] && for f in /proc/adeos/*; do loudly cat $f; done
-    [ -d /proc/ipipe ] && for f in /proc/ipipe/*; do loudly cat $f; done
-    filter=""
-}
-
-boxstatus() {     # get dynamic status
-    loudly cat /proc/interrupts
-    loudly cat /proc/loadavg
-    loudly cat /proc/meminfo
-
-    if [ -d /proc/xenomai ]; then
-       for f in /proc/xenomai/*;   do [ -f $f ] && loudly cat $f; done
-       for f in /proc/xenomai/*/*; do [ -f $f ] && loudly cat $f; done
-    fi
-    [ -n "$prepost" ] && loudly $prepost
-    if test 0 -eq $withBusybox ; then
-       loudly top -bn1c | head -n $(( 12 + $workload ))
-    else
-       loudly top | head -n $(( 12 + $workload ))
-    fi
-}
-
-
-run_w_load() {
-    local latpass
-    local sbpass
-
-    while :; do 
-       case $1 in
-       *=*)
-           eval "$1"
-           shift;;
-       *)
-           break;;
-       esac
-    done
-
-    latpass="$*";
-    [ "$latpass" = '' ] && latpass='-sh -T 120'
-    [ "$sbpass" = '' ] && sbpass='-h'
-
-    boxinfo
-    loudly generate_loads $workload
-    boxstatus
-    (
-        cd $pkgdatadir/testsuite/latency
-       loudly ./run -- $XENOT_LATENCY $latpass -t0 '# latency'
-       loudly ./run -- $XENOT_LATENCY $latpass -t1 '# latency'
-       loudly ./run -- $XENOT_LATENCY $latpass -t2 '# latency'
-    )
-    (  cd $pkgdatadir/testsuite/switchtest
-       loudly ./run -- -T 120 $XENOT_SWITCHTEST '# switchtest'
-    )
-    (  cd $pkgdatadir/testsuite/switchbench
-       loudly ./run -- $XENOT_SWITCHBENCH $sbpass '# switchbench'
-    )
-    (  cd $pkgdatadir/testsuite/cyclic
-       loudly ./run -- -p 10 -n -l 1000 $XENOT_CYCLIC '# cyclictest'
-    )
-
-    if [ "$XENOT_IRQBENCH" != "" ] ; then
-       (
-           cd $pkgdatadir/testsuite/irqbench
-           loudly ./run -- -P 10 $XENOT_IRQBENCH -t0 '# irqbench user'
-           loudly ./run -- -P 10 $XENOT_IRQBENCH -t1 '# irqbench kernel'
-           loudly ./run -- -P 10 $XENOT_IRQBENCH -t2 '# irqbench irq-handler'
-           loudly ./run -- -P 10 $XENOT_IRQBENCH -t3 '# irqbench 
hard-irq-handler'
-       )
-    fi
-
-    boxstatus
-    cleanup_load
-}
-
-#####################
-# MAIN
-checkUtilities
-
-if [ -f /proc/config.gz ] ; then
-
-    # check/warn on problem configs
-    eval `zcat /proc/config.gz | grep CONFIG_CPU_FREQ` ;
-    if [ ! -z "$CONFIG_CPU_FREQ" ] ; then
-       echo "warning: CONFIG_CPU_FREQ=$CONFIG_CPU_FREQ may be problematic"
-    fi
-fi
-
-workload=1     # default = 1 job
-
-# *pass get all legit options, except -N, -L
-latpass=       # pass thru to latency
-sbpass=         # pass thru to switchbench
-loadpass=      # pass thru to subshell, not to actual tests
-
-logging=       # no logging by default
-logfile=test-`uname -r` # defaults to test-`uname -r`-<datestampe>
-logprefix=/tmp/        # someplace usually there
-prepost=       # command to run pre, and post test (ex ntpq -p)
-
-email='xenomai-d...@gna.org'           # may reject til you subscribe
-sentby='xenotest.sen...@xenomai.org'   # tbd
-url=
-sendit=                # send it by m-mail, u-url
-verbose=
-dateargs='+%y%m%d.%H%M%S'
-
-sendit() {
-    file=$1
-    if test "$sendit" = 'm' ; then
-       echo "mailing $file to $email"
-       if test -n "$file" ; then
-           mail -s 'xeno-test results' $email -- -F $sentby < $file
-       else
-           cat - | mail -s 'xeno-test results' $email -- -F $sentby
-       fi
-    elif test "$sendit" = 'u' ; then
-       echo "uploading $file to $url"
-       which curl && curl -T $file $url
-       # -x $proxy >/tmp/.submit_result
-       # which wget && curl -T $file $url \
-    else
-       echo "sendit unsupported option '$sendit'"
-    fi
-    file=""
-}
-
-handle_options() {     # called for XENOTEST_OPTS, ARGV
-    case $FOO in
-
-       # latency & switchbench passthrus
-       h)
-           latpass="$latpass -$FOO"
-           sbpass="$sbpass -$FOO" ;;
-       p)
-           latpass="$latpass -$FOO $OPTARG"
-           sbpass="$sbpass -$FOO $OPTARG" ;;
-
-       # latency only passthrus
-       s|q)
-           latpass="$latpass -$FOO" ;;
-       T|l|H|B)
-           latpass="$latpass -$FOO $OPTARG" ;;
-
-       # workload related
-       d) 
-           device=$OPTARG    
-           echo creating workload using dd if=$device
-           if !(mount | grep -q ^$device) ; then
-               echo d option must be a block device, ie one of:
-               mount | cut -d\  -f1 | egrep -ve 'sysfs|proc|depts'
-               exit 1;
-           fi
-           loadpass="$loadpass -d $device"
-           ;;
-       w)
-           workload=$OPTARG
-           loadpass="$loadpass -w $OPTARG"  ;;
-       W)
-           altwork=$OPTARG
-           loadpass="$loadpass -W '$OPTARG'"  ;;
-       P)
-           prepost=$OPTARG 
-           loadpass="$loadpass -P '$OPTARG'"  ;;
-
-       # output disposition
-       L)
-           logging=1
-           logfile=test-`uname -r`  ;;
-       N)
-           logging=1
-           logprefix=$OPTARG ;;
-       M)
-           email=$OPTARG 
-           sendit='m' ;;
-       m)
-           sendit='m' ;;
-       U)
-           url=$OPTARG 
-           sendit='u' ;;
-       v)
-           verbose=1 ;;
-       D)
-           dateargs=$OPTARG ;;
-       ?)
-           myusage ;;
-    esac
-}
-
-# process options from envar, then from cmd-line
-while getopts 'd:shqvT:l:H:B:uLN:w:W:p:mM:U:P:D:' FOO $XENOTEST_OPTS ; do
-    handle_options;
-done
-while getopts 'd:shqvT:l:H:B:uLN:w:W:p:mM:U:P:D:' FOO ; do
-    handle_options;
-done
-
-checkHelpers
-
-# all args have been handled, and split into 2 passthrus
-shift $(($OPTIND - 1));
-
-if test -f pidFile && ! test -w $pidFile ; then
-  echo  "pidfile $pidFile not writable "; 
-  exit 4
-fi
-
-echo "xeno-test: running tests"
-
-wfile=$logprefix$logfile-`date $dateargs`
-if test "$logging" != "" ; then
-    # restart inside a script invocation, passing appropriate args
-    script -c "`dirname $0`/xeno-test $loadpass $latpass $*" $wfile
-    res="$?"
-    if test "$res" = "0" ; then
-       sendit $wfile
-    fi
-else
-    if test "$altwork" != "" ; then
-       mkload() { exec $altwork; }
-    fi
-    run_w_load sbpass="$sbpass" $latpass $* 2>&1 | tee $wfile
-    res="$?"
-    if test "$sendit" != '' && test $res -eq 0  ; then
-       sendit $wfile
-    fi
-fi
-
-echo "xeno-test: finished"
-exit 0
-
-
-#################################################
-#
-#DONE:
-#
-#1. added -W <program invocation>
-#
-#The program should generate a load that is appropriately demanding
-#upon cpu, interrupts, devices, etc.
-#
-#It should also work when invoked more than once, and scale the loads
-#reasonably linearly (since the -w will count by N).
-#
-#Also, if it spawns subtasks, it should end them all when it gets SIGTERM.
-#
-#
-#2. added timestamp to the output filename to avoid overwriting
-#   previous results.
-#
-#3. added -p 'command', which runs command before, between, and after
-#   the latency tests.
-#
-#
-#TODO:
-#
-#1. get workload child reaper to work when child is killed from
-#separate window, or when it finishes.  Forex, 'dd if=/dev/hda ...'
-#will eventually finish, and should be restarted to keep the load up.
-#Figure out why killall didnt work properly.
-#
-#2. Much more testing.  Heres a weak start. You might be better off
-#using and improving test/test-xeno-test.rb.
-#
-##!/bin/bash
-#PATH=.:$PATH
-#xeno-test -L
-#xeno-test -N foo -T 18 -l 6 -s
-#xeno-test -L -N foo1-
-#xeno-test -m
-#xeno-test -T 1 -M $u...@localhost
-#xeno-test -N foo0 -w0 -l 5 -T 30 -h
-#xeno-test -L -N foo4- -w4
-#xeno-test -L -N foo4W- -w4 -W 'dd if=/dev/hda1 of=/dev/null'
-#
-#3. Repeat the same tests under the BusyBox.
-#
-#4. Check for border cases like missing awk, curl, mail, script, 
/proc/config.gz
diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am
index 70ab3ce..761a58d 100644
--- a/src/testsuite/Makefile.am
+++ b/src/testsuite/Makefile.am
@@ -1 +1,10 @@
-SUBDIRS = latency cyclic switchtest irqbench clocktest klatency unit sigtest
+SUBDIRS = \
+       latency \
+       cyclic \
+       switchtest \
+       irqbench \
+       clocktest \
+       klatency \
+       unit \
+       sigtest \
+       xeno-test
diff --git a/src/testsuite/xeno-test/Makefile.am 
b/src/testsuite/xeno-test/Makefile.am
new file mode 100644
index 0000000..f3e0e5a
--- /dev/null
+++ b/src/testsuite/xeno-test/Makefile.am
@@ -0,0 +1,9 @@
+testdir = @XENO_TEST_DIR@
+
+test_SCRIPTS = xeno-test-run-wrapper dohell
+test_PROGRAMS = xeno-test-run
+bin_SCRIPTS = xeno-test
+
+xeno_test_run_CPPFLAGS = -DTESTDIR=\"$(testdir)\"
+
+EXTRA_DIST = $(test_SCRIPTS)
diff --git a/src/testsuite/xeno-test/dohell b/src/testsuite/xeno-test/dohell
new file mode 100644
index 0000000..cdece39
--- /dev/null
+++ b/src/testsuite/xeno-test/dohell
@@ -0,0 +1,96 @@
+#! /bin/sh
+
+usage() {
+    cat <<EOF
+$0 [ -b path ] [ -s server ] [ -p port ] [ -m mntpoint ] [ -l path | seconds ]
+
+Generate load, using:
+- hackbench if the path to the hackbench binary is specified with -b;
+- nc to send TCP data to "server" port "port" if -s is specified (if -p
+is not specified, the port 9, aka discard is used);
+- dd to write data under "mntpoint" if -m is specified.
+- during the runtime of the LTP test if the path to the LTP installation
+directory is specifed with -l
+- or during "seconds" seconds
+EOF
+}
+
+port=9
+while [ $# -gt 0 ]; do
+    case $1 in
+       -h|--help) usage
+           exit 0;;
+       -b) shift; hackbench="$1"; shift
+           ;;
+       -s) shift; server="$1"; shift
+           ;;
+       -p) shift; port="$1"; shift
+           ;;
+       -m) shift; mntpoint="$1"; shift
+           ;;
+       -l) shift; ltpdir="$1"; shift
+           ;;
+       -*) usage
+           exit 1;;
+       *) break;;
+    esac
+done
+
+if [ -z "$ltpdir" -a $# -ne 1 ]; then
+    usage
+    exit 1
+fi
+
+pids=""
+
+if [ -n "$server" ]; then
+    if type nc > /dev/null 2>&1; then
+       nc=nc
+    elif type netcat > /dev/null 2>&1; then
+       nc=netcat
+    else
+       echo netcat or nc not found
+       exit 1
+    fi
+
+    seq 1 399999 > /tmp/netcat.data
+    ( while :; do cat /tmp/netcat.data; sleep 15; done | $nc $server $port ) &
+    pids="$!"
+fi
+
+if [ -n "$mntpoint" ]; then
+    while :; do dd if=/dev/zero of=$mntpoint/bigfile bs=1024000 count=100; 
done &
+    pids="$pids $!"
+fi
+
+if [ -n "$hackbench" ]; then
+    while :; do $hackbench 1; done &
+    pids="$pids $!"
+fi
+
+while :; do cat /proc/interrupts; done > /dev/null 2>&1 &
+pids="$pids $!"
+
+while :; do ps w; done > /dev/null 2>&1 &
+pids="$pids $!"
+
+dd if=/dev/zero of=/dev/null &
+pids="$pids $!"
+
+while :; do ls -lR / > /dev/null 2>&1; done &
+pids="$pids $!"
+
+test -e /proc/sys/kernel/hung_task_timeout_secs && \
+echo 0 > /proc/sys/kernel/hung_task_timeout_secs
+
+if [ -n "$ltpdir" ]; then
+    cd "$ltpdir" && ./runalltests.sh
+    cd "$ltpdir" && ./runalltests.sh
+else
+    sleep $1
+fi
+
+kill $pids > /dev/null 2>&1
+sleep 5
+killall -KILL -q cat $nc dd hackbench ls ps
+killall -KILL -q `basename $0` sleep
diff --git a/src/testsuite/xeno-test/xeno-test-run-wrapper 
b/src/testsuite/xeno-test/xeno-test-run-wrapper
new file mode 100644
index 0000000..d12d6a5
--- /dev/null
+++ b/src/testsuite/xeno-test/xeno-test-run-wrapper
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+check_alive()
+{
+    echo check_alive ${1+"$@"} >&1023
+}
+
+start_load()
+{
+    echo start_load >&1023
+}
+
+wait_load()
+{
+    read rc <&1022
+}
+
+script="$1"; shift
+set -- ${1+"$@"}
+source $script
diff --git a/src/testsuite/xeno-test/xeno-test-run.c 
b/src/testsuite/xeno-test/xeno-test-run.c
new file mode 100644
index 0000000..e1db488
--- /dev/null
+++ b/src/testsuite/xeno-test/xeno-test-run.c
@@ -0,0 +1,567 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/select.h>
+
+#define CHILD_SCRIPT  0
+#define CHILD_CHECKED 1
+#define CHILD_LOAD    2
+#define CHILD_ANY     -1
+
+struct child {
+       unsigned type: 2;
+       unsigned dead: 1;
+       pid_t pid;
+       struct child *next;
+       int in, out;
+       time_t timeout;
+       int exit_status;
+       void (*handle)(struct child *, fd_set *);
+};
+
+#define fail_fprintf(f, fmt, args...) \
+       fprintf(f, "%s failed: " fmt, scriptname , ##args)
+
+#define fail_perror(str) \
+       fail_fprintf(stderr, "%s: %s\n", str, strerror(errno))
+
+static const char *scriptname;
+static volatile int sigexit;
+static sigset_t sigchld_mask;
+static struct child *first_child;
+static char *loadcmd = "exec dd if=/dev/zero of=/dev/null";
+static fd_set inputs;
+static struct child script, load;
+
+void handle_checked_child(struct child *child, fd_set *fds);
+void handle_script_child(struct child *child, fd_set *fds);
+void handle_load_child(struct child *child, fd_set *fds);
+
+int child_initv(struct child *child, int type, char *argv[])
+{
+       int pipe_in[2];
+       int pipe_out[2];
+       int err, i;
+       pid_t pid;
+
+       if (pipe(pipe_out) < 0)
+               return -errno;
+
+       /* Set the CLOEXEC flag so that we do not leak file
+          descriptors in our children. */
+       fcntl(pipe_out[0], F_SETFD,
+             fcntl(pipe_out[0], F_GETFD) | FD_CLOEXEC);
+       fcntl(pipe_out[1], F_SETFD,
+             fcntl(pipe_out[0], F_GETFD) | FD_CLOEXEC);
+
+       if (type == CHILD_SCRIPT) {
+               if (pipe(pipe_in) < 0)
+                       goto err_close_pipe_out;
+
+               /* Set the CLOEXEC flag so that we do not leak file
+                  descriptors in our children. */
+               fcntl(pipe_in[0], F_SETFD,
+                     fcntl(pipe_out[0], F_GETFD) | FD_CLOEXEC);
+               fcntl(pipe_in[1], F_SETFD,
+                     fcntl(pipe_out[0], F_GETFD) | FD_CLOEXEC);
+
+       }
+
+       sigprocmask(SIG_BLOCK, &sigchld_mask, NULL);
+       pid = vfork();
+       if (pid < 0) {
+               sigprocmask(SIG_UNBLOCK, &sigchld_mask, NULL);
+               err = -errno;
+               goto out_close_pipe;
+       }
+
+       if (pid == 0) {
+               sigprocmask(SIG_UNBLOCK, &sigchld_mask, NULL);
+
+               switch(type) {
+               case CHILD_CHECKED:
+               case CHILD_LOAD:
+                       if (dup2(pipe_out[1], STDOUT_FILENO) < 0) {
+                               fail_perror("dup2(pipe_out)");
+                               _exit(EXIT_FAILURE);
+                       }
+                       if (dup2(pipe_out[1], STDERR_FILENO) < 0) {
+                               fail_perror("dup2(pipe_err)");
+                               _exit(EXIT_FAILURE);
+                       }
+                       break;
+
+               case CHILD_SCRIPT:
+                       if (dup2(pipe_in[0], 1022) < 0) {
+                               fail_perror("dup2(pipe_in)");
+                               _exit(EXIT_FAILURE);
+                       }
+                       if (dup2(pipe_out[1], 1023) < 0) {
+                               fail_perror("dup2(pipe_out)");
+                               _exit(EXIT_FAILURE);
+                       }
+                       break;
+               }
+
+               err = execvp(argv[0], argv);
+               if (err < 0) {
+                       fail_fprintf(stderr, "execvp(%s): %m", argv[0]);
+                       _exit(EXIT_FAILURE);
+               }
+       }
+       child->type = type;
+       child->dead = 0;
+       child->pid = pid;
+
+       child->next = first_child;
+       first_child = child;
+       sigprocmask(SIG_UNBLOCK, &sigchld_mask, NULL);
+
+       fprintf(stderr, "Started child %d:", pid);
+       for (i = 0; argv[i]; i++)
+               fprintf(stderr, " %s", argv[i]);
+       fputc('\n', stderr);
+
+       close(pipe_out[1]);
+       fcntl(pipe_out[0], F_SETFL,
+             fcntl(pipe_out[0], F_GETFL) | O_NONBLOCK);
+       child->out = pipe_out[0];
+       FD_SET(child->out, &inputs);
+
+       if (type == CHILD_SCRIPT) {
+               close(pipe_in[0]);
+               child->in = pipe_in[1];
+       }
+
+       time(&child->timeout);
+       child->timeout += 300;
+
+       switch(type) {
+       case CHILD_CHECKED:
+               child->handle = handle_checked_child;
+               break;
+       case CHILD_SCRIPT:
+               child->handle = handle_script_child;
+               break;
+       case CHILD_LOAD:
+               child->handle = handle_load_child;
+               break;
+       }
+
+       return 0;
+
+  out_close_pipe:
+       if (type == CHILD_SCRIPT) {
+               close(pipe_in[0]);
+               close(pipe_in[1]);
+       }
+  err_close_pipe_out:
+       close(pipe_out[0]);
+       close(pipe_out[1]);
+       return err;
+}
+
+int child_init(struct child *child, int type, char *cmdline)
+{
+       char *argv[] = {
+               getenv("SHELL") ?: "sh" , "-c", cmdline, NULL
+       };
+       return child_initv(child, type, argv);
+}
+
+void child_cleanup(struct child *child)
+{
+       struct child *prev;
+
+       if (child == first_child)
+               first_child = child->next;
+       else
+               for (prev = first_child; prev; prev = prev->next)
+                       if (prev->next == child) {
+                               prev->next = child->next;
+                               break;
+                       }
+
+       FD_CLR(child->out, &inputs);
+       close(child->out);
+       if (child->type == CHILD_SCRIPT)
+               close(child->in);
+}
+
+struct child *child_search(pid_t pid)
+{
+       struct child *child;
+
+       for (child = first_child; child; child = child->next)
+               if (child->pid == pid)
+                       break;
+
+       return child;
+}
+
+int children_done_p(int type)
+{
+       struct child *child;
+
+       for (child = first_child; child; child = child->next)
+               if ((type == CHILD_ANY || type == child->type) && !child->dead)
+                       return 0;
+
+       return 1;
+}
+
+int children_term(int type)
+{
+       struct child *child;
+       struct timespec ts;
+
+       for (child = first_child; child; child = child->next)
+               if (type == CHILD_ANY || child->type == type)
+                       kill(child->pid, SIGTERM);
+
+       ts.tv_sec = 5;
+       ts.tv_nsec = 0;
+       do {
+               if (children_done_p(type))
+                       return 1;
+       } while (nanosleep(&ts, &ts) == -1 && errno == EINTR);
+
+       for (child = first_child; child; child = child->next)
+               if ((type == CHILD_ANY || child->type == type)
+                   && !child->dead) {
+                       fail_fprintf(stderr, "child %d would not die, sending "
+                                  "SIGKILL\n", child->pid);
+                       kill(child->pid, SIGKILL);
+               }
+
+       return 0;
+}
+
+void sigchld_handler(int sig)
+{
+       struct child *child;
+       int status;
+       pid_t pid;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+               child = child_search(pid);
+               if (!child) {
+                       fail_fprintf(stderr, "dead child %d not found!\n", pid);
+                       exit(EXIT_FAILURE);
+               }
+
+               child->exit_status = status;
+               child->dead = 1;
+       }
+}
+
+void cleanup(void)
+{
+       if (!children_term(CHILD_ANY))
+               _exit(EXIT_FAILURE);
+}
+
+void termsig(int sig)
+{
+       sigexit = sig;
+       cleanup();
+}
+
+void copy(int from, int to)
+{
+       char buffer[4096];
+       ssize_t sz;
+
+       do {
+               ssize_t written, wsz;
+               sz = read(from, buffer, sizeof(buffer));
+               if (sz == -1) {
+                       if (errno == EAGAIN)
+                               break;
+                       fail_perror("read");
+                       exit(EXIT_FAILURE);
+               }
+
+               for (written = 0; written < sz;
+                    written += (wsz > 0 ? wsz : 0)) {
+                       wsz = write(to, buffer + written, sz - written);
+                       if (wsz == -1) {
+                               fail_perror("write");
+                               exit(EXIT_FAILURE);
+                       }
+               }
+       } while (sz > 0);
+}
+
+void handle_checked_child(struct child *child, fd_set *fds)
+{
+       time_t now = time(NULL);
+
+       if (FD_ISSET(child->out, fds)) {
+               copy(child->out, STDOUT_FILENO);
+               child->timeout = now + 300;
+       }
+
+       if (child->dead) {
+               int status = child->exit_status;
+
+               /* A checked child died, this may be abnormal if no
+                  termination signal was sent. */
+               if (WIFEXITED(status)) {
+                       if (sigexit)
+                               goto cleanup;
+                       fail_fprintf(stderr,
+                                  "child %d exited with status %d\n",
+                                  child->pid, WEXITSTATUS(status));
+               }
+
+               if (WIFSIGNALED(status)) {
+                       if (sigexit && WTERMSIG(status) == SIGTERM) {
+                         cleanup:
+                               child_cleanup(child);
+                               free(child);
+                               return;
+                       }
+                       fail_fprintf(stderr, "child %d exited with signal %d\n",
+                                  child->pid, WTERMSIG(status));
+                       if (WCOREDUMP(status))
+                               fprintf(stderr, "(core dumped)\n");
+               }
+
+               exit(EXIT_FAILURE);
+               return;
+       }
+
+       if (now > child->timeout) {
+               fail_fprintf(stderr, "child %d produced no output for 5 
minutes.\n",
+                          child->pid);
+               exit(EXIT_FAILURE);
+       }
+
+}
+
+void handle_script_child(struct child *child, fd_set *fds)
+{
+       static char buffer[4096];
+       static unsigned pos;
+       char *l, *eol;
+       ssize_t sz;
+       int rc;
+
+       if (child->dead)
+               exit(child->exit_status);
+
+       if (!FD_ISSET(child->out, fds))
+               return;
+
+       sz = read(child->out, buffer + pos, sizeof(buffer) - pos);
+       for (l = buffer; (eol = strchr(l, '\n')); l = eol + 1) {
+               char buf[16];
+               *eol = '\0';
+
+               if (!memcmp(l, "check_alive ", 12)) {
+                       struct child *new_child;
+
+                       new_child = malloc(sizeof(*new_child));
+                       if (!new_child) {
+                               fail_fprintf(stderr, "allocation failed\n");
+                               exit(EXIT_FAILURE);
+                       }
+
+                       rc = child_init(new_child, CHILD_CHECKED, l + 12);
+                       if (rc) {
+                               fail_perror("child_init");
+                               exit(EXIT_FAILURE);
+                       }
+               } else if (!memcmp(l, "start_load", 10)) {
+                       if (!load.dead) {
+                               fail_fprintf(stderr, "start_load run while load"
+                                            " script is already running.\n");
+                               exit(EXIT_FAILURE);
+                       }
+
+                       rc = child_init(&load, CHILD_LOAD, loadcmd);
+                       if (rc) {
+                               fail_perror("child_init");
+                               exit(EXIT_FAILURE);
+                       }
+               } else {
+                       fprintf(stderr, "Invalid command %s\n", l);
+                       exit(EXIT_FAILURE);
+               }
+       }
+       if (l != buffer) {
+               pos = strlen(l);
+               memmove(buffer, l, pos + 1);
+       }
+}
+
+void handle_load_child(struct child *child, fd_set *fds)
+{
+       struct child *next;
+
+       if (FD_ISSET(child->out, fds))
+               copy(child->out, STDOUT_FILENO);
+
+       if (child->dead) {
+               child_cleanup(child);
+               if (sigexit)
+                       return;
+
+               sigexit = SIGTERM;
+
+               fprintf(stderr, "Load script terminated, "
+                       "terminating checked scripts\n");
+
+               if (!children_term(CHILD_CHECKED))
+                       exit(EXIT_FAILURE);
+
+               for (child = first_child; child; child = child->next)
+                       if (child->type == CHILD_CHECKED) {
+                               child_cleanup(child);
+                               free(child);
+                       }
+
+               sigexit = 0;
+
+               write(script.in, "0\n", 2);
+               return;
+       }
+}
+
+void usage(const char *progname)
+{
+       fprintf(stderr, "%s [-l \"load command\"] script arguments...\n"
+               "Run \"script\" with \"arguments\" in a shell supplemented with"
+               " a few commands\nsuitable for running Xenomai tests.\n"
+               "\"load command\" is a command line to be run in order to"
+               " generate load\nwhile running tests.\n", progname);
+}
+
+void setpath(void)
+{
+       char *path;
+       size_t path_len;
+
+       path_len = strlen(getenv("PATH") ?: "") + strlen(TESTDIR) + 2;
+       path = malloc(path_len);
+       if (!path) {
+               perror("malloc");
+               exit(EXIT_FAILURE);
+       }
+       if (getenv("PATH"))
+               snprintf(path, path_len, TESTDIR ":%s", getenv("PATH"));
+       else
+               snprintf(path, path_len, TESTDIR);
+
+       setenv("PATH", path, 1);
+}
+
+int main(int argc, char *argv[])
+{
+       struct sigaction action;
+       int rc, maxfd;
+
+       if (argc < 2) {
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       if (!strcmp(argv[argc - 1], "-h")
+           || !strcmp(argv[argc - 1], "--help")) {
+               usage(argv[0]);
+               exit(EXIT_SUCCESS);
+       }
+
+       if (argc >= 3) {
+               if (!strcmp(argv[2], "-l")) {
+                       if (argc == 3) {
+                               usage(argv[0]);
+                               exit(EXIT_FAILURE);
+                       }
+
+                       loadcmd = argv[3];
+
+                       argv[3] = argv[1];
+                       argv += 2;
+               }
+       }
+       scriptname = argv[1];
+
+       setpath();
+
+       action.sa_handler = termsig;
+       sigemptyset(&action.sa_mask);
+       action.sa_flags = SA_RESTART;
+       if (sigaction(SIGTERM, &action, NULL) < 0) {
+               fail_perror("sigaction(SIGTERM)");
+               exit(EXIT_FAILURE);
+       }
+       if (sigaction(SIGINT, &action, NULL) < 0) {
+               fail_perror("sigaction(SIGTERM)");
+               exit(EXIT_FAILURE);
+       }
+
+       action.sa_flags |= SA_NOCLDSTOP;
+       action.sa_handler = sigchld_handler;
+       if (sigaction(SIGCHLD, &action, NULL) < 0) {
+               fail_perror("sigaction(SIGCHLD)");
+               exit(EXIT_FAILURE);
+       }
+       atexit(&cleanup);
+
+       load.dead = 1;
+       FD_ZERO(&inputs);
+       argv[0] = TESTDIR "/xeno-test-run-wrapper";
+       rc = child_initv(&script, CHILD_SCRIPT, argv);
+       if (rc < 0) {
+               fail_fprintf(stderr, "script creation failed: %s\n", 
strerror(-rc));
+               exit(EXIT_FAILURE);
+       }
+       maxfd = script.out;
+
+       for (;;) {
+               struct child *child, *next;
+               struct timeval tv;
+               fd_set in;
+               int rc;
+
+               tv.tv_sec = 0;
+               tv.tv_usec = 100000;
+
+               in = inputs;
+               rc = select(maxfd + 1, &in, NULL, NULL, &tv);
+
+               if (rc == -1) {
+                       if (errno == EINTR)
+                               continue;
+                       fail_perror("select");
+                       exit(EXIT_FAILURE);
+               }
+
+               maxfd = 0;
+               for (child = first_child; child; child = next) {
+                       next = child->next;
+
+                       if (child->out > maxfd)
+                               maxfd = child->out;
+
+                       child->handle(child, &in);
+               }
+
+               if (children_done_p(CHILD_ANY)) {
+                       if (sigexit) {
+                               signal(sigexit, SIG_DFL);
+                               raise(sigexit);
+                       }
+                       exit(EXIT_SUCCESS);
+               }
+       }
+}
diff --git a/src/testsuite/xeno-test/xeno-test.in 
b/src/testsuite/xeno-test/xeno-test.in
new file mode 100644
index 0000000..4636856
--- /dev/null
+++ b/src/testsuite/xeno-test/xeno-test.in
@@ -0,0 +1,17 @@
+#! @XENO_TEST_DIR@/xeno-test-run
+
+set -e
+
+arith
+check-vdso
+clocktest -T 10
+cond-torture-native
+cond-torture-posix
+mutex-torture-native
+mutex-torture-posix
+
+start_load
+
+check_alive latency ${1+"$@"}
+
+wait_load


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to