[BACK]Return to tty.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/tty.c between version 1.214 and 1.214.2.2

version 1.214, 2008/04/05 14:03:16 version 1.214.2.2, 2008/06/04 02:05:40
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
    * Copyright (c) 2008 The NetBSD Foundation, Inc.
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    *
    * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
    * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
    * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    * POSSIBILITY OF SUCH DAMAGE.
    */
   
   /*-
  * Copyright (c) 1982, 1986, 1990, 1991, 1993   * Copyright (c) 1982, 1986, 1990, 1991, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  * (c) UNIX System Laboratories, Inc.   * (c) UNIX System Laboratories, Inc.
Line 54  __KERNEL_RCSID(0, "$NetBSD$");
Line 80  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/vnode.h>  #include <sys/vnode.h>
 #include <sys/syslog.h>  #include <sys/syslog.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #include <sys/pool.h>  #include <sys/kmem.h>
 #include <sys/signalvar.h>  #include <sys/signalvar.h>
 #include <sys/resourcevar.h>  #include <sys/resourcevar.h>
 #include <sys/poll.h>  #include <sys/poll.h>
Line 172  struct ttylist_head ttylist = TAILQ_HEAD
Line 198  struct ttylist_head ttylist = TAILQ_HEAD
 int tty_count;  int tty_count;
 kmutex_t tty_lock;  kmutex_t tty_lock;
   
 POOL_INIT(tty_pool, sizeof(struct tty), 0, 0, 0, "ttypl",  
     &pool_allocator_nointr, IPL_NONE);  
   
 uint64_t tk_cancc;  uint64_t tk_cancc;
 uint64_t tk_nin;  uint64_t tk_nin;
 uint64_t tk_nout;  uint64_t tk_nout;
Line 252  ttyopen(struct tty *tp, int dialout, int
Line 275  ttyopen(struct tty *tp, int dialout, int
                         while (ISSET(tp->t_state, TS_DIALOUT) ||                          while (ISSET(tp->t_state, TS_DIALOUT) ||
                                !CONNECTED(tp)) {                                 !CONNECTED(tp)) {
                                 tp->t_wopen++;                                  tp->t_wopen++;
                                 error = ttysleep(tp, &tp->t_rawq.c_cv, true, 0);                                  error = ttysleep(tp, &tp->t_rawcv, true, 0);
                                 tp->t_wopen--;                                  tp->t_wopen--;
                                 if (error)                                  if (error)
                                         goto out;                                          goto out;
Line 320  ttyclose(struct tty *tp)
Line 343  ttyclose(struct tty *tp)
   
         mutex_spin_exit(&tty_lock);          mutex_spin_exit(&tty_lock);
   
         mutex_enter(&proclist_lock);          mutex_enter(proc_lock);
         if (sess != NULL)          if (sess != NULL)
                 SESSRELE(sess);                  SESSRELE(sess);
         mutex_exit(&proclist_lock);          mutex_exit(proc_lock);
   
         return (0);          return (0);
 }  }
Line 605  ttyinput_wlock(int c, struct tty *tp)
Line 628  ttyinput_wlock(int c, struct tty *tp)
                          * ^T - kernel info and generate SIGINFO                           * ^T - kernel info and generate SIGINFO
                          */                           */
                         if (CCEQ(cc[VSTATUS], c)) {                          if (CCEQ(cc[VSTATUS], c)) {
                                 if (!ISSET(lflag, NOKERNINFO))                                  ttysig(tp, TTYSIG_PG1, SIGINFO);
                                         ttyinfo(tp, 1);  
                                 if (ISSET(lflag, ISIG))  
                                         ttysig(tp, TTYSIG_PG1, SIGINFO);  
                                 goto endcase;                                  goto endcase;
                         }                          }
                 }                  }
