Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/tty_inq.c
Show First 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | else \ | ||||
TTYINQ_INSERT_TAIL(ti, tib); \ | TTYINQ_INSERT_TAIL(ti, tib); \ | ||||
} while (0) | } while (0) | ||||
int | int | ||||
ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) | ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) | ||||
{ | { | ||||
struct ttyinq_block *tib; | struct ttyinq_block *tib; | ||||
tty_assert_locked(tp); | |||||
ttydisc_assert_locked(tp); | |||||
ti->ti_quota = howmany(size, TTYINQ_DATASIZE); | ti->ti_quota = howmany(size, TTYINQ_DATASIZE); | ||||
while (ti->ti_quota > ti->ti_nblocks) { | while (ti->ti_quota > ti->ti_nblocks) { | ||||
/* | /* | ||||
* List is getting bigger. | * List is getting bigger. | ||||
* Add new blocks to the tail of the list. | * Add new blocks to the tail of the list. | ||||
* | * | ||||
* We must unlock the TTY temporarily, because we need | * We must unlock the ttydisc, but we're still holding on to | ||||
* to allocate memory. This won't be a problem, because | * the tty lock so we should avoid problems. | ||||
* in the worst case, another thread ends up here, which | |||||
* may cause us to allocate too many blocks, but this | |||||
* will be caught by the loop below. | |||||
*/ | */ | ||||
tty_unlock(tp); | ttydisc_unlock(tp); | ||||
tib = uma_zalloc(ttyinq_zone, M_WAITOK); | tib = uma_zalloc(ttyinq_zone, M_WAITOK); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
if (tty_gone(tp)) { | if (tty_gone(tp)) { | ||||
uma_zfree(ttyinq_zone, tib); | uma_zfree(ttyinq_zone, tib); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
TTYINQ_INSERT_TAIL(ti, tib); | TTYINQ_INSERT_TAIL(ti, tib); | ||||
} | } | ||||
Show All 16 Lines | ttyinq_free(struct ttyinq *ti) | ||||
MPASS(ti->ti_nblocks == 0); | MPASS(ti->ti_nblocks == 0); | ||||
} | } | ||||
int | int | ||||
ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, | ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, | ||||
size_t rlen, size_t flen) | size_t rlen, size_t flen) | ||||
{ | { | ||||
ttydisc_assert_locked(tp); | |||||
/* rlen includes flen, flen bytes will be trimmed from the end. */ | /* rlen includes flen, flen bytes will be trimmed from the end. */ | ||||
MPASS(rlen - flen <= uio->uio_resid); | MPASS(rlen - flen <= uio->uio_resid); | ||||
while (rlen > 0) { | while (rlen > 0) { | ||||
int error; | int error; | ||||
struct ttyinq_block *tib; | struct ttyinq_block *tib; | ||||
size_t cbegin, cend, clen; | size_t cbegin, cend, clen; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | t -= TTYINQ_DATASIZE; \ | ||||
CORRECT_BLOCK(ti->ti_end); | CORRECT_BLOCK(ti->ti_end); | ||||
#undef CORRECT_BLOCK | #undef CORRECT_BLOCK | ||||
/* | /* | ||||
* Temporary unlock and copy the data to | * Temporary unlock and copy the data to | ||||
* userspace. We may need to flush trailing | * userspace. We may need to flush trailing | ||||
* bytes, like EOF characters. | * bytes, like EOF characters. | ||||
*/ | */ | ||||
tty_unlock(tp); | ttydisc_unlock(tp); | ||||
error = uiomove(tib->tib_data + cbegin, | error = uiomove(tib->tib_data + cbegin, | ||||
clen - flen, uio); | clen - flen, uio); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
/* Block can now be readded to the list. */ | /* Block can now be readded to the list. */ | ||||
TTYINQ_RECYCLE(ti, tib); | TTYINQ_RECYCLE(ti, tib); | ||||
} else { | } else { | ||||
char ob[TTYINQ_DATASIZE - 1]; | char ob[TTYINQ_DATASIZE - 1]; | ||||
/* | /* | ||||
* Slow path: store data in a temporary buffer. | * Slow path: store data in a temporary buffer. | ||||
*/ | */ | ||||
memcpy(ob, tib->tib_data + cbegin, clen - flen); | memcpy(ob, tib->tib_data + cbegin, clen - flen); | ||||
ti->ti_begin += clen; | ti->ti_begin += clen; | ||||
MPASS(ti->ti_begin < TTYINQ_DATASIZE); | MPASS(ti->ti_begin < TTYINQ_DATASIZE); | ||||
/* Temporary unlock and copy the data to userspace. */ | /* Temporary unlock and copy the data to userspace. */ | ||||
tty_unlock(tp); | ttydisc_unlock(tp); | ||||
error = uiomove(ob, clen - flen, uio); | error = uiomove(ob, clen - flen, uio); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
} | } | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (tty_gone(tp)) | if (tty_gone(tp)) | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 285 Lines • Show Last 20 Lines |