- 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:
parent
f78cce945e
commit
92a9826daf
108
sys/kern/tty.c
108
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 <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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user