Line 809  ttioctl(struct tty *tp, u_long cmd, void
Line 829  ttioctl(struct tty *tp, u_long cmd, void
         struct linesw   *lp;          struct linesw   *lp;
         int             s, error;          int             s, error;
         struct nameidata nd;          struct nameidata nd;
           char            infobuf[200];
   
         /* If the ioctl involves modification, hang if in the background. */          /* If the ioctl involves modification, hang if in the background. */
         switch (cmd) {          switch (cmd) {
Line 845  ttioctl(struct tty *tp, u_long cmd, void
Line 866  ttioctl(struct tty *tp, u_long cmd, void
                     !sigismasked(l, SIGTTOU)) {                      !sigismasked(l, SIGTTOU)) {
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
   
                         mutex_enter(&proclist_mutex);                          mutex_enter(proc_lock);
                         pgsignal(p->p_pgrp, SIGTTOU, 1);                          pgsignal(p->p_pgrp, SIGTTOU, 1);
                         mutex_exit(&proclist_mutex);                          mutex_exit(proc_lock);
   
                         mutex_spin_enter(&tty_lock);                          mutex_spin_enter(&tty_lock);
                         error = ttysleep(tp, &lbolt, true, 0);                          error = ttysleep(tp, &lbolt, true, 0);
Line 944  ttioctl(struct tty *tp, u_long cmd, void
Line 965  ttioctl(struct tty *tp, u_long cmd, void
                 *(struct winsize *)data = tp->t_winsize;                  *(struct winsize *)data = tp->t_winsize;
                 break;                  break;
         case FIOGETOWN:          case FIOGETOWN:
                 if (tp->t_session != NULL && !isctty(p, tp))                  mutex_enter(proc_lock);
                   if (tp->t_session != NULL && !isctty(p, tp)) {
                           mutex_exit(proc_lock);
                         return (ENOTTY);                          return (ENOTTY);
                   }
                 *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;                  *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
                   mutex_exit(proc_lock);
                 break;                  break;
         case TIOCGPGRP:                 /* get pgrp of tty */          case TIOCGPGRP:                 /* get pgrp of tty */
                 if (!isctty(p, tp))                  mutex_enter(proc_lock);
                   if (!isctty(p, tp)) {
                           mutex_exit(proc_lock);
                         return (ENOTTY);                          return (ENOTTY);
                   }
                 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;                  *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
                   mutex_exit(proc_lock);
                 break;                  break;
         case TIOCGSID:                  /* get sid of tty */          case TIOCGSID:                  /* get sid of tty */
                 if (!isctty(p, tp))                  mutex_enter(proc_lock);
                   if (!isctty(p, tp)) {
                           mutex_exit(proc_lock);
                         return (ENOTTY);                          return (ENOTTY);
                   }
                 *(int *)data = tp->t_session->s_sid;                  *(int *)data = tp->t_session->s_sid;
                   mutex_exit(proc_lock);
                 break;                  break;
 #ifdef TIOCHPCL  #ifdef TIOCHPCL
         case TIOCHPCL:                  /* hang up on last close */          case TIOCHPCL:                  /* hang up on last close */
Line 1114  ttioctl(struct tty *tp, u_long cmd, void
Line 1147  ttioctl(struct tty *tp, u_long cmd, void
                 break;                  break;
         }          }
         case TIOCSCTTY:                 /* become controlling tty */          case TIOCSCTTY:                 /* become controlling tty */
                 mutex_enter(&proclist_lock);                  mutex_enter(proc_lock);
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
   
                 /* Session ctty vnode pointer set in vnode layer. */                  /* Session ctty vnode pointer set in vnode layer. */
Line 1122  ttioctl(struct tty *tp, u_long cmd, void
Line 1155  ttioctl(struct tty *tp, u_long cmd, void
                     ((p->p_session->s_ttyvp || tp->t_session) &&                      ((p->p_session->s_ttyvp || tp->t_session) &&
                     (tp->t_session != p->p_session))) {                      (tp->t_session != p->p_session))) {
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
                         mutex_exit(&proclist_lock);                          mutex_exit(proc_lock);
                         return (EPERM);                          return (EPERM);
                 }                  }
   
Line 1140  ttioctl(struct tty *tp, u_long cmd, void
Line 1173  ttioctl(struct tty *tp, u_long cmd, void
                 p->p_session->s_ttyp = tp;                  p->p_session->s_ttyp = tp;
                 p->p_lflag |= PL_CONTROLT;                  p->p_lflag |= PL_CONTROLT;
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 mutex_exit(&proclist_lock);                  mutex_exit(proc_lock);
                 break;                  break;
         case FIOSETOWN: {               /* set pgrp of tty */          case FIOSETOWN: {               /* set pgrp of tty */
                 pid_t pgid = *(int *)data;                  pid_t pgid = *(int *)data;
                 struct pgrp *pgrp;                  struct pgrp *pgrp;
   
                 mutex_enter(&proclist_lock);                  mutex_enter(proc_lock);
                 if (tp->t_session != NULL && !isctty(p, tp)) {                  if (tp->t_session != NULL && !isctty(p, tp)) {
                         mutex_exit(&proclist_lock);                          mutex_exit(proc_lock);
                         return (ENOTTY);                          return (ENOTTY);
                 }                  }
   
Line 1165  ttioctl(struct tty *tp, u_long cmd, void
Line 1198  ttioctl(struct tty *tp, u_long cmd, void
                 }                  }
   
                 if (pgrp->pg_session != p->p_session) {                  if (pgrp->pg_session != p->p_session) {
                         mutex_exit(&proclist_lock);                          mutex_exit(proc_lock);
                         return (EPERM);                          return (EPERM);
                 }                  }
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
                 tp->t_pgrp = pgrp;                  tp->t_pgrp = pgrp;
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 mutex_exit(&proclist_lock);                  mutex_exit(proc_lock);
                 break;                  break;
         }          }
         case TIOCSPGRP: {               /* set pgrp of tty */          case TIOCSPGRP: {               /* set pgrp of tty */
                 struct pgrp *pgrp;                  struct pgrp *pgrp;
   
                 mutex_enter(&proclist_lock);                  mutex_enter(proc_lock);
                 if (!isctty(p, tp)) {                  if (!isctty(p, tp)) {
                         mutex_exit(&proclist_lock);                          mutex_exit(proc_lock);
                         return (ENOTTY);                          return (ENOTTY);
                 }                  }
                 pgrp = pg_find(*(int *)data, PFIND_LOCKED | PFIND_UNLOCK_FAIL);                  pgrp = pg_find(*(int *)data, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
                 if (pgrp == NULL)                  if (pgrp == NULL)
                         return (EINVAL);                          return (EINVAL);
                 if (pgrp->pg_session != p->p_session) {                  if (pgrp->pg_session != p->p_session) {
                         mutex_exit(&proclist_lock);                          mutex_exit(proc_lock);
                         return (EPERM);                          return (EPERM);
                 }                  }
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
                 tp->t_pgrp = pgrp;                  tp->t_pgrp = pgrp;
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 mutex_exit(&proclist_lock);                  mutex_exit(proc_lock);
                 break;                  break;
         }          }
         case TIOCSTAT:                  /* get load avg stats */          case TIOCSTAT:                  /* get load avg stats */
                   mutex_enter(proc_lock);
                   ttygetinfo(tp, 0, infobuf, sizeof(infobuf));
                   mutex_exit(proc_lock);
   
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
                 ttyinfo(tp, 0);                  ttyputinfo(tp, infobuf);
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 break;                  break;
         case TIOCSWINSZ:                /* set window size */          case TIOCSWINSZ:                /* set window size */
Line 1375  ttywait(struct tty *tp)
Line 1412  ttywait(struct tty *tp)
         while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&          while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
             CONNECTED(tp) && tp->t_oproc) {              CONNECTED(tp) && tp->t_oproc) {
                 (*tp->t_oproc)(tp);                  (*tp->t_oproc)(tp);
                 error = ttysleep(tp, &tp->t_outq.c_cv, true, 0);                  error = ttysleep(tp, &tp->t_outcv, true, 0);
                 if (error)                  if (error)
                         break;                          break;
         }          }
Line 1422  ttyflush(struct tty *tp, int rw)
Line 1459  ttyflush(struct tty *tp, int rw)
                 CLR(tp->t_state, TS_TTSTOP);                  CLR(tp->t_state, TS_TTSTOP);
                 cdev_stop(tp, rw);                  cdev_stop(tp, rw);
                 FLUSHQ(&tp->t_outq);                  FLUSHQ(&tp->t_outq);
                 clwakeup(&tp->t_outq);                  cv_broadcast(&tp->t_outcv);
                 selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);                  selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
         }          }
 }  }
Line 1641  ttread(struct tty *tp, struct uio *uio, 
Line 1678  ttread(struct tty *tp, struct uio *uio, 
          * Hang process if it's in the background.           * Hang process if it's in the background.
          */           */
         if (isbackground(p, tp)) {          if (isbackground(p, tp)) {
                 if (sigismember(&p->p_sigctx.ps_sigignore, SIGTTIN) ||                  if (sigismasked(curlwp, SIGTTIN) ||
                     sigismember(&curlwp->l_sigmask, SIGTTIN) ||  
                     p->p_sflag & PS_PPWAIT || p->p_pgrp->pg_jobc == 0) {                      p->p_sflag & PS_PPWAIT || p->p_pgrp->pg_jobc == 0) {
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
                         return (EIO);                          return (EIO);
                 }                  }
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
   
                 mutex_enter(&proclist_mutex);                  mutex_enter(proc_lock);
                 pgsignal(p->p_pgrp, SIGTTIN, 1);                  pgsignal(p->p_pgrp, SIGTTIN, 1);
                 mutex_exit(&proclist_mutex);                  mutex_exit(proc_lock);
   
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
                 error = ttysleep(tp, &lbolt, true, 0);                  error = ttysleep(tp, &lbolt, true, 0);
Line 1751  ttread(struct tty *tp, struct uio *uio, 
Line 1787  ttread(struct tty *tp, struct uio *uio, 
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
                         return (EWOULDBLOCK);                          return (EWOULDBLOCK);
                 }                  }
                 error = ttysleep(tp, &tp->t_rawq.c_cv, true, slp);                  error = ttysleep(tp, &tp->t_rawcv, true, slp);
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 /* VMIN == 0: any quantity read satisfies */                  /* VMIN == 0: any quantity read satisfies */
                 if (cc[VMIN] == 0 && error == EWOULDBLOCK)                  if (cc[VMIN] == 0 && error == EWOULDBLOCK)
Line 1849  ttycheckoutq_wlock(struct tty *tp, int w
Line 1885  ttycheckoutq_wlock(struct tty *tp, int w
                         ttstart(tp);                          ttstart(tp);
                         if (wait == 0)                          if (wait == 0)
                                 return (0);                                  return (0);
                         error = ttysleep(tp, &tp->t_outq.c_cv, true, hz);                          error = ttysleep(tp, &tp->t_outcv, true, hz);
                         if (error == EINTR)                          if (error == EINTR)
                                 wait = 0;                                  wait = 0;
                 }                  }
Line 1898  ttwrite(struct tty *tp, struct uio *uio,
Line 1934  ttwrite(struct tty *tp, struct uio *uio,
                         goto out;                          goto out;
                 } else {                  } else {
                         /* Sleep awaiting carrier. */                          /* Sleep awaiting carrier. */
                         error = ttysleep(tp, &tp->t_rawq.c_cv, true, 0);                          error = ttysleep(tp, &tp->t_rawcv, true, 0);
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
                         if (error)                          if (error)
                                 goto out;                                  goto out;
Line 1912  ttwrite(struct tty *tp, struct uio *uio,
Line 1948  ttwrite(struct tty *tp, struct uio *uio,
         p = curproc;          p = curproc;
         if (isbackground(p, tp) &&          if (isbackground(p, tp) &&
             ISSET(tp->t_lflag, TOSTOP) && (p->p_sflag & PS_PPWAIT) == 0 &&              ISSET(tp->t_lflag, TOSTOP) && (p->p_sflag & PS_PPWAIT) == 0 &&
             !sigismember(&p->p_sigctx.ps_sigignore, SIGTTOU) &&              !sigismasked(curlwp, SIGTTOU)) {
             !sigismember(&curlwp->l_sigmask, SIGTTOU)) {  
                 if (p->p_pgrp->pg_jobc == 0) {                  if (p->p_pgrp->pg_jobc == 0) {
                         error = EIO;                          error = EIO;
                         mutex_spin_exit(&tty_lock);                          mutex_spin_exit(&tty_lock);
Line 1921  ttwrite(struct tty *tp, struct uio *uio,
Line 1956  ttwrite(struct tty *tp, struct uio *uio,
                 }                  }
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
   
                 mutex_enter(&proclist_mutex);                  mutex_enter(proc_lock);
                 pgsignal(p->p_pgrp, SIGTTOU, 1);                  pgsignal(p->p_pgrp, SIGTTOU, 1);
                 mutex_exit(&proclist_mutex);                  mutex_exit(proc_lock);
   
                 mutex_spin_enter(&tty_lock);                  mutex_spin_enter(&tty_lock);
                 error = ttysleep(tp, &lbolt, true, 0);                  error = ttysleep(tp, &lbolt, true, 0);
Line 2057  ttwrite(struct tty *tp, struct uio *uio,
Line 2092  ttwrite(struct tty *tp, struct uio *uio,
                 error = EWOULDBLOCK;                  error = EWOULDBLOCK;
                 goto out;                  goto out;
         }          }
         error = ttysleep(tp, &tp->t_outq.c_cv, true, 0);          error = ttysleep(tp, &tp->t_outcv, true, 0);
         mutex_spin_exit(&tty_lock);          mutex_spin_exit(&tty_lock);
         if (error)          if (error)
                 goto out;                  goto out;
Line 2075  ttypull(struct tty *tp)
Line 2110  ttypull(struct tty *tp)
         /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */          /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
   
         if (tp->t_outq.c_cc <= tp->t_lowat) {          if (tp->t_outq.c_cc <= tp->t_lowat) {
                 clwakeup(&tp->t_outq);                  cv_broadcast(&tp->t_outcv);
                 selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);                  selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
         }          }
         return tp->t_outq.c_cc != 0;          return tp->t_outq.c_cc != 0;
Line 2250  ttwakeup(struct tty *tp)
Line 2285  ttwakeup(struct tty *tp)
         selnotify(&tp->t_rsel, 0, NOTE_SUBMIT);          selnotify(&tp->t_rsel, 0, NOTE_SUBMIT);
         if (ISSET(tp->t_state, TS_ASYNC))          if (ISSET(tp->t_state, TS_ASYNC))
                 ttysig(tp, TTYSIG_PG2, SIGIO);                  ttysig(tp, TTYSIG_PG2, SIGIO);
 #if 0          cv_broadcast(&tp->t_rawcv);
         /* XXX tp->t_rawq.c_cv.cv_waiters dropping to zero early!? */  
         clwakeup(&tp->t_rawq);  
 #else  
         cv_wakeup(&tp->t_rawq.c_cv);  
 #endif  
 }  }
   
 /*  /*
Line 2296  ttsetwater(struct tty *tp)
Line 2326  ttsetwater(struct tty *tp)
 }  }
   
 /*  /*
  * Report on state of foreground process group.   * Prepare report on state of foreground process group.
  * Call with tty lock held.   * Call with proc_lock held.
  */   */
 void  void
 ttyinfo(struct tty *tp, int fromsig)  ttygetinfo(struct tty *tp, int fromsig, char *buf, size_t bufsz)
 {  {
         struct lwp      *l;          struct lwp      *l;
         struct proc     *p, *pick = NULL;          struct proc     *p, *pick = NULL;
Line 2308  ttyinfo(struct tty *tp, int fromsig)
Line 2338  ttyinfo(struct tty *tp, int fromsig)
         int             tmp;          int             tmp;
         fixpt_t         pctcpu = 0;          fixpt_t         pctcpu = 0;
         const char      *msg;          const char      *msg;
           char            lmsg[100];
           long            rss;
   
         if (ttycheckoutq_wlock(tp, 0) == 0)          KASSERT(mutex_owned(proc_lock));
                 return;  
           *buf = '\0';
   
         if (tp->t_session == NULL)          if (tp->t_session == NULL)
                 msg = "not a controlling terminal\n";                  msg = "not a controlling terminal\n";
Line 2320  ttyinfo(struct tty *tp, int fromsig)
Line 2353  ttyinfo(struct tty *tp, int fromsig)
                 msg = "empty foreground process group\n";                  msg = "empty foreground process group\n";
         else {          else {
                 /* Pick interesting process. */                  /* Pick interesting process. */
                 for (; p != NULL; p = LIST_NEXT(p, p_pglist))                  for (; p != NULL; p = LIST_NEXT(p, p_pglist)) {
                           struct proc *oldpick;
   
                           if (pick == NULL) {
                                   pick = p;
                                   continue;
                           }
                           if (pick->p_lock < p->p_lock) {
                                   mutex_enter(pick->p_lock);
                                   mutex_enter(p->p_lock);
                           } else if (pick->p_lock > p->p_lock) {
                                   mutex_enter(p->p_lock);
                                   mutex_enter(pick->p_lock);
                           } else
                                   mutex_enter(p->p_lock);
                           oldpick = pick;
                         if (proc_compare(pick, p))                          if (proc_compare(pick, p))
                                 pick = p;                                  pick = p;
                           mutex_exit(p->p_lock);
                           if (p->p_lock != oldpick->p_lock)
                                   mutex_exit(oldpick->p_lock);
                   }
                 if (fromsig &&                  if (fromsig &&
                     (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &                      (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
                     SA_NOKERNINFO))                      SA_NOKERNINFO))
Line 2332  ttyinfo(struct tty *tp, int fromsig)
Line 2384  ttyinfo(struct tty *tp, int fromsig)
   
         /* Print load average. */          /* Print load average. */
         tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;          tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
         ttyprintf_nolock(tp, "load: %d.%02d ", tmp / 100, tmp % 100);          snprintf(lmsg, sizeof(lmsg), "load: %d.%02d ", tmp / 100, tmp % 100);
           strlcat(buf, lmsg, bufsz);
   
         if (pick == NULL) {          if (pick == NULL) {
                 ttyprintf_nolock(tp, msg);                  strlcat(buf, msg, bufsz);
                 tp->t_rocount = 0; /* so pending input will be retyped if BS */  
                 return;                  return;
         }          }
   
         ttyprintf_nolock(tp, " cmd: %s %d [", pick->p_comm, pick->p_pid);          snprintf(lmsg, sizeof(lmsg), " cmd: %s %d [", pick->p_comm,
         LIST_FOREACH(l, &pick->p_lwps, l_sibling) {              pick->p_pid);
                 char lmsg[16];          strlcat(buf, lmsg, bufsz);
   
           mutex_enter(pick->p_lock);
           LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
                 lwp_lock(l);                  lwp_lock(l);
                 snprintf(lmsg, sizeof(lmsg), "%s%s",                  snprintf(lmsg, sizeof(lmsg), "%s%s",
                     l->l_stat == LSONPROC ? "running" :                      l->l_stat == LSONPROC ? "running" :
Line 2351  ttyinfo(struct tty *tp, int fromsig)
Line 2405  ttyinfo(struct tty *tp, int fromsig)
                     l->l_wchan ? l->l_wmesg : "iowait",                      l->l_wchan ? l->l_wmesg : "iowait",
                     (LIST_NEXT(l, l_sibling) != NULL) ? " " : "] ");                      (LIST_NEXT(l, l_sibling) != NULL) ? " " : "] ");
                 lwp_unlock(l);                  lwp_unlock(l);
                 ttyprintf_nolock(tp, "%s", lmsg);                  strlcat(buf, lmsg, bufsz);
                 pctcpu += l->l_pctcpu;                  pctcpu += l->l_pctcpu;
         }          }
         pctcpu += pick->p_pctcpu;          pctcpu += pick->p_pctcpu;
   
         /* XXXXSMP order tty_lock -> p_smutex is bad */  
         mutex_enter(&pick->p_smutex);  
         calcru(pick, &utime, &stime, NULL, NULL);          calcru(pick, &utime, &stime, NULL, NULL);
         mutex_exit(&pick->p_smutex);          mutex_exit(pick->p_lock);
   
         /* Round up and print user time. */          /* Round up and print user+system time, %CPU and RSS. */
         utime.tv_usec += 5000;          utime.tv_usec += 5000;
         if (utime.tv_usec >= 1000000) {          if (utime.tv_usec >= 1000000) {
                 utime.tv_sec += 1;                  utime.tv_sec += 1;
                 utime.tv_usec -= 1000000;                  utime.tv_usec -= 1000000;
         }          }
         ttyprintf_nolock(tp, "%ld.%02ldu ", (long int)utime.tv_sec,  
             (long int)utime.tv_usec / 10000);  
   
         /* Round up and print system time. */  
         stime.tv_usec += 5000;          stime.tv_usec += 5000;
         if (stime.tv_usec >= 1000000) {          if (stime.tv_usec >= 1000000) {
                 stime.tv_sec += 1;                  stime.tv_sec += 1;
                 stime.tv_usec -= 1000000;                  stime.tv_usec -= 1000000;
         }          }
         ttyprintf_nolock(tp, "%ld.%02lds ", (long int)stime.tv_sec,  
             (long int)stime.tv_usec / 10000);  
   
 #define pgtok(a)        (((u_long) ((a) * PAGE_SIZE) / 1024))  #define pgtok(a)        (((u_long) ((a) * PAGE_SIZE) / 1024))
         /* Print percentage CPU. */  
         tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;          tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
         ttyprintf_nolock(tp, "%d%% ", tmp / 100);  
   
         /* Print resident set size. */  
         if (pick->p_stat == SIDL || P_ZOMBIE(pick))          if (pick->p_stat == SIDL || P_ZOMBIE(pick))
                 tmp = 0;                  rss = 0;
         else {          else
                 struct vmspace *vm = pick->p_vmspace;                  rss = pgtok(vm_resident_count(pick->p_vmspace));
                 tmp = pgtok(vm_resident_count(vm));  
         }          snprintf(lmsg, sizeof(lmsg), "%ld.%02ldu %ld.%02lds %d%% %ldk",
         ttyprintf_nolock(tp, "%dk\n", tmp);              (long)utime.tv_sec, (long)utime.tv_usec / 10000,
               (long)stime.tv_sec, (long)stime.tv_usec / 10000,
               tmp / 100, rss);
           strlcat(buf, lmsg, bufsz);
   }
   
   /*
    * Print report on state of foreground process group.
    * Call with tty_lock held.
    */
   void
   ttyputinfo(struct tty *tp, char *buf)
   {
   
           KASSERT(mutex_owned(&tty_lock));
   
           if (ttycheckoutq_wlock(tp, 0) == 0)
                   return;
           ttyprintf_nolock(tp, "%s\n", buf);
         tp->t_rocount = 0;      /* so pending input will be retyped if BS */          tp->t_rocount = 0;      /* so pending input will be retyped if BS */
 }  }
   
Line 2407  ttyinfo(struct tty *tp, int fromsig)
Line 2465  ttyinfo(struct tty *tp, int fromsig)
  *      3) The sleeper with the shortest sleep time is next.  With ties,   *      3) The sleeper with the shortest sleep time is next.  With ties,
  *         we pick out just "short-term" sleepers (P_SINTR == 0).   *         we pick out just "short-term" sleepers (P_SINTR == 0).
  *      4) Further ties are broken by picking the highest pid.   *      4) Further ties are broken by picking the highest pid.
  *  
  * XXXSMP  
  */   */
 #define ISRUN(p)        ((p)->p_nrlwps > 0)  #define ISRUN(p)        ((p)->p_nrlwps > 0)
 #define TESTAB(a, b)    ((a)<<1 | (b))  #define TESTAB(a, b)    ((a)<<1 | (b))
Line 2421  proc_compare(struct proc *p1, struct pro
Line 2477  proc_compare(struct proc *p1, struct pro
 {  {
         lwp_t *l1, *l2;          lwp_t *l1, *l2;
   
         if (p1 == NULL)          KASSERT(mutex_owned(p1->p_lock));
           KASSERT(mutex_owned(p2->p_lock));
   
           if ((l1 = LIST_FIRST(&p1->p_lwps)) == NULL)
                 return (1);                  return (1);
           if ((l2 = LIST_FIRST(&p2->p_lwps)) == NULL)
                   return (0);
         /*          /*
          * see if at least one of them is runnable           * see if at least one of them is runnable
          */           */
Line 2435  proc_compare(struct proc *p1, struct pro
Line 2496  proc_compare(struct proc *p1, struct pro
                 /*                  /*
                  * tie - favor one with highest recent CPU utilization                   * tie - favor one with highest recent CPU utilization
                  */                   */
                 l1 = LIST_FIRST(&p1->p_lwps);  
                 l2 = LIST_FIRST(&p2->p_lwps);  
                 if (l2->l_pctcpu > l1->l_pctcpu)                  if (l2->l_pctcpu > l1->l_pctcpu)
                         return (1);                          return (1);
                 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */                  return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
Line 2452  proc_compare(struct proc *p1, struct pro
Line 2511  proc_compare(struct proc *p1, struct pro
         case BOTH:          case BOTH:
                 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */                  return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
         }          }
 #if 0 /* XXX NJWLWP */  
         /*          /*
          * pick the one with the smallest sleep time           * pick the one with the smallest sleep time
          */           */
         if (p2->p_slptime > p1->p_slptime)          if (l2->l_slptime > l2->l_slptime)
                 return (0);                  return (0);
         if (p1->p_slptime > p2->p_slptime)          if (l2->l_slptime > l2->l_slptime)
                 return (1);                  return (1);
         /*          /*
          * favor one sleeping in a non-interruptible sleep           * favor one sleeping in a non-interruptible sleep
          */           */
         if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)          if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
                 return (1);                  return (1);
         if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)          if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
                 return (0);                  return (0);
 #endif  
         return (p2->p_pid > p1->p_pid);         /* tie - return highest pid */          return (p2->p_pid > p1->p_pid);         /* tie - return highest pid */
 }  }
   
Line 2570  ttymalloc(void)
Line 2627  ttymalloc(void)
         struct tty      *tp;          struct tty      *tp;
         int i;          int i;
   
         tp = pool_get(&tty_pool, PR_WAITOK);          tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
         memset(tp, 0, sizeof(*tp));  
         callout_init(&tp->t_rstrt_ch, 0);          callout_init(&tp->t_rstrt_ch, 0);
         callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp);          callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp);
         /* XXX: default to 1024 chars for now */          /* XXX: default to 1024 chars for now */
         clalloc(&tp->t_rawq, 1024, 1);          clalloc(&tp->t_rawq, 1024, 1);
           cv_init(&tp->t_rawcv, "ttyraw");
           cv_init(&tp->t_rawcvf, "ttyrawf");
         clalloc(&tp->t_canq, 1024, 1);          clalloc(&tp->t_canq, 1024, 1);
           cv_init(&tp->t_cancv, "ttycan");
           cv_init(&tp->t_cancvf, "ttycanf");
         /* output queue doesn't need quoting */          /* output queue doesn't need quoting */
         clalloc(&tp->t_outq, 1024, 0);          clalloc(&tp->t_outq, 1024, 0);
           cv_init(&tp->t_outcv, "ttycan");
           cv_init(&tp->t_outcvf, "ttycanf");
         /* Set default line discipline. */          /* Set default line discipline. */
         tp->t_linesw = ttyldisc_default();          tp->t_linesw = ttyldisc_default();
         selinit(&tp->t_rsel);          selinit(&tp->t_rsel);
Line 2599  ttyfree(struct tty *tp)
Line 2661  ttyfree(struct tty *tp)
 {  {
         int i;          int i;
   
           mutex_enter(proc_lock);
         mutex_enter(&tty_lock);          mutex_enter(&tty_lock);
         for (i = 0; i < TTYSIG_COUNT; i++)          for (i = 0; i < TTYSIG_COUNT; i++)
                 sigemptyset(&tp->t_sigs[i]);                  sigemptyset(&tp->t_sigs[i]);
         if (tp->t_sigcount != 0)          if (tp->t_sigcount != 0)
                 TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);                  TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
         mutex_exit(&tty_lock);          mutex_exit(&tty_lock);
           mutex_exit(proc_lock);
   
         callout_stop(&tp->t_rstrt_ch);          callout_halt(&tp->t_rstrt_ch, NULL);
           callout_destroy(&tp->t_rstrt_ch);
         ttyldisc_release(tp->t_linesw);          ttyldisc_release(tp->t_linesw);
         clfree(&tp->t_rawq);          clfree(&tp->t_rawq);
         clfree(&tp->t_canq);          clfree(&tp->t_canq);
         clfree(&tp->t_outq);          clfree(&tp->t_outq);
         callout_destroy(&tp->t_rstrt_ch);          cv_destroy(&tp->t_rawcv);
           cv_destroy(&tp->t_rawcvf);
           cv_destroy(&tp->t_cancv);
           cv_destroy(&tp->t_cancvf);
           cv_destroy(&tp->t_outcv);
           cv_destroy(&tp->t_outcvf);
         seldestroy(&tp->t_rsel);          seldestroy(&tp->t_rsel);
         seldestroy(&tp->t_wsel);          seldestroy(&tp->t_wsel);
         pool_put(&tty_pool, tp);          kmem_free(tp, sizeof(*tp));
 }  }
   
 /*  /*
Line 2681  ttysigintr(void *cookie)
Line 2751  ttysigintr(void *cookie)
         enum ttysigtype st;          enum ttysigtype st;
         struct pgrp *pgrp;          struct pgrp *pgrp;
         struct session *sess;          struct session *sess;
         int sig;          int sig, lflag;
           char infobuf[200];
   
         mutex_enter(&proclist_lock);          mutex_enter(proc_lock);
         for (;;) {          mutex_spin_enter(&tty_lock);
                 mutex_spin_enter(&tty_lock);          while ((tp = TAILQ_FIRST(&tty_sigqueue)) != NULL) {
                 if ((tp = TAILQ_FIRST(&tty_sigqueue)) == NULL) {  
                         mutex_spin_exit(&tty_lock);  
                         break;  
                 }  
                 KASSERT(tp->t_sigcount > 0);                  KASSERT(tp->t_sigcount > 0);
                 for (st = 0; st < TTYSIG_COUNT; st++) {                  for (st = 0; st < TTYSIG_COUNT; st++) {
                         if ((sig = firstsig(&tp->t_sigs[st])) != 0)                          if ((sig = firstsig(&tp->t_sigs[st])) != 0)
Line 2701  ttysigintr(void *cookie)
Line 2768  ttysigintr(void *cookie)
                         TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);                          TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
                 pgrp = tp->t_pgrp;                  pgrp = tp->t_pgrp;
                 sess = tp->t_session;                  sess = tp->t_session;
                   lflag = tp->t_lflag;
                   if  (sig == SIGINFO) {
                           if (ISSET(tp->t_state, TS_SIGINFO)) {
                                   /* Via ioctl: ignore tty option. */
                                   tp->t_state &= ~TS_SIGINFO;
                                   lflag |= ISIG;
                           }
                           if (!ISSET(lflag, NOKERNINFO)) {
                                   mutex_spin_exit(&tty_lock);
                                   ttygetinfo(tp, 1, infobuf, sizeof(infobuf));
                                   mutex_spin_enter(&tty_lock);
                                   ttyputinfo(tp, infobuf);
                           }
                           if (!ISSET(lflag, ISIG))
                                   continue;
                   }
                 mutex_spin_exit(&tty_lock);                  mutex_spin_exit(&tty_lock);
                 if (sig == 0)                  KASSERT(sig != 0);
                         panic("ttysigintr");  
                 mutex_enter(&proclist_mutex);  
                 switch (st) {                  switch (st) {
                 case TTYSIG_PG1:                  case TTYSIG_PG1:
                         if (pgrp != NULL)                          if (pgrp != NULL)
Line 2722  ttysigintr(void *cookie)
Line 2803  ttysigintr(void *cookie)
                         /* NOTREACHED */                          /* NOTREACHED */
                         break;                          break;
                 }                  }
                 mutex_exit(&proclist_mutex);                  mutex_spin_enter(&tty_lock);
         }          }
         mutex_exit(&proclist_lock);          mutex_spin_exit(&tty_lock);
           mutex_exit(proc_lock);
 }  }

Legend:
Removed from v.1.214  
changed lines
  Added in v.1.214.2.2

CVSweb <webmaster@jp.NetBSD.org>