diff options
author | bde <bde@FreeBSD.org> | 1995-04-15 21:04:58 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1995-04-15 21:04:58 +0000 |
commit | 3431d053fa86499ee92a8ee702ab458cc8262022 (patch) | |
tree | 26ab3b3e48ca95c23e0a2367aa4d731f8f9bc5e4 /sys | |
parent | 8508e12794afd48fa3d0f83de39b591b6784927b (diff) | |
download | FreeBSD-src-3431d053fa86499ee92a8ee702ab458cc8262022.zip FreeBSD-src-3431d053fa86499ee92a8ee702ab458cc8262022.tar.gz |
Speed up ttnread() in the !(ICANON | ISIG) case by copying to user space
through a temporary buffer instead of one character at a time. The old
method takes about 6 usec/char on a 486DX2/66. This is larger than than
the combined interrupt and PIO overhead for a 16550!
This change was first implemented in 1.1.5. It was rewritten for 2.1.
The clist access functions allow a simpler implementation at some cost
in correctness and speed. There needs to be an ungetc() function to
recover from EFAULT, and it wastes time to copy through a temporary
buffer.
Don't snoop on single characters that weren't read due to EFAULT.
Rewrite a snoop comment in my approximation to English.
Undo bogus exportation of ttnread().
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/tty.c | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index b1a56ce..94a4770 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)tty.c 8.8 (Berkeley) 1/21/94 - * $Id: tty.c,v 1.40 1995/03/29 19:22:37 ache Exp $ + * $Id: tty.c,v 1.41 1995/03/29 19:24:46 ache Exp $ */ #include "snp.h" @@ -66,6 +66,7 @@ static int proc_compare __P((struct proc *p1, struct proc *p2)); +static int ttnread __P((struct tty *)); static void ttyblock __P((struct tty *tp)); static void ttyecho __P((int, struct tty *tp)); static void ttyrubo __P((struct tty *, int)); @@ -1005,7 +1006,7 @@ ttselect(dev, rw, p) * This is now exported to the cy driver as well; if you hack this code, * then be sure to keep /sys/i386/isa/cy.c properly advised! -jkh */ -int +static int ttnread(tp) struct tty *tp; { @@ -1486,7 +1487,44 @@ read: * Input present, check for input mapping and processing. */ first = 1; - while ((c = getc(qp)) >= 0) { + if (ISSET(lflag, ICANON | ISIG)) + goto slowcase; + for (;;) { + char ibuf[IBUFSIZ]; + int icc; + + icc = min(uio->uio_resid, IBUFSIZ); + icc = q_to_b(qp, ibuf, icc); + if (icc <= 0) { + if (first) + goto loop; + break; + } + error = uiomove(ibuf, icc, uio); + /* + * XXX if there was an error then we should ungetc() the + * unmoved chars and reduce icc here. + */ +#if NSNP > 0 + if (ISSET(tp->t_lflag, ECHO) && + ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) + snpin((struct snoop *)tp->t_sc, ibuf, icc); +#endif + if (error) + break; + if (uio->uio_resid == 0) + break; + first = 0; + } + goto out; +slowcase: + for (;;) { + c = getc(qp); + if (c < 0) { + if (first) + goto loop; + break; + } /* * delayed suspend (^Y) */ @@ -1506,24 +1544,22 @@ read: */ if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) break; - -#if NSNP > 0 - /* - * Only when tty echoes characters , we want to - * feed them to the snoop device.Else they will come - * there if the application would like to. - */ - if (ISSET(tp->t_lflag, ECHO)) - if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) - snpinc((struct snoop *)tp->t_sc, (char)c); -#endif - /* * Give user character. */ error = ureadc(c, uio); if (error) + /* XXX should ungetc(c, qp). */ break; +#if NSNP > 0 + /* + * Only snoop directly on input in echo mode. Non-echoed + * input will be snooped later iff the application echoes it. + */ + if (ISSET(tp->t_lflag, ECHO) && + ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) + snpinc((struct snoop *)tp->t_sc, (char)c); +#endif if (uio->uio_resid == 0) break; /* @@ -1535,9 +1571,10 @@ read: first = 0; } /* - * Look to unblock output now that (presumably) + * Look to unblock input now that (presumably) * the input queue has gone down. */ +out: s = spltty(); if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) { int queue_full = 0; |