summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2002-03-31 06:49:38 +0000
committerbde <bde@FreeBSD.org>2002-03-31 06:49:38 +0000
commitaa2c17836eb806e15dd98aa23cbacb169aa21c6a (patch)
treef609af9a7b7ef8fd1aba6e79370115d5bfce5f83 /sys
parent5e89c7151fda80668414be4d13aa88d973cda61b (diff)
downloadFreeBSD-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.c44
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
/*
OpenPOWER on IntegriCloud