svn commit: r188487 - in head: sys/kern sys/sys usr.sbin/pstat

Ed Schouten ed at FreeBSD.org
Wed Feb 11 08:28:50 PST 2009


Author: ed
Date: Wed Feb 11 16:28:49 2009
New Revision: 188487
URL: http://svn.freebsd.org/changeset/base/188487

Log:
  Serialize write() calls on TTYs.
  
  Just like the old TTY layer, the current MPSAFE TTY layer does not make
  any attempt to serialize calls of write(). Data is copied into the
  kernel in 256 (TTY_STACKBUF) byte chunks. If a write() call occurs at
  the same time, the data may interleave. This is especially likely when
  the TTY starts blocking, because the output queue reaches the high
  watermark.
  
  I've implemented this by adding a new flag, TTY_BUSY_OUT, which is used
  to mark a TTY as having a thread stuck in write(). Because I don't want
  non-blocking processes to be possibly blocked by a sleeping thread, I'm
  still allowing it to bypass the protection. According to this message,
  the Linux kernel returns EAGAIN in such cases, but I think that's a
  little too restrictive:
  
  	http://kerneltrap.org/index.php?q=mailarchive/linux-kernel/2007/5/2/85418/thread
  
  PR:		kern/118287

Modified:
  head/sys/kern/tty.c
  head/sys/sys/tty.h
  head/usr.sbin/pstat/pstat.8
  head/usr.sbin/pstat/pstat.c

Modified: head/sys/kern/tty.c
==============================================================================
--- head/sys/kern/tty.c	Wed Feb 11 15:55:01 2009	(r188486)
+++ head/sys/kern/tty.c	Wed Feb 11 16:28:49 2009	(r188487)
@@ -438,15 +438,28 @@ ttydev_write(struct cdev *dev, struct ui
 
 	if (tp->t_termios.c_lflag & TOSTOP) {
 		error = tty_wait_background(tp, curthread, SIGTTOU);
-		if (error) {
-			tty_unlock(tp);
-			return (error);
-		}
+		if (error)
+			goto done;
 	}
 
-	error = ttydisc_write(tp, uio, ioflag);
-	tty_unlock(tp);
+	if (ioflag & IO_NDELAY && tp->t_flags & TF_BUSY_OUT) {
+		/* Allow non-blocking writes to bypass serialization. */
+		error = ttydisc_write(tp, uio, ioflag);
+	} else {
+		/* Serialize write() calls. */
+		while (tp->t_flags & TF_BUSY_OUT) {
+			error = tty_wait(tp, &tp->t_bgwait);
+			if (error)
+				goto done;
+		}
+ 
+ 		tp->t_flags |= TF_BUSY_OUT;
+		error = ttydisc_write(tp, uio, ioflag);
+ 		tp->t_flags &= ~TF_BUSY_OUT;
+		cv_broadcast(&tp->t_bgwait);
+	}
 
+done:	tty_unlock(tp);
 	return (error);
 }
 
@@ -1880,6 +1893,11 @@ static struct {
 	{ TF_ZOMBIE,		'Z' },
 	{ TF_HOOK,		's' },
 
+	/* Keep these together -> 'bi' and 'bo'. */
+	{ TF_BUSY,		'b' },
+	{ TF_BUSY_IN,		'i' },
+	{ TF_BUSY_OUT,		'o' },
+
 	{ 0,			'\0'},
 };
 

Modified: head/sys/sys/tty.h
==============================================================================
--- head/sys/sys/tty.h	Wed Feb 11 15:55:01 2009	(r188486)
+++ head/sys/sys/tty.h	Wed Feb 11 16:28:49 2009	(r188487)
@@ -83,6 +83,9 @@ struct tty {
 #define	TF_BYPASS	0x04000	/* Optimized input path. */
 #define	TF_ZOMBIE	0x08000	/* Modem disconnect received. */
 #define	TF_HOOK		0x10000	/* TTY has hook attached. */
+#define	TF_BUSY_IN	0x20000	/* Process busy in read() -- not supported. */
+#define	TF_BUSY_OUT	0x40000	/* Process busy in write(). */
+#define	TF_BUSY		(TF_BUSY_IN|TF_BUSY_OUT)
 	unsigned int	t_revokecnt;	/* (t) revoke() count. */
 
 	/* Buffering mechanisms. */

Modified: head/usr.sbin/pstat/pstat.8
==============================================================================
--- head/usr.sbin/pstat/pstat.8	Wed Feb 11 15:55:01 2009	(r188486)
+++ head/usr.sbin/pstat/pstat.8	Wed Feb 11 16:28:49 2009	(r188487)
@@ -206,6 +206,11 @@ block mode input routine in use
 connection lost
 .It s
 i/o being snooped
+.It b
+busy in
+.Xr read 2
+or
+.Xr write 2
 .El
 .Pp
 The

Modified: head/usr.sbin/pstat/pstat.c
==============================================================================
--- head/usr.sbin/pstat/pstat.c	Wed Feb 11 15:55:01 2009	(r188486)
+++ head/usr.sbin/pstat/pstat.c	Wed Feb 11 16:28:49 2009	(r188487)
@@ -315,6 +315,11 @@ static struct {
 	{ TF_ZOMBIE,		'Z' },
 	{ TF_HOOK,		's' },
 
+	/* Keep these together -> 'bi' and 'bo'. */
+	{ TF_BUSY,		'b' },
+	{ TF_BUSY_IN,		'i' },
+	{ TF_BUSY_OUT,		'o' },
+
 	{ 0,			'\0'},
 };
 


More information about the svn-src-all mailing list