Module Name:    src
Committed By:   christos
Date:           Sat Sep 24 00:05:39 UTC 2011

Modified Files:
        src/sys/kern: tty.c tty_subr.c
        src/sys/sys: tty.h ttycom.h

Log Message:
- 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:


To generate a diff of this commit:
cvs rdiff -u -r1.247 -r1.248 src/sys/kern/tty.c
cvs rdiff -u -r1.39 -r1.40 src/sys/kern/tty_subr.c
cvs rdiff -u -r1.89 -r1.90 src/sys/sys/tty.h
cvs rdiff -u -r1.18 -r1.19 src/sys/sys/ttycom.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/tty.c
diff -u src/sys/kern/tty.c:1.247 src/sys/kern/tty.c:1.248
--- src/sys/kern/tty.c:1.247	Fri Sep 23 11:29:08 2011
+++ src/sys/kern/tty.c	Fri Sep 23 20:05:38 2011
@@ -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 @@
 #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 @@
 
 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
+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_tkstat_setup(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_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 @@
 		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 @@
 	case  TIOCSTAT:
 	case  TIOCSTI:
 	case  TIOCSWINSZ:
+	case  TIOCSQSIZE:
 	case  TIOCLBIC:
 	case  TIOCLBIS:
 	case  TIOCLSET:
@@ -974,6 +1056,9 @@
 	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 @@
 		}
 		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 @@
 	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_listener = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
 	    tty_listener_cb, NULL);
 
-	sysctl_kern_tkstat_setup();
+	sysctl_kern_tty_setup();
 }
 
 /*

Index: src/sys/kern/tty_subr.c
diff -u src/sys/kern/tty_subr.c:1.39 src/sys/kern/tty_subr.c:1.40
--- src/sys/kern/tty_subr.c:1.39	Sat Nov 14 08:18:41 2009
+++ src/sys/kern/tty_subr.c	Fri Sep 23 20:05:38 2011
@@ -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 @@
 #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 @@
 #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;

Index: src/sys/sys/tty.h
diff -u src/sys/sys/tty.h:1.89 src/sys/sys/tty.h:1.90
--- src/sys/sys/tty.h:1.89	Fri Sep 23 11:29:09 2011
+++ src/sys/sys/tty.h	Fri Sep 23 20:05:38 2011
@@ -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 @@
 	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 @@
 	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 @@
 
 #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 */
 

Index: src/sys/sys/ttycom.h
diff -u src/sys/sys/ttycom.h:1.18 src/sys/sys/ttycom.h:1.19
--- src/sys/sys/ttycom.h:1.18	Sun Dec 11 07:25:21 2005
+++ src/sys/sys/ttycom.h	Fri Sep 23 20:05:39 2011
@@ -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 @@
 #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 */

Reply via email to