diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/kern/tty.c | 32 | ||||
| -rw-r--r-- | sys/kern/tty_inq.c | 65 | ||||
| -rw-r--r-- | sys/kern/tty_outq.c | 71 | ||||
| -rw-r--r-- | sys/sys/ttyqueue.h | 18 |
4 files changed, 80 insertions, 106 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index df781e8d033b..1c3791663d08 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -112,23 +112,6 @@ tty_watermarks(struct tty *tp) tp->t_outlow = (ttyoutq_getsize(&tp->t_outq) * 9) / 10; } -static void -tty_freebuffers(struct tty *tp) -{ - - /* Destroy input buffers. */ - ttyinq_flush(&tp->t_inq); - ttyinq_setsize(&tp->t_inq, NULL, 0); - MPASS(ttyinq_getsize(&tp->t_inq) == 0); - tp->t_inlow = 0; - - /* Destroy output buffers. */ - ttyoutq_flush(&tp->t_outq); - ttyoutq_setsize(&tp->t_outq, NULL, 0); - MPASS(ttyoutq_getsize(&tp->t_outq) == 0); - tp->t_outlow = 0; -} - static int tty_drain(struct tty *tp) { @@ -199,7 +182,10 @@ ttydev_leave(struct tty *tp) ttydisc_close(tp); /* Destroy associated buffers already. */ - tty_freebuffers(tp); + ttyinq_free(&tp->t_inq); + tp->t_inlow = 0; + ttyoutq_free(&tp->t_outq); + tp->t_outlow = 0; knlist_clear(&tp->t_inpoll.si_note, 1); knlist_clear(&tp->t_outpoll.si_note, 1); @@ -875,8 +861,8 @@ tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex) cv_init(&tp->t_bgwait, "tty background"); cv_init(&tp->t_dcdwait, "tty dcd"); - TAILQ_INIT(&tp->t_inq.ti_list); - STAILQ_INIT(&tp->t_outq.to_list); + ttyinq_init(&tp->t_inq); + ttyoutq_init(&tp->t_outq); /* Allow drivers to use a custom mutex to lock the TTY. */ if (mutex != NULL) { @@ -907,6 +893,10 @@ tty_dealloc(void *arg) tty_list_count--; sx_xunlock(&tty_list_sx); + /* Make sure we haven't leaked buffers. */ + MPASS(ttyinq_getsize(&tp->t_inq) == 0); + MPASS(ttyoutq_getsize(&tp->t_outq) == 0); + knlist_destroy(&tp->t_inpoll.si_note); knlist_destroy(&tp->t_outpoll.si_note); @@ -935,8 +925,6 @@ tty_rel_free(struct tty *tp) return; } - tty_freebuffers(tp); - /* TTY can be deallocated. */ dev = tp->t_dev; tp->t_dev = NULL; diff --git a/sys/kern/tty_inq.c b/sys/kern/tty_inq.c index b93dde6fe83c..fc99729fe4ec 100644 --- a/sys/kern/tty_inq.c +++ b/sys/kern/tty_inq.c @@ -89,12 +89,11 @@ static uma_zone_t ttyinq_zone; void ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) { - unsigned int nblocks; struct ttyinq_block *tib; - nblocks = howmany(size, TTYINQ_DATASIZE); + ti->ti_quota = howmany(size, TTYINQ_DATASIZE); - while (nblocks > ti->ti_nblocks) { + while (ti->ti_quota > ti->ti_nblocks) { /* * List is getting bigger. * Add new blocks to the tail of the list. @@ -109,36 +108,26 @@ ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) tib = uma_zalloc(ttyinq_zone, M_WAITOK); tty_lock(tp); - if (tty_gone(tp)) - return; - TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); ti->ti_nblocks++; } +} - while (nblocks < ti->ti_nblocks) { - /* - * List is getting smaller. Remove unused blocks at the - * end. This means we cannot guarantee this routine - * shrinks buffers properly, when we need to reclaim - * more space than there is available. - * - * XXX TODO: Two solutions here: - * - Throw data away - * - Temporarily hit the watermark until enough data has - * been flushed, so we can remove the blocks. - */ +void +ttyinq_free(struct ttyinq *ti) +{ + struct ttyinq_block *tib; + + ttyinq_flush(ti); + ti->ti_quota = 0; - if (ti->ti_end == 0) - tib = TAILQ_FIRST(&ti->ti_list); - else - tib = TAILQ_NEXT(ti->ti_lastblock, tib_list); - if (tib == NULL) - break; + while ((tib = TAILQ_FIRST(&ti->ti_list)) != NULL) { TAILQ_REMOVE(&ti->ti_list, tib, tib_list); uma_zfree(ttyinq_zone, tib); ti->ti_nblocks--; } + + MPASS(ti->ti_nblocks == 0); } int @@ -217,21 +206,13 @@ ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, clen - flen, uio); tty_lock(tp); - if (tty_gone(tp)) { - /* Something went bad - discard this block. */ + /* Block can now be readded to the list. */ + if (ti->ti_quota <= ti->ti_nblocks) { uma_zfree(ttyinq_zone, tib); - return (ENXIO); + } else { + TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); + ti->ti_nblocks++; } - /* Block can now be readded to the list. */ - /* - * XXX: we could remove the blocks here when the - * queue was shrunk, but still in use. See - * ttyinq_setsize(). - */ - TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); - ti->ti_nblocks++; - if (error != 0) - return (error); } else { char ob[TTYINQ_DATASIZE - 1]; atomic_add_long(&ttyinq_nslow, 1); @@ -247,12 +228,12 @@ ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, tty_unlock(tp); error = uiomove(ob, clen - flen, uio); tty_lock(tp); - - if (error != 0) - return (error); - if (tty_gone(tp)) - return (ENXIO); } + + if (error != 0) + return (error); + if (tty_gone(tp)) + return (ENXIO); } return (0); diff --git a/sys/kern/tty_outq.c b/sys/kern/tty_outq.c index 30df4eb8bdde..d55ec1509af9 100644 --- a/sys/kern/tty_outq.c +++ b/sys/kern/tty_outq.c @@ -78,12 +78,11 @@ ttyoutq_flush(struct ttyoutq *to) void ttyoutq_setsize(struct ttyoutq *to, struct tty *tp, size_t size) { - unsigned int nblocks; struct ttyoutq_block *tob; - nblocks = howmany(size, TTYOUTQ_DATASIZE); + to->to_quota = howmany(size, TTYOUTQ_DATASIZE); - while (nblocks > to->to_nblocks) { + while (to->to_quota > to->to_nblocks) { /* * List is getting bigger. * Add new blocks to the tail of the list. @@ -98,40 +97,26 @@ ttyoutq_setsize(struct ttyoutq *to, struct tty *tp, size_t size) tob = uma_zalloc(ttyoutq_zone, M_WAITOK); tty_lock(tp); - if (tty_gone(tp)) - return; - STAILQ_INSERT_TAIL(&to->to_list, tob, tob_list); to->to_nblocks++; } +} - while (nblocks < to->to_nblocks) { - /* - * List is getting smaller. Remove unused blocks at the - * end. This means we cannot guarantee this routine - * shrinks buffers properly, when we need to reclaim - * more space than there is available. - * - * XXX TODO: Two solutions here: - * - Throw data away - * - Temporarily hit the watermark until enough data has - * been flushed, so we can remove the blocks. - */ +void +ttyoutq_free(struct ttyoutq *to) +{ + struct ttyoutq_block *tob; + + ttyoutq_flush(to); + to->to_quota = 0; - if (to->to_end == 0) { - tob = STAILQ_FIRST(&to->to_list); - if (tob == NULL) - break; - STAILQ_REMOVE_HEAD(&to->to_list, tob_list); - } else { - tob = STAILQ_NEXT(to->to_lastblock, tob_list); - if (tob == NULL) - break; - STAILQ_REMOVE_NEXT(&to->to_list, to->to_lastblock, tob_list); - } + while ((tob = STAILQ_FIRST(&to->to_list)) != NULL) { + STAILQ_REMOVE_HEAD(&to->to_list, tob_list); uma_zfree(ttyoutq_zone, tob); to->to_nblocks--; } + + MPASS(to->to_nblocks == 0); } size_t @@ -164,7 +149,12 @@ ttyoutq_read(struct ttyoutq *to, void *buf, size_t len) if (cend == TTYOUTQ_DATASIZE || cend == to->to_end) { /* Read the block until the end. */ STAILQ_REMOVE_HEAD(&to->to_list, tob_list); - STAILQ_INSERT_TAIL(&to->to_list, tob, tob_list); + if (to->to_quota < to->to_nblocks) { + uma_zfree(ttyoutq_zone, tob); + to->to_nblocks--; + } else { + STAILQ_INSERT_TAIL(&to->to_list, tob, tob_list); + } to->to_begin = 0; if (to->to_end <= TTYOUTQ_DATASIZE) { to->to_end = 0; @@ -251,15 +241,12 @@ ttyoutq_read_uio(struct ttyoutq *to, struct tty *tp, struct uio *uio) tty_lock(tp); /* Block can now be readded to the list. */ - /* - * XXX: we could remove the blocks here when the - * queue was shrunk, but still in use. See - * ttyoutq_setsize(). - */ - STAILQ_INSERT_TAIL(&to->to_list, tob, tob_list); - to->to_nblocks++; - if (error != 0) - return (error); + if (to->to_quota <= to->to_nblocks) { + uma_zfree(ttyoutq_zone, tob); + } else { + STAILQ_INSERT_TAIL(&to->to_list, tob, tob_list); + to->to_nblocks++; + } } else { char ob[TTYOUTQ_DATASIZE - 1]; atomic_add_long(&ttyoutq_nslow, 1); @@ -275,10 +262,10 @@ ttyoutq_read_uio(struct ttyoutq *to, struct tty *tp, struct uio *uio) tty_unlock(tp); error = uiomove(ob, clen, uio); tty_lock(tp); - - if (error != 0) - return (error); } + + if (error != 0) + return (error); } return (0); diff --git a/sys/sys/ttyqueue.h b/sys/sys/ttyqueue.h index 3e72fefb0c97..24e1187636ea 100644 --- a/sys/sys/ttyqueue.h +++ b/sys/sys/ttyqueue.h @@ -52,6 +52,7 @@ struct ttyinq { unsigned int ti_reprint; unsigned int ti_end; unsigned int ti_nblocks; + unsigned int ti_quota; }; #define TTYINQ_DATASIZE 128 @@ -62,12 +63,14 @@ struct ttyoutq { unsigned int to_begin; unsigned int to_end; unsigned int to_nblocks; + unsigned int to_quota; }; #define TTYOUTQ_DATASIZE (256 - sizeof(STAILQ_ENTRY(ttyoutq_block))) #ifdef _KERNEL /* Input queue handling routines. */ void ttyinq_setsize(struct ttyinq *, struct tty *, size_t); +void ttyinq_free(struct ttyinq *); int ttyinq_read_uio(struct ttyinq *, struct tty *, struct uio *, size_t, size_t); size_t ttyinq_write(struct ttyinq *, const void *, size_t, int); @@ -80,6 +83,13 @@ void ttyinq_unputchar(struct ttyinq *); void ttyinq_reprintpos_set(struct ttyinq *); void ttyinq_reprintpos_reset(struct ttyinq *); +static __inline void +ttyinq_init(struct ttyinq *ti) +{ + + TAILQ_INIT(&ti->ti_list); +} + static __inline size_t ttyinq_getsize(struct ttyinq *ti) { @@ -124,11 +134,19 @@ void ttyinq_line_iterate_from_reprintpos(struct ttyinq *, /* Output queue handling routines. */ void ttyoutq_flush(struct ttyoutq *); void ttyoutq_setsize(struct ttyoutq *, struct tty *, size_t); +void ttyoutq_free(struct ttyoutq *); size_t ttyoutq_read(struct ttyoutq *, void *, size_t); int ttyoutq_read_uio(struct ttyoutq *, struct tty *, struct uio *); size_t ttyoutq_write(struct ttyoutq *, const void *, size_t); int ttyoutq_write_nofrag(struct ttyoutq *, const void *, size_t); +static __inline void +ttyoutq_init(struct ttyoutq *to) +{ + + STAILQ_INIT(&to->to_list); +} + static __inline size_t ttyoutq_getsize(struct ttyoutq *to) { |
