Subject: Re: kern/37455: tty related lockup
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: netbsd-bugs
Date: 12/01/2007 22:03:24
it seems that the merge of c_cv and c_cvf introduced the problem.

ttwrite essentially does something like the following.

	while (overfull or ovhiwat) {
		ttstart();
		ttysleep();
	}

if it's a pty, ttstart calls cv_broadcast(c_cv) via ptsstart.
it makes two or more lwps doing ttwrite on the same tty wake up each other
and busy-loop.

the problem disappered on my box with the following patch, which simply
revives c_cvf.

YAMAMOTO Takashi


Index: sys/tty.h
===================================================================
RCS file: /cvsroot/src/sys/sys/tty.h,v
retrieving revision 1.76
diff -u -p -r1.76 tty.h
--- sys/tty.h	19 Nov 2007 18:51:52 -0000	1.76
+++ sys/tty.h	1 Dec 2007 12:52:19 -0000
@@ -62,6 +62,7 @@ struct clist {
 	u_char	*c_ce;		/* c_ce + c_len */
 	u_char	*c_cq;		/* N bits/bytes long, see tty_subr.c */
 	kcondvar_t c_cv;	/* notifier, locked by tty lock */
+	kcondvar_t c_cvf;	/* notifier, locked by tty lock */
 	int	c_cc;		/* count of characters in queue */
 	int	c_cn;		/* total ring buffer length */
 };
Index: kern/tty_pty.c
===================================================================
RCS file: /cvsroot/src/sys/kern/tty_pty.c,v
retrieving revision 1.104
diff -u -p -r1.104 tty_pty.c
--- kern/tty_pty.c	19 Nov 2007 19:47:00 -0000	1.104
+++ kern/tty_pty.c	1 Dec 2007 12:52:19 -0000
@@ -483,7 +483,7 @@ ptsstart(tp)
 	}
 
 	selnotify(&pti->pt_selr, NOTE_SUBMIT);
-	clwakeup(&tp->t_outq);
+	cv_broadcast(&tp->t_outq.c_cvf);
 }
 
 /*
@@ -509,11 +509,11 @@ ptsstop(tp, flush)
 	/* change of perspective */
 	if (flush & FREAD) {
 		selnotify(&pti->pt_selw, NOTE_SUBMIT);
-		clwakeup(&tp->t_rawq);
+		cv_broadcast(&tp->t_rawq.c_cvf);
 	}
 	if (flush & FWRITE) {
 		selnotify(&pti->pt_selr, NOTE_SUBMIT);
-		clwakeup(&tp->t_outq);
+		cv_broadcast(&tp->t_outq.c_cvf);
 	}
 }
 
@@ -527,11 +527,11 @@ ptcwakeup(tp, flag)
 	mutex_spin_enter(&tty_lock);
 	if (flag & FREAD) {
 		selnotify(&pti->pt_selr, NOTE_SUBMIT);
-		clwakeup(&tp->t_outq);
+		cv_broadcast(&tp->t_outq.c_cvf);
 	}
 	if (flag & FWRITE) {
 		selnotify(&pti->pt_selw, NOTE_SUBMIT);
-		clwakeup(&tp->t_rawq);
+		cv_broadcast(&tp->t_rawq.c_cvf);
 	}
 	mutex_spin_exit(&tty_lock);
 }
@@ -640,7 +640,7 @@ ptcread(dev, uio, flag)
 			error = EWOULDBLOCK;
 			goto out;
 		}
-		error = cv_wait_sig(&tp->t_outq.c_cv, &tty_lock);
+		error = cv_wait_sig(&tp->t_outq.c_cvf, &tty_lock);
 		if (error)
 			goto out;
 	}
Index: kern/tty_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/tty_subr.c,v
retrieving revision 1.31
diff -u -p -r1.31 tty_subr.c
--- kern/tty_subr.c	19 Nov 2007 18:51:52 -0000	1.31
+++ kern/tty_subr.c	1 Dec 2007 12:52:19 -0000
@@ -94,6 +94,7 @@ clalloc(struct clist *clp, int size, int
 	clp->c_cc = 0;
 
 	cv_init(&clp->c_cv, "tty");
+	cv_init(&clp->c_cvf, "ttyf");
 	return (0);
 }
 
@@ -106,6 +107,7 @@ clfree(struct clist *clp)
 		free(clp->c_cq, M_TTYS);
 	clp->c_cs = clp->c_cq = (u_char *)0;
 	cv_destroy(&clp->c_cv);
+	cv_destroy(&clp->c_cvf);
 }
 
 void