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/02/2007 06:45:03
The following reply was made to PR kern/37455; it has been noted by GNATS.

From: yamt@mwd.biglobe.ne.jp (YAMAMOTO Takashi)
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/37455: tty related lockup
Date: Sun,  2 Dec 2007 15:41:18 +0900 (JST)

 resend to gnats-bugs@ to update db.
 
 > 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