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
exit defined in line 48; used 4 times
rexit defined in line 32; used 2 times
wait1 defined in line 184; used 1 times
wait4 defined in line 167; used 2 times

Defined struct's

a defined in line 34; used 2 times
  • in line 36(2)
args defined in line 158; used 6 times
Last modified: 2000-02-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 49
Valid CSS Valid XHTML 1.0 Strict