From 92a9826dafc8c4f700370f96169f6574e3ca9b9e Mon Sep 17 00:00:00 2001 From: christos Date: Sat, 24 Sep 2011 00:05:38 +0000 Subject: [PATCH] - Introduce a sysctl to control the default tty queue size kern.tty.qsize, which defaults to 1024 as before. - Add two ioctls TIOC{G,S}QSIZE to read and adjust the queue size on individual ptys. NB: ttys (and ptys) still silently (or beepingly (IMAXBEL)) drop characters if the queue size is exceeded. I.e. you can appear to succeed writing to the {p,t}ty, but not all characters will have made it if the queue overflows. CVS: --- sys/kern/tty.c | 108 ++++++++++++++++++++++++++++++++++++++++---- sys/kern/tty_subr.c | 8 ++-- sys/sys/tty.h | 17 +++---- sys/sys/ttycom.h | 4 +- 4 files changed, 115 insertions(+), 22 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 8cd898728202..a0aef23dfcff 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.247 2011/09/23 15:29:08 christos Exp $ */ +/* $NetBSD: tty.c,v 1.248 2011/09/24 00:05:38 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.247 2011/09/23 15:29:08 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.248 2011/09/24 00:05:38 christos Exp $"); #include #include @@ -91,6 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.247 2011/09/23 15:29:08 christos Exp $"); #include #include #include +#include static int ttnread(struct tty *); static void ttyblock(struct tty *); @@ -207,12 +208,77 @@ uint64_t tk_rawcc; static kauth_listener_t tty_listener; -static struct sysctllog *kern_tkstat_sysctllog; +#define TTY_MINQSIZE 0x00400 +#define TTY_MAXQSIZE 0x10000 +int tty_qsize = TTY_MINQSIZE; + +static int +tty_get_qsize(int *qsize, int newsize) +{ + newsize = 1 << ilog2(newsize); /* Make it a power of two */ + + if (newsize < TTY_MINQSIZE || newsize > TTY_MAXQSIZE) + return EINVAL; + + *qsize = newsize; + return 0; +} static void -sysctl_kern_tkstat_setup(void) +tty_set_qsize(struct tty *tp, int newsize) { + struct clist rawq, canq, outq; + struct clist orawq, ocanq, ooutq; + clalloc(&rawq, newsize, 1); + clalloc(&canq, newsize, 1); + clalloc(&outq, newsize, 0); + + mutex_spin_enter(&tty_lock); + + orawq = tp->t_rawq; + ocanq = tp->t_canq; + ooutq = tp->t_outq; + + tp->t_qsize = newsize; + tp->t_rawq = rawq; + tp->t_canq = canq; + tp->t_outq = outq; + + ttsetwater(tp); + + mutex_spin_exit(&tty_lock); + + clfree(&orawq); + clfree(&ocanq); + clfree(&ooutq); +} + +static int +sysctl_kern_tty_qsize(SYSCTLFN_ARGS) +{ + int newsize; + int error; + struct sysctlnode node; + node = *rnode; + node.sysctl_data = &newsize; + + newsize = tty_qsize; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + + + return tty_get_qsize(&tty_qsize, newsize); +} + +static void +sysctl_kern_tty_setup(void) +{ + const struct sysctlnode *rnode, *cnode; + struct sysctllog *kern_tkstat_sysctllog, *kern_tty_sysctllog; + + kern_tkstat_sysctllog = NULL; sysctl_createv(&kern_tkstat_sysctllog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL, @@ -250,6 +316,19 @@ sysctl_kern_tkstat_setup(void) SYSCTL_DESCR("Number of raw tty input characters"), NULL, 0, &tk_rawcc, 0, CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_RAWCC, CTL_EOL); + + kern_tty_sysctllog = NULL; + sysctl_createv(&kern_tty_sysctllog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "tty", NULL, + NULL, 0, NULL, 0, + CTL_KERN, CTL_CREATE, CTL_EOL); + sysctl_createv(&kern_tty_sysctllog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "qsize", + SYSCTL_DESCR("TTY input and output queue size"), + sysctl_kern_tty_qsize, 0, &tty_qsize, 0, + CTL_CREATE, CTL_EOL); } int @@ -319,6 +398,8 @@ ttylopen(dev_t device, struct tty *tp) tp->t_flags = 0; } mutex_spin_exit(&tty_lock); + if (tp->t_qsize != tty_qsize) + tty_set_qsize(tp, tty_qsize); return (0); } @@ -856,6 +937,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l) case TIOCSTAT: case TIOCSTI: case TIOCSWINSZ: + case TIOCSQSIZE: case TIOCLBIC: case TIOCLBIS: case TIOCLSET: @@ -974,6 +1056,9 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l) case TIOCGWINSZ: /* get window size */ *(struct winsize *)data = tp->t_winsize; break; + case TIOCGQSIZE: + *(int *)data = tp->t_qsize; + break; case FIOGETOWN: mutex_enter(proc_lock); if (tp->t_session != NULL && !isctty(p, tp)) { @@ -1262,6 +1347,11 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l) } mutex_spin_exit(&tty_lock); break; + case TIOCSQSIZE: + if ((error = tty_get_qsize(&s, *(int *)data)) == 0 && + s != tp->t_qsize) + tty_set_qsize(tp, s); + return error; default: /* We may have to load the compat module for this. */ for (;;) { @@ -2694,15 +2784,15 @@ tty_alloc(void) tp = kmem_zalloc(sizeof(*tp), KM_SLEEP); callout_init(&tp->t_rstrt_ch, 0); callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp); - /* XXX: default to 1024 chars for now */ - clalloc(&tp->t_rawq, 1024, 1); + tp->t_qsize = tty_qsize; + clalloc(&tp->t_rawq, tp->t_qsize, 1); cv_init(&tp->t_rawcv, "ttyraw"); cv_init(&tp->t_rawcvf, "ttyrawf"); - clalloc(&tp->t_canq, 1024, 1); + clalloc(&tp->t_canq, tp->t_qsize, 1); cv_init(&tp->t_cancv, "ttycan"); cv_init(&tp->t_cancvf, "ttycanf"); /* output queue doesn't need quoting */ - clalloc(&tp->t_outq, 1024, 0); + clalloc(&tp->t_outq, tp->t_qsize, 0); cv_init(&tp->t_outcv, "ttyout"); cv_init(&tp->t_outcvf, "ttyoutf"); /* Set default line discipline. */ @@ -2817,7 +2907,7 @@ tty_init(void) tty_listener = kauth_listen_scope(KAUTH_SCOPE_DEVICE, tty_listener_cb, NULL); - sysctl_kern_tkstat_setup(); + sysctl_kern_tty_setup(); } /* diff --git a/sys/kern/tty_subr.c b/sys/kern/tty_subr.c index 6dbc4ebf902e..603a54d56b25 100644 --- a/sys/kern/tty_subr.c +++ b/sys/kern/tty_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty_subr.c,v 1.39 2009/11/14 13:18:41 dsl Exp $ */ +/* $NetBSD: tty_subr.c,v 1.40 2011/09/24 00:05:38 christos Exp $ */ /* * Copyright (c) 1993, 1994 Theo de Raadt @@ -29,7 +29,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tty_subr.c,v 1.39 2009/11/14 13:18:41 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tty_subr.c,v 1.40 2011/09/24 00:05:38 christos Exp $"); #include #include @@ -263,7 +263,7 @@ putc(int c, struct clist *clp) #if defined(DIAGNOSTIC) || 1 printf("putc: required clalloc\n"); #endif - if (clalloc(clp, 1024, 1)) { + if (clalloc(clp, clp->c_cn, 1)) { out: splx(s); return -1; @@ -352,7 +352,7 @@ b_to_q(const u_char *cp, int count, struct clist *clp) #if defined(DIAGNOSTIC) || 1 printf("b_to_q: required clalloc\n"); #endif - if (clalloc(clp, 1024, 1)) + if (clalloc(clp, clp->c_cn, 1)) goto out; } clp->c_cf = clp->c_cl = clp->c_cs; diff --git a/sys/sys/tty.h b/sys/sys/tty.h index 4e3a3d1f913c..b9f51027ca29 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.89 2011/09/23 15:29:09 christos Exp $ */ +/* $NetBSD: tty.h,v 1.90 2011/09/24 00:05:38 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -126,6 +126,7 @@ struct tty { int t_state; /* Device and driver (TS*) state. */ int t_wopen; /* Processes waiting for open. */ int t_flags; /* Tty flags. */ + int t_qsize; /* Tty character queue size */ struct pgrp *t_pgrp; /* Foreground process group. */ struct session *t_session; /* Enclosing session. */ struct selinfo t_rsel; /* Tty read/oob select. */ @@ -141,8 +142,8 @@ struct tty { void *t_sc; /* XXX: net/if_sl.c:sl_softc. */ short t_column; /* Tty output column. */ short t_rocount, t_rocol; /* Tty. */ - short t_hiwat; /* High water mark. */ - short t_lowat; /* Low water mark. */ + int t_hiwat; /* High water mark. */ + int t_lowat; /* Low water mark. */ short t_gen; /* Generation number. */ sigset_t t_sigs[TTYSIG_COUNT]; /* Pending signals */ int t_sigcount; /* # pending signals */ @@ -162,13 +163,13 @@ struct tty { #define TTMASK 15 #define OBUFSIZ 100 -#define TTYHOG 1024 +#define TTYHOG tp->t_qsize #ifdef _KERNEL -#define TTMAXHIWAT roundup(2048, TTROUND) -#define TTMINHIWAT roundup(100, TTROUND) -#define TTMAXLOWAT 256 -#define TTMINLOWAT 32 +#define TTMAXHIWAT roundup(tp->t_qsize << 1, 64) +#define TTMINHIWAT roundup(tp->t_qsize >> 3, 64) +#define TTMAXLOWAT (tp->t_qsize >> 2) +#define TTMINLOWAT (tp->t_qsize >> 5) #define TTROUND 64 #endif /* _KERNEL */ diff --git a/sys/sys/ttycom.h b/sys/sys/ttycom.h index ca74c247b0a5..d8937eb69511 100644 --- a/sys/sys/ttycom.h +++ b/sys/sys/ttycom.h @@ -1,4 +1,4 @@ -/* $NetBSD: ttycom.h,v 1.18 2005/12/11 12:25:21 christos Exp $ */ +/* $NetBSD: ttycom.h,v 1.19 2011/09/24 00:05:39 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1993, 1994 @@ -153,6 +153,8 @@ typedef char linedn_t[TTLINEDNAMELEN]; #define TIOCGRANTPT _IO('t', 71) /* grantpt(3) */ #define TIOCPTSNAME _IOR('t', 72, struct ptmget) /* ptsname(3) */ +#define TIOCSQSIZE _IOW('t', 128, int) /* set queue size */ +#define TIOCGQSIZE _IOR('t', 129, int) /* get queue size */ #define TTYDISC 0 /* termios tty line discipline */ #define TABLDISC 3 /* tablet discipline */