home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-28  |  8.0 KB  |  323 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_proc.c    7.16 (Berkeley) 6/28/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "map.h"
  39. #include "kernel.h"
  40. #include "proc.h"
  41. #include "buf.h"
  42. #include "seg.h"
  43. #include "acct.h"
  44. #include "wait.h"
  45. #include "file.h"
  46. #include "../ufs/quota.h"
  47. #include "uio.h"
  48. #include "malloc.h"
  49. #include "mbuf.h"
  50. #include "ioctl.h"
  51. #include "tty.h"
  52.  
  53. /*
  54.  * Is p an inferior of the current process?
  55.  */
  56. inferior(p)
  57.     register struct proc *p;
  58. {
  59.  
  60.     for (; p != curproc; p = p->p_pptr)
  61.         if (p->p_pid == 0)
  62.             return (0);
  63.     return (1);
  64. }
  65.  
  66. /*
  67.  * Locate a process by number
  68.  */
  69. struct proc *
  70. pfind(pid)
  71.     register pid;
  72. {
  73.     register struct proc *p = pidhash[PIDHASH(pid)];
  74.  
  75.     for (; p; p = p->p_hash)
  76.         if (p->p_pid == pid)
  77.             return (p);
  78.     return ((struct proc *)0);
  79. }
  80.  
  81. /*
  82.  * Locate a process group by number
  83.  */
  84. struct pgrp *
  85. pgfind(pgid)
  86.     register pid_t pgid;
  87. {
  88.     register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
  89.  
  90.     for (; pgrp; pgrp = pgrp->pg_hforw)
  91.         if (pgrp->pg_id == pgid)
  92.             return (pgrp);
  93.     return ((struct pgrp *)0);
  94. }
  95.  
  96. /*
  97.  * Move p to a new or existing process group (and session)
  98.  */
  99. enterpgrp(p, pgid, mksess)
  100.     register struct proc *p;
  101.     pid_t pgid;
  102. {
  103.     register struct pgrp *pgrp = pgfind(pgid);
  104.     register struct proc **pp;
  105.     register struct proc *cp;
  106.     int n;
  107.  
  108. #ifdef DIAGNOSTIC
  109.     if (pgrp && mksess)    /* firewalls */
  110.         panic("enterpgrp: setsid into non-empty pgrp");
  111.     if (SESS_LEADER(p))
  112.         panic("enterpgrp: session leader attempted setpgrp");
  113. #endif
  114.     if (pgrp == NULL) {
  115.         /*
  116.          * new process group
  117.          */
  118. #ifdef DIAGNOSTIC
  119.         if (p->p_pid != pgid)
  120.             panic("enterpgrp: new pgrp and pid != pgid");
  121. #endif
  122.         MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
  123.                M_WAITOK);
  124.         if (mksess) {
  125.             register struct session *sess;
  126.  
  127.             /*
  128.              * new session
  129.              */
  130.             MALLOC(sess, struct session *, sizeof(struct session),
  131.                 M_SESSION, M_WAITOK);
  132.             sess->s_leader = p;
  133.             sess->s_count = 1;
  134.             sess->s_ttyvp = NULL;
  135.             sess->s_ttyp = NULL;
  136.             bcopy(p->p_session->s_login, sess->s_login,
  137.                 sizeof(sess->s_login));
  138.             p->p_flag &= ~SCTTY;
  139.             pgrp->pg_session = sess;
  140. #ifdef DIAGNOSTIC
  141.             if (p != curproc)
  142.                 panic("enterpgrp: mksession and p != curproc");
  143. #endif
  144.         } else {
  145.             pgrp->pg_session = p->p_session;
  146.             pgrp->pg_session->s_count++;
  147.         }
  148.         pgrp->pg_id = pgid;
  149.         pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
  150.         pgrphash[n] = pgrp;
  151.         pgrp->pg_jobc = 0;
  152.         pgrp->pg_mem = NULL;
  153.     } else if (pgrp == p->p_pgrp)
  154.         return;
  155.  
  156.     /*
  157.      * Adjust eligibility of affected pgrps to participate in job control.
  158.      * Increment eligibility counts before decrementing, otherwise we
  159.      * could reach 0 spuriously during the first call.
  160.      */
  161.     fixjobc(p, pgrp, 1);
  162.     fixjobc(p, p->p_pgrp, 0);
  163.  
  164.     /*
  165.      * unlink p from old process group
  166.      */
  167.     for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
  168.         if (*pp == p) {
  169.             *pp = p->p_pgrpnxt;
  170.             goto done;
  171.         }
  172.     panic("enterpgrp: can't find p on old pgrp");
  173. done:
  174.     /*
  175.      * delete old if empty
  176.      */
  177.     if (p->p_pgrp->pg_mem == 0)
  178.         pgdelete(p->p_pgrp);
  179.     /*
  180.      * link into new one
  181.      */
  182.     p->p_pgrp = pgrp;
  183.     p->p_pgrpnxt = pgrp->pg_mem;
  184.     pgrp->pg_mem = p;
  185. }
  186.  
  187. /*
  188.  * remove process from process group
  189.  */
  190. leavepgrp(p)
  191.     register struct proc *p;
  192. {
  193.     register struct proc **pp = &p->p_pgrp->pg_mem;
  194.  
  195.     for (; *pp; pp = &(*pp)->p_pgrpnxt)
  196.         if (*pp == p) {
  197.             *pp = p->p_pgrpnxt;
  198.             goto done;
  199.         }
  200.     panic("leavepgrp: can't find p in pgrp");
  201. done:
  202.     if (!p->p_pgrp->pg_mem)
  203.         pgdelete(p->p_pgrp);
  204.     p->p_pgrp = 0;
  205. }
  206.  
  207. /*
  208.  * delete a process group
  209.  */
  210. pgdelete(pgrp)
  211.     register struct pgrp *pgrp;
  212. {
  213.     register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
  214.  
  215.     if (pgrp->pg_session->s_ttyp != NULL && 
  216.         pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
  217.         pgrp->pg_session->s_ttyp->t_pgrp = NULL;
  218.     for (; *pgp; pgp = &(*pgp)->pg_hforw)
  219.         if (*pgp == pgrp) {
  220.             *pgp = pgrp->pg_hforw;
  221.             goto done;
  222.         }
  223.     panic("pgdelete: can't find pgrp on hash chain");
  224. done:
  225.     if (--pgrp->pg_session->s_count == 0)
  226.         FREE(pgrp->pg_session, M_SESSION);
  227.     FREE(pgrp, M_PGRP);
  228. }
  229.  
  230. static orphanpg();
  231.  
  232. /*
  233.  * Adjust pgrp jobc counters when specified process changes process group.
  234.  * We count the number of processes in each process group that "qualify"
  235.  * the group for terminal job control (those with a parent in a different
  236.  * process group of the same session).  If that count reaches zero, the
  237.  * process group becomes orphaned.  Check both the specified process'
  238.  * process group and that of its children.
  239.  * entering == 0 => p is leaving specified group.
  240.  * entering == 1 => p is entering specified group.
  241.  */
  242. fixjobc(p, pgrp, entering)
  243.     register struct proc *p;
  244.     register struct pgrp *pgrp;
  245.     int entering;
  246. {
  247.     register struct pgrp *hispgrp;
  248.     register struct session *mysession = pgrp->pg_session;
  249.  
  250.     /*
  251.      * Check p's parent to see whether p qualifies its own process
  252.      * group; if so, adjust count for p's process group.
  253.      */
  254.     if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
  255.         hispgrp->pg_session == mysession)
  256.         if (entering)
  257.             pgrp->pg_jobc++;
  258.         else if (--pgrp->pg_jobc == 0)
  259.             orphanpg(pgrp);
  260.  
  261.     /*
  262.      * Check this process' children to see whether they qualify
  263.      * their process groups; if so, adjust counts for children's
  264.      * process groups.
  265.      */
  266.     for (p = p->p_cptr; p; p = p->p_osptr)
  267.         if ((hispgrp = p->p_pgrp) != pgrp &&
  268.             hispgrp->pg_session == mysession &&
  269.             p->p_stat != SZOMB)
  270.             if (entering)
  271.                 hispgrp->pg_jobc++;
  272.             else if (--hispgrp->pg_jobc == 0)
  273.                 orphanpg(hispgrp);
  274. }
  275.  
  276. /* 
  277.  * A process group has become orphaned;
  278.  * if there are any stopped processes in the group,
  279.  * hang-up all process in that group.
  280.  */
  281. static
  282. orphanpg(pg)
  283.     struct pgrp *pg;
  284. {
  285.     register struct proc *p;
  286.  
  287.     for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
  288.         if (p->p_stat == SSTOP) {
  289.             for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
  290.                 psignal(p, SIGHUP);
  291.                 psignal(p, SIGCONT);
  292.             }
  293.             return;
  294.         }
  295.     }
  296. }
  297.  
  298. #ifdef debug
  299. /* DEBUG */
  300. pgrpdump()
  301. {
  302.     register struct pgrp *pgrp;
  303.     register struct proc *p;
  304.     register i;
  305.  
  306.     for (i=0; i<PIDHSZ; i++) {
  307.         if (pgrphash[i]) {
  308.           printf("\tindx %d\n", i);
  309.           for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
  310.             printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
  311.             pgrp, pgrp->pg_id, pgrp->pg_session,
  312.             pgrp->pg_session->s_count, pgrp->pg_mem);
  313.             for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
  314.             printf("\t\tpid %d addr %x pgrp %x\n", 
  315.                 p->p_pid, p, p->p_pgrp);
  316.             }
  317.           }
  318.  
  319.         }
  320.     }
  321. }
  322. #endif /* debug */
  323.