The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_exit.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
   39  * $FreeBSD$
   40  */
   41 
   42 #include "opt_compat.h"
   43 #include "opt_ktrace.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/sysproto.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/proc.h>
   51 #include <sys/pioctl.h>
   52 #include <sys/tty.h>
   53 #include <sys/wait.h>
   54 #include <sys/vnode.h>
   55 #include <sys/resourcevar.h>
   56 #include <sys/signalvar.h>
   57 #include <sys/ptrace.h>
   58 #include <sys/acct.h>           /* for acct_process() function prototype */
   59 #include <sys/filedesc.h>
   60 #include <sys/shm.h>
   61 #include <sys/sem.h>
   62 #include <sys/aio.h>
   63 
   64 #ifdef COMPAT_43
   65 #include <machine/reg.h>
   66 #include <machine/psl.h>
   67 #endif
   68 #include <machine/limits.h>     /* for UCHAR_MAX = typeof(p_priority)_MAX */
   69 
   70 #include <vm/vm.h>
   71 #include <vm/vm_param.h>
   72 #include <sys/lock.h>
   73 #include <vm/pmap.h>
   74 #include <vm/vm_map.h>
   75 #include <vm/vm_zone.h>
   76 #include <sys/user.h>
   77 
   78 static MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status");
   79 
   80 static int wait1 __P((struct proc *, struct wait_args *, int));
   81 
   82 /*
   83  * callout list for things to do at exit time
   84  */
   85 typedef struct exit_list_element {
   86         struct exit_list_element *next;
   87         exitlist_fn function;
   88 } *ele_p;
   89 
   90 static ele_p exit_list;
   91 
   92 /*
   93  * exit --
   94  *      Death of process.
   95  */
   96 void
   97 exit(p, uap)
   98         struct proc *p;
   99         struct rexit_args /* {
  100                 int     rval;
  101         } */ *uap;
  102 {
  103 
  104         exit1(p, W_EXITCODE(uap->rval, 0));
  105         /* NOTREACHED */
  106 }
  107 
  108 /*
  109  * Exit: deallocate address space and other resources, change proc state
  110  * to zombie, and unlink proc from allproc and parent's lists.  Save exit
  111  * status and rusage for wait().  Check for child processes and orphan them.
  112  */
  113 void
  114 exit1(p, rv)
  115         register struct proc *p;
  116         int rv;
  117 {
  118         register struct proc *q, *nq;
  119         register struct vmspace *vm;
  120         ele_p ep = exit_list;
  121 
  122         if (p->p_pid == 1) {
  123                 printf("init died (signal %d, exit %d)\n",
  124                     WTERMSIG(rv), WEXITSTATUS(rv));
  125                 panic("Going nowhere without my init!");
  126         }
  127 
  128         aio_proc_rundown(p);
  129 
  130         /* are we a task leader? */
  131         if(p == p->p_leader) {
  132                 struct kill_args killArgs;
  133                 killArgs.signum = SIGKILL;
  134                 q = p->p_peers;
  135                 while(q) {
  136                         killArgs.pid = q->p_pid;
  137                         /*
  138                          * The interface for kill is better
  139                          * than the internal signal
  140                          */
  141                         kill(p, &killArgs);
  142                         nq = q;
  143                         q = q->p_peers;
  144                 }
  145                 while (p->p_peers) 
  146                   tsleep((caddr_t)p, PWAIT, "exit1", 0);
  147         } 
  148 
  149 #ifdef PGINPROF
  150         vmsizmon();
  151 #endif
  152         STOPEVENT(p, S_EXIT, rv);
  153 
  154         /* 
  155          * Check if any LKMs need anything done at process exit.
  156          * e.g. SYSV IPC stuff
  157          * XXX what if one of these generates an error?
  158          */
  159         while (ep) {
  160                 (*ep->function)(p);
  161                 ep = ep->next;
  162         }
  163 
  164         if (p->p_flag & P_PROFIL)
  165                 stopprofclock(p);
  166         MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
  167                 M_ZOMBIE, M_WAITOK);
  168         /*
  169          * If parent is waiting for us to exit or exec,
  170          * P_PPWAIT is set; we will wakeup the parent below.
  171          */
  172         p->p_flag &= ~(P_TRACED | P_PPWAIT);
  173         p->p_flag |= P_WEXIT;
  174         p->p_siglist = 0;
  175         if (timevalisset(&p->p_realtimer.it_value))
  176                 untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
  177 
  178         /*
  179          * Reset any sigio structures pointing to us as a result of
  180          * F_SETOWN with our pid.
  181          */
  182         funsetownlst(&p->p_sigiolst);
  183 
  184         /*
  185          * Close open files and release open-file table.
  186          * This may block!
  187          */
  188         fdfree(p);
  189 
  190         if(p->p_leader->p_peers) {
  191                 q = p->p_leader;
  192                 while(q->p_peers != p)
  193                         q = q->p_peers;
  194                 q->p_peers = p->p_peers;
  195                 wakeup((caddr_t)p->p_leader);
  196         }
  197 
  198         /*
  199          * XXX Shutdown SYSV semaphores
  200          */
  201         semexit(p);
  202 
  203         /* The next two chunks should probably be moved to vmspace_exit. */
  204         vm = p->p_vmspace;
  205         /*
  206          * Release user portion of address space.
  207          * This releases references to vnodes,
  208          * which could cause I/O if the file has been unlinked.
  209          * Need to do this early enough that we can still sleep.
  210          * Can't free the entire vmspace as the kernel stack
  211          * may be mapped within that space also.
  212          */
  213         if (vm->vm_refcnt == 1) {
  214                 if (vm->vm_shm)
  215                         shmexit(p);
  216                 pmap_remove_pages(&vm->vm_pmap, VM_MIN_ADDRESS,
  217                     VM_MAXUSER_ADDRESS);
  218                 (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
  219                     VM_MAXUSER_ADDRESS);
  220         }
  221 
  222         if (SESS_LEADER(p)) {
  223                 register struct session *sp = p->p_session;
  224 
  225                 if (sp->s_ttyvp) {
  226                         /*
  227                          * Controlling process.
  228                          * Signal foreground pgrp,
  229                          * drain controlling terminal
  230                          * and revoke access to controlling terminal.
  231                          */
  232                         if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) {
  233                                 if (sp->s_ttyp->t_pgrp)
  234                                         pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
  235                                 (void) ttywait(sp->s_ttyp);
  236                                 /*
  237                                  * The tty could have been revoked
  238                                  * if we blocked.
  239                                  */
  240                                 if (sp->s_ttyvp)
  241                                         VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
  242                         }
  243                         if (sp->s_ttyvp)
  244                                 vrele(sp->s_ttyvp);
  245                         sp->s_ttyvp = NULL;
  246                         /*
  247                          * s_ttyp is not zero'd; we use this to indicate
  248                          * that the session once had a controlling terminal.
  249                          * (for logging and informational purposes)
  250                          */
  251                 }
  252                 sp->s_leader = NULL;
  253         }
  254         fixjobc(p, p->p_pgrp, 0);
  255         (void)acct_process(p);
  256 #ifdef KTRACE
  257         /*
  258          * release trace file
  259          */
  260         p->p_traceflag = 0;     /* don't trace the vrele() */
  261         if (p->p_tracep)
  262                 vrele(p->p_tracep);
  263 #endif
  264         /*
  265          * Remove proc from allproc queue and pidhash chain.
  266          * Place onto zombproc.  Unlink from parent's child list.
  267          */
  268         LIST_REMOVE(p, p_list);
  269         LIST_INSERT_HEAD(&zombproc, p, p_list);
  270         p->p_stat = SZOMB;
  271 
  272         LIST_REMOVE(p, p_hash);
  273 
  274         q = p->p_children.lh_first;
  275         if (q)          /* only need this if any child is S_ZOMB */
  276                 wakeup((caddr_t) initproc);
  277         for (; q != 0; q = nq) {
  278                 nq = q->p_sibling.le_next;
  279                 LIST_REMOVE(q, p_sibling);
  280                 LIST_INSERT_HEAD(&initproc->p_children, q, p_sibling);
  281                 q->p_pptr = initproc;
  282                 q->p_sigparent = SIGCHLD;
  283                 /*
  284                  * Traced processes are killed
  285                  * since their existence means someone is screwing up.
  286                  */
  287                 if (q->p_flag & P_TRACED) {
  288                         q->p_flag &= ~P_TRACED;
  289                         psignal(q, SIGKILL);
  290                 }
  291         }
  292 
  293         /*
  294          * Save exit status and final rusage info, adding in child rusage
  295          * info and self times.
  296          */
  297         p->p_xstat = rv;
  298         *p->p_ru = p->p_stats->p_ru;
  299         calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL);
  300         ruadd(p->p_ru, &p->p_stats->p_cru);
  301 
  302         /*
  303          * Notify parent that we're gone.  If parent has the P_NOCLDWAIT
  304          * flag set, notify process 1 instead (and hope it will handle
  305          * this situation).
  306          */
  307         if (p->p_pptr->p_procsig->ps_flag & P_NOCLDWAIT) {
  308                 struct proc *pp = p->p_pptr;
  309                 proc_reparent(p, initproc);
  310                 /*
  311                  * If this was the last child of our parent, notify
  312                  * parent, so in case he was wait(2)ing, he will
  313                  * continue.
  314                  */
  315                 if (LIST_EMPTY(&pp->p_children))
  316                         wakeup((caddr_t)pp);
  317         }
  318 
  319         if (p->p_sigparent && p->p_pptr != initproc) {
  320                 psignal(p->p_pptr, p->p_sigparent);
  321         } else {
  322                 psignal(p->p_pptr, SIGCHLD);
  323         }
  324 
  325         wakeup((caddr_t)p->p_pptr);
  326 #if defined(tahoe)
  327         /* move this to cpu_exit */
  328         p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
  329 #endif
  330         /*
  331          * Clear curproc after we've done all operations
  332          * that could block, and before tearing down the rest
  333          * of the process state that might be used from clock, etc.
  334          * Also, can't clear curproc while we're still runnable,
  335          * as we're not on a run queue (we are current, just not
  336          * a proper proc any longer!).
  337          *
  338          * Other substructures are freed from wait().
  339          */
  340         curproc = NULL;
  341         if (--p->p_limit->p_refcnt == 0) {
  342                 FREE(p->p_limit, M_SUBPROC);
  343                 p->p_limit = NULL;
  344         }
  345 
  346         /*
  347          * Finally, call machine-dependent code to release the remaining
  348          * resources including address space, the kernel stack and pcb.
  349          * The address space is released by "vmspace_free(p->p_vmspace)";
  350          * This is machine-dependent, as we may have to change stacks
  351          * or ensure that the current one isn't reallocated before we
  352          * finish.  cpu_exit will end with a call to cpu_switch(), finishing
  353          * our execution (pun intended).
  354          */
  355         cpu_exit(p);
  356 }
  357 
  358 #ifdef COMPAT_43
  359 #if defined(hp300) || defined(luna68k)
  360 #include <machine/frame.h>
  361 #define GETPS(rp)       ((struct frame *)(rp))->f_sr
  362 #else
  363 #define GETPS(rp)       (rp)[PS]
  364 #endif
  365 
  366 int
  367 owait(p, uap)
  368         struct proc *p;
  369         register struct owait_args /* {
  370                 int     dummy;
  371         } */ *uap;
  372 {
  373         struct wait_args w;
  374 
  375 #ifdef PSL_ALLCC
  376         if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) {
  377                 w.options = 0;
  378                 w.rusage = NULL;
  379         } else {
  380                 w.options = p->p_md.md_regs[R0];
  381                 w.rusage = (struct rusage *)p->p_md.md_regs[R1];
  382         }
  383 #else
  384         w.options = 0;
  385         w.rusage = NULL;
  386 #endif
  387         w.pid = WAIT_ANY;
  388         w.status = NULL;
  389         return (wait1(p, &w, 1));
  390 }
  391 #endif /* COMPAT_43 */
  392 
  393 int
  394 wait4(p, uap)
  395         struct proc *p;
  396         struct wait_args *uap;
  397 {
  398 
  399         return (wait1(p, uap, 0));
  400 }
  401 
  402 static int
  403 wait1(q, uap, compat)
  404         register struct proc *q;
  405         register struct wait_args /* {
  406                 int pid;
  407                 int *status;
  408                 int options;
  409                 struct rusage *rusage;
  410         } */ *uap;
  411         int compat;
  412 {
  413         register int nfound;
  414         register struct proc *p, *t;
  415         int status, error;
  416 
  417         if (uap->pid == 0)
  418                 uap->pid = -q->p_pgid;
  419         if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE))
  420                 return (EINVAL);
  421 loop:
  422         nfound = 0;
  423         for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) {
  424                 if (uap->pid != WAIT_ANY &&
  425                     p->p_pid != uap->pid && p->p_pgid != -uap->pid)
  426                         continue;
  427 
  428                 /* This special case handles a kthread spawned by linux_clone 
  429                  * (see linux_misc.c).  The linux_wait4 and linux_waitpid functions
  430                  * need to be able to distinguish between waiting on a process and
  431                  * waiting on a thread.  It is a thread if p_sigparent is not SIGCHLD,
  432                  * and the WLINUXCLONE option signifies we want to wait for threads
  433                  * and not processes.
  434                  */
  435                 if ((p->p_sigparent != SIGCHLD) ^ ((uap->options & WLINUXCLONE) != 0))
  436                         continue;
  437 
  438                 nfound++;
  439                 if (p->p_stat == SZOMB) {
  440                         /* charge childs scheduling cpu usage to parent */
  441                         if (curproc->p_pid != 1) {
  442                                 curproc->p_estcpu = min(curproc->p_estcpu +
  443                                     p->p_estcpu, UCHAR_MAX);
  444                         }
  445 
  446                         q->p_retval[0] = p->p_pid;
  447 #ifdef COMPAT_43
  448                         if (compat)
  449                                 q->p_retval[1] = p->p_xstat;
  450                         else
  451 #endif
  452                         if (uap->status) {
  453                                 status = p->p_xstat;    /* convert to int */
  454                                 if ((error = copyout((caddr_t)&status,
  455                                     (caddr_t)uap->status, sizeof(status))))
  456                                         return (error);
  457                         }
  458                         if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
  459                             (caddr_t)uap->rusage, sizeof (struct rusage))))
  460                                 return (error);
  461                         /*
  462                          * If we got the child via a ptrace 'attach',
  463                          * we need to give it back to the old parent.
  464                          */
  465                         if (p->p_oppid && (t = pfind(p->p_oppid))) {
  466                                 p->p_oppid = 0;
  467                                 proc_reparent(p, t);
  468                                 psignal(t, SIGCHLD);
  469                                 wakeup((caddr_t)t);
  470                                 return (0);
  471                         }
  472                         p->p_xstat = 0;
  473                         ruadd(&q->p_stats->p_cru, p->p_ru);
  474                         FREE(p->p_ru, M_ZOMBIE);
  475                         p->p_ru = NULL;
  476 
  477                         /*
  478                          * Decrement the count of procs running with this uid.
  479                          */
  480                         (void)chgproccnt(p->p_cred->p_ruid, -1);
  481 
  482                         /*
  483                          * Release reference to text vnode
  484                          */
  485                         if (p->p_textvp)
  486                                 vrele(p->p_textvp);
  487 
  488                         /*
  489                          * Free up credentials.
  490                          */
  491                         if (--p->p_cred->p_refcnt == 0) {
  492                                 crfree(p->p_cred->pc_ucred);
  493                                 FREE(p->p_cred, M_SUBPROC);
  494                                 p->p_cred = NULL;
  495                         }
  496 
  497                         /*
  498                          * Finally finished with old proc entry.
  499                          * Unlink it from its process group and free it.
  500                          */
  501                         leavepgrp(p);
  502                         LIST_REMOVE(p, p_list); /* off zombproc */
  503                         LIST_REMOVE(p, p_sibling);
  504 
  505                         if (--p->p_procsig->ps_refcnt == 0) {
  506                                 if (p->p_sigacts != &p->p_addr->u_sigacts)
  507                                         FREE(p->p_sigacts, M_SUBPROC);
  508                                 FREE(p->p_procsig, M_SUBPROC);
  509                                 p->p_procsig = NULL;
  510                         }
  511 
  512                         /*
  513                          * Give machine-dependent layer a chance
  514                          * to free anything that cpu_exit couldn't
  515                          * release while still running in process context.
  516                          */
  517                         cpu_wait(p);
  518                         zfree(proc_zone, p);
  519                         nprocs--;
  520                         return (0);
  521                 }
  522                 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
  523                     (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
  524                         p->p_flag |= P_WAITED;
  525                         q->p_retval[0] = p->p_pid;
  526 #ifdef COMPAT_43
  527                         if (compat) {
  528                                 q->p_retval[1] = W_STOPCODE(p->p_xstat);
  529                                 error = 0;
  530                         } else
  531 #endif
  532                         if (uap->status) {
  533                                 status = W_STOPCODE(p->p_xstat);
  534                                 error = copyout((caddr_t)&status,
  535                                         (caddr_t)uap->status, sizeof(status));
  536                         } else
  537                                 error = 0;
  538                         return (error);
  539                 }
  540         }
  541         if (nfound == 0)
  542                 return (ECHILD);
  543         if (uap->options & WNOHANG) {
  544                 q->p_retval[0] = 0;
  545                 return (0);
  546         }
  547         if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)))
  548                 return (error);
  549         goto loop;
  550 }
  551 
  552 /*
  553  * make process 'parent' the new parent of process 'child'.
  554  */
  555 void
  556 proc_reparent(child, parent)
  557         register struct proc *child;
  558         register struct proc *parent;
  559 {
  560 
  561         if (child->p_pptr == parent)
  562                 return;
  563 
  564         LIST_REMOVE(child, p_sibling);
  565         LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
  566         child->p_pptr = parent;
  567 }
  568 
  569 /*
  570  * The next two functions are to handle adding/deleting items on the
  571  * exit callout list
  572  * 
  573  * at_exit():
  574  * Take the arguments given and put them onto the exit callout list,
  575  * However first make sure that it's not already there.
  576  * returns 0 on success.
  577  */
  578 int
  579 at_exit(function)
  580         exitlist_fn function;
  581 {
  582         ele_p ep;
  583 
  584         /* Be noisy if the programmer has lost track of things */
  585         if (rm_at_exit(function)) 
  586                 printf("exit callout entry already present\n");
  587         ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
  588         if (ep == NULL)
  589                 return (ENOMEM);
  590         ep->next = exit_list;
  591         ep->function = function;
  592         exit_list = ep;
  593         return (0);
  594 }
  595 /*
  596  * Scan the exit callout list for the given items and remove them.
  597  * Returns the number of items removed.
  598  * Logically this can only be 0 or 1.
  599  */
  600 int
  601 rm_at_exit(function)
  602         exitlist_fn function;
  603 {
  604         ele_p *epp, ep;
  605         int count;
  606 
  607         count = 0;
  608         epp = &exit_list;
  609         ep = *epp;
  610         while (ep) {
  611                 if (ep->function == function) {
  612                         *epp = ep->next;
  613                         free(ep, M_TEMP);
  614                         count++;
  615                 } else {
  616                         epp = &ep->next;
  617                 }
  618                 ep = *epp;
  619         }
  620         return (count);
  621 }
  622 
  623 void check_sigacts (void)
  624 {
  625         struct proc *p = curproc;
  626         struct sigacts *pss;
  627         int s;
  628 
  629         if (p->p_procsig->ps_refcnt == 1 &&
  630             p->p_sigacts != &p->p_addr->u_sigacts) {
  631                 pss = p->p_sigacts;
  632                 s = splhigh();
  633                 p->p_addr->u_sigacts = *pss;
  634                 p->p_sigacts = &p->p_addr->u_sigacts;
  635                 splx(s);
  636                 FREE(pss, M_SUBPROC);
  637         }
  638 }
  639 

Cache object: 556db4d4a12ec7c0076db8d546228aba


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.