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