Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/tty_outq.c
Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | ttyoutq_flush(struct ttyoutq *to) | ||||
to->to_end = 0; | to->to_end = 0; | ||||
} | } | ||||
int | int | ||||
ttyoutq_setsize(struct ttyoutq *to, struct tty *tp, size_t size) | ttyoutq_setsize(struct ttyoutq *to, struct tty *tp, size_t size) | ||||
{ | { | ||||
struct ttyoutq_block *tob; | struct ttyoutq_block *tob; | ||||
tty_assert_locked(tp); | |||||
ttydisc_assert_locked(tp); | |||||
to->to_quota = howmany(size, TTYOUTQ_DATASIZE); | to->to_quota = howmany(size, TTYOUTQ_DATASIZE); | ||||
while (to->to_quota > to->to_nblocks) { | while (to->to_quota > to->to_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); | ||||
tob = uma_zalloc(ttyoutq_zone, M_WAITOK); | tob = uma_zalloc(ttyoutq_zone, M_WAITOK); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
if (tty_gone(tp)) { | |||||
uma_zfree(ttyoutq_zone, tob); | |||||
return (ENXIO); | |||||
} | |||||
TTYOUTQ_INSERT_TAIL(to, tob); | TTYOUTQ_INSERT_TAIL(to, tob); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
ttyoutq_free(struct ttyoutq *to) | ttyoutq_free(struct ttyoutq *to) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
* back to the user, because we temporarily remove the block from the | * back to the user, because we temporarily remove the block from the | ||||
* queue. Otherwise we need to copy it to a temporary buffer first, to | * queue. Otherwise we need to copy it to a temporary buffer first, to | ||||
* make sure data remains in the correct order. | * make sure data remains in the correct order. | ||||
*/ | */ | ||||
int | int | ||||
ttyoutq_read_uio(struct ttyoutq *to, struct tty *tp, struct uio *uio) | ttyoutq_read_uio(struct ttyoutq *to, struct tty *tp, struct uio *uio) | ||||
{ | { | ||||
ttydisc_assert_locked(tp); | |||||
while (uio->uio_resid > 0) { | while (uio->uio_resid > 0) { | ||||
int error; | int error; | ||||
struct ttyoutq_block *tob; | struct ttyoutq_block *tob; | ||||
size_t cbegin, cend, clen; | size_t cbegin, cend, clen; | ||||
/* See if there still is data. */ | /* See if there still is data. */ | ||||
if (to->to_begin == to->to_end) | if (to->to_begin == to->to_end) | ||||
return (0); | return (0); | ||||
Show All 27 Lines | if (cend == TTYOUTQ_DATASIZE || cend == to->to_end) { | ||||
TTYOUTQ_REMOVE_HEAD(to); | TTYOUTQ_REMOVE_HEAD(to); | ||||
to->to_begin = 0; | to->to_begin = 0; | ||||
if (to->to_end <= TTYOUTQ_DATASIZE) | if (to->to_end <= TTYOUTQ_DATASIZE) | ||||
to->to_end = 0; | to->to_end = 0; | ||||
else | else | ||||
to->to_end -= TTYOUTQ_DATASIZE; | to->to_end -= TTYOUTQ_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(tob->tob_data + cbegin, clen, uio); | error = uiomove(tob->tob_data + cbegin, clen, uio); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
/* Block can now be readded to the list. */ | /* Block can now be readded to the list. */ | ||||
TTYOUTQ_RECYCLE(to, tob); | TTYOUTQ_RECYCLE(to, tob); | ||||
} else { | } else { | ||||
char ob[TTYOUTQ_DATASIZE - 1]; | char ob[TTYOUTQ_DATASIZE - 1]; | ||||
/* | /* | ||||
* Slow path: store data in a temporary buffer. | * Slow path: store data in a temporary buffer. | ||||
*/ | */ | ||||
memcpy(ob, tob->tob_data + cbegin, clen); | memcpy(ob, tob->tob_data + cbegin, clen); | ||||
to->to_begin += clen; | to->to_begin += clen; | ||||
MPASS(to->to_begin < TTYOUTQ_DATASIZE); | MPASS(to->to_begin < TTYOUTQ_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, uio); | error = uiomove(ob, clen, uio); | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
} | } | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 70 Lines • Show Last 20 Lines |