X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..5eebf7385fedb1517b66b53c28e5aa6bb0a2be50:/bsd/kern/tty.c diff --git a/bsd/kern/tty.c b/bsd/kern/tty.c index 922299b3d..dee8138ff 100644 --- a/bsd/kern/tty.c +++ b/bsd/kern/tty.c @@ -106,6 +106,8 @@ #include #include #include +#include +#include #include #ifndef NeXT #include @@ -243,7 +245,9 @@ ttyopen(device, tp) register struct tty *tp; { int s; + boolean_t funnel_state; + funnel_state = thread_funnel_set(kernel_flock, TRUE); s = spltty(); tp->t_dev = device; if (!ISSET(tp->t_state, TS_ISOPEN)) { @@ -265,6 +269,7 @@ ttyopen(device, tp) #endif /* !NeXT */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -791,7 +796,9 @@ ttioctl(tp, cmd, data, flag, p) register struct proc *p = curproc; /* XXX */ #endif int s, error; + struct uthread *ut; + ut = (struct uthread *)get_bsdthread_info(current_act()); /* If the ioctl involves modification, hang if in the background. */ switch (cmd) { case TIOCFLUSH: @@ -818,7 +825,7 @@ ttioctl(tp, cmd, data, flag, p) while (isbackground(p, tp) && (p->p_flag & P_PPWAIT) == 0 && (p->p_sigignore & sigmask(SIGTTOU)) == 0 && - (p->p_sigmask & sigmask(SIGTTOU)) == 0) { + (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) { if (p->p_pgrp->pg_jobc == 0) return (EIO); pgsignal(p->p_pgrp, SIGTTOU, 1); @@ -1093,6 +1100,10 @@ ttioctl(tp, cmd, data, flag, p) tp->t_pgrp = p->p_pgrp; p->p_session->s_ttyp = tp; p->p_flag |= P_CONTROLT; + /* The backgrounded process blocking on tty now + * could be foregound process. Wake such processes + */ + tty_pgsignal(tp->t_pgrp, SIGCONT); break; case TIOCSPGRP: { /* set pgrp of tty */ register struct pgrp *pgrp = pgfind(*(int *)data); @@ -1102,6 +1113,10 @@ ttioctl(tp, cmd, data, flag, p) else if (pgrp == NULL || pgrp->pg_session != p->p_session) return (EPERM); tp->t_pgrp = pgrp; + /* The backgrounded process blocking on tty now + * could be foregound process. Wake such processes + */ + tty_pgsignal(tp->t_pgrp, SIGCONT); break; } case TIOCSTAT: /* simulate control-T */ @@ -1143,9 +1158,10 @@ ttioctl(tp, cmd, data, flag, p) } int -ttyselect(tp, rw, p) +ttyselect(tp, rw, wql, p) struct tty *tp; int rw; + void * wql; struct proc *p; { int s; @@ -1158,7 +1174,7 @@ ttyselect(tp, rw, p) case FREAD: if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE)) goto win; - selrecord(p, &tp->t_rsel); + selrecord(p, &tp->t_rsel, wql); break; case FWRITE: if ((tp->t_outq.c_cc <= tp->t_lowat && @@ -1167,7 +1183,7 @@ ttyselect(tp, rw, p) win: splx(s); return (1); } - selrecord(p, &tp->t_wsel); + selrecord(p, &tp->t_wsel, wql); break; } splx(s); @@ -1179,15 +1195,16 @@ win: splx(s); * cdevsw. It relies on a proper xxxdevtotty routine. */ int -ttselect(dev, rw, p) +ttselect(dev, rw, wql, p) dev_t dev; int rw; + void * wql; struct proc *p; { #ifndef NeXT - return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, p); + return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, wql, p); #else - return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, p); + return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, wql, p); #endif } @@ -1430,9 +1447,13 @@ int ttstart(tp) struct tty *tp; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ (*tp->t_oproc)(tp); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -1444,8 +1465,12 @@ ttylclose(tp, flag) struct tty *tp; int flag; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if ( (flag & FNONBLOCK) || ttywflush(tp)) ttyflush(tp, FREAD | FWRITE); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -1459,6 +1484,9 @@ ttymodem(tp, flag) register struct tty *tp; int flag; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) { /* @@ -1487,6 +1515,7 @@ ttymodem(tp, flag) if (tp->t_session && tp->t_session->s_leader) psignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); + thread_funnel_set(kernel_flock, funnel_state); return (0); } } else { @@ -1500,6 +1529,7 @@ ttymodem(tp, flag) ttwakeup(tp); ttwwakeup(tp); } + thread_funnel_set(kernel_flock, funnel_state); return (1); } @@ -1554,6 +1584,12 @@ ttread(tp, uio, flag) int s, first, error = 0; int has_etime = 0, last_cc = 0; long slp = 0; /* XXX this should be renamed `timo'. */ + boolean_t funnel_state; + struct uthread *ut; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); + + ut = (struct uthread *)get_bsdthread_info(current_act()); loop: s = spltty(); @@ -1574,18 +1610,23 @@ loop: if (isbackground(p, tp)) { splx(s); if ((p->p_sigignore & sigmask(SIGTTIN)) || - (p->p_sigmask & sigmask(SIGTTIN)) || - p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) + (ut->uu_sigmask & sigmask(SIGTTIN)) || + p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) { + thread_funnel_set(kernel_flock, funnel_state); return (EIO); + } pgsignal(p->p_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg2", 0); - if (error) + if (error){ + thread_funnel_set(kernel_flock, funnel_state); return (error); + } goto loop; } if (ISSET(tp->t_state, TS_ZOMBIE)) { splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); /* EOF */ } @@ -1602,9 +1643,11 @@ loop: goto read; if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) { splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (EWOULDBLOCK); } if (!ISSET(lflag, ICANON)) { @@ -1629,6 +1672,7 @@ loop: /* m, t and qp->c_cc are all 0. 0 is enough input. */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } t *= 100000; /* time in us */ @@ -1685,6 +1729,7 @@ loop: if (timercmp(&etime, &timecopy, <=)) { /* Timed out, but 0 is enough input. */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } slp = diff(etime, timecopy); @@ -1714,8 +1759,10 @@ sleep: splx(s); if (error == EWOULDBLOCK) error = 0; - else if (error) + else if (error) { + thread_funnel_set(kernel_flock, funnel_state); return (error); + } /* * XXX what happens if another process eats some input * while we are asleep (not just here)? It would be @@ -1832,6 +1879,7 @@ out: ttyunblock(tp); splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (error); } @@ -1848,16 +1896,19 @@ ttycheckoutq(tp, wait) int wait; { int hiwat, s, oldsig; + struct uthread *ut; + + ut = (struct uthread *)get_bsdthread_info(current_act()); hiwat = tp->t_hiwat; s = spltty(); - oldsig = wait ? current_proc()->p_siglist : 0; + oldsig = wait ? ut->uu_siglist : 0; if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) while (tp->t_outq.c_cc > hiwat) { ttstart(tp); if (tp->t_outq.c_cc <= hiwat) break; - if (wait == 0 || current_proc()->p_siglist != oldsig) { + if (wait == 0 || ut->uu_siglist != oldsig) { splx(s); return (0); } @@ -1882,7 +1933,12 @@ ttwrite(tp, uio, flag) register struct proc *p; int i, hiwat, cnt, error, s; char obuf[OBUFSIZ]; + boolean_t funnel_state; + struct uthread *ut; + funnel_state = thread_funnel_set(kernel_flock, TRUE); + + ut = (struct uthread *)get_bsdthread_info(current_act()); hiwat = tp->t_hiwat; cnt = uio->uio_resid; error = 0; @@ -1916,7 +1972,7 @@ loop: if (isbackground(p, tp) && ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 && (p->p_sigignore & sigmask(SIGTTOU)) == 0 && - (p->p_sigmask & sigmask(SIGTTOU)) == 0) { + (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) { if (p->p_pgrp->pg_jobc == 0) { error = EIO; goto out; @@ -1935,6 +1991,7 @@ loop: while (uio->uio_resid > 0 || cc > 0) { if (ISSET(tp->t_lflag, FLUSHO)) { uio->uio_resid = 0; + thread_funnel_set(kernel_flock, funnel_state); return (0); } if (tp->t_outq.c_cc > hiwat) @@ -2049,6 +2106,7 @@ out: * (the call will either return short or restart with a new uio). */ uio->uio_resid += cc; + thread_funnel_set(kernel_flock, funnel_state); return (error); #ifdef NeXT @@ -2077,6 +2135,7 @@ ovhiwat: if (flag & IO_NDELAY) { splx(s); uio->uio_resid += cc; + thread_funnel_set(kernel_flock, funnel_state); return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); } SET(tp->t_state, TS_SO_OLOWAT);