diff options
author | bde <bde@FreeBSD.org> | 2002-03-31 06:49:38 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 2002-03-31 06:49:38 +0000 |
commit | aa2c17836eb806e15dd98aa23cbacb169aa21c6a (patch) | |
tree | f609af9a7b7ef8fd1aba6e79370115d5bfce5f83 /sys | |
parent | 5e89c7151fda80668414be4d13aa88d973cda61b (diff) | |
download | FreeBSD-src-aa2c17836eb806e15dd98aa23cbacb169aa21c6a.zip FreeBSD-src-aa2c17836eb806e15dd98aa23cbacb169aa21c6a.tar.gz |
Hacks for measuring interrupt latency. Interrupt latency can be
measured accurately for periodic interrupts provided the interrupts
don't need to be serviced very quickly to keep their period almost
constant. sio output interrupts have this property (interrupt service
can be delayed for up to 1 character time without the period changing).
This is non-optional and undocumented so that it can be added and
removed easily. It has no significant effect unless it is enabled by
hacking on a variable using a debugger. Hardclock and statclock interrupts
would work even better for this, at least on i386's, provided their
interrupt handlers are fast (as they are in -current but not in -stable
or in my version of -current).
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sio/sio.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index 91b6aff..2728e25 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -71,6 +71,7 @@ #include <sys/rman.h> #include <sys/timetc.h> #include <sys/timepps.h> +#include <sys/uio.h> #include <isa/isavar.h> @@ -1676,6 +1677,39 @@ siointr(arg) #endif /* COM_MULTIPORT */ } +static struct timespec siots[8192]; +static int siotso; +static int volatile siotsunit = -1; + +static int +sysctl_siots(SYSCTL_HANDLER_ARGS) +{ + char buf[128]; + long long delta; + size_t len; + int error, i; + + for (i = 1; i < siotso; i++) { + delta = (long long)(siots[i].tv_sec - siots[i - 1].tv_sec) * + 1000000000 + + (siots[i].tv_nsec - siots[i - 1].tv_nsec); + len = sprintf(buf, "%lld\n", delta); + if (delta >= 110000) + len += sprintf(buf + len - 1, ": *** %ld.%09ld\n", + (long)siots[i].tv_sec, siots[i].tv_nsec); + if (i == siotso - 1) + buf[len - 1] = '\0'; + error = SYSCTL_OUT(req, buf, len); + if (error != 0) + return (error); + uio_yield(); + } + return (0); +} + +SYSCTL_PROC(_machdep, OID_AUTO, siots, CTLTYPE_STRING | CTLFLAG_RD, + 0, 0, sysctl_siots, "A", "sio timestamps"); + static void siointr1(com) struct com_s *com; @@ -1845,7 +1879,7 @@ cont: if (line_status & LSR_TXRDY && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { ioptr = com->obufq.l_head; - if (com->tx_fifo_size > 1) { + if (com->tx_fifo_size > 1 && com->unit != siotsunit) { u_int ocount; ocount = com->obufq.l_tail - ioptr; @@ -1858,6 +1892,11 @@ cont: } else { outb(com->data_port, *ioptr++); ++com->bytes_out; + if (com->unit == siotsunit) { + nanouptime(&siots[siotso]); + siotso = (siotso + 1) % + (sizeof siots / sizeof siots[0]); + } } com->obufq.l_head = ioptr; if (COM_IIR_TXRDYBUG(com->flags)) { @@ -2206,7 +2245,8 @@ comparam(tp, t) * interrupt disablement times in other parts of the system, * without producing silo overflow errors. */ - com->fifo_image = t->c_ospeed <= 4800 + com->fifo_image = com->unit == siotsunit ? 0 + : t->c_ospeed <= 4800 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH; #ifdef COM_ESP /* |