Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Philippe Gerum wrote: > On Thu, 2006-06-29 at 13:20 +0200, Jan Kiszka wrote: >> Jan Kiszka wrote: >> >>> Here comes an update of the irqbench patch. >>> >> And this add-on fixes a classic copy&paste issue. >> > > Merged, along with the generic trace support. Thanks. > Almost :) - but it's fixed now. Jan ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
On Thu, 2006-06-29 at 13:20 +0200, Jan Kiszka wrote: > Jan Kiszka wrote: > > > Here comes an update of the irqbench patch. > > > And this add-on fixes a classic copy&paste issue. > Merged, along with the generic trace support. Thanks. -- Philippe. ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Jan Kiszka wrote: > Here comes an update of the irqbench patch. > And this add-on fixes a classic copy&paste issue. Jan --- ksrc/drivers/testing/irqbench.c |8 1 file changed, 4 insertions(+), 4 deletions(-) Index: xenomai/ksrc/drivers/testing/irqbench.c === --- xenomai.orig/ksrc/drivers/testing/irqbench.c +++ xenomai/ksrc/drivers/testing/irqbench.c @@ -444,7 +444,7 @@ static struct rtdm_device device = { proc_name: device.device_name, }; -int __init __timerbench_init(void) +int __init __irqbench_init(void) { int ret; @@ -460,11 +460,11 @@ int __init __timerbench_init(void) } -void __exit __timerbench_exit(void) +void __exit __irqbench_exit(void) { rtdm_dev_unregister(&device, 1000); } -module_init(__timerbench_init); -module_exit(__timerbench_exit); +module_init(__irqbench_init); +module_exit(__irqbench_exit); signature.asc Description: OpenPGP digital signature ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Here comes an update of the irqbench patch. Changelog: - avoid printf from signal context in irqloop - reorder irq-enable code in the driver to avoid spurious replies on startup - avoid creating/destroying pthread under SCHED_FIFO (but still suffers from prio inversion during cleanup here) - fix broken conditional compilation of irqbench for x86 (probably unnoticed due to forgotten bootstrap run, sigh) - include irqbench-doc.patch Jan Subject: Introduce IRQ latency benchmark This patch introduces another rttesting driver, xeno_irqbench, for measuring external IRQ latencies. The irqbench device is controlled by a user-mode tool irqloop. A second tool for plain Linux, irqbench, is provided to trigger the event over serial or parallel cross-link (the latter is incomplete yet) and measure the reaction latency. --- configure.in |2 doc/txt/Makefile.am|1 doc/txt/irqbench.txt | 51 include/rtdm/rttesting.h | 38 ++ ksrc/drivers/Makefile |2 ksrc/drivers/testing/Kconfig | 21 + ksrc/drivers/testing/Makefile | 13 - ksrc/drivers/testing/irqbench.c| 470 + src/testsuite/Makefile.am |2 src/testsuite/irqbench/Makefile.am | 47 +++ src/testsuite/irqbench/irqbench.c | 306 src/testsuite/irqbench/irqloop.c | 173 + src/testsuite/irqbench/runinfo |1 13 files changed, 1116 insertions(+), 11 deletions(-) Index: xenomai/include/rtdm/rttesting.h === --- xenomai.orig/include/rtdm/rttesting.h +++ xenomai/include/rtdm/rttesting.h @@ -94,6 +94,28 @@ typedef struct rttst_tmbench_config { } rttst_tmbench_config_t; +#define RTTST_IRQBENCH_USER_TASK0 +#define RTTST_IRQBENCH_KERNEL_TASK 1 +#define RTTST_IRQBENCH_HANDLER 2 + +#define RTTST_IRQBENCH_SERPORT 0 +#define RTTST_IRQBENCH_PARPORT 1 + +struct rttst_irqbench_config { +int mode; +int priority; +int calibration_loops; +unsigned intport_type; +unsigned long port_ioaddr; +unsigned intport_irq; +} rttst_irqbench_config_t; + +struct rttst_irqbench_stats { +unsigned long long irqs_received; +unsigned long long irqs_acknowledged; +} rttst_irqbench_stats_t; + + #define RTTST_SWTEST_FPU0x1 #define RTTST_SWTEST_USE_FPU0x2 /* Only for kernel-space tasks. */ @@ -134,6 +156,22 @@ struct rttst_swtest_dir { _IOWR(RTIOC_TYPE_TESTING, 0x11, struct rttst_overall_bench_res) +#define RTTST_RTIOC_IRQBENCH_START \ +_IOW(RTIOC_TYPE_TESTING, 0x20, struct rttst_irqbench_config) + +#define RTTST_RTIOC_IRQBENCH_STOP \ +_IO(RTIOC_TYPE_TESTING, 0x21) + +#define RTTST_RTIOC_IRQBENCH_GET_STATS \ +_IOR(RTIOC_TYPE_TESTING, 0x22, struct rttst_irqbench_stats) + +#define RTTST_RTIOC_IRQBENCH_WAIT_IRQ \ +_IO(RTIOC_TYPE_TESTING, 0x23) + +#define RTTST_RTIOC_IRQBENCH_REPLY_IRQ \ +_IO(RTIOC_TYPE_TESTING, 0x24) + + #define RTTST_RTIOC_SWTEST_SET_TASKS_COUNT \ _IOW(RTIOC_TYPE_TESTING, 0x30, unsigned long) Index: xenomai/configure.in === --- xenomai.orig/configure.in +++ xenomai/configure.in @@ -82,6 +82,7 @@ case "$host" in esac AC_MSG_RESULT([$XENO_TARGET_ARCH]) +AM_CONDITIONAL(XENO_TARGET_ARCH_I386,[test $XENO_TARGET_ARCH = i386]) dnl dnl Parse options @@ -602,6 +603,7 @@ AC_CONFIG_FILES([ \ src/testsuite/switchbench/Makefile \ src/testsuite/cyclic/Makefile \ src/testsuite/switchtest/Makefile \ + src/testsuite/irqbench/Makefile \ include/Makefile \ include/asm-generic/Makefile \ include/asm-blackfin/Makefile \ Index: xenomai/ksrc/drivers/Makefile === --- xenomai.orig/ksrc/drivers/Makefile +++ xenomai/ksrc/drivers/Makefile @@ -11,7 +11,7 @@ else subdir-$(CONFIG_XENO_DRIVERS_16550A) += 16550A subdir-$(CONFIG_XENO_DRIVERS_TIMERBENCH) += testing - +subdir-$(CONFIG_XENO_DRIVERS_IRQBENCH) += testing subdir-$(CONFIG_XENO_DRIVERS_SWITCHTEST) += testing include $(TOPDIR)/Rules.make Index: xenomai/ksrc/drivers/testing/Kconfig === --- xenomai.orig/ksrc/drivers/testing/Kconfig +++ xenomai/ksrc/drivers/testing/Kconfig @@ -6,10 +6,19 @@ config XENO_DRIVERS_TIMERBENCH Kernel-based benchmark driver for timer latency evaluation. See testsuite/latency for a possible front-end. +config XENO_DRIVERS_IRQBENCH + depends on XENO_SKIN_RTDM + tristate "IRQ benchmark driver" + default n + help + Loopback driver for IRQ latency evaluation over serial or parallel + port links. Additionally requires user-space helper and a logging tool + (see testsuite/irqbench). + co
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Jan Kiszka wrote: > > > > Also note that calling printf from a signal handler risk deadlocking if > > the signal handler get called on the return path of the write call that > > take place in the middle of a printf call on the main thread. > > > > Ok, then we also need a fix for the latency test (this is where I > grabbed that pattern from). Is there a high risk that this locks up? I > wonder why I never observed or heard of problems with latency. The mutex used by the stdio lib depends on the file descriptor, so, it is possible to use a different file descriptor in the signal handler and on the interrupted context. -- Gilles Chanteperdrix. ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
> > Then all other threads must block signal delivering with sigprocmask() > so that the main thread is the only one which "accepts" signals. Is that required, i.e. does pause() only wake up if the signal handler executed in the main thread's context? Then cyclictest contains a bug as well... If strictly speaking, then yes, it's required. But I expect your fix to be working perfectly, just because the current linux implementation always favors the main thread when it comes to choosing a thread to handle the signal. look at signal.c :: __group_complete_signal() routine where the actual magic happens. from the comments /* * Now find a thread we can wake up to take the signal off the queue. * * If the main thread wants the signal, it gets first crack. * Probably the least surprising to the average bear. */ ... As I understand, the only case when another thread may handle the signal indeed is when the main thread has already another pending signal. But even then nothing bad happens as pause() (in the main thread) will be interrupted by this pending signal. Just "finished" will be set up by some other thread but it doesn't really matter. -- Best regards, Dmitry Adamushko ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Gilles Chanteperdrix wrote: > Jan Kiszka wrote: > > > Is there no way to make this code easier to port for example by using > > > native or posix services for timings measurement and by abstracting the > > > non portable part and moving them to include/asm-i386 ? > > > > This tool is intentionally left Xenomai-free. You can put it on any x86 > > box around (and I assume that there is almost always some...) and run > > the test. Thus, no need for a second RT-patched system. > > > > Anyway, suggestions or patches to add a porting layer are welcome. The > > following points need to be addressed: time measuring, irq protection, > > hardware access. I just wonder if this is worth the effort. > > I do not understand: it appears to me that Xenomai trunk does not > compile on other architectures than x86 when applying the IRQ latency > benchmark patch. So, something needs to be done. It may be the enabling > of an automake conditional in configure.in when compiling for x86. > See the patch: Index: xenomai/src/testsuite/irqbench/Makefile.am === --- /dev/null +++ xenomai/src/testsuite/irqbench/Makefile.am @@ -0,0 +1,47 @@ +testdir = $(prefix)/testsuite/irqbench + +test_PROGRAMS = irqloop + +ifeq ($(XENO_TARGET_ARCH),i386) +test_PROGRAMS += irqbench +endif I just realised that some hint in the documentation that irqbench can easily be compiled outside Xenomai is required. > > > > > > > > Also note that calling printf from a signal handler risk deadlocking if > > > the signal handler get called on the return path of the write call that > > > take place in the middle of a printf call on the main thread. > > > > > > > Ok, then we also need a fix for the latency test (this is where I > > grabbed that pattern from). Is there a high risk that this locks up? I > > wonder why I never observed or heard of problems with latency. > > The latency test used to deadlock, that is why the summary printed on > signal is printed on stderr. Unfortunately, there seem to be one display > left on stdout, so it should still deadlock. The reason why we never see > the deadlock is (perhaps) that the continuous intermediate results are > printed on the context of the "display" thread, whereas the termination > signals are preferably delivered by the kernel to the "main" thread, > that only calls pause. Which makes the use of stderr in signals handlers > pointless. > > Anyway, since your program is frequently using printf on the context of > the main thread, the risk of deadlock is real. > Ok, I'm going to address this. Thanks for the hint! Jan signature.asc Description: OpenPGP digital signature ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Dmitry Adamushko wrote: > On 28/06/06, Gilles Chanteperdrix <[EMAIL PROTECTED]> wrote: >> Jan Kiszka wrote: >> > >> > Ok, then we also need a fix for the latency test (this is where I >> > grabbed that pattern from). Is there a high risk that this locks up? I >> > wonder why I never observed or heard of problems with latency. >> >> The latency test used to deadlock, that is why the summary printed on >> signal is printed on stderr. Unfortunately, there seem to be one display >> left on stdout, so it should still deadlock. The reason why we never see >> the deadlock is (perhaps) that the continuous intermediate results are >> printed on the context of the "display" thread, whereas the termination >> signals are preferably delivered by the kernel to the "main" thread, >> that only calls pause. Which makes the use of stderr in signals handlers >> pointless. > > It's very likely so. > > The main thread would use instead something like : > ... > while (!sig_term_received) >pause(); > > do_cleanup_chores(); > return 0; > > cleanup_upon_sig() should only set the sig_term_received flag up. > > Then all other threads must block signal delivering with sigprocmask() > so that the main thread is the only one which "accepts" signals. Is that required, i.e. does pause() only wake up if the signal handler executed in the main thread's context? Then cyclictest contains a bug as well... > > btw, according to POSIX 1003.1-2003, the write() call is amongst "safe" > ones. > http://www.die.net/doc/linux/man/man2/signal.2.html > > So write(1, ); heh... not that nice? :) > > Something like this? Developed on top of my prio-switch patch. So far without signal masking. Jan --- src/testsuite/latency/latency.c | 46 1 file changed, 24 insertions(+), 22 deletions(-) Index: xenomai/src/testsuite/latency/latency.c === --- xenomai.orig/src/testsuite/latency/latency.c +++ xenomai/src/testsuite/latency/latency.c @@ -293,7 +293,7 @@ double dump_histogram (long *histogram, double avg = 0; /* used to sum hits 1st */ if (do_histogram) -fprintf(stderr,"---|--param|range-|--samples\n"); +printf("---|--param|range-|--samples\n"); for (n = 0; n < histogram_size; n++) { @@ -304,12 +304,11 @@ double dump_histogram (long *histogram, total_hits += hits; avg += n * hits; if (do_histogram) -fprintf(stderr, -"HSD|%s| %3d -%3d | %8ld\n", -kind, -n, -n+1, -hits); +printf("HSD|%s| %3d -%3d | %8ld\n", + kind, + n, + n+1, + hits); } } @@ -338,8 +337,8 @@ void dump_stats (long *histogram, char* variance /= total_hits - 1; variance = sqrt(variance); -fprintf(stderr,"HSS|%s| %9d| %10.3f| %10.3f\n", -kind, total_hits, avg, variance); +printf("HSS|%s| %9d| %10.3f| %10.3f\n", + kind, total_hits, avg, variance); } void dump_hist_stats (void) @@ -351,23 +350,18 @@ void dump_hist_stats (void) avgavg = dump_histogram (histogram_avg, "avg"); maxavg = dump_histogram (histogram_max, "max"); -fprintf(stderr,"HSH|--param|--samples-|--average--|---stddev--\n"); +printf("HSH|--param|--samples-|--average--|---stddev--\n"); dump_stats (histogram_min, "min", minavg); dump_stats (histogram_avg, "avg", avgavg); dump_stats (histogram_max, "max", maxavg); } -void cleanup_upon_sig(int sig __attribute__((unused))) +void cleanup(void) { time_t actual_duration; long gmaxj, gminj, gavgj; -if (finished) -return; - -finished = 1; - if (test_mode == USER_TASK) { rt_sem_delete(&display_sem); @@ -421,6 +415,11 @@ void cleanup_upon_sig(int sig __attribut exit(0); } +void sighand(int sig __attribute__((unused))) +{ +finished = 1; +} + int main (int argc, char **argv) { int c, err; @@ -532,7 +531,7 @@ int main (int argc, char **argv) histogram_min = calloc(histogram_size, sizeof(long)); if (!(histogram_avg && histogram_max && histogram_min)) -cleanup_upon_sig(0); +cleanup(); if (period_ns == 0) period_ns = 10LL; /* ns */ @@ -542,10 +541,10 @@ int main (int argc, char **argv) else if (priority > T_HIPRIO) priority = T_HIPRIO; -signal(SIGINT, cleanup_upon_sig); -signal(SIGTERM, cleanup_upon_sig); -signal(SIGHUP, cleanup_upon_sig); -signal(SIGALRM, cleanup_upon_sig); +signal(SIGINT, sighand); +signal(SIGTERM, sighand); +signal(SIGHUP, sighand); +signal(SIGALRM, sighand); setlinebuf(stdout); @@ -610,7 +609,10 @@ int main (int argc, char
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
On 28/06/06, Gilles Chanteperdrix <[EMAIL PROTECTED]> wrote: Jan Kiszka wrote: > > Ok, then we also need a fix for the latency test (this is where I > grabbed that pattern from). Is there a high risk that this locks up? I > wonder why I never observed or heard of problems with latency. The latency test used to deadlock, that is why the summary printed on signal is printed on stderr. Unfortunately, there seem to be one display left on stdout, so it should still deadlock. The reason why we never see the deadlock is (perhaps) that the continuous intermediate results are printed on the context of the "display" thread, whereas the termination signals are preferably delivered by the kernel to the "main" thread, that only calls pause. Which makes the use of stderr in signals handlers pointless. It's very likely so. The main thread would use instead something like : ... while (!sig_term_received) pause(); do_cleanup_chores(); return 0; cleanup_upon_sig() should only set the sig_term_received flag up. Then all other threads must block signal delivering with sigprocmask() so that the main thread is the only one which "accepts" signals. btw, according to POSIX 1003.1-2003, the write() call is amongst "safe" ones. http://www.die.net/doc/linux/man/man2/signal.2.html So write(1, ); heh... not that nice? :) -- Best regards, Dmitry Adamushko ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Jan Kiszka wrote: > > Is there no way to make this code easier to port for example by using > > native or posix services for timings measurement and by abstracting the > > non portable part and moving them to include/asm-i386 ? > > This tool is intentionally left Xenomai-free. You can put it on any x86 > box around (and I assume that there is almost always some...) and run > the test. Thus, no need for a second RT-patched system. > > Anyway, suggestions or patches to add a porting layer are welcome. The > following points need to be addressed: time measuring, irq protection, > hardware access. I just wonder if this is worth the effort. I do not understand: it appears to me that Xenomai trunk does not compile on other architectures than x86 when applying the IRQ latency benchmark patch. So, something needs to be done. It may be the enabling of an automake conditional in configure.in when compiling for x86. > > > > > Also note that calling printf from a signal handler risk deadlocking if > > the signal handler get called on the return path of the write call that > > take place in the middle of a printf call on the main thread. > > > > Ok, then we also need a fix for the latency test (this is where I > grabbed that pattern from). Is there a high risk that this locks up? I > wonder why I never observed or heard of problems with latency. The latency test used to deadlock, that is why the summary printed on signal is printed on stderr. Unfortunately, there seem to be one display left on stdout, so it should still deadlock. The reason why we never see the deadlock is (perhaps) that the continuous intermediate results are printed on the context of the "display" thread, whereas the termination signals are preferably delivered by the kernel to the "main" thread, that only calls pause. Which makes the use of stderr in signals handlers pointless. Anyway, since your program is frequently using printf on the context of the main thread, the risk of deadlock is real. -- Gilles Chanteperdrix. ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
Gilles Chanteperdrix wrote: > [EMAIL PROTECTED] wrote: > > Index: xenomai/src/testsuite/irqbench/irqbench.c > > === > > --- /dev/null > > +++ xenomai/src/testsuite/irqbench/irqbench.c > > @@ -0,0 +1,301 @@ > > +/* > > + * Copyright (C) 2006 Jan Kiszka <[EMAIL PROTECTED]>. > > + * > > + * Xenomai 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. > > + * > > + * Xenomai 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 Xenomai; if not, write to the Free Software Foundation, > > + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > + > > +#define SERPORT 0 > > +#define PARPORT 1 > > + > > +/* --- Serial port --- */ > > + > > +#define MCR_DTR 0x01 > > +#define MCR_RTS 0x02 > > +#define MCR_OUT20x08 > > + > > +#define MSR_DELTA 0x0F > > + > > +#define LCR(base) (base + 3) /* Line Control Register */ > > +#define MCR(base) (base + 4) /* Modem Control Register */ > > +#define LSR(base) (base + 5) /* Line Status Register */ > > +#define MSR(base) (base + 6) /* Modem Status Register */ > > + > > +/* --- Parallel port --- */ > > + > > +#define CTRL_INIT 0x04 > > + > > +#define STAT_STROBE 0x10 > > + > > +#define DATA(base) (base + 0) /* Data register */ > > +#define STAT(base) (base + 1) /* Status register */ > > +#define CTRL(base) (base + 2) /* Control register */ > > + > > +double tsc2ns_scale; > > +long long min_lat = LLONG_MAX; > > +long long max_lat = LLONG_MIN; > > +long long avg_lat = 0; > > +long outer_loops = 0; > > +int warmup = 1; > > + > > +static inline long long rdtsc(void) > > +{ > > +unsigned long long tsc; > > + > > +__asm__ __volatile__("rdtsc" : "=A" (tsc)); > > +return tsc; > > +} > > + > > + > > +static long tsc2ns(long long tsc) > > +{ > > +if ((tsc > LONG_MAX) || (tsc < LONG_MIN)) { > > +fprintf(stderr, "irqbench: overflow (%lld ns)!\n", > > +(long long)(tsc2ns_scale * (double)tsc)); > > +exit(2); > > +} > > +return (long)(tsc2ns_scale * (double)tsc); > > +} > > + > > + > > +static inline long long ns2tsc(long long ns) > > +{ > > +return (long long)(((double)ns) / tsc2ns_scale); > > +} > > + > > + > > +void calibrate_tsc(void) > > +{ > > +FILE *proc; > > +char *lineptr = NULL; > > +size_t len; > > +double cpu_mhz; > > + > > +proc = fopen("/proc/cpuinfo", "r"); > > +if (proc == NULL) { > > +perror("irqbench: Unable to open /proc/cpuinfo"); > > +exit(1); > > +} > > + > > +while (getline(&lineptr, &len, proc) != -1) > > +if (strncmp(lineptr, "cpu MHz", 7) == 0) { > > +sscanf(strchr(lineptr, ':') + 1, "%lf", &cpu_mhz); > > +break; > > +} > > + > > +if (lineptr) > > +free(lineptr); > > +fclose(proc); > > + > > +printf("CPU frequency: %.3lf MHz\n", cpu_mhz); > > + > > +tsc2ns_scale = 1000.0 / cpu_mhz; > > +} > > + > > + > > +void sighand(int signal) > > +{ > > +if (!warmup) { > > +avg_lat /= outer_loops; > > +printf("---\n%.3f / %.3f / %.3f us\n", > > + ((double)min_lat) / 1000.0, ((double)avg_lat) / 1000.0, > > + ((double)max_lat) / 1000.0); > > +} > > +exit(0); > > +} > > + > > + > > +int main(int argc, char *argv[]) > > +{ > > +int port_type = SERPORT; > > +unsigned long port_ioaddr = 0x3F8; > > +long long period = 10; > > +long long timeout; > > +long long start, delay; > > +unsigned inttoggle; > > +int trigger_trace = 0; > > +int c; > > + > > + > > +signal(SIGINT, sighand); > > +signal(SIGTERM, sighand); > > +signal(SIGHUP, sighand); > > +signal(SIGALRM, sighand); > > + > > +calibrate_tsc(); > > + > > +while ((c = getopt(argc,argv,"p:T:o:a:f")) != EOF) > > +switch (c) { > > +case 'p': > > +period = atoi(optarg) * 1000; > > +break; > > + > > +case 'T': > > +alarm(atoi(optarg)); > > +
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
[EMAIL PROTECTED] wrote: > Index: xenomai/src/testsuite/irqbench/irqbench.c > === > --- /dev/null > +++ xenomai/src/testsuite/irqbench/irqbench.c > @@ -0,0 +1,301 @@ > +/* > + * Copyright (C) 2006 Jan Kiszka <[EMAIL PROTECTED]>. > + * > + * Xenomai 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. > + * > + * Xenomai 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 Xenomai; if not, write to the Free Software Foundation, > + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > + > +#define SERPORT 0 > +#define PARPORT 1 > + > +/* --- Serial port --- */ > + > +#define MCR_DTR 0x01 > +#define MCR_RTS 0x02 > +#define MCR_OUT20x08 > + > +#define MSR_DELTA 0x0F > + > +#define LCR(base) (base + 3) /* Line Control Register */ > +#define MCR(base) (base + 4) /* Modem Control Register */ > +#define LSR(base) (base + 5) /* Line Status Register */ > +#define MSR(base) (base + 6) /* Modem Status Register */ > + > +/* --- Parallel port --- */ > + > +#define CTRL_INIT 0x04 > + > +#define STAT_STROBE 0x10 > + > +#define DATA(base) (base + 0) /* Data register */ > +#define STAT(base) (base + 1) /* Status register */ > +#define CTRL(base) (base + 2) /* Control register */ > + > +double tsc2ns_scale; > +long long min_lat = LLONG_MAX; > +long long max_lat = LLONG_MIN; > +long long avg_lat = 0; > +long outer_loops = 0; > +int warmup = 1; > + > +static inline long long rdtsc(void) > +{ > +unsigned long long tsc; > + > +__asm__ __volatile__("rdtsc" : "=A" (tsc)); > +return tsc; > +} > + > + > +static long tsc2ns(long long tsc) > +{ > +if ((tsc > LONG_MAX) || (tsc < LONG_MIN)) { > +fprintf(stderr, "irqbench: overflow (%lld ns)!\n", > +(long long)(tsc2ns_scale * (double)tsc)); > +exit(2); > +} > +return (long)(tsc2ns_scale * (double)tsc); > +} > + > + > +static inline long long ns2tsc(long long ns) > +{ > +return (long long)(((double)ns) / tsc2ns_scale); > +} > + > + > +void calibrate_tsc(void) > +{ > +FILE *proc; > +char *lineptr = NULL; > +size_t len; > +double cpu_mhz; > + > +proc = fopen("/proc/cpuinfo", "r"); > +if (proc == NULL) { > +perror("irqbench: Unable to open /proc/cpuinfo"); > +exit(1); > +} > + > +while (getline(&lineptr, &len, proc) != -1) > +if (strncmp(lineptr, "cpu MHz", 7) == 0) { > +sscanf(strchr(lineptr, ':') + 1, "%lf", &cpu_mhz); > +break; > +} > + > +if (lineptr) > +free(lineptr); > +fclose(proc); > + > +printf("CPU frequency: %.3lf MHz\n", cpu_mhz); > + > +tsc2ns_scale = 1000.0 / cpu_mhz; > +} > + > + > +void sighand(int signal) > +{ > +if (!warmup) { > +avg_lat /= outer_loops; > +printf("---\n%.3f / %.3f / %.3f us\n", > + ((double)min_lat) / 1000.0, ((double)avg_lat) / 1000.0, > + ((double)max_lat) / 1000.0); > +} > +exit(0); > +} > + > + > +int main(int argc, char *argv[]) > +{ > +int port_type = SERPORT; > +unsigned long port_ioaddr = 0x3F8; > +long long period = 10; > +long long timeout; > +long long start, delay; > +unsigned inttoggle; > +int trigger_trace = 0; > +int c; > + > + > +signal(SIGINT, sighand); > +signal(SIGTERM, sighand); > +signal(SIGHUP, sighand); > +signal(SIGALRM, sighand); > + > +calibrate_tsc(); > + > +while ((c = getopt(argc,argv,"p:T:o:a:f")) != EOF) > +switch (c) { > +case 'p': > +period = atoi(optarg) * 1000; > +break; > + > +case 'T': > +alarm(atoi(optarg)); > +break; > + > +case 'o': > +port_type = atoi(optarg); > +break; > + > +case 'a': > +port_ioaddr = strtol(optarg, NULL, > +(strncmp(optarg, "0x", 2) == 0) ? 16 : 10); > +break; > + > +case 'f': > +tr
Re: [Xenomai-core] [PATCH 6/6] Introduce IRQ latency benchmark
[EMAIL PROTECTED] wrote: > This patch introduces another rttesting driver, xeno_irqbench, for > measuring external IRQ latencies. The irqbench device is controlled > by a user-mode tool irqloop. A second tool for plain Linux, irqbench, > is provided to trigger the event over serial or parallel cross-link > (the latter is incomplete yet) and measure the reaction latency. > As a follow-up, here is a patch to add some documentation for irqbench. I do not repeat the command line args of irqbench/irqloop, but feel free to point out missing explanations. Jan Index: xenomai/doc/txt/irqbench.txt === --- /dev/null +++ xenomai/doc/txt/irqbench.txt @@ -0,0 +1,48 @@ +IRQ Latency Benchmark +- + +This latency benchmark for external interrupts consists of three parts: + +1. xeno_irqbench (ksrc/drivers/testing) + RTDM driver for the test target to handle and reply to the IRQ events, or + forward them to user-space. + +2. irqloop (src/testsuite/irqbench) + xeno_irqbench control front-end and user-space loop-closer. Runs against + the POSIX skin on the test target. + +3. irqbench (src/testsuite/irqbench) + IRQ triggering and reaction measuring tool for the log system. Runs over + plain Linux on x86 hosts (contains inline assembly, ports to other archs + will be welcome). + +To link both test and log system, a null-modem cable between 8250-compatible +two RS232 ports is required. The infrastructure for parallel port cross-over +is prepared as well, but yet untested and incomplete. The null-modem cable +must provide at least the following links: + +test target log system +--- -- + CTS(8) <-- RTS(7)IRQ trigger + RTS(7) --> CTS(8)reply + + DCD(1) + and/or <-- DTR(4)trace trigger (optional) + DSR(6) + +(Pin number on 9-pin sub-D socket) + +Test and log system can be started in arbitrary order, they will wait on +each other. + +The log system runs each single IRQ measurement with local IRQs disabled. It +will wait up to 100 times the current period on the test system's reply (after +initial successful synchronisation, which happens with IRQs enabled). Note that +these timeouts may disturb other processes or drivers on the log system. + +Keep in mind for test evaluations that, by design, irqbench will not trigger a +new IRQ event before the reply on the previous one has arrived or timed out. +Thus the specified test period may be dynamically expended in case of +overload. But maximum a latency close or above the period will clearly +indicate this. + Index: xenomai/doc/txt/Makefile.am === --- xenomai.orig/doc/txt/Makefile.am +++ xenomai/doc/txt/Makefile.am @@ -2,6 +2,7 @@ txtdocdir = $(datadir)/doc/$(PACKAGE)-$( dist_txtdoc_DATA = \ 16550A-driver.txt \ + irqbench.txt \ pse51-skin.txt \ psos-skin.txt \ rtai-skin.txt \ signature.asc Description: OpenPGP digital signature ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core