# 2.11BSD#431 - /usr/src/sys/sys/kern_exit.c

##### Functions

    endvfork          X
    exit              X
    rexit             X
    wait1             X
    wait4             X

##### struct's

    a                 X
    args              X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)kern_exit.c	2.6 (2.11BSD) 2000/2/20
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/psl.h"
      11: #include "../machine/reg.h"
      12:
      13: #include "systm.h"
      14: #include "map.h"
      15: #include "user.h"
      16: #include "proc.h"
      17: #include "inode.h"
      18: #include "vm.h"
      19: #include "file.h"
      20: #include "wait.h"
      21: #include "kernel.h"
      22: #ifdef QUOTA
      23: #include "quota.h"
      24: #endif
      25: #include "ingres.h"
      26:
      27: extern  int Acctopen;   /* kern_acct.c */
      28:
      29: /*
      30:  * exit system call: pass back caller's arg
      31:  */
      32: rexit()
      33: {
      34:     register struct a {
      35:         int rval;
      36:     } *uap = (struct a *)u.u_ap;
      37:
      38:     exit(W_EXITCODE(uap->rval, 0));
      39:     /* NOTREACHED */
      40: }
      41:
      42: /*
      43:  * Exit: deallocate address space and other resources,
      44:  * change proc state to zombie, and unlink proc from allproc
      45:  * list.  Save exit status and rusage for wait4().
      46:  * Check for child processes and orphan them.
      47:  */
      48: exit(rv)
      49: {
      50:     register int i;
      51:     register struct proc *p;
      52:     struct  proc **pp;
      53:
      54:     p = u.u_procp;
      55:     p->p_flag &= ~(P_TRACED|SULOCK);
      56:     p->p_sigignore = ~0;
      57:     p->p_sig = 0;
      58:     /*
      59: 	 * 2.11 doesn't need to do this and it gets overwritten anyway.
      60: 	 * p->p_realtimer.it_value = 0;
      61: 	 */
      62:     for (i = 0; i <= u.u_lastfile; i++) {
      63:         register struct file *f;
      64:
      65:         f = u.u_ofile[i];
      66:         u.u_ofile[i] = NULL;
      67:         u.u_pofile[i] = 0;
      68:         (void) closef(f);
      69:     }
      70:     ilock(u.u_cdir);
      71:     iput(u.u_cdir);
      72:     if (u.u_rdir) {
      73:         ilock(u.u_rdir);
      74:         iput(u.u_rdir);
      75:     }
      76:     u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
      77:     if  (Acctopen)
      78:         (void) acct();
      79: #ifdef QUOTA
      80:     QUOTAMAP();
      81:     qclean();
      82:     QUOTAUNMAP();
      83: #endif
      84:     /*
      85: 	 * Freeing the user structure and kernel stack
      86: 	 * for the current process: have to run a bit longer
      87: 	 * using the slots which are about to be freed...
      88: 	 */
      89:     if (p->p_flag & SVFORK)
      90:         endvfork();
      91:     else {
      92:         xfree();
      93:         mfree(coremap, p->p_dsize, p->p_daddr);
      94:         mfree(coremap, p->p_ssize, p->p_saddr);
      95:     }
      96:     mfree(coremap, USIZE, p->p_addr);
      97:
      98:     if (p->p_pid == 1)
      99:         panic("init died");
     100:     if (*p->p_prev = p->p_nxt)      /* off allproc queue */
     101:         p->p_nxt->p_prev = p->p_prev;
     102:     if (p->p_nxt = zombproc)        /* onto zombproc */
     103:         p->p_nxt->p_prev = &p->p_nxt;
     104:     p->p_prev = &zombproc;
     105:     zombproc = p;
     106:     p->p_stat = SZOMB;
     107:
     108: #if NINGRES > 0
     109:     ingres_rma(p->p_pid);       /* Remove any ingres locks */
     110: #endif
     111:
     112:     noproc = 1;
     113:     for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
     114:         if (*pp == p) {
     115:             *pp = p->p_hash;
     116:             goto done;
     117:         }
     118:     panic("exit");
     119: done:
     120:     /*
     121: 	 * Overwrite p_alive substructure of proc - better not be anything
     122: 	 * important left!
     123: 	 */
     124:     p->p_xstat = rv;
     125:     p->p_ru = u.u_ru;
     126:     ruadd(&p->p_ru, &u.u_cru);
     127:     {
     128:         register struct proc *q;
     129:         int doingzomb = 0;
     130:
     131:         q = allproc;
     132: again:
     133:         for(; q; q = q->p_nxt)
     134:             if (q->p_pptr == p) {
     135:                 q->p_pptr = &proc[1];
     136:                 q->p_ppid = 1;
     137:                 wakeup((caddr_t)&proc[1]);
     138:                 if (q->p_flag& P_TRACED) {
     139:                     q->p_flag &= ~P_TRACED;
     140:                     psignal(q, SIGKILL);
     141:                 } else if (q->p_stat == SSTOP) {
     142:                     psignal(q, SIGHUP);
     143:                     psignal(q, SIGCONT);
     144:                 }
     145:             }
     146:         if (!doingzomb) {
     147:             doingzomb = 1;
     148:             q = zombproc;
     149:             goto again;
     150:         }
     151:     }
     152:     psignal(p->p_pptr, SIGCHLD);
     153:     wakeup((caddr_t)p->p_pptr);
     154:     swtch();
     155:     /* NOTREACHED */
     156: }
     157:
     158:     struct  args
     159:         {
     160:         int pid;
     161:         int *status;
     162:         int options;
     163:         struct rusage *rusage;
     164:         int compat;
     165:         };
     166:
     167: wait4()
     168: {
     169:     int retval[2];
     170:     register struct args *uap = (struct args *)u.u_ap;
     171:
     172:     uap->compat = 0;
     173:     u.u_error = wait1(u.u_procp, uap, retval);
     174:     if (!u.u_error)
     175:         u.u_r.r_val1 = retval[0];
     176: }
     177:
     178: /*
     179:  * Wait: check child processes to see if any have exited,
     180:  * stopped under trace or (optionally) stopped by a signal.
     181:  * Pass back status and make available for reuse the exited
     182:  * child's proc structure.
     183:  */
     184: wait1(q, uap, retval)
     185:     struct proc *q;
     186:     register struct args *uap;
     187:     int retval[];
     188: {
     189:     int nfound, status;
     190:     struct rusage ru;           /* used for local conversion */
     191:     register struct proc *p;
     192:     register int error;
     193:
     194:     if (uap->pid == WAIT_MYPGRP)        /* == 0 */
     195:         uap->pid = -q->p_pgrp;
     196: loop:
     197:     nfound = 0;
     198:     /*
     199: 	 * 4.X has child links in the proc structure, so they consolidate
     200: 	 * these two tests into one loop.  We only have the zombie chain
     201: 	 * and the allproc chain, so we check for ZOMBIES first, then for
     202: 	 * children that have changed state.  We check for ZOMBIES first
     203: 	 * because they are more common, and, as the list is typically small,
     204: 	 * a faster check.
     205: 	 */
     206:     for (p = zombproc; p;p = p->p_nxt) {
     207:         if (p->p_pptr != q) /* are we the parent of this process? */
     208:             continue;
     209:         if (uap->pid != WAIT_ANY &&
     210:             p->p_pid != uap->pid && p->p_pgrp != -uap->pid)
     211:             continue;
     212:         retval[0] = p->p_pid;
     213:         retval[1] = p->p_xstat;
     214:         if (uap->status && (error = copyout(&p->p_xstat, uap->status,
     215:                         sizeof (uap->status))))
     216:             return(error);
     217:         if (uap->rusage) {
     218:             rucvt(&ru, &p->p_ru);
     219:             if (error = copyout(&ru, uap->rusage, sizeof (ru)))
     220:                 return(error);
     221:         }
     222:         ruadd(&u.u_cru, &p->p_ru);
     223:         p->p_xstat = 0;
     224:         p->p_stat = NULL;
     225:         p->p_pid = 0;
     226:         p->p_ppid = 0;
     227:         if (*p->p_prev = p->p_nxt)  /* off zombproc */
     228:             p->p_nxt->p_prev = p->p_prev;
     229:         p->p_nxt = freeproc;        /* onto freeproc */
     230:         freeproc = p;
     231:         p->p_pptr = 0;
     232:         p->p_sig = 0;
     233:         p->p_sigcatch = 0;
     234:         p->p_sigignore = 0;
     235:         p->p_sigmask = 0;
     236:         p->p_pgrp = 0;
     237:         p->p_flag = 0;
     238:         p->p_wchan = 0;
     239:         return (0);
     240:     }
     241:     for (p = allproc; p;p = p->p_nxt) {
     242:         if (p->p_pptr != q)
     243:             continue;
     244:         if (uap->pid != WAIT_ANY &&
     245:             p->p_pid != uap->pid && p->p_pgrp != -uap->pid)
     246:             continue;
     247:         ++nfound;
     248:         if (p->p_stat == SSTOP && (p->p_flag& P_WAITED)==0 &&
     249:             (p->p_flag&P_TRACED || uap->options&WUNTRACED)) {
     250:             p->p_flag |= P_WAITED;
     251:             retval[0] = p->p_pid;
     252:             error = 0;
     253:             if (uap->compat)
     254:                 retval[1] = W_STOPCODE(p->p_ptracesig);
     255:             else if (uap->status) {
     256:                 status = W_STOPCODE(p->p_ptracesig);
     257:                 error = copyout(&status, uap->status,
     258:                         sizeof (status));
     259:             }
     260:             return (error);
     261:         }
     262:     }
     263:     if (nfound == 0)
     264:         return (ECHILD);
     265:     if (uap->options&WNOHANG) {
     266:         retval[0] = 0;
     267:         return (0);
     268:     }
     269:     error = tsleep(q, PWAIT|PCATCH, 0);
     270:     if  (error == 0)
     271:         goto loop;
     272:     return(error);
     273: }
     274:
     275: /*
     276:  * Notify parent that vfork child is finished with parent's data.  Called
     277:  * during exit/exec(getxfile); must be called before xfree().  The child
     278:  * must be locked in core so it will be in core when the parent runs.
     279:  */
     280: endvfork()
     281: {
     282:     register struct proc *rip, *rpp;
     283:
     284:     rpp = u.u_procp;
     285:     rip = rpp->p_pptr;
     286:     rpp->p_flag &= ~SVFORK;
     287:     rpp->p_flag |= SLOCK;
     288:     wakeup((caddr_t)rpp);
     289:     while(!(rpp->p_flag&SVFDONE))
     290:         sleep((caddr_t)rip,PZERO-1);
     291:     /*
     292: 	 * The parent has taken back our data+stack, set our sizes to 0.
     293: 	 */
     294:     u.u_dsize = rpp->p_dsize = 0;
     295:     u.u_ssize = rpp->p_ssize = 0;
     296:     rpp->p_flag &= ~(SVFDONE | SLOCK);
     297: }

#### Defined functions

endvfork defined in line 280; used 2 times

- in line 90
- in /usr/src/sys/sys/kern_exec.c line 572

exit defined in line 48; used 4 times

- in line 38
- in /usr/src/sys/pdp/genassym.c line 107
- in /usr/src/sys/sys/kern_sig.c line 605
- in /usr/src/sys/sys/sys_process.c line 191

rexit defined in line 32; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 20, 111

wait1 defined in line 184; used 1 times

- in line 173

wait4 defined in line 167; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 21, 117

#### Defined struct's

a defined in line 34; used 2 times

- in line 36(2)

args defined in line 158; used 6 times

- in line 170(4), 186(2)

Last modified: 2000-02-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 964 |