Module: xenomai-forge Branch: master Commit: 1d290f9b623aa450a59ced64b6455e94bf95d41e URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=1d290f9b623aa450a59ced64b6455e94bf95d41e
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Sep 23 17:16:29 2014 +0200 demo/alchemy/latency: revamp for removing legacy NOTE: we stop using TSC as the time reference unit, as this is unreliable for long durations, due to accumulated rounding errors. --- demo/alchemy/Makefile.am | 9 ++ demo/alchemy/Makefile.in | 9 ++ demo/alchemy/latency.c | 229 +++++++++++++++++----------------------------- 3 files changed, 101 insertions(+), 146 deletions(-) diff --git a/demo/alchemy/Makefile.am b/demo/alchemy/Makefile.am index c2bd0e5..406bccb 100644 --- a/demo/alchemy/Makefile.am +++ b/demo/alchemy/Makefile.am @@ -22,3 +22,12 @@ latency_SOURCES = latency.c latency_CPPFLAGS = $(cppflags) latency_LDADD = $(ldadd) -lpthread -lrt -lm latency_LDFLAGS = @XENO_AUTOINIT_LDFLAGS@ $(XENO_POSIX_WRAPPERS) + +# This demo mixes the Alchemy and Xenomai-enabled POSIX APIs over +# Cobalt, so we ask for both set of flags. --posix along with +# --ldflags will get us the linker switches causing the symbol +# wrapping for open/read/write/ioctl and friends. Over Mercury, +# --posix is ignored since it's implicitly enabled. +# +# CFLAGS = $(shell xeno-config --alchemy --posix --cflags) +# LDFLAGS = $(shell xeno-config --alchemy --posix --ldflags) diff --git a/demo/alchemy/Makefile.in b/demo/alchemy/Makefile.in index b7abefa..f606a03 100644 --- a/demo/alchemy/Makefile.in +++ b/demo/alchemy/Makefile.in @@ -816,6 +816,15 @@ uninstall-am: uninstall-demoPROGRAMS uninstall-am uninstall-demoPROGRAMS +# This demo mixes the Alchemy and Xenomai-enabled POSIX APIs over +# Cobalt, so we ask for both set of flags. --posix along with +# --ldflags will get us the linker switches causing the symbol +# wrapping for open/read/write/ioctl and friends. Over Mercury, +# --posix is ignored since it's implicitly enabled. +# +# CFLAGS = $(shell xeno-config --alchemy --posix --cflags) +# LDFLAGS = $(shell xeno-config --alchemy --posix --ldflags) + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/demo/alchemy/latency.c b/demo/alchemy/latency.c index 70c717e..7d1bf0a 100644 --- a/demo/alchemy/latency.c +++ b/demo/alchemy/latency.c @@ -3,12 +3,10 @@ #include <stdio.h> #include <string.h> #include <errno.h> -#include <signal.h> #include <sched.h> #include <time.h> -#include <sys/mman.h> -#include <sys/time.h> #include <unistd.h> +#include <signal.h> #include <alchemy/task.h> #include <alchemy/timer.h> #include <alchemy/sem.h> @@ -30,8 +28,7 @@ long long period_ns = 0; int test_duration = 0; /* sec of testing, via -T <sec>, 0 is inf */ int data_lines = 21; /* data lines per header line, -l <lines> to change */ int quiet = 0; /* suppress printing of RTH, RTD lines when -T given */ -int benchdev_no = 0; -int benchdev = -1; +int devfd = -1; int freeze_max = 0; int priority = T_HIPRIO; int stop_upon_switch = 0; @@ -51,9 +48,6 @@ const char *test_mode_names[] = { time_t test_start, test_end; /* report test duration */ int test_loops = 0; /* outer loop count */ -#define MEASURE_PERIOD ONE_BILLION -#define SAMPLE_COUNT (MEASURE_PERIOD / period_ns) - /* Warmup time : in order to avoid spurious cache effects on low-end machines. */ #define WARMUP_TIME 1 #define HISTOGRAM_CELLS 300 @@ -69,52 +63,39 @@ int bucketsize = 1000; /* default = 1000ns, -B <size> to override */ static inline void add_histogram(long *histogram, long addval) { /* bucketsize steps */ - long inabs = - rt_timer_tsc2ns(addval >= 0 ? addval : -addval) / bucketsize; + long inabs = (addval >= 0 ? addval : -addval) / bucketsize; histogram[inabs < histogram_size ? inabs : histogram_size - 1]++; } static void latency(void *cookie) { - int err, count, nsamples, warmup = 1; - RTIME expected_tsc, period_tsc, start_ticks, fault_threshold; - RT_TIMER_INFO timer_info; - unsigned old_relaxed = 0; - - err = rt_timer_inquire(&timer_info); - - if (err) { - fprintf(stderr, "latency: rt_timer_inquire, code %d\n", err); - return; - } - - fault_threshold = rt_timer_ns2tsc(CONFIG_XENO_DEFAULT_PERIOD); - nsamples = ONE_BILLION / period_ns; - period_tsc = rt_timer_ns2tsc(period_ns); - /* start time: one millisecond from now. */ - start_ticks = timer_info.date + rt_timer_ns2ticks(1000000); - expected_tsc = timer_info.tsc + rt_timer_ns2tsc(1000000); - - err = rt_task_set_periodic(NULL, start_ticks, - rt_timer_ns2ticks(period_ns)); - if (err) { + RTIME expected_ns, start_ns, fault_threshold; + unsigned int old_relaxed = 0, new_relaxed; + int ret, count, nsamples, warmup = 1; + long minj, maxj, dt, overrun, sumj; + unsigned long ov; + + fault_threshold = CONFIG_XENO_DEFAULT_PERIOD; + nsamples = (long long)ONE_BILLION / period_ns; + start_ns = rt_timer_read() + 1000000; /* 1ms from now */ + expected_ns = start_ns; + + ret = rt_task_set_periodic(NULL, start_ns, period_ns); + if (ret) { fprintf(stderr, "latency: failed to set periodic, code %d\n", - err); + ret); return; } for (;;) { - long minj = TEN_MILLIONS, maxj = -TEN_MILLIONS, dt; - long overrun = 0; - long long sumj; + minj = TEN_MILLIONS; + maxj = -TEN_MILLIONS; + overrun = 0; test_loops++; for (count = sumj = 0; count < nsamples; count++) { - unsigned new_relaxed; - unsigned long ov; - - err = rt_task_wait_period(&ov); - dt = (long)(rt_timer_tsc() - expected_tsc); + ret = rt_task_wait_period(&ov); + dt = (long)(rt_timer_read() - expected_ns); new_relaxed = sampling_relaxed; if (dt > maxj) { if (new_relaxed != old_relaxed @@ -128,21 +109,21 @@ static void latency(void *cookie) minj = dt; sumj += dt; - if (err) { - if (err != -ETIMEDOUT) { + if (ret) { + if (ret != -ETIMEDOUT) { fprintf(stderr, "latency: wait period failed, code %d\n", - err); + ret); exit(EXIT_FAILURE); /* Timer stopped. */ } overrun += ov; - expected_tsc += period_tsc * ov; + expected_ns += period_ns * ov; } - expected_tsc += period_tsc; + expected_ns += period_ns; if (freeze_max && (dt > gmaxjitter) && !(finished || warmup)) { - xntrace_user_freeze(rt_timer_tsc2ns(dt), 0); + xntrace_user_freeze(dt, 0); gmaxjitter = dt; } @@ -179,18 +160,17 @@ static void latency(void *cookie) static void display(void *cookie) { - int err, n = 0; - time_t start; char sem_name[16]; + int ret, n = 0; + time_t start; if (test_mode == USER_TASK) { snprintf(sem_name, sizeof(sem_name), "dispsem-%d", getpid()); - err = rt_sem_create(&display_sem, sem_name, 0, S_FIFO); - - if (err) { + ret = rt_sem_create(&display_sem, sem_name, 0, S_FIFO); + if (ret) { fprintf(stderr, "latency: cannot create semaphore: %s\n", - strerror(-err)); + strerror(-ret)); return; } @@ -209,13 +189,11 @@ static void display(void *cookie) config.histogram_bucketsize = bucketsize; config.freeze_max = freeze_max; - err = - rt_dev_ioctl(benchdev, RTTST_RTIOC_TMBENCH_START, &config); - - if (err) { + ret = ioctl(devfd, RTTST_RTIOC_TMBENCH_START, &config); + if (ret) { fprintf(stderr, "latency: failed to start in-kernel timer benchmark, code %d\n", - err); + ret); return; } } @@ -233,36 +211,30 @@ static void display(void *cookie) long minj, gminj, maxj, gmaxj, avgj; if (test_mode == USER_TASK) { - err = rt_sem_p(&display_sem, TM_INFINITE); - - if (err) { - if (err != -EIDRM) + ret = rt_sem_p(&display_sem, TM_INFINITE); + if (ret) { + if (ret != -EIDRM) fprintf(stderr, "latency: failed to pend on semaphore, code %d\n", - err); + ret); return; } - /* convert jitters to nanoseconds. */ - minj = rt_timer_tsc2ns(minjitter); - gminj = rt_timer_tsc2ns(gminjitter); - avgj = rt_timer_tsc2ns(avgjitter); - maxj = rt_timer_tsc2ns(maxjitter); - gmaxj = rt_timer_tsc2ns(gmaxjitter); + minj = minjitter; + gminj = gminjitter; + avgj = avgjitter; + maxj = maxjitter; + gmaxj = gmaxjitter; } else { struct rttst_interm_bench_res result; - err = - rt_dev_ioctl(benchdev, RTTST_RTIOC_INTERM_BENCH_RES, - &result); - - if (err) { - if (err != -EIDRM) + ret = ioctl(devfd, RTTST_RTIOC_INTERM_BENCH_RES, &result); + if (ret) { + if (ret != -EIDRM) fprintf(stderr, - "latency: failed to call RTTST_RTIOC_INTERM_BENCH_RES, code %d\n", - err); + "latency: failed to call RTTST_RTIOC_INTERM_BENCH_RES, %m\n"); return; } @@ -408,26 +380,24 @@ static void cleanup(void) gavgjitter /= (test_loops > 1 ? test_loops : 2) - 1; - gminj = rt_timer_tsc2ns(gminjitter); - gmaxj = rt_timer_tsc2ns(gmaxjitter); - gavgj = rt_timer_tsc2ns(gavgjitter); + gminj = gminjitter; + gmaxj = gmaxjitter; + gavgj = gavgjitter; } else { struct rttst_overall_bench_res overall; overall.histogram_min = histogram_min; overall.histogram_max = histogram_max; overall.histogram_avg = histogram_avg; - - rt_dev_ioctl(benchdev, RTTST_RTIOC_TMBENCH_STOP, &overall); - + ioctl(devfd, RTTST_RTIOC_TMBENCH_STOP, &overall); gminj = overall.result.min; gmaxj = overall.result.max; gavgj = overall.result.avg; goverrun = overall.result.overruns; } - if (benchdev >= 0) - rt_dev_close(benchdev); + if (devfd >= 0) + close(devfd); if (need_histo()) dump_hist_stats(); @@ -463,7 +433,7 @@ static void faulthand(int sig) { xntrace_user_freeze(0, 1); signal(sig, SIG_DFL); - kill(getpid(), sig); + __STD(kill(getpid(), sig)); } #ifdef CONFIG_XENO_COBALT @@ -510,7 +480,7 @@ static void sigdebug(int sig, siginfo_t *si, void *context) n = snprintf(buffer, sizeof(buffer), fmt, reason_str[reason]); n = write(STDERR_FILENO, buffer, n); signal(sig, SIG_DFL); - kill(getpid(), sig); + __STD(kill(getpid(), sig)); } #endif /* CONFIG_XENO_COBALT */ @@ -518,7 +488,7 @@ static void sigdebug(int sig, siginfo_t *si, void *context) int main(int argc, char *const *argv) { struct sigaction sa __attribute__((unused)); - int c, err, sig, cpu = -1; + int c, ret, sig, cpu = -1; char task_name[16]; cpu_set_t cpus; sigset_t mask; @@ -528,63 +498,41 @@ int main(int argc, char *const *argv) case 'g': do_gnuplot = strdup(optarg); break; - case 'h': - do_histogram = 1; break; - case 's': - do_stats = 1; break; - case 'H': - histogram_size = atoi(optarg); break; - case 'B': - bucketsize = atoi(optarg); break; - case 'p': - period_ns = atoi(optarg) * 1000LL; + if (period_ns > ONE_BILLION) { + fprintf(stderr, "latency: invalid period (> 1s).\n"); + exit(2); + } break; - case 'l': - data_lines = atoi(optarg); break; - case 'T': - test_duration = atoi(optarg); alarm(test_duration + WARMUP_TIME); break; - case 'q': - quiet = 1; break; - - case 'D': - - benchdev_no = atoi(optarg); - break; - case 't': - test_mode = atoi(optarg); break; - case 'f': - freeze_max = 1; break; - case 'c': cpu = atoi(optarg); if (cpu < 0 || cpu >= CPU_SETSIZE) { @@ -592,15 +540,12 @@ int main(int argc, char *const *argv) return 1; } break; - case 'P': priority = atoi(optarg); break; - case 'b': stop_upon_switch = 1; break; - default: fprintf(stderr, @@ -614,7 +559,6 @@ int main(int argc, char *const *argv) " [-l <data-lines per header>] # default=21, 0 to supress headers\n" " [-T <test_duration_seconds>] # default=0, so ^C to end\n" " [-q] # supresses RTD, RTH lines if -T is used\n" -" [-D <testing_device_no>] # number of testing device, default=0\n" " [-t <test_mode>] # 0=user task (default), 1=kernel task, 2=timer IRQ\n" " [-f] # freeze trace for each new max latency\n" " [-c <cpu>] # pin measuring task down to given CPU\n" @@ -680,73 +624,66 @@ int main(int argc, char *const *argv) "== All results in microseconds\n", period_ns / 1000, test_mode_names[test_mode]); - mlockall(MCL_CURRENT | MCL_FUTURE); - if (test_mode != USER_TASK) { - benchdev = open("/dev/rtdm/timerbench", O_RDWR); - if (benchdev < 0) { + devfd = open("/dev/rtdm/timerbench", O_RDWR); + if (devfd < 0) { fprintf(stderr, - "latency: failed to open benchmark device, code %d\n" - "(modprobe xeno_timerbench?)\n", benchdev); + "latency: failed to open timerbench device, %m\n" + "(modprobe xeno_timerbench?)\n"); return 0; } } snprintf(task_name, sizeof(task_name), "display-%d", getpid()); - err = rt_task_create(&display_task, task_name, 0, 0, 0); - - if (err) { + ret = rt_task_create(&display_task, task_name, 0, 0, 0); + if (ret) { fprintf(stderr, "latency: failed to create display task, code %d\n", - err); + ret); return 0; } - err = rt_task_start(&display_task, &display, NULL); - - if (err) { + ret = rt_task_start(&display_task, &display, NULL); + if (ret) { fprintf(stderr, "latency: failed to start display task, code %d\n", - err); + ret); return 0; } if (test_mode == USER_TASK) { snprintf(task_name, sizeof(task_name), "sampling-%d", getpid()); - err = - rt_task_create(&latency_task, task_name, 0, priority, - T_WARNSW); - - if (err) { + ret = rt_task_create(&latency_task, task_name, 0, priority, + T_WARNSW); + if (ret) { fprintf(stderr, "latency: failed to create latency task, code %d\n", - err); + ret); return 0; } if (cpu >= 0) { CPU_ZERO(&cpus); CPU_SET(cpu, &cpus); - err = rt_task_set_affinity(&latency_task, &cpus); - if (err) { + ret = rt_task_set_affinity(&latency_task, &cpus); + if (ret) { fprintf(stderr, "latency: failed to set CPU affinity, code %d\n", - err); + ret); return 0; } } - err = rt_task_start(&latency_task, &latency, NULL); - - if (err) { + ret = rt_task_start(&latency_task, &latency, NULL); + if (ret) { fprintf(stderr, "latency: failed to start latency task, code %d\n", - err); + ret); return 0; } } - sigwait(&mask, &sig); + __STD(sigwait(&mask, &sig)); finished = 1; cleanup(); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git