Annotation of Net2/kern/kern_exit.c, revision 1.1

1.1     ! root        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_exit.c 7.35 (Berkeley) 6/27/91
        !            34:  */
        !            35: 
        !            36: #include "param.h"
        !            37: #include "systm.h"
        !            38: #include "map.h"
        !            39: #include "ioctl.h"
        !            40: #include "tty.h"
        !            41: #include "time.h"
        !            42: #include "resource.h"
        !            43: #include "kernel.h"
        !            44: #include "proc.h"
        !            45: #include "buf.h"
        !            46: #include "wait.h"
        !            47: #include "file.h"
        !            48: #include "vnode.h"
        !            49: #include "syslog.h"
        !            50: #include "malloc.h"
        !            51: #include "resourcevar.h"
        !            52: 
        !            53: #include "machine/cpu.h"
        !            54: #ifdef COMPAT_43
        !            55: #include "machine/reg.h"
        !            56: #include "machine/psl.h"
        !            57: #endif
        !            58: 
        !            59: #include "vm/vm.h"
        !            60: #include "vm/vm_kern.h"
        !            61: 
        !            62: /*
        !            63:  * Exit system call: pass back caller's arg
        !            64:  */
        !            65: /* ARGSUSED */
        !            66: rexit(p, uap, retval)
        !            67:        struct proc *p;
        !            68:        struct args {
        !            69:                int     rval;
        !            70:        } *uap;
        !            71:        int *retval;
        !            72: {
        !            73: 
        !            74:        exit(p, W_EXITCODE(uap->rval, 0));
        !            75:        /* NOTREACHED */
        !            76: }
        !            77: 
        !            78: /*
        !            79:  * Exit: deallocate address space and other resources,
        !            80:  * change proc state to zombie, and unlink proc from allproc
        !            81:  * and parent's lists.  Save exit status and rusage for wait().
        !            82:  * Check for child processes and orphan them.
        !            83:  */
        !            84: exit(p, rv)
        !            85:        register struct proc *p;
        !            86:        int rv;
        !            87: {
        !            88:        register struct proc *q, *nq;
        !            89:        register struct proc **pp;
        !            90:        int s;
        !            91: 
        !            92: #ifdef PGINPROF
        !            93:        vmsizmon();
        !            94: #endif
        !            95:        MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
        !            96:                M_ZOMBIE, M_WAITOK);
        !            97:        /*
        !            98:         * If parent is waiting for us to exit or exec,
        !            99:         * SPPWAIT is set; we will wakeup the parent below.
        !           100:         */
        !           101:        p->p_flag &= ~(STRC|SPPWAIT);
        !           102:        p->p_flag |= SWEXIT;
        !           103:        p->p_sigignore = ~0;
        !           104:        p->p_sig = 0;
        !           105:        untimeout(realitexpire, (caddr_t)p);
        !           106: 
        !           107:        /*
        !           108:         * Close open files and release open-file table.
        !           109:         * This may block!
        !           110:         */
        !           111:        fdfree(p);
        !           112: 
        !           113:        /* The next two chunks should probably be moved to vmspace_exit. */
        !           114: #ifdef SYSVSHM
        !           115:        if (p->p_vmspace->vm_shm)
        !           116:                shmexit(p);
        !           117: #endif
        !           118:        /*
        !           119:         * Release user portion of address space.
        !           120:         * This releases references to vnodes,
        !           121:         * which could cause I/O if the file has been unlinked.
        !           122:         * Need to do this early enough that we can still sleep.
        !           123:         * Can't free the entire vmspace as the kernel stack
        !           124:         * may be mapped within that space also.
        !           125:         */
        !           126:        if (p->p_vmspace->vm_refcnt == 1)
        !           127:                (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS,
        !           128:                    VM_MAXUSER_ADDRESS);
        !           129: 
        !           130:        if (p->p_pid == 1)
        !           131:                panic("init died");
        !           132:        if (SESS_LEADER(p)) {
        !           133:                register struct session *sp = p->p_session;
        !           134: 
        !           135:                if (sp->s_ttyvp) {
        !           136:                        /*
        !           137:                         * Controlling process.
        !           138:                         * Signal foreground pgrp,
        !           139:                         * drain controlling terminal
        !           140:                         * and revoke access to controlling terminal.
        !           141:                         */
        !           142:                        if (sp->s_ttyp->t_session == sp) {
        !           143:                                if (sp->s_ttyp->t_pgrp)
        !           144:                                        pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
        !           145:                                (void) ttywait(sp->s_ttyp);
        !           146:                                vgoneall(sp->s_ttyvp);
        !           147:                        }
        !           148:                        vrele(sp->s_ttyvp);
        !           149:                        sp->s_ttyvp = NULL;
        !           150:                        /*
        !           151:                         * s_ttyp is not zero'd; we use this to indicate
        !           152:                         * that the session once had a controlling terminal.
        !           153:                         * (for logging and informational purposes)
        !           154:                         */
        !           155:                }
        !           156:                sp->s_leader = NULL;
        !           157:        }
        !           158:        fixjobc(p, p->p_pgrp, 0);
        !           159:        p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
        !           160:        (void) acct(p);
        !           161:        if (--p->p_limit->p_refcnt == 0)
        !           162:                FREE(p->p_limit, M_SUBPROC);
        !           163: #ifdef KTRACE
        !           164:        /* 
        !           165:         * release trace file
        !           166:         */
        !           167:        if (p->p_tracep)
        !           168:                vrele(p->p_tracep);
        !           169: #endif
        !           170: 
        !           171:        /*
        !           172:         * Remove proc from allproc queue and pidhash chain.
        !           173:         * Place onto zombproc.  Unlink from parent's child list.
        !           174:         */
        !           175:        if (*p->p_prev = p->p_nxt)
        !           176:                p->p_nxt->p_prev = p->p_prev;
        !           177:        if (p->p_nxt = zombproc)
        !           178:                p->p_nxt->p_prev = &p->p_nxt;
        !           179:        p->p_prev = &zombproc;
        !           180:        zombproc = p;
        !           181:        p->p_stat = SZOMB;
        !           182:        curproc = NULL;
        !           183:        for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
        !           184:                if (*pp == p) {
        !           185:                        *pp = p->p_hash;
        !           186:                        goto done;
        !           187:                }
        !           188:        panic("exit");
        !           189: done:
        !           190: 
        !           191:        if (p->p_cptr)          /* only need this if any child is S_ZOMB */
        !           192:                wakeup((caddr_t) initproc);
        !           193:        for (q = p->p_cptr; q != NULL; q = nq) {
        !           194:                nq = q->p_osptr;
        !           195:                if (nq != NULL)
        !           196:                        nq->p_ysptr = NULL;
        !           197:                if (initproc->p_cptr)
        !           198:                        initproc->p_cptr->p_ysptr = q;
        !           199:                q->p_osptr = initproc->p_cptr;
        !           200:                q->p_ysptr = NULL;
        !           201:                initproc->p_cptr = q;
        !           202: 
        !           203:                q->p_pptr = initproc;
        !           204:                /*
        !           205:                 * Traced processes are killed
        !           206:                 * since their existence means someone is screwing up.
        !           207:                 */
        !           208:                if (q->p_flag&STRC) {
        !           209:                        q->p_flag &= ~STRC;
        !           210:                        psignal(q, SIGKILL);
        !           211:                }
        !           212:        }
        !           213:        p->p_cptr = NULL;
        !           214: 
        !           215:        /*
        !           216:         * Save exit status and final rusage info,
        !           217:         * adding in child rusage info and self times.
        !           218:         */
        !           219:        p->p_xstat = rv;
        !           220:        *p->p_ru = p->p_stats->p_ru;
        !           221:        p->p_ru->ru_stime = p->p_stime;
        !           222:        p->p_ru->ru_utime = p->p_utime;
        !           223:        ruadd(p->p_ru, &p->p_stats->p_cru);
        !           224: 
        !           225:        /*
        !           226:         * Notify parent that we're gone.
        !           227:         */
        !           228:        psignal(p->p_pptr, SIGCHLD);
        !           229:        wakeup((caddr_t)p->p_pptr);
        !           230: #if defined(tahoe)
        !           231:        /* move this to cpu_exit */
        !           232:        p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
        !           233: #endif
        !           234:        /*
        !           235:         * Finally, call machine-dependent code to release the remaining
        !           236:         * resources including address space, the kernel stack and pcb.
        !           237:         * The address space is released by "vmspace_free(p->p_vmspace)";
        !           238:         * This is machine-dependent, as we may have to change stacks
        !           239:         * or ensure that the current one isn't reallocated before we
        !           240:         * finish.  cpu_exit will end with a call to swtch(), finishing
        !           241:         * our execution (pun intended).
        !           242:         */
        !           243:        cpu_exit(p);
        !           244:        /* NOTREACHED */
        !           245: }
        !           246: 
        !           247: #ifdef COMPAT_43
        !           248: owait(p, uap, retval)
        !           249:        struct proc *p;
        !           250:        register struct args {
        !           251:                int     pid;
        !           252:                int     *status;
        !           253:                int     options;
        !           254:                struct  rusage *rusage;
        !           255:                int     compat;
        !           256:        } *uap;
        !           257:        int *retval;
        !           258: {
        !           259: 
        !           260:        if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) {
        !           261:                uap->options = 0;
        !           262:                uap->rusage = 0;
        !           263:        } else {
        !           264:                uap->options = p->p_regs[R0];
        !           265:                uap->rusage = (struct rusage *)p->p_regs[R1];
        !           266:        }
        !           267:        uap->pid = WAIT_ANY;
        !           268:        uap->status = 0;
        !           269:        uap->compat = 1;
        !           270:        return (wait1(p, uap, retval));
        !           271: }
        !           272: 
        !           273: wait4(p, uap, retval)
        !           274:        struct proc *p;
        !           275:        struct args {
        !           276:                int     pid;
        !           277:                int     *status;
        !           278:                int     options;
        !           279:                struct  rusage *rusage;
        !           280:                int     compat;
        !           281:        } *uap;
        !           282:        int *retval;
        !           283: {
        !           284: 
        !           285:        uap->compat = 0;
        !           286:        return (wait1(p, uap, retval));
        !           287: }
        !           288: #else
        !           289: #define        wait1   wait4
        !           290: #endif
        !           291: 
        !           292: /*
        !           293:  * Wait: check child processes to see if any have exited,
        !           294:  * stopped under trace, or (optionally) stopped by a signal.
        !           295:  * Pass back status and deallocate exited child's proc structure.
        !           296:  */
        !           297: wait1(q, uap, retval)
        !           298:        register struct proc *q;
        !           299:        register struct args {
        !           300:                int     pid;
        !           301:                int     *status;
        !           302:                int     options;
        !           303:                struct  rusage *rusage;
        !           304: #ifdef COMPAT_43
        !           305:                int compat;
        !           306: #endif
        !           307:        } *uap;
        !           308:        int retval[];
        !           309: {
        !           310:        register int nfound;
        !           311:        register struct proc *p;
        !           312:        int status, error;
        !           313: 
        !           314:        if (uap->pid == 0)
        !           315:                uap->pid = -q->p_pgid;
        !           316: #ifdef notyet
        !           317:        if (uap->options &~ (WUNTRACED|WNOHANG))
        !           318:                return (EINVAL);
        !           319: #endif
        !           320: loop:
        !           321:        nfound = 0;
        !           322:        for (p = q->p_cptr; p; p = p->p_osptr) {
        !           323:                if (uap->pid != WAIT_ANY &&
        !           324:                    p->p_pid != uap->pid && p->p_pgid != -uap->pid)
        !           325:                        continue;
        !           326:                nfound++;
        !           327:                if (p->p_stat == SZOMB) {
        !           328:                        retval[0] = p->p_pid;
        !           329: #ifdef COMPAT_43
        !           330:                        if (uap->compat)
        !           331:                                retval[1] = p->p_xstat;
        !           332:                        else
        !           333: #endif
        !           334:                        if (uap->status) {
        !           335:                                status = p->p_xstat;    /* convert to int */
        !           336:                                if (error = copyout((caddr_t)&status,
        !           337:                                    (caddr_t)uap->status, sizeof(status)))
        !           338:                                        return (error);
        !           339:                        }
        !           340:                        if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
        !           341:                            (caddr_t)uap->rusage, sizeof (struct rusage))))
        !           342:                                return (error);
        !           343:                        p->p_xstat = 0;
        !           344:                        ruadd(&q->p_stats->p_cru, p->p_ru);
        !           345:                        FREE(p->p_ru, M_ZOMBIE);
        !           346:                        if (--p->p_cred->p_refcnt == 0) {
        !           347:                                crfree(p->p_cred->pc_ucred);
        !           348:                                FREE(p->p_cred, M_SUBPROC);
        !           349:                        }
        !           350: 
        !           351:                        /*
        !           352:                         * Finally finished with old proc entry.
        !           353:                         * Unlink it from its process group and free it.
        !           354:                         */
        !           355:                        leavepgrp(p);
        !           356:                        if (*p->p_prev = p->p_nxt)      /* off zombproc */
        !           357:                                p->p_nxt->p_prev = p->p_prev;
        !           358:                        if (q = p->p_ysptr)
        !           359:                                q->p_osptr = p->p_osptr;
        !           360:                        if (q = p->p_osptr)
        !           361:                                q->p_ysptr = p->p_ysptr;
        !           362:                        if ((q = p->p_pptr)->p_cptr == p)
        !           363:                                q->p_cptr = p->p_osptr;
        !           364: 
        !           365:                        /*
        !           366:                         * Give machine-dependent layer a chance
        !           367:                         * to free anything that cpu_exit couldn't
        !           368:                         * release while still running in process context.
        !           369:                         */
        !           370:                        cpu_wait(p);
        !           371:                        FREE(p, M_PROC);
        !           372:                        nprocs--;
        !           373:                        return (0);
        !           374:                }
        !           375:                if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
        !           376:                    (p->p_flag & STRC || uap->options & WUNTRACED)) {
        !           377:                        p->p_flag |= SWTED;
        !           378:                        retval[0] = p->p_pid;
        !           379: #ifdef COMPAT_43
        !           380:                        if (uap->compat) {
        !           381:                                retval[1] = W_STOPCODE(p->p_xstat);
        !           382:                                error = 0;
        !           383:                        } else
        !           384: #endif
        !           385:                        if (uap->status) {
        !           386:                                status = W_STOPCODE(p->p_xstat);
        !           387:                                error = copyout((caddr_t)&status,
        !           388:                                    (caddr_t)uap->status, sizeof(status));
        !           389:                        } else
        !           390:                                error = 0;
        !           391:                        return (error);
        !           392:                }
        !           393:        }
        !           394:        if (nfound == 0)
        !           395:                return (ECHILD);
        !           396:        if (uap->options & WNOHANG) {
        !           397:                retval[0] = 0;
        !           398:                return (0);
        !           399:        }
        !           400:        if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
        !           401:                return (error);
        !           402:        goto loop;
        !           403: }

unix.superglobalmegacorp.com

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