diff options
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r-- | sys/kern/tty.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index d73683c..ee95958 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'}, }; |