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

Annotation of src/sys/kern/kern_fork.c, Revision 1.27

1.27    ! mycroft     1: /*     $NetBSD: kern_fork.c,v 1.26 1995/12/09 04:23:07 mycroft Exp $   */
1.19      cgd         2:
1.16      cgd         3: /*
1.17      cgd         4:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.16      cgd         6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
1.19      cgd        40:  *     @(#)kern_fork.c 8.6 (Berkeley) 4/8/94
1.16      cgd        41:  */
                     42:
                     43: #include <sys/param.h>
                     44: #include <sys/systm.h>
1.17      cgd        45: #include <sys/map.h>
1.16      cgd        46: #include <sys/filedesc.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/malloc.h>
                     49: #include <sys/proc.h>
                     50: #include <sys/resourcevar.h>
                     51: #include <sys/vnode.h>
                     52: #include <sys/file.h>
                     53: #include <sys/acct.h>
                     54: #include <sys/ktrace.h>
                     55:
1.26      mycroft    56: int    nprocs = 1;             /* process 0 */
                     57:
                     58: int
1.25      mycroft    59: sys_fork(p, v, retval)
1.16      cgd        60:        struct proc *p;
1.25      mycroft    61:        void *v;
1.22      cgd        62:        register_t *retval;
1.16      cgd        63: {
                     64:
                     65:        return (fork1(p, 0, retval));
                     66: }
                     67:
1.26      mycroft    68: int
1.25      mycroft    69: sys_vfork(p, v, retval)
1.16      cgd        70:        struct proc *p;
1.25      mycroft    71:        void *v;
1.22      cgd        72:        register_t *retval;
1.16      cgd        73: {
                     74:
                     75:        return (fork1(p, 1, retval));
                     76: }
                     77:
1.26      mycroft    78: int
1.16      cgd        79: fork1(p1, isvfork, retval)
                     80:        register struct proc *p1;
1.22      cgd        81:        int isvfork;
                     82:        register_t *retval;
1.16      cgd        83: {
                     84:        register struct proc *p2;
1.17      cgd        85:        register uid_t uid;
                     86:        struct proc *newproc;
                     87:        struct proc **hash;
                     88:        int count;
1.16      cgd        89:        static int nextpid, pidchecked = 0;
                     90:
                     91:        /*
1.17      cgd        92:         * Although process entries are dynamically created, we still keep
1.16      cgd        93:         * a global limit on the maximum number we will create.  Don't allow
                     94:         * a nonprivileged user to use the last process; don't let root
1.17      cgd        95:         * exceed the limit. The variable nprocs is the current number of
1.16      cgd        96:         * processes, maxproc is the limit.
                     97:         */
1.17      cgd        98:        uid = p1->p_cred->p_ruid;
1.16      cgd        99:        if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) {
                    100:                tablefull("proc");
                    101:                return (EAGAIN);
                    102:        }
1.21      mycroft   103:
1.17      cgd       104:        /*
                    105:         * Increment the count of procs running with this uid. Don't allow
                    106:         * a nonprivileged user to exceed their current limit.
                    107:         */
                    108:        count = chgproccnt(uid, 1);
                    109:        if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
                    110:                (void)chgproccnt(uid, -1);
1.16      cgd       111:                return (EAGAIN);
1.17      cgd       112:        }
                    113:
                    114:        /* Allocate new proc. */
                    115:        MALLOC(newproc, struct proc *, sizeof(struct proc), M_PROC, M_WAITOK);
