Annotation of XNU/bsd/kern/kern_fork.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
                     23: /*
                     24:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
                     25:  *     The Regents of the University of California.  All rights reserved.
                     26:  * (c) UNIX System Laboratories, Inc.
                     27:  * All or some portions of this file are derived from material licensed
                     28:  * to the University of California by American Telephone and Telegraph
                     29:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     30:  * the permission of UNIX System Laboratories, Inc.
                     31:  *
                     32:  * Redistribution and use in source and binary forms, with or without
                     33:  * modification, are permitted provided that the following conditions
                     34:  * are met:
                     35:  * 1. Redistributions of source code must retain the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer.
                     37:  * 2. Redistributions in binary form must reproduce the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer in the
                     39:  *    documentation and/or other materials provided with the distribution.
                     40:  * 3. All advertising materials mentioning features or use of this software
                     41:  *    must display the following acknowledgement:
                     42:  *     This product includes software developed by the University of
                     43:  *     California, Berkeley and its contributors.
                     44:  * 4. Neither the name of the University nor the names of its contributors
                     45:  *    may be used to endorse or promote products derived from this software
                     46:  *    without specific prior written permission.
                     47:  *
                     48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     58:  * SUCH DAMAGE.
                     59:  *
                     60:  *     @(#)kern_fork.c 8.8 (Berkeley) 2/14/95
                     61:  */
                     62: 
                     63: #include <sys/param.h>
                     64: #include <sys/systm.h>
                     65: #include <sys/filedesc.h>
                     66: #include <sys/kernel.h>
                     67: #include <sys/malloc.h>
                     68: #include <sys/proc.h>
                     69: #include <sys/user.h>
                     70: #include <sys/resourcevar.h>
                     71: #include <sys/vnode.h>
                     72: #include <sys/file.h>
                     73: #include <sys/acct.h>
                     74: #include <sys/ktrace.h>
                     75: 
                     76: #import <mach/mach_types.h>
                     77: #import <kern/mach_param.h>
                     78: 
                     79: #import <machine/spl.h>
                     80: 
                     81: thread_t       cloneproc(), procdup();
                     82: 
                     83: #define        DOFORK  0x1     /* fork() system call */
                     84: #define        DOVFORK 0x2     /* vfork() system call */
                     85: static int fork1(struct proc *, long, register_t *);
                     86: 
                     87: /*
                     88:  * fork system call.
                     89:  */
                     90: int
                     91: fork(p, uap, retval)
                     92:        struct proc *p;
                     93:        void *uap;
                     94:        register_t *retval;
                     95: {
                     96:        return (fork1(p, (long)DOFORK, retval));
                     97: }
                     98: 
                     99: /*
                    100:  * vfork system call
                    101:  */
                    102: int
                    103: vfork(p, uap, retval)
                    104:        struct proc *p;
                    105:        void *uap;
                    106:        register_t *retval;
                    107: {
                    108:        return (fork1(p, (long)DOVFORK, retval));
                    109: }
                    110: 
                    111: static int
                    112: fork1(p1, flags, retval)
                    113:        struct proc *p1;
                    114:        long flags;
                    115:        register_t *retval;
                    116: {
                    117:        register struct proc *p2;
                    118:        register uid_t uid;
                    119:        thread_t newth, self = current_thread();
                    120:        int s, count;
                    121: 
                    122:        /*
                    123:         * Although process entries are dynamically created, we still keep
                    124:         * a global limit on the maximum number we will create.  Don't allow
                    125:         * a nonprivileged user to use the last process; don't let root
                    126:         * exceed the limit. The variable nprocs is the current number of
                    127:         * processes, maxproc is the limit.
                    128:         */
                    129:        uid = p1->p_cred->p_ruid;
                    130:        if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) {
                    131:                tablefull("proc");
                    132:                retval[1] = 0;
                    133:                return (EAGAIN);
                    134:        }
                    135: 
                    136:        /*
                    137:         * Increment the count of procs running with this uid. Don't allow
                    138:         * a nonprivileged user to exceed their current limit.
                    139:         */
                    140:        count = chgproccnt(uid, 1);
                    141:        if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
                    142:                (void)chgproccnt(uid, -1);
                    143:                return (EAGAIN);
                    144:        }
                    145: 
                    146:        newth = cloneproc(p1);
                    147:        thread_dup(current_act(), newth);
                    148:        /* p2 = newth->task->proc; */
                    149:        p2 = (struct proc *)(get_bsdtask_info(get_threadtask(newth)));
                    150: 
                    151:        thread_set_child(newth, p2->p_pid);
                    152: 
                    153:        s = splhigh();
                    154:        p2->p_stats->p_start = time;
                    155:        splx(s);
                    156:        p2->p_acflag = AFORK;
                    157: 
                    158:        /*
                    159:         * Preserve synchronization semantics of vfork.  If waiting for
                    160:         * child to exec or exit, set P_PPWAIT on child, and sleep on our
                    161:         * proc (in case of exit).
                    162:         */
                    163:        if (flags == DOVFORK)
                    164:                p2->p_flag |= P_PPWAIT;
                    165: 
                    166:        (void) thread_resume(newth);
                    167: 
                    168:        while (p2->p_flag & P_PPWAIT)
                    169:                tsleep(p1, PWAIT, "ppwait", 0);
                    170: 
                    171:        retval[0] = p2->p_pid;
                    172:        retval[1] = 0;                  /* mark parent */
                    173: 
                    174:        return (0);
                    175: }
                    176: 
                    177: /*
                    178:  * cloneproc()
                    179:  *
                    180:  * Create a new process from a specified process.
                    181:  */
                    182: thread_t
                    183: cloneproc(p1)
                    184:        register struct proc *p1;
                    185: {
                    186:        register struct proc *p2, *newproc;
                    187:        static int nextpid = 0, pidchecked = 0;
                    188:        thread_t th;
                    189: 
                    190:        /* Allocate new proc. */
                    191:        MALLOC_ZONE(newproc, struct proc *,
                    192:                        sizeof *newproc, M_PROC, M_WAITOK);
                    193:        MALLOC_ZONE(newproc->p_cred, struct pcred *,
                    194:                        sizeof *newproc->p_cred, M_SUBPROC, M_WAITOK);
                    195:        MALLOC_ZONE(newproc->p_stats, struct pstats *,
                    196:                        sizeof *newproc->p_stats, M_SUBPROC, M_WAITOK);
                    197:        MALLOC_ZONE(newproc->p_sigacts, struct sigacts *,
                    198:                        sizeof *newproc->p_sigacts, M_SUBPROC, M_WAITOK);
                    199: 
                    200:        /*
                    201:         * Find an unused process ID.  We remember a range of unused IDs
                    202:         * ready to use (from nextpid+1 through pidchecked-1).
                    203:         */
                    204:        nextpid++;
                    205: retry:
                    206:        /*
                    207:         * If the process ID prototype has wrapped around,
                    208:         * restart somewhat above 0, as the low-numbered procs
                    209:         * tend to include daemons that don't exit.
                    210:         */
                    211:        if (nextpid >= PID_MAX) {
                    212:                nextpid = 100;
                    213:                pidchecked = 0;
                    214:        }
                    215:        if (nextpid >= pidchecked) {
                    216:                int doingzomb = 0;
                    217: 
                    218:                pidchecked = PID_MAX;
                    219:                /*
                    220:                 * Scan the active and zombie procs to check whether this pid
                    221:                 * is in use.  Remember the lowest pid that's greater
                    222:                 * than nextpid, so we can avoid checking for a while.
                    223:                 */
                    224:                p2 = allproc.lh_first;
                    225: again:
                    226:                for (; p2 != 0; p2 = p2->p_list.le_next) {
                    227:                        while (p2->p_pid == nextpid ||
                    228:                            p2->p_pgrp->pg_id == nextpid) {
                    229:                                nextpid++;
                    230:                                if (nextpid >= pidchecked)
                    231:                                        goto retry;
                    232:                        }
                    233:                        if (p2->p_pid > nextpid && pidchecked > p2->p_pid)
                    234:                                pidchecked = p2->p_pid;
                    235:                        if (p2->p_pgrp->pg_id > nextpid && 
                    236:                            pidchecked > p2->p_pgrp->pg_id)
                    237:                                pidchecked = p2->p_pgrp->pg_id;
                    238:                }
                    239:                if (!doingzomb) {
                    240:                        doingzomb = 1;
                    241:                        p2 = zombproc.lh_first;
                    242:                        goto again;
                    243:                }
                    244:        }
                    245: 
                    246:        nprocs++;
                    247:        p2 = newproc;
                    248:        p2->p_stat = SIDL;
                    249:        p2->p_pid = nextpid;
                    250: 
                    251:        /*
                    252:         * Make a proc table entry for the new process.
                    253:         * Start by zeroing the section of proc that is zero-initialized,
                    254:         * then copy the section that is copied directly from the parent.
                    255:         */
                    256:        bzero(&p2->p_startzero,
                    257:            (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
                    258:        bcopy(&p1->p_startcopy, &p2->p_startcopy,
                    259:            (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
                    260:        p2->vm_shm = (void *)NULL; /* Make sure it is zero */
                    261: 
                    262:        /*
                    263:         * Duplicate sub-structures as needed.
                    264:         * Increase reference counts on shared objects.
                    265:         * The p_stats and p_sigacts substructs are set in vm_fork.
                    266:         */
                    267:        p2->p_flag = P_INMEM;
                    268:        if (p1->p_flag & P_PROFIL)
                    269:                startprofclock(p2);
                    270:        bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
                    271:        p2->p_cred->p_refcnt = 1;
                    272:        crhold(p1->p_ucred);
                    273:        lockinit(&p2->p_cred->pc_lock, PLOCK, "proc cred", 0, 0);
                    274: 
                    275:        /* bump references to the text vnode (for procfs) */
                    276:        p2->p_textvp = p1->p_textvp;
                    277:        if (p2->p_textvp)
                    278:                VREF(p2->p_textvp);
                    279: 
                    280:        p2->p_fd = fdcopy(p1);
                    281:        if (p1->vm_shm) {
                    282:                shmfork(p1,p2);
                    283:        }
                    284:        /*
                    285:         * If p_limit is still copy-on-write, bump refcnt,
                    286:         * otherwise get a copy that won't be modified.
                    287:         * (If PL_SHAREMOD is clear, the structure is shared
                    288:         * copy-on-write.)
                    289:         */
                    290:        if (p1->p_limit->p_lflags & PL_SHAREMOD)
                    291:                p2->p_limit = limcopy(p1->p_limit);
                    292:        else {
                    293:                p2->p_limit = p1->p_limit;
                    294:                p2->p_limit->p_refcnt++;
                    295:        }
                    296: 
                    297:        bzero(&p2->p_stats->pstat_startzero,
                    298:            (unsigned) ((caddr_t)&p2->p_stats->pstat_endzero -
                    299:            (caddr_t)&p2->p_stats->pstat_startzero));
                    300:        bcopy(&p1->p_stats->pstat_startcopy, &p2->p_stats->pstat_startcopy,
                    301:            ((caddr_t)&p2->p_stats->pstat_endcopy -
                    302:             (caddr_t)&p2->p_stats->pstat_startcopy));
                    303: 
                    304:        if (p1->p_sigacts != NULL)
                    305:                (void)memcpy(p2->p_sigacts,
                    306:                                p1->p_sigacts, sizeof *p2->p_sigacts);
                    307:        else
                    308:                (void)memset(p2->p_sigacts, 0, sizeof *p2->p_sigacts);
                    309: 
                    310:        if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
                    311:                p2->p_flag |= P_CONTROLT;
                    312: 
                    313:        p2->p_xstat = 0;
                    314:        p2->p_ru = NULL;
                    315: 
                    316:        p2->p_debugger = 0;     /* don't inherit */
                    317:        simple_lock_init(&p2->siglock);
                    318:        p2->sigwait = FALSE;
                    319:        p2->sigwait_thread = NULL;
                    320:        p2->exit_thread = NULL;
                    321:        p2->user_stack = p1->user_stack;
                    322: 
                    323: #if KTRACE
                    324:        /*
                    325:         * Copy traceflag and tracefile if enabled.
                    326:         * If not inherited, these were zeroed above.
                    327:         */
                    328:        if (p1->p_traceflag&KTRFAC_INHERIT) {
                    329:                p2->p_traceflag = p1->p_traceflag;
                    330:                if ((p2->p_tracep = p1->p_tracep) != NULL)
                    331:                        VREF(p2->p_tracep);
                    332:        }
                    333: #endif
                    334: 
                    335:        th = procdup(p2, p1);   /* child, parent */
                    336:        LIST_INSERT_AFTER(p1, p2, p_pglist);
                    337:        p2->p_pptr = p1;
                    338:        LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
                    339:        LIST_INIT(&p2->p_children);
                    340:        LIST_INSERT_HEAD(&allproc, p2, p_list);
                    341:        LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
                    342:        TAILQ_INIT(&p2->p_evlist);
                    343:        /*
                    344:         * Make child runnable, set start time.
                    345:         */
                    346:        p2->p_stat = SRUN;
                    347: 
                    348:        return(th);
                    349: }
                    350: 
                    351: struct zone    *u_thread_zone;
                    352: 
                    353: void
                    354: uzone_init()
                    355: {
                    356:        u_thread_zone = zinit(sizeof(struct uthread),
                    357:                        THREAD_MAX * sizeof(struct uthread),
                    358:                        THREAD_CHUNK * sizeof(struct uthread),
                    359:                        "uthreads");
                    360: }
                    361: 
                    362: void
                    363: uthread_free(uthread)
                    364:        struct uthread  *uthread;
                    365: {
                    366:        zfree(u_thread_zone, (vm_offset_t) uthread);
                    367: }
                    368:        

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.