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