]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/tty.c
xnu-517.9.5.tar.gz
[apple/xnu.git] / bsd / kern / tty.c
index 922299b3da78ae3dea19df8e6604d7910af48232..dee8138ff8a9a28b6143f8edc4607c3b90675cf6 100644 (file)
 #include <sys/kernel.h>
 #include <sys/vnode.h>
 #include <sys/syslog.h>
+#include <sys/user.h>
+#include <sys/signalvar.h>
 #include <sys/signalvar.h>
 #ifndef NeXT
 #include <sys/resourcevar.h>
@@ -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);