- 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:
This commit is contained in:
christos 2011-09-24 00:05:38 +00:00
parent f78cce945e
commit 92a9826daf
4 changed files with 115 additions and 22 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -91,6 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.247 2011/09/23 15:29:08 christos Exp $");
#include <sys/intr.h>
#include <sys/ioctl_compat.h>
#include <sys/module.h>
#include <sys/bitops.h>
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();
}
/*

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -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;

View File

@ -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 */

View File

@ -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 */