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/sys_process.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) 1994, Sean Eric Fagan
    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 Sean Eric Fagan.
   16  * 4. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/sysproto.h>
   37 #include <sys/proc.h>
   38 #include <sys/vnode.h>
   39 #include <sys/ptrace.h>
   40 
   41 #include <machine/reg.h>
   42 #include <vm/vm.h>
   43 #include <sys/lock.h>
   44 #include <vm/pmap.h>
   45 #include <vm/vm_map.h>
   46 #include <vm/vm_page.h>
   47 
   48 #include <sys/user.h>
   49 #include <miscfs/procfs/procfs.h>
   50 
   51 /* use the equivalent procfs code */
   52 #if 0
   53 static int
   54 pread (struct proc *procp, unsigned int addr, unsigned int *retval) {
   55         int             rv;
   56         vm_map_t        map, tmap;
   57         vm_object_t     object;
   58         vm_offset_t     kva = 0;
   59         int             page_offset;    /* offset into page */
   60         vm_offset_t     pageno;         /* page number */
   61         vm_map_entry_t  out_entry;
   62         vm_prot_t       out_prot;
   63         boolean_t       wired;
   64         vm_pindex_t     pindex;
   65 
   66         /* Map page into kernel space */
   67 
   68         map = &procp->p_vmspace->vm_map;
   69 
   70         page_offset = addr - trunc_page(addr);
   71         pageno = trunc_page(addr);
   72 
   73         tmap = map;
   74         rv = vm_map_lookup (&tmap, pageno, VM_PROT_READ, &out_entry,
   75                 &object, &pindex, &out_prot, &wired);
   76 
   77         if (rv != KERN_SUCCESS)
   78                 return EINVAL;
   79 
   80         vm_map_lookup_done (tmap, out_entry);
   81 
   82         /* Find space in kernel_map for the page we're interested in */
   83         rv = vm_map_find (kernel_map, object, IDX_TO_OFF(pindex),
   84                 &kva, PAGE_SIZE, 0, VM_PROT_ALL, VM_PROT_ALL, 0);
   85 
   86         if (!rv) {
   87                 vm_object_reference (object);
   88 
   89                 rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
   90                 if (!rv) {
   91                         *retval = 0;
   92                         bcopy ((caddr_t)kva + page_offset,
   93                                retval, sizeof *retval);
   94                 }
   95                 vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
   96         }
   97 
   98         return rv;
   99 }
  100 
  101 static int
  102 pwrite (struct proc *procp, unsigned int addr, unsigned int datum) {
  103         int             rv;
  104         vm_map_t        map, tmap;
  105         vm_object_t     object;
  106         vm_offset_t     kva = 0;
  107         int             page_offset;    /* offset into page */
  108         vm_offset_t     pageno;         /* page number */
  109         vm_map_entry_t  out_entry;
  110         vm_prot_t       out_prot;
  111         boolean_t       wired;
  112         vm_pindex_t     pindex;
  113         boolean_t       fix_prot = 0;
  114 
  115         /* Map page into kernel space */
  116 
  117         map = &procp->p_vmspace->vm_map;
  118 
  119         page_offset = addr - trunc_page(addr);
  120         pageno = trunc_page(addr);
  121 
  122         /*
  123          * Check the permissions for the area we're interested in.
  124          */
  125 
  126         if (vm_map_check_protection (map, pageno, pageno + PAGE_SIZE,
  127                 VM_PROT_WRITE) == FALSE) {
  128                 /*
  129                  * If the page was not writable, we make it so.
  130                  * XXX It is possible a page may *not* be read/executable,
  131                  * if a process changes that!
  132                  */
  133                 fix_prot = 1;
  134                 /* The page isn't writable, so let's try making it so... */
  135                 if ((rv = vm_map_protect (map, pageno, pageno + PAGE_SIZE,
  136                         VM_PROT_ALL, 0)) != KERN_SUCCESS)
  137                   return EFAULT;        /* I guess... */
  138         }
  139 
  140         /*
  141          * Now we need to get the page.  out_entry, out_prot, wired, and
  142          * single_use aren't used.  One would think the vm code would be
  143          * a *bit* nicer...  We use tmap because vm_map_lookup() can
  144          * change the map argument.
  145          */
  146 
  147         tmap = map;
  148         rv = vm_map_lookup (&tmap, pageno, VM_PROT_WRITE, &out_entry,
  149                 &object, &pindex, &out_prot, &wired);
  150         if (rv != KERN_SUCCESS) {
  151                 return EINVAL;
  152         }
  153 
  154         /*
  155          * Okay, we've got the page.  Let's release tmap.
  156          */
  157 
  158         vm_map_lookup_done (tmap, out_entry);
  159 
  160         /*
  161          * Fault the page in...
  162          */
  163 
  164         rv = vm_fault(map, pageno, VM_PROT_WRITE|VM_PROT_READ, FALSE);
  165         if (rv != KERN_SUCCESS)
  166                 return EFAULT;
  167 
  168         /* Find space in kernel_map for the page we're interested in */
  169         rv = vm_map_find (kernel_map, object, IDX_TO_OFF(pindex),
  170                 &kva, PAGE_SIZE, 0,
  171                 VM_PROT_ALL, VM_PROT_ALL, 0);
  172         if (!rv) {
  173                 vm_object_reference (object);
  174 
  175                 rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
  176                 if (!rv) {
  177                   bcopy (&datum, (caddr_t)kva + page_offset, sizeof datum);
  178                 }
  179                 vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
  180         }
  181 
  182         if (fix_prot)
  183                 vm_map_protect (map, pageno, pageno + PAGE_SIZE,
  184                         VM_PROT_READ|VM_PROT_EXECUTE, 0);
  185         return rv;
  186 }
  187 #endif
  188 
  189 /*
  190  * Process debugging system call.
  191  */
  192 #ifndef _SYS_SYSPROTO_H_
  193 struct ptrace_args {
  194         int     req;
  195         pid_t   pid;
  196         caddr_t addr;
  197         int     data;
  198 };
  199 #endif
  200 
  201 int
  202 ptrace(struct proc *p, struct ptrace_args *uap)
  203 {
  204         /*
  205          * XXX this obfuscation is to reduce stack usage, but the register
  206          * structs may be too large to put on the stack anyway.
  207          */
  208         union {
  209                 struct ptrace_io_desc piod;
  210                 struct dbreg dbreg;
  211                 struct fpreg fpreg;
  212                 struct reg reg;
  213         } r;
  214         void *addr;
  215         int error = 0;
  216 
  217         addr = &r;
  218         switch (uap->req) {
  219         case PT_GETREGS:
  220         case PT_GETFPREGS:
  221 #ifdef PT_GETDBREGS
  222         case PT_GETDBREGS:
  223 #endif
  224                 break;
  225         case PT_SETREGS:
  226                 error = copyin(uap->addr, &r.reg, sizeof r.reg);
  227                 break;
  228         case PT_SETFPREGS:
  229                 error = copyin(uap->addr, &r.fpreg, sizeof r.fpreg);
  230                 break;
  231 #ifdef PT_SETDBREGS
  232         case PT_SETDBREGS:
  233                 error = copyin(uap->addr, &r.dbreg, sizeof r.dbreg);
  234                 break;
  235 #endif
  236         case PT_IO:
  237                 error = copyin(uap->addr, &r.piod, sizeof r.piod);
  238                 break;
  239         default:
  240                 addr = uap->addr;
  241         }
  242         if (error)
  243                 return (error);
  244 
  245         error = kern_ptrace(p, uap->req, uap->pid, addr, uap->data);
  246         if (error)
  247                 return (error);
  248 
  249         switch (uap->req) {
  250         case PT_IO:
  251                 (void)copyout(&r.piod, uap->addr, sizeof r.piod);
  252                 break;
  253         case PT_GETREGS:
  254                 error = copyout(&r.reg, uap->addr, sizeof r.reg);
  255                 break;
  256         case PT_GETFPREGS:
  257                 error = copyout(&r.fpreg, uap->addr, sizeof r.fpreg);
  258                 break;
  259 #ifdef PT_GETDBREGS
  260         case PT_GETDBREGS:
  261                 error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg);
  262                 break;
  263 #endif
  264         }
  265 
  266         return (error);
  267 }
  268 
  269 int
  270 kern_ptrace(struct proc *curp, int req, pid_t pid, void *addr, int data)
  271 {
  272         struct proc *p, *pp;
  273         struct iovec iov;
  274         struct uio uio;
  275         struct ptrace_io_desc *piod;
  276         int error = 0;
  277         int write, tmp, s;
  278 
  279         write = 0;
  280         if (req == PT_TRACE_ME)
  281                 p = curp;
  282         else {
  283                 if ((p = pfind(pid)) == NULL)
  284                         return ESRCH;
  285         }
  286         if (!PRISON_CHECK(curp, p))
  287                 return (ESRCH);
  288 
  289         /* Can't trace a process that's currently exec'ing. */
  290         if ((p->p_flag & P_INEXEC) != 0)
  291                 return EAGAIN;
  292 
  293         /*
  294          * Permissions check
  295          */
  296         switch (req) {
  297         case PT_TRACE_ME:
  298                 /* Always legal. */
  299                 break;
  300 
  301         case PT_ATTACH:
  302                 /* Self */
  303                 if (p->p_pid == curp->p_pid)
  304                         return EINVAL;
  305 
  306                 /* Already traced */
  307                 if (p->p_flag & P_TRACED)
  308                         return EBUSY;
  309 
  310                 if (curp->p_flag & P_TRACED)
  311                         for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr)
  312                                 if (pp == p)
  313                                         return (EINVAL);
  314 
  315                 /* not owned by you, has done setuid (unless you're root) */
  316                 if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||
  317                      (p->p_flag & P_SUGID)) {
  318                         if ((error = suser(curp)) != 0)
  319                                 return error;
  320                 }
  321 
  322                 /* can't trace init when securelevel > 0 */
  323                 if (securelevel > 0 && p->p_pid == 1)
  324                         return EPERM;
  325 
  326                 /* OK */
  327                 break;
  328 
  329         case PT_READ_I:
  330         case PT_READ_D:
  331         case PT_WRITE_I:
  332         case PT_WRITE_D:
  333         case PT_IO:
  334         case PT_CONTINUE:
  335         case PT_KILL:
  336         case PT_STEP:
  337         case PT_DETACH:
  338 #ifdef PT_GETREGS
  339         case PT_GETREGS:
  340 #endif
  341 #ifdef PT_SETREGS
  342         case PT_SETREGS:
  343 #endif
  344 #ifdef PT_GETFPREGS
  345         case PT_GETFPREGS:
  346 #endif
  347 #ifdef PT_SETFPREGS
  348         case PT_SETFPREGS:
  349 #endif
  350 #ifdef PT_GETDBREGS
  351         case PT_GETDBREGS:
  352 #endif
  353 #ifdef PT_SETDBREGS
  354         case PT_SETDBREGS:
  355 #endif
  356                 /* not being traced... */
  357                 if ((p->p_flag & P_TRACED) == 0)
  358                         return EPERM;
  359 
  360                 /* not being traced by YOU */
  361                 if (p->p_pptr != curp)
  362                         return EBUSY;
  363 
  364                 /* not currently stopped */
  365                 if (p->p_stat != SSTOP || (p->p_flag & P_WAITED) == 0)
  366                         return EBUSY;
  367 
  368                 /* OK */
  369                 break;
  370 
  371         default:
  372                 return EINVAL;
  373         }
  374 
  375 #ifdef FIX_SSTEP
  376         /*
  377          * Single step fixup ala procfs
  378          */
  379         FIX_SSTEP(p);
  380 #endif
  381 
  382         /*
  383          * Actually do the requests
  384          */
  385 
  386         curp->p_retval[0] = 0;
  387 
  388         switch (req) {
  389         case PT_TRACE_ME:
  390                 /* set my trace flag and "owner" so it can read/write me */
  391                 p->p_flag |= P_TRACED;
  392                 p->p_oppid = p->p_pptr->p_pid;
  393                 return 0;
  394 
  395         case PT_ATTACH:
  396                 /* security check done above */
  397                 p->p_flag |= P_TRACED;
  398                 p->p_oppid = p->p_pptr->p_pid;
  399                 if (p->p_pptr != curp)
  400                         proc_reparent(p, curp);
  401                 data = SIGSTOP;
  402                 goto sendsig;   /* in PT_CONTINUE below */
  403 
  404         case PT_STEP:
  405         case PT_CONTINUE:
  406         case PT_DETACH:
  407                 /* Zero means do not send any signal */
  408                 if (data < 0 || data > _SIG_MAXSIG)
  409                         return EINVAL;
  410 
  411                 PHOLD(p);
  412 
  413                 if (req == PT_STEP) {
  414                         if ((error = ptrace_single_step (p))) {
  415                                 PRELE(p);
  416                                 return error;
  417                         }
  418                 }
  419 
  420                 if (addr != (void *)1) {
  421                         if ((error = ptrace_set_pc (p,
  422                             (u_long)(uintfptr_t)addr))) {
  423                                 PRELE(p);
  424                                 return error;
  425                         }
  426                 }
  427                 PRELE(p);
  428 
  429                 if (req == PT_DETACH) {
  430                         /* reset process parent */
  431                         if (p->p_oppid != p->p_pptr->p_pid) {
  432                                 struct proc *pp;
  433 
  434                                 pp = pfind(p->p_oppid);
  435                                 proc_reparent(p, pp ? pp : initproc);
  436                                 if (pp == NULL)
  437                                         p->p_sigparent = SIGCHLD;
  438                         }
  439 
  440                         p->p_flag &= ~(P_TRACED | P_WAITED);
  441                         p->p_oppid = 0;
  442 
  443                         /* should we send SIGCHLD? */
  444                 }
  445 
  446         sendsig:
  447                 /* deliver or queue signal */
  448                 s = splhigh();
  449                 if (p->p_stat == SSTOP) {
  450                         p->p_xstat = data;
  451                         setrunnable(p);
  452                 } else if (data) {
  453                         psignal(p, data);
  454                 }
  455                 splx(s);
  456                 return 0;
  457 
  458         case PT_WRITE_I:
  459         case PT_WRITE_D:
  460                 write = 1;
  461                 /* fallthrough */
  462         case PT_READ_I:
  463         case PT_READ_D:
  464                 tmp = 0;
  465                 /* write = 0 set above */
  466                 iov.iov_base = write ? (caddr_t)&data : (caddr_t)&tmp;
  467                 iov.iov_len = sizeof(int);
  468                 uio.uio_iov = &iov;
  469                 uio.uio_iovcnt = 1;
  470                 uio.uio_offset = (off_t)(uintptr_t)addr;
  471                 uio.uio_resid = sizeof(int);
  472                 uio.uio_segflg = UIO_SYSSPACE;
  473                 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  474                 uio.uio_procp = p;
  475                 error = procfs_domem(curp, p, NULL, &uio);
  476                 if (uio.uio_resid != 0) {
  477                         /*
  478                          * XXX procfs_domem() doesn't currently return ENOSPC,
  479                          * so I think write() can bogusly return 0.
  480                          * XXX what happens for short writes?  We don't want
  481                          * to write partial data.
  482                          * XXX procfs_domem() returns EPERM for other invalid
  483                          * addresses.  Convert this to EINVAL.  Does this
  484                          * clobber returns of EPERM for other reasons?
  485                          */
  486                         if (error == 0 || error == ENOSPC || error == EPERM)
  487                                 error = EINVAL; /* EOF */
  488                 }
  489                 if (!write)
  490                         curp->p_retval[0] = tmp;
  491                 return (error);
  492 
  493         case PT_IO:
  494                 piod = addr;
  495                 iov.iov_base = piod->piod_addr;
  496                 iov.iov_len = piod->piod_len;
  497                 uio.uio_iov = &iov;
  498                 uio.uio_iovcnt = 1;
  499                 uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs;
  500                 uio.uio_resid = piod->piod_len;
  501                 uio.uio_segflg = UIO_USERSPACE;
  502                 uio.uio_procp = p;
  503                 switch (piod->piod_op) {
  504                 case PIOD_READ_D:
  505                 case PIOD_READ_I:
  506                         uio.uio_rw = UIO_READ;
  507                         break;
  508                 case PIOD_WRITE_D:
  509                 case PIOD_WRITE_I:
  510                         uio.uio_rw = UIO_WRITE;
  511                         break;
  512                 default:
  513                         return (EINVAL);
  514                 }
  515                 error = procfs_domem(curp, p, NULL, &uio);
  516                 piod->piod_len -= uio.uio_resid;
  517                 return (error);
  518 
  519         case PT_KILL:
  520                 data = SIGKILL;
  521                 goto sendsig;   /* in PT_CONTINUE above */
  522 
  523 #ifdef PT_SETREGS
  524         case PT_SETREGS:
  525                 write = 1;
  526                 /* fallthrough */
  527 #endif /* PT_SETREGS */
  528 #ifdef PT_GETREGS
  529         case PT_GETREGS:
  530                 /* write = 0 above */
  531 #endif /* PT_SETREGS */
  532 #if defined(PT_SETREGS) || defined(PT_GETREGS)
  533                 if (!procfs_validregs(p))       /* no P_SYSTEM procs please */
  534                         return EINVAL;
  535                 else {
  536                         iov.iov_base = addr;
  537                         iov.iov_len = sizeof(struct reg);
  538                         uio.uio_iov = &iov;
  539                         uio.uio_iovcnt = 1;
  540                         uio.uio_offset = 0;
  541                         uio.uio_resid = sizeof(struct reg);
  542                         uio.uio_segflg = UIO_SYSSPACE;
  543                         uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  544                         uio.uio_procp = curp;
  545                         return (procfs_doregs(curp, p, NULL, &uio));
  546                 }
  547 #endif /* defined(PT_SETREGS) || defined(PT_GETREGS) */
  548 
  549 #ifdef PT_SETFPREGS
  550         case PT_SETFPREGS:
  551                 write = 1;
  552                 /* fallthrough */
  553 #endif /* PT_SETFPREGS */
  554 #ifdef PT_GETFPREGS
  555         case PT_GETFPREGS:
  556                 /* write = 0 above */
  557 #endif /* PT_SETFPREGS */
  558 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
  559                 if (!procfs_validfpregs(p))     /* no P_SYSTEM procs please */
  560                         return EINVAL;
  561                 else {
  562                         iov.iov_base = addr;
  563                         iov.iov_len = sizeof(struct fpreg);
  564                         uio.uio_iov = &iov;
  565                         uio.uio_iovcnt = 1;
  566                         uio.uio_offset = 0;
  567                         uio.uio_resid = sizeof(struct fpreg);
  568                         uio.uio_segflg = UIO_SYSSPACE;
  569                         uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  570                         uio.uio_procp = curp;
  571                         return (procfs_dofpregs(curp, p, NULL, &uio));
  572                 }
  573 #endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */
  574 
  575 #ifdef PT_SETDBREGS
  576         case PT_SETDBREGS:
  577                 write = 1;
  578                 /* fallthrough */
  579 #endif /* PT_SETDBREGS */
  580 #ifdef PT_GETDBREGS
  581         case PT_GETDBREGS:
  582                 /* write = 0 above */
  583 #endif /* PT_SETDBREGS */
  584 #if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
  585                 if (!procfs_validdbregs(p))     /* no P_SYSTEM procs please */
  586                         return EINVAL;
  587                 else {
  588                         iov.iov_base = addr;
  589                         iov.iov_len = sizeof(struct dbreg);
  590                         uio.uio_iov = &iov;
  591                         uio.uio_iovcnt = 1;
  592                         uio.uio_offset = 0;
  593                         uio.uio_resid = sizeof(struct dbreg);
  594                         uio.uio_segflg = UIO_SYSSPACE;
  595                         uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  596                         uio.uio_procp = curp;
  597                         return (procfs_dodbregs(curp, p, NULL, &uio));
  598                 }
  599 #endif /* defined(PT_SETDBREGS) || defined(PT_GETDBREGS) */
  600 
  601         default:
  602                 break;
  603         }
  604 
  605         return 0;
  606 }
  607 
  608 int
  609 trace_req(p)
  610         struct proc *p;
  611 {
  612         return 1;
  613 }
  614 
  615 /*
  616  * stopevent()
  617  * Stop a process because of a procfs event;
  618  * stay stopped until p->p_step is cleared
  619  * (cleared by PIOCCONT in procfs).
  620  */
  621 
  622 void
  623 stopevent(struct proc *p, unsigned int event, unsigned int val) {
  624         p->p_step = 1;
  625 
  626         do {
  627                 p->p_xstat = val;
  628                 p->p_stype = event;     /* Which event caused the stop? */
  629                 wakeup(&p->p_stype);    /* Wake up any PIOCWAIT'ing procs */
  630                 tsleep(&p->p_step, PWAIT, "stopevent", 0);
  631         } while (p->p_step);
  632 }

Cache object: d206a14bbf3b7062d3ecc24f916d3a95


[ 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.