home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_fork.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-20  |  8.1 KB  |  297 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_fork.c    7.29 (Berkeley) 5/15/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "map.h"
  39. #include "filedesc.h"
  40. #include "kernel.h"
  41. #include "malloc.h"
  42. #include "proc.h"
  43. #include "resourcevar.h"
  44. #include "vnode.h"
  45. #include "seg.h"
  46. #include "file.h"
  47. #include "acct.h"
  48. #include "ktrace.h"
  49.  
  50. /* ARGSUSED */
  51. fork(p, uap, retval)
  52.     struct proc *p;
  53.     void *uap;
  54.     int retval[];
  55. {
  56.  
  57.     return (fork1(p, 0, retval));
  58. }
  59.  
  60. /* ARGSUSED */
  61. vfork(p, uap, retval)
  62.     struct proc *p;
  63.     void *uap;
  64.     int retval[];
  65. {
  66.  
  67.     return (fork1(p, 1, retval));
  68. }
  69.  
  70. int    nprocs = 1;        /* process 0 */
  71.  
  72. fork1(p1, isvfork, retval)
  73.     register struct proc *p1;
  74.     int isvfork, retval[];
  75. {
  76.     register struct proc *p2;
  77.     register int count, uid;
  78.     static int nextpid, pidchecked = 0;
  79.  
  80.     count = 0;
  81.     if ((uid = p1->p_ucred->cr_uid) != 0) {
  82.         for (p2 = allproc; p2; p2 = p2->p_nxt)
  83.             if (p2->p_ucred->cr_uid == uid)
  84.                 count++;
  85.         for (p2 = zombproc; p2; p2 = p2->p_nxt)
  86.             if (p2->p_ucred->cr_uid == uid)
  87.                 count++;
  88.     }
  89.     /*
  90.      * Although process entries are dynamically entries,
  91.      * we still keep a global limit on the maximum number
  92.      * we will create.  Don't allow a nonprivileged user
  93.      * to exceed its current limit or to bring us within one
  94.      * of the global limit; don't let root exceed the limit.
  95.      * nprocs is the current number of processes,
  96.      * maxproc is the limit.
  97.      */
  98.     if (nprocs >= maxproc || uid == 0 && nprocs >= maxproc + 1) {
  99.         tablefull("proc");
  100.         return (EAGAIN);
  101.     }
  102.     if (count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur)
  103.         return (EAGAIN);
  104.  
  105.     /*
  106.      * Find an unused process ID.
  107.      * We remember a range of unused IDs ready to use
  108.      * (from nextpid+1 through pidchecked-1).
  109.      */
  110.     nextpid++;
  111. retry:
  112.     /*
  113.      * If the process ID prototype has wrapped around,
  114.      * restart somewhat above 0, as the low-numbered procs
  115.      * tend to include daemons that don't exit.
  116.      */
  117.     if (nextpid >= PID_MAX) {
  118.         nextpid = 100;
  119.         pidchecked = 0;
  120.     }
  121.     if (nextpid >= pidchecked) {
  122.         int doingzomb = 0;
  123.  
  124.         pidchecked = PID_MAX;
  125.         /*
  126.          * Scan the active and zombie procs to check whether this pid
  127.          * is in use.  Remember the lowest pid that's greater
  128.          * than nextpid, so we can avoid checking for a while.
  129.          */
  130.         p2 = allproc;
  131. again:
  132.         for (; p2 != NULL; p2 = p2->p_nxt) {
  133.             if (p2->p_pid == nextpid ||
  134.                 p2->p_pgrp->pg_id == nextpid) {
  135.                 nextpid++;
  136.                 if (nextpid >= pidchecked)
  137.                     goto retry;
  138.             }
  139.             if (p2->p_pid > nextpid && pidchecked > p2->p_pid)
  140.                 pidchecked = p2->p_pid;
  141.             if (p2->p_pgrp->pg_id > nextpid && 
  142.                 pidchecked > p2->p_pgrp->pg_id)
  143.                 pidchecked = p2->p_pgrp->pg_id;
  144.         }
  145.         if (!doingzomb) {
  146.             doingzomb = 1;
  147.             p2 = zombproc;
  148.             goto again;
  149.         }
  150.     }
  151.  
  152.  
  153.     /*
  154.      * Allocate new proc.
  155.      * Link onto allproc (this should probably be delayed).
  156.      */
  157.     MALLOC(p2, struct proc *, sizeof(struct proc), M_PROC, M_WAITOK);
  158.     nprocs++;
  159.     p2->p_nxt = allproc;
  160.     p2->p_nxt->p_prev = &p2->p_nxt;        /* allproc is never NULL */
  161.     p2->p_prev = &allproc;
  162.     allproc = p2;
  163.     p2->p_link = NULL;            /* shouldn't be necessary */
  164.     p2->p_rlink = NULL;            /* shouldn't be necessary */
  165.  
  166.     /*
  167.      * Make a proc table entry for the new process.
  168.      * Start by zeroing the section of proc that is zero-initialized,
  169.      * then copy the section that is copied directly from the parent.
  170.      */
  171.     bzero(&p2->p_startzero,
  172.         (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
  173.     bcopy(&p1->p_startcopy, &p2->p_startcopy,
  174.         (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
  175.     p2->p_spare[0] = 0;    /* XXX - should be in zero range */
  176.     p2->p_spare[1] = 0;    /* XXX - should be in zero range */
  177.     p2->p_spare[2] = 0;    /* XXX - should be in zero range */
  178.     p2->p_spare[3] = 0;    /* XXX - should be in zero range */
  179.  
  180.     /*
  181.      * Duplicate sub-structures as needed.
  182.      * Increase reference counts on shared objects.
  183.      * The p_stats and p_sigacts substructs are set in vm_fork.
  184.      */
  185.     MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
  186.         M_SUBPROC, M_WAITOK);
  187.     bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
  188.     p2->p_cred->p_refcnt = 1;
  189.     crhold(p1->p_ucred);
  190.  
  191.     p2->p_fd = fdcopy(p1);
  192.     /*
  193.      * If p_limit is still copy-on-write, bump refcnt,
  194.      * otherwise get a copy that won't be modified.
  195.      * (If PL_SHAREMOD is clear, the structure is shared
  196.      * copy-on-write.)
  197.      */
  198.     if (p1->p_limit->p_lflags & PL_SHAREMOD)
  199.         p2->p_limit = limcopy(p1->p_limit);
  200.     else {
  201.         p2->p_limit = p1->p_limit;
  202.         p2->p_limit->p_refcnt++;
  203.     }
  204.  
  205.     p2->p_flag = SLOAD | (p1->p_flag & SHPUX);
  206.     if (p1->p_session->s_ttyvp != NULL && p1->p_flag & SCTTY)
  207.         p2->p_flag |= SCTTY;
  208.     if (isvfork)
  209.         p2->p_flag |= SPPWAIT;
  210.     p2->p_stat = SIDL;
  211.     p2->p_pid = nextpid;
  212.     {
  213.     struct proc **hash = &pidhash[PIDHASH(p2->p_pid)];
  214.  
  215.     p2->p_hash = *hash;
  216.     *hash = p2;
  217.     }
  218.     p2->p_pgrpnxt = p1->p_pgrpnxt;
  219.     p1->p_pgrpnxt = p2;
  220.     p2->p_pptr = p1;
  221.     p2->p_osptr = p1->p_cptr;
  222.     if (p1->p_cptr)
  223.         p1->p_cptr->p_ysptr = p2;
  224.     p1->p_cptr = p2;
  225. #ifdef KTRACE
  226.     /*
  227.      * Copy traceflag and tracefile if enabled.
  228.      * If not inherited, these were zeroed above.
  229.      */
  230.     if (p1->p_traceflag&KTRFAC_INHERIT) {
  231.         p2->p_traceflag = p1->p_traceflag;
  232.         if ((p2->p_tracep = p1->p_tracep) != NULL)
  233.             VREF(p2->p_tracep);
  234.     }
  235. #endif
  236.  
  237. #if defined(tahoe)
  238.     p2->p_vmspace->p_ckey = p1->p_vmspace->p_ckey; /* XXX move this */
  239. #endif
  240.  
  241.     /*
  242.      * This begins the section where we must prevent the parent
  243.      * from being swapped.
  244.      */
  245.     p1->p_flag |= SKEEP;
  246.     /*
  247.      * Set return values for child before vm_fork,
  248.      * so they can be copied to child stack.
  249.      * We return parent pid, and mark as child in retval[1].
  250.      * NOTE: the kernel stack may be at a different location in the child
  251.      * process, and thus addresses of automatic variables (including retval)
  252.      * may be invalid after vm_fork returns in the child process.
  253.      */
  254.     retval[0] = p1->p_pid;
  255.     retval[1] = 1;
  256.     if (vm_fork(p1, p2, isvfork)) {
  257.         /*
  258.          * Child process.  Set start time and get to work.
  259.          */
  260.         (void) splclock();
  261.         p2->p_stats->p_start = time;
  262.         (void) spl0();
  263.         p2->p_acflag = AFORK;
  264.         return (0);
  265.     }
  266.  
  267.     /*
  268.      * Make child runnable and add to run queue.
  269.      */
  270.     (void) splhigh();
  271.     p2->p_stat = SRUN;
  272.     setrq(p2);
  273.     (void) spl0();
  274.  
  275.     /*
  276.      * Now can be swapped.
  277.      */
  278.     p1->p_flag &= ~SKEEP;
  279.  
  280.     /*
  281.      * Preserve synchronization semantics of vfork.
  282.      * If waiting for child to exec or exit, set SPPWAIT
  283.      * on child, and sleep on our proc (in case of exit).
  284.      */
  285.     if (isvfork)
  286.         while (p2->p_flag & SPPWAIT)
  287.             tsleep((caddr_t)p1, PWAIT, "ppwait", 0);
  288.  
  289.     /*
  290.      * Return child pid to parent process,
  291.      * marking us as parent via retval[1].
  292.      */
  293.     retval[0] = p2->p_pid;
  294.     retval[1] = 0;
  295.     return (0);
  296. }
  297.