tty_inq.c (181905) | tty_inq.c (182471) |
---|---|
1/*- 2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Portions of this software were developed under sponsorship from Snow 6 * B.V., the Netherlands. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Portions of this software were developed under sponsorship from Snow 6 * B.V., the Netherlands. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/kern/tty_inq.c 181905 2008-08-20 08:31:58Z ed $"); | 31__FBSDID("$FreeBSD: head/sys/kern/tty_inq.c 182471 2008-08-30 09:18:27Z ed $"); |
32 33#include <sys/param.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/queue.h> 37#include <sys/sysctl.h> 38#include <sys/systm.h> 39#include <sys/tty.h> --- 44 unchanged lines hidden (view full) --- 84 char tib_data[TTYINQ_DATASIZE]; 85}; 86 87static uma_zone_t ttyinq_zone; 88 89void 90ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) 91{ | 32 33#include <sys/param.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/queue.h> 37#include <sys/sysctl.h> 38#include <sys/systm.h> 39#include <sys/tty.h> --- 44 unchanged lines hidden (view full) --- 84 char tib_data[TTYINQ_DATASIZE]; 85}; 86 87static uma_zone_t ttyinq_zone; 88 89void 90ttyinq_setsize(struct ttyinq *ti, struct tty *tp, size_t size) 91{ |
92 unsigned int nblocks; | |
93 struct ttyinq_block *tib; 94 | 92 struct ttyinq_block *tib; 93 |
95 nblocks = howmany(size, TTYINQ_DATASIZE); | 94 ti->ti_quota = howmany(size, TTYINQ_DATASIZE); |
96 | 95 |
97 while (nblocks > ti->ti_nblocks) { | 96 while (ti->ti_quota > ti->ti_nblocks) { |
98 /* 99 * List is getting bigger. 100 * Add new blocks to the tail of the list. 101 * 102 * We must unlock the TTY temporarily, because we need 103 * to allocate memory. This won't be a problem, because 104 * in the worst case, another thread ends up here, which 105 * may cause us to allocate too many blocks, but this 106 * will be caught by the loop below. 107 */ 108 tty_unlock(tp); 109 tib = uma_zalloc(ttyinq_zone, M_WAITOK); 110 tty_lock(tp); 111 | 97 /* 98 * List is getting bigger. 99 * Add new blocks to the tail of the list. 100 * 101 * We must unlock the TTY temporarily, because we need 102 * to allocate memory. This won't be a problem, because 103 * in the worst case, another thread ends up here, which 104 * may cause us to allocate too many blocks, but this 105 * will be caught by the loop below. 106 */ 107 tty_unlock(tp); 108 tib = uma_zalloc(ttyinq_zone, M_WAITOK); 109 tty_lock(tp); 110 |
112 if (tty_gone(tp)) 113 return; 114 | |
115 TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); 116 ti->ti_nblocks++; 117 } | 111 TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); 112 ti->ti_nblocks++; 113 } |
114} |
|
118 | 115 |
119 while (nblocks < ti->ti_nblocks) { 120 /* 121 * List is getting smaller. Remove unused blocks at the 122 * end. This means we cannot guarantee this routine 123 * shrinks buffers properly, when we need to reclaim 124 * more space than there is available. 125 * 126 * XXX TODO: Two solutions here: 127 * - Throw data away 128 * - Temporarily hit the watermark until enough data has 129 * been flushed, so we can remove the blocks. 130 */ | 116void 117ttyinq_free(struct ttyinq *ti) 118{ 119 struct ttyinq_block *tib; 120 121 ttyinq_flush(ti); 122 ti->ti_quota = 0; |
131 | 123 |
132 if (ti->ti_end == 0) 133 tib = TAILQ_FIRST(&ti->ti_list); 134 else 135 tib = TAILQ_NEXT(ti->ti_lastblock, tib_list); 136 if (tib == NULL) 137 break; | 124 while ((tib = TAILQ_FIRST(&ti->ti_list)) != NULL) { |
138 TAILQ_REMOVE(&ti->ti_list, tib, tib_list); 139 uma_zfree(ttyinq_zone, tib); 140 ti->ti_nblocks--; 141 } | 125 TAILQ_REMOVE(&ti->ti_list, tib, tib_list); 126 uma_zfree(ttyinq_zone, tib); 127 ti->ti_nblocks--; 128 } |
129 130 MPASS(ti->ti_nblocks == 0); |
|
142} 143 144int 145ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, 146 size_t rlen, size_t flen) 147{ 148 149 MPASS(rlen <= uio->uio_resid); --- 62 unchanged lines hidden (view full) --- 212 * userspace. We may need to flush trailing 213 * bytes, like EOF characters. 214 */ 215 tty_unlock(tp); 216 error = uiomove(tib->tib_data + cbegin, 217 clen - flen, uio); 218 tty_lock(tp); 219 | 131} 132 133int 134ttyinq_read_uio(struct ttyinq *ti, struct tty *tp, struct uio *uio, 135 size_t rlen, size_t flen) 136{ 137 138 MPASS(rlen <= uio->uio_resid); --- 62 unchanged lines hidden (view full) --- 201 * userspace. We may need to flush trailing 202 * bytes, like EOF characters. 203 */ 204 tty_unlock(tp); 205 error = uiomove(tib->tib_data + cbegin, 206 clen - flen, uio); 207 tty_lock(tp); 208 |
220 if (tty_gone(tp)) { 221 /* Something went bad - discard this block. */ | 209 /* Block can now be readded to the list. */ 210 if (ti->ti_quota <= ti->ti_nblocks) { |
222 uma_zfree(ttyinq_zone, tib); | 211 uma_zfree(ttyinq_zone, tib); |
223 return (ENXIO); | 212 } else { 213 TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); 214 ti->ti_nblocks++; |
224 } | 215 } |
225 /* Block can now be readded to the list. */ 226 /* 227 * XXX: we could remove the blocks here when the 228 * queue was shrunk, but still in use. See 229 * ttyinq_setsize(). 230 */ 231 TAILQ_INSERT_TAIL(&ti->ti_list, tib, tib_list); 232 ti->ti_nblocks++; 233 if (error != 0) 234 return (error); | |
235 } else { 236 char ob[TTYINQ_DATASIZE - 1]; 237 atomic_add_long(&ttyinq_nslow, 1); 238 239 /* 240 * Slow path: store data in a temporary buffer. 241 */ 242 memcpy(ob, tib->tib_data + cbegin, clen - flen); 243 ti->ti_begin += clen; 244 MPASS(ti->ti_begin < TTYINQ_DATASIZE); 245 246 /* Temporary unlock and copy the data to userspace. */ 247 tty_unlock(tp); 248 error = uiomove(ob, clen - flen, uio); 249 tty_lock(tp); | 216 } else { 217 char ob[TTYINQ_DATASIZE - 1]; 218 atomic_add_long(&ttyinq_nslow, 1); 219 220 /* 221 * Slow path: store data in a temporary buffer. 222 */ 223 memcpy(ob, tib->tib_data + cbegin, clen - flen); 224 ti->ti_begin += clen; 225 MPASS(ti->ti_begin < TTYINQ_DATASIZE); 226 227 /* Temporary unlock and copy the data to userspace. */ 228 tty_unlock(tp); 229 error = uiomove(ob, clen - flen, uio); 230 tty_lock(tp); |
250 251 if (error != 0) 252 return (error); 253 if (tty_gone(tp)) 254 return (ENXIO); | |
255 } | 231 } |
232 233 if (error != 0) 234 return (error); 235 if (tty_gone(tp)) 236 return (ENXIO); |
|
256 } 257 258 return (0); 259} 260 261static __inline void 262ttyinq_set_quotes(struct ttyinq_block *tib, size_t offset, 263 size_t length, int value) --- 239 unchanged lines hidden --- | 237 } 238 239 return (0); 240} 241 242static __inline void 243ttyinq_set_quotes(struct ttyinq_block *tib, size_t offset, 244 size_t length, int value) --- 239 unchanged lines hidden --- |