diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1995-06-11 19:33:05 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1995-06-11 19:33:05 +0000 |
commit | 1b1ee5553889e207087539ddafa5dfd4e28bd585 (patch) | |
tree | ba998dfb4fcad03e00a5cbf58e2a0ad648bab6e6 /sys/kern/tty.c | |
parent | b1a97daa1e06ab0de3071f979965878fd056292b (diff) | |
download | FreeBSD-src-1b1ee5553889e207087539ddafa5dfd4e28bd585.zip FreeBSD-src-1b1ee5553889e207087539ddafa5dfd4e28bd585.tar.gz |
Merge RELENG_2_0_5 into HEAD
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r-- | sys/kern/tty.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index b5b5f67..1df2b4a 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.44 1995/05/07 23:53:36 ache Exp $ + * $Id: tty.c,v 1.45.2.3 1995/06/05 01:23:10 davidg Exp $ */ #include "snp.h" @@ -1037,7 +1037,25 @@ ttywait(tp) while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) && tp->t_oproc) { - (*tp->t_oproc)(tp); + /* + * XXX the call to t_oproc() can cause livelock. + * + * If two processes wait for output to drain from the same + * tty, and the amount of output to drain is <= tp->t_lowat, + * then the processes will take turns uselessly waking each + * other up until the output drains, all running at spltty() + * so that even interrupts on other terminals are blocked. + * + * Skipping the call when TS_BUSY is set avoids the problem + * for current drivers but isn't "right". There is no + * problem for ptys - we only get woken up when the output + * queue is actually reduced. Hardware ttys should be + * handled similarly. There would still be excessive + * wakeups for output below low water when we only care + * about output complete. + */ + if (!ISSET(tp->t_state, TS_BUSY)) + (*tp->t_oproc)(tp); if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) { SET(tp->t_state, TS_ASLEEP); @@ -1812,8 +1830,7 @@ ovhiwat: return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); } SET(tp->t_state, TS_ASLEEP); - error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "ttywri", - tp->t_timeout); + error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "ttywri", tp->t_timeout); splx(s); if (error) goto out; |