diff --git a/sys/kern/tty.c b/sys/kern/tty.c index d73683c19665..ee9595871d75 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -438,15 +438,28 @@ ttydev_write(struct cdev *dev, struct uio *uio, int ioflag) if (tp->t_termios.c_lflag & TOSTOP) { error = tty_wait_background(tp, curthread, SIGTTOU); - if (error) { - tty_unlock(tp); - return (error); - } + if (error) + goto done; } - error = ttydisc_write(tp, uio, ioflag); - tty_unlock(tp); + if (ioflag & IO_NDELAY && tp->t_flags & TF_BUSY_OUT) { + /* Allow non-blocking writes to bypass serialization. */ + error = ttydisc_write(tp, uio, ioflag); + } else { + /* Serialize write() calls. */ + while (tp->t_flags & TF_BUSY_OUT) { + error = tty_wait(tp, &tp->t_bgwait); + if (error) + goto done; + } + + tp->t_flags |= TF_BUSY_OUT; + error = ttydisc_write(tp, uio, ioflag); + tp->t_flags &= ~TF_BUSY_OUT; + cv_broadcast(&tp->t_bgwait); + } +done: tty_unlock(tp); return (error); } @@ -1880,6 +1893,11 @@ static struct { { TF_ZOMBIE, 'Z' }, { TF_HOOK, 's' }, + /* Keep these together -> 'bi' and 'bo'. */ + { TF_BUSY, 'b' }, + { TF_BUSY_IN, 'i' }, + { TF_BUSY_OUT, 'o' }, + { 0, '\0'}, }; diff --git a/sys/sys/tty.h b/sys/sys/tty.h index 218fd214cfd0..893509395e44 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -83,6 +83,9 @@ struct tty { #define TF_BYPASS 0x04000 /* Optimized input path. */ #define TF_ZOMBIE 0x08000 /* Modem disconnect received. */ #define TF_HOOK 0x10000 /* TTY has hook attached. */ +#define TF_BUSY_IN 0x20000 /* Process busy in read() -- not supported. */ +#define TF_BUSY_OUT 0x40000 /* Process busy in write(). */ +#define TF_BUSY (TF_BUSY_IN|TF_BUSY_OUT) unsigned int t_revokecnt; /* (t) revoke() count. */ /* Buffering mechanisms. */ diff --git a/usr.sbin/pstat/pstat.8 b/usr.sbin/pstat/pstat.8 index b92abd8ae783..5e3760cecb7e 100644 --- a/usr.sbin/pstat/pstat.8 +++ b/usr.sbin/pstat/pstat.8 @@ -206,6 +206,11 @@ block mode input routine in use connection lost .It s i/o being snooped +.It b +busy in +.Xr read 2 +or +.Xr write 2 .El .Pp The diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c index 2cb52fec8812..8272eee38bd6 100644 --- a/usr.sbin/pstat/pstat.c +++ b/usr.sbin/pstat/pstat.c @@ -315,6 +315,11 @@ static struct { { TF_ZOMBIE, 'Z' }, { TF_HOOK, 's' }, + /* Keep these together -> 'bi' and 'bo'. */ + { TF_BUSY, 'b' }, + { TF_BUSY_IN, 'i' }, + { TF_BUSY_OUT, 'o' }, + { 0, '\0'}, };