1.16      cgd       116:
                    117:        /*
1.17      cgd       118:         * Find an unused process ID.  We remember a range of unused IDs
                    119:         * ready to use (from nextpid+1 through pidchecked-1).
1.16      cgd       120:         */
                    121:        nextpid++;
                    122: retry:
                    123:        /*
                    124:         * If the process ID prototype has wrapped around,
                    125:         * restart somewhat above 0, as the low-numbered procs
                    126:         * tend to include daemons that don't exit.
                    127:         */
                    128:        if (nextpid >= PID_MAX) {
                    129:                nextpid = 100;
                    130:                pidchecked = 0;
                    131:        }
                    132:        if (nextpid >= pidchecked) {
                    133:                int doingzomb = 0;
                    134:
                    135:                pidchecked = PID_MAX;
                    136:                /*
                    137:                 * Scan the active and zombie procs to check whether this pid
                    138:                 * is in use.  Remember the lowest pid that's greater
                    139:                 * than nextpid, so we can avoid checking for a while.
                    140:                 */
1.20      mycroft   141:                p2 = allproc.lh_first;
1.16      cgd       142: again:
1.20      mycroft   143:                for (; p2 != 0; p2 = p2->p_list.le_next) {
1.16      cgd       144:                        while (p2->p_pid == nextpid ||
                    145:                            p2->p_pgrp->pg_id == nextpid) {
                    146:                                nextpid++;
                    147:                                if (nextpid >= pidchecked)
                    148:                                        goto retry;
                    149:                        }
                    150:                        if (p2->p_pid > nextpid && pidchecked > p2->p_pid)
                    151:                                pidchecked = p2->p_pid;
                    152:                        if (p2->p_pgrp->pg_id > nextpid &&
                    153:                            pidchecked > p2->p_pgrp->pg_id)
                    154:                                pidchecked = p2->p_pgrp->pg_id;
                    155:                }
                    156:                if (!doingzomb) {
                    157:                        doingzomb = 1;
1.20      mycroft   158:                        p2 = zombproc.lh_first;
1.16      cgd       159:                        goto again;
                    160:                }
                    161:        }
                    162:
                    163:        nprocs++;
1.17      cgd       164:        p2 = newproc;
1.20      mycroft   165:        p2->p_stat = SIDL;                      /* protect against others */
                    166:        p2->p_pid = nextpid;
                    167:        LIST_INSERT_HEAD(&allproc, p2, p_list);
