Annotation of 43BSDReno/sys/kern/kern_fork.c, revision 1.1.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.