Annotation of 43BSDReno/sys/kern/kern_fork.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution is only permitted until one year after the first shipment
        !             6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !             7:  * binary forms are permitted provided that: (1) source distributions retain
        !             8:  * this entire copyright notice and comment, and (2) distributions including
        !             9:  * binaries display the following acknowledgement:  This product includes
        !            10:  * software developed by the University of California, Berkeley and its
        !            11:  * contributors'' in the documentation or other materials provided with the
        !            12:  * distribution and in all advertising materials mentioning features or use
        !            13:  * of this software.  Neither the name of the University nor the names of
        !            14:  * its contributors may be used to endorse or promote products derived from
        !            15:  * this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)kern_fork.c 7.20 (Berkeley) 7/27/90
        !            21:  */
        !            22: 
        !            23: #include "param.h"
        !            24: #include "systm.h"
        !            25: #include "map.h"
        !            26: #include "user.h"
        !            27: #include "kernel.h"
        !            28: #include "proc.h"
        !            29: #include "vnode.h"
        !            30: #include "seg.h"
        !            31: #include "vm.h"
        !            32: #include "text.h"
        !            33: #include "file.h"
        !            34: #include "acct.h"
        !            35: #include "ktrace.h"
        !            36: #include "../ufs/quota.h"
        !            37: 
        !            38: #include "machine/reg.h"
        !            39: #include "machine/pte.h"
        !            40: #include "machine/psl.h"
        !            41: 
        !            42: /*
        !            43:  * fork system call.
        !            44:  */
        !            45: /* ARGSUSED */
        !            46: fork(p, uap, retval)
        !            47:        struct proc *p;
        !            48:        struct args *uap;
        !            49:        int retval[];
        !            50: {
        !            51:        int error;
        !            52: 
        !            53:        u.u_cdmap = zdmap;
        !            54:        u.u_csmap = zdmap;
        !            55:        if (error = swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap)) {
        !            56:                retval[1] = 0;
        !            57:                return (error);
        !            58:        }
        !            59:        return (fork1(p, 0, retval));
        !            60: }
        !            61: 
        !            62: /* ARGSUSED */
        !            63: vfork(p, uap, retval)
        !            64:        struct proc *p;
        !            65:        struct args *uap;
        !            66:        int retval[];
        !            67: {
        !            68: 
        !            69:        return (fork1(p, 1, retval));
        !            70: }
        !            71: 
        !            72: fork1(p1, isvfork, retval)
        !            73:        register struct proc *p1;
        !            74:        int isvfork, retval[];
        !            75: {
        !            76:        register struct proc *p2;
        !            77:        register int a;
        !            78: 
        !            79:        a = 0;
        !            80:        if (p1->p_uid != 0) {
        !            81:                for (p2 = allproc; p2; p2 = p2->p_nxt)
        !            82:                        if (p2->p_uid == p1->p_uid)
        !            83:                                a++;
        !            84:                for (p2 = zombproc; p2; p2 = p2->p_nxt)
        !            85:                        if (p2->p_uid == p1->p_uid)
        !            86:                                a++;
        !            87:        }
        !            88:        /*
        !            89:         * Disallow if
        !            90:         *  No processes at all;
        !            91:         *  not su and too many procs owned; or
        !            92:         *  not su and would take last slot.
        !            93:         */
        !            94:        p2 = freeproc;
        !            95:        if (p2==NULL)
        !            96:                tablefull("proc");
        !            97:        if (p2 == NULL ||
        !            98:            (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) {
        !            99:                if (!isvfork) {
        !           100:                        (void) vsexpand((segsz_t)0, &u.u_cdmap, 1);
        !           101:                        (void) vsexpand((segsz_t)0, &u.u_csmap, 1);
        !           102:                }
        !           103:                retval[1] = 0;
        !           104:                return (EAGAIN);
        !           105:        }
        !           106:        if (newproc(isvfork)) {
        !           107:                retval[0] = p1->p_pid;
        !           108:                retval[1] = 1;  /* child */
        !           109:                u.u_acflag = AFORK;
        !           110:                return (0);
        !           111:        }
        !           112:        retval[0] = p2->p_pid;
        !           113:        retval[1] = 0;
        !           114:        return (0);
        !           115: }
        !           116: 
        !           117: /*
        !           118:  * Create a new process-- the internal version of
        !           119:  * sys fork.
        !           120:  * It returns 1 in the new process, 0 in the old.
        !           121:  */
        !           122: newproc(isvfork)
        !           123:        int isvfork;
        !           124: {
        !           125:        register struct proc *rpp, *rip;
        !           126:        register int n;
        !           127:        register struct file *fp;
        !           128:        static int pidchecked = 0;
        !           129: 
        !           130:        /*
        !           131:         * First, just locate a slot for a process
        !           132:         * and copy the useful info from this process into it.
        !           133:         * The panic "cannot happen" because fork has already
        !           134:         * checked for the existence of a slot.
        !           135:         */
        !           136:        mpid++;
        !           137: retry:
        !           138:        if (mpid >= PID_MAX) {
        !           139:                mpid = 100;
        !           140:                pidchecked = 0;
        !           141:        }
        !           142:        if (mpid >= pidchecked) {
        !           143:                int doingzomb = 0;
        !           144: 
        !           145:                pidchecked = PID_MAX;
        !           146:                /*
        !           147:                 * Scan the proc table to check whether this pid
        !           148:                 * is in use.  Remember the lowest pid that's greater
        !           149:                 * than mpid, so we can avoid checking for a while.
        !           150:                 */
        !           151:                rpp = allproc;
        !           152: again:
        !           153:                for (; rpp != NULL; rpp = rpp->p_nxt) {
        !           154:                        if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) {
        !           155:                                mpid++;
        !           156:                                if (mpid >= pidchecked)
        !           157:                                        goto retry;
        !           158:                        }
        !           159:                        if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
        !           160:                                pidchecked = rpp->p_pid;
        !           161:                        if (rpp->p_pgrp->pg_id > mpid && 
        !           162:                            pidchecked > rpp->p_pgrp->pg_id)
        !           163:                                pidchecked = rpp->p_pgrp->pg_id;
        !           164:                }
        !           165:                if (!doingzomb) {
        !           166:                        doingzomb = 1;
        !           167:                        rpp = zombproc;
        !           168:                        goto again;
        !           169:                }
        !           170:        }
        !           171:        if ((rpp = freeproc) == NULL)
        !           172:                panic("no procs");
        !           173: 
        !           174:        freeproc = rpp->p_nxt;                  /* off freeproc */
        !           175:        rpp->p_nxt = allproc;                   /* onto allproc */
        !           176:        rpp->p_nxt->p_prev = &rpp->p_nxt;       /*   (allproc is never NULL) */
        !           177:        rpp->p_prev = &allproc;
        !           178:        allproc = rpp;
        !           179: 
        !           180:        /*
        !           181:         * Make a proc table entry for the new process.
        !           182:         */
        !           183:        rip = u.u_procp;
        !           184: #if defined(tahoe)
        !           185:        rpp->p_ckey = rip->p_ckey;
        !           186:        rpp->p_dkey = 0;
        !           187: #endif
        !           188:        rpp->p_stat = SIDL;
        !           189:        timerclear(&rpp->p_realtimer.it_value);
        !           190:        rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX));
        !           191:        if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY)
        !           192:                rpp->p_flag |= SCTTY;
        !           193:        if (isvfork) {
        !           194:                rpp->p_flag |= SVFORK;
        !           195:                rpp->p_ndx = rip->p_ndx;
        !           196:        } else
        !           197:                rpp->p_ndx = rpp - proc;
        !           198:        bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1);
        !           199:        bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME);
        !           200:        rpp->p_uid = rip->p_uid;
        !           201:        rpp->p_ruid = rip->p_ruid;
        !           202:        rpp->p_rgid = rip->p_rgid;
        !           203:        rpp->p_pgrp = rip->p_pgrp;
        !           204:        rpp->p_pgrpnxt = rip->p_pgrpnxt;
        !           205:        rip->p_pgrpnxt = rpp;
        !           206:        rpp->p_nice = rip->p_nice;
        !           207:        rpp->p_textp = isvfork ? 0 : rip->p_textp;
        !           208:        rpp->p_pid = mpid;
        !           209:        rpp->p_ppid = rip->p_pid;
        !           210:        rpp->p_pptr = rip;
        !           211:        rpp->p_osptr = rip->p_cptr;
        !           212:        if (rip->p_cptr)
        !           213:                rip->p_cptr->p_ysptr = rpp;
        !           214:        rpp->p_ysptr = NULL;
        !           215:        rpp->p_cptr = NULL;
        !           216:        rip->p_cptr = rpp;
        !           217:        rpp->p_time = 0;
        !           218:        bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval));
        !           219:        bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval));
        !           220:        rpp->p_cpu = 0;
        !           221:        rpp->p_sigmask = rip->p_sigmask;
        !           222:        rpp->p_sigcatch = rip->p_sigcatch;
        !           223:        rpp->p_sigignore = rip->p_sigignore;
        !           224:        /* take along any pending signals like stops? */
        !           225:        if (isvfork) {
        !           226:                rpp->p_tsize = rpp->p_dsize = rpp->p_mmsize = rpp->p_ssize = 0;
        !           227:                rpp->p_szpt = clrnd(ctopt(HIGHPAGES));
        !           228:                forkstat.cntvfork++;
        !           229:                forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
        !           230:        } else {
        !           231:                rpp->p_tsize = rip->p_tsize;
        !           232:                rpp->p_dsize = rip->p_dsize;
        !           233:                rpp->p_mmsize = rip->p_mmsize;
        !           234:                rpp->p_ssize = rip->p_ssize;
        !           235:                rpp->p_szpt = rip->p_szpt;
        !           236:                forkstat.cntfork++;
        !           237:                forkstat.sizfork += rip->p_dsize + rip->p_ssize;
        !           238:        }
        !           239: #ifdef KTRACE
        !           240:        if (rip->p_traceflag&KTRFAC_INHERIT) {
        !           241:                rpp->p_traceflag = rip->p_traceflag;
        !           242:                if ((rpp->p_tracep = rip->p_tracep) != NULL)
        !           243:                        VREF(rpp->p_tracep);
        !           244:        } else {
        !           245:                rpp->p_tracep = NULL;
        !           246:                rpp->p_traceflag = 0;
        !           247:        }
        !           248: #endif
        !           249:        rpp->p_rssize = 0;
        !           250:        rpp->p_maxrss = rip->p_maxrss;
        !           251:        rpp->p_wchan = 0;
        !           252:        rpp->p_slptime = 0;
        !           253:        rpp->p_pctcpu = 0;
        !           254:        rpp->p_cpticks = 0;
        !           255:        {
        !           256:        struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)];
        !           257: 
        !           258:        rpp->p_hash = *hash;
        !           259:        *hash = rpp;
        !           260:        }
        !           261:        multprog++;
        !           262: 
        !           263:        /*
        !           264:         * Increase reference counts on shared objects.
        !           265:         */
        !           266:        for (n = 0; n <= u.u_lastfile; n++) {
        !           267:                fp = u.u_ofile[n];
        !           268:                if (fp == NULL)
        !           269:                        continue;
        !           270:                fp->f_count++;
        !           271:        }
        !           272:        VREF(u.u_cdir);
        !           273:        if (u.u_rdir)
        !           274:                VREF(u.u_rdir);
        !           275:        crhold(u.u_cred);
        !           276: 
        !           277:        /*
        !           278:         * This begins the section where we must prevent the parent
        !           279:         * from being swapped.
        !           280:         */
        !           281:        rip->p_flag |= SKEEP;
        !           282:        if (procdup(rpp, isvfork)) {
        !           283:                (void) splclock();
        !           284:                u.u_start = time;
        !           285:                (void) spl0();
        !           286:                return (1);
        !           287:        }
        !           288: 
        !           289:        /*
        !           290:         * Make child runnable and add to run queue.
        !           291:         */
        !           292:        (void) splclock();
        !           293:        rpp->p_stat = SRUN;
        !           294:        setrq(rpp);
        !           295:        (void) spl0();
        !           296: 
        !           297:        /*
        !           298:         * Cause child to take a non-local goto as soon as it runs.
        !           299:         * On older systems this was done with SSWAP bit in proc
        !           300:         * table; on VAX we use u.u_pcb.pcb_sswap so don't need
        !           301:         * to do rpp->p_flag |= SSWAP.  Actually do nothing here.
        !           302:         */
        !           303:        /* rpp->p_flag |= SSWAP; */
        !           304: 
        !           305:        /*
        !           306:         * Now can be swapped.
        !           307:         */
        !           308:        rip->p_flag &= ~SKEEP;
        !           309: 
        !           310:        /*
        !           311:         * If vfork make chain from parent process to child
        !           312:         * (where virtal memory is temporarily).  Wait for
        !           313:         * child to finish, steal virtual memory back,
        !           314:         * and wakeup child to let it die.
        !           315:         */
        !           316:        if (isvfork) {
        !           317:                u.u_procp->p_xlink = rpp;
        !           318:                u.u_procp->p_flag |= SNOVM;
        !           319:                while (rpp->p_flag & SVFORK)
        !           320:                        sleep((caddr_t)rpp, PZERO - 1);
        !           321:                if ((rpp->p_flag & SLOAD) == 0)
        !           322:                        panic("newproc vfork");
        !           323:                uaccess(rpp, Vfmap, &vfutl);
        !           324:                u.u_procp->p_xlink = 0;
        !           325:                vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
        !           326:                u.u_procp->p_flag &= ~SNOVM;
        !           327:                rpp->p_ndx = rpp - proc;
        !           328:                rpp->p_flag |= SVFDONE;
        !           329:                wakeup((caddr_t)rpp);
        !           330:        }
        !           331: 
        !           332:        /*
        !           333:         * 0 return means parent.
        !           334:         */
        !           335:        return (0);
        !           336: }

unix.superglobalmegacorp.com

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