1.17      cgd       168:        p2->p_forw = p2->p_back = NULL;         /* shouldn't be necessary */
1.20      mycroft   169:        LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
1.16      cgd       170:
                    171:        /*
                    172:         * Make a proc table entry for the new process.
                    173:         * Start by zeroing the section of proc that is zero-initialized,
                    174:         * then copy the section that is copied directly from the parent.
                    175:         */
                    176:        bzero(&p2->p_startzero,
                    177:            (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
                    178:        bcopy(&p1->p_startcopy, &p2->p_startcopy,
                    179:            (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
                    180:
                    181:        /*
                    182:         * Duplicate sub-structures as needed.
                    183:         * Increase reference counts on shared objects.
                    184:         * The p_stats and p_sigacts substructs are set in vm_fork.
                    185:         */
1.17      cgd       186:        p2->p_flag = P_INMEM;
1.21      mycroft   187:        p2->p_emul = p1->p_emul;
1.17      cgd       188:        if (p1->p_flag & P_PROFIL)
                    189:                startprofclock(p2);
1.16      cgd       190:        MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
                    191:            M_SUBPROC, M_WAITOK);
                    192:        bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
                    193:        p2->p_cred->p_refcnt = 1;
                    194:        crhold(p1->p_ucred);
                    195:
1.17      cgd       196:        /* bump references to the text vnode (for procfs) */
                    197:        p2->p_textvp = p1->p_textvp;
                    198:        if (p2->p_textvp)
1.16      cgd       199:                VREF(p2->p_textvp);
                    200:
                    201:        p2->p_fd = fdcopy(p1);
                    202:        /*
                    203:         * If p_limit is still copy-on-write, bump refcnt,
                    204:         * otherwise get a copy that won't be modified.
                    205:         * (If PL_SHAREMOD is clear, the structure is shared
                    206:         * copy-on-write.)
                    207:         */
                    208:        if (p1->p_limit->p_lflags & PL_SHAREMOD)
                    209:                p2->p_limit = limcopy(p1->p_limit);
                    210:        else {
                    211:                p2->p_limit = p1->p_limit;
                    212:                p2->p_limit->p_refcnt++;
                    213:        }
                    214:
                    215:        if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
                    216:                p2->p_flag |= P_CONTROLT;
                    217:        if (isvfork)
                    218:                p2->p_flag |= P_PPWAIT;
1.20      mycroft   219:        LIST_INSERT_AFTER(p1, p2, p_pglist);
1.16      cgd       220:        p2->p_pptr = p1;
1.20      mycroft   221:        LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
                    222:        LIST_INIT(&p2->p_children);
                    223:
1.16      cgd       224: #ifdef KTRACE
                    225:        /*
                    226:         * Copy traceflag and tracefile if enabled.
                    227:         * If not inherited, these were zeroed above.
                    228:         */
                    229:        if (p1->p_traceflag&KTRFAC_INHERIT) {
                    230:                p2->p_traceflag = p1->p_traceflag;
                    231:                if ((p2->p_tracep = p1->p_tracep) != NULL)
                    232:                        VREF(p2->p_tracep);
                    233:        }
                    234: #endif
                    235:
                    236:        /*
                    237:         * This begins the section where we must prevent the parent
                    238:         * from being swapped.
                    239:         */
1.18      mycroft   240:        p1->p_holdcnt++;
1.26      mycroft   241:
                    242: #ifdef __FORK_BRAINDAMAGE
1.16      cgd       243:        /*
                    244:         * Set return values for child before vm_fork,
                    245:         * so they can be copied to child stack.
1.26      mycroft   246:         * We return 0, rather than the traditional behaviour of modifying the
                    247:         * return value in the system call stub.
1.16      cgd       248:         * NOTE: the kernel stack may be at a different location in the child
                    249:         * process, and thus addresses of automatic variables (including retval)
                    250:         * may be invalid after vm_fork returns in the child process.
                    251:         */
1.26      mycroft   252:        retval[0] = 0;
1.27    ! mycroft   253:        retval[1] = 1;
1.26      mycroft   254:        if (vm_fork(p1, p2))
1.16      cgd       255:                return (0);
1.26      mycroft   256: #else
                    257:        /*
                    258:         * Finish creating the child process.  It will return through a
                    259:         * different path later.
                    260:         */
                    261:        vm_fork(p1, p2);
                    262: #endif
1.16      cgd       263:
                    264:        /*
1.24      mycroft   265:         * Make child runnable, set start time, and add to run queue.
1.16      cgd       266:         */
1.26      mycroft   267:        (void) splstatclock();
1.23      mycroft   268:        p2->p_stats->p_start = time;
                    269:        p2->p_acflag = AFORK;
1.16      cgd       270:        p2->p_stat = SRUN;
                    271:        setrunqueue(p2);
                    272:        (void) spl0();
                    273:
                    274:        /*
                    275:         * Now can be swapped.
                    276:         */
1.18      mycroft   277:        p1->p_holdcnt--;
1.16      cgd       278:
                    279:        /*
1.17      cgd       280:         * Preserve synchronization semantics of vfork.  If waiting for
                    281:         * child to exec or exit, set P_PPWAIT on child, and sleep on our
                    282:         * proc (in case of exit).
1.16      cgd       283:         */
                    284:        if (isvfork)
                    285:                while (p2->p_flag & P_PPWAIT)
1.17      cgd       286:                        tsleep(p1, PWAIT, "ppwait", 0);
1.16      cgd       287:
                    288:        /*
                    289:         * Return child pid to parent process,
                    290:         * marking us as parent via retval[1].
                    291:         */
                    292:        retval[0] = p2->p_pid;
                    293:        retval[1] = 0;
                    294:        return (0);
                    295: }

CVSweb <webmaster@jp.NetBSD.org>