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_lwp.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 /*      $NetBSD: kern_lwp.c,v 1.49.2.1 2007/04/01 16:16:20 bouyer Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Nathan J. Williams.
    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 NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.49.2.1 2007/04/01 16:16:20 bouyer Exp $");
   41 
   42 #include "opt_multiprocessor.h"
   43 
   44 #define _LWP_API_PRIVATE
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/pool.h>
   49 #include <sys/lock.h>
   50 #include <sys/proc.h>
   51 #include <sys/sa.h>
   52 #include <sys/savar.h>
   53 #include <sys/types.h>
   54 #include <sys/ucontext.h>
   55 #include <sys/resourcevar.h>
   56 #include <sys/mount.h>
   57 #include <sys/syscallargs.h>
   58 #include <sys/kauth.h>
   59 
   60 #include <uvm/uvm_extern.h>
   61 
   62 POOL_INIT(lwp_pool, sizeof(struct lwp), 0, 0, 0, "lwppl",
   63     &pool_allocator_nointr);
   64 POOL_INIT(lwp_uc_pool, sizeof(ucontext_t), 0, 0, 0, "lwpucpl",
   65     &pool_allocator_nointr);
   66 
   67 static specificdata_domain_t lwp_specificdata_domain;
   68 
   69 struct lwplist alllwp;
   70 
   71 #define LWP_DEBUG
   72 
   73 #ifdef LWP_DEBUG
   74 int lwp_debug = 0;
   75 #define DPRINTF(x) if (lwp_debug) printf x
   76 #else
   77 #define DPRINTF(x)
   78 #endif
   79 
   80 void
   81 lwpinit(void)
   82 {
   83 
   84         lwp_specificdata_domain = specificdata_domain_create();
   85         KASSERT(lwp_specificdata_domain != NULL);
   86 }
   87 
   88 /* ARGSUSED */
   89 int
   90 sys__lwp_create(struct lwp *l, void *v, register_t *retval)
   91 {
   92         struct sys__lwp_create_args /* {
   93                 syscallarg(const ucontext_t *) ucp;
   94                 syscallarg(u_long) flags;
   95                 syscallarg(lwpid_t *) new_lwp;
   96         } */ *uap = v;
   97         struct proc *p = l->l_proc;
   98         struct lwp *l2;
   99         vaddr_t uaddr;
  100         boolean_t inmem;
  101         ucontext_t *newuc;
  102         int s, error;
  103 
  104         if (p->p_flag & P_SA)
  105                 return EINVAL;
  106 
  107         newuc = pool_get(&lwp_uc_pool, PR_WAITOK);
  108 
  109         error = copyin(SCARG(uap, ucp), newuc,
  110             l->l_proc->p_emul->e_sa->sae_ucsize);
  111         if (error) {
  112                 pool_put(&lwp_uc_pool, newuc);
  113                 return (error);
  114         }
  115 
  116         /* XXX check against resource limits */
  117 
  118         inmem = uvm_uarea_alloc(&uaddr);
  119         if (__predict_false(uaddr == 0)) {
  120                 pool_put(&lwp_uc_pool, newuc);
  121                 return (ENOMEM);
  122         }
  123 
  124         /* XXX flags:
  125          * __LWP_ASLWP is probably needed for Solaris compat.
  126          */
  127 
  128         newlwp(l, p, uaddr, inmem,
  129             SCARG(uap, flags) & LWP_DETACHED,
  130             NULL, 0, startlwp, newuc, &l2);
  131 
  132         if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0) {
  133                 SCHED_LOCK(s);
  134                 l2->l_stat = LSRUN;
  135                 setrunqueue(l2);
  136                 p->p_nrlwps++;
  137                 SCHED_UNLOCK(s);
  138         } else {
  139                 l2->l_stat = LSSUSPENDED;
  140         }
  141 
  142         error = copyout(&l2->l_lid, SCARG(uap, new_lwp),
  143             sizeof(l2->l_lid));
  144         if (error) {
  145                 /* XXX We should destroy the LWP. */
  146                 return (error);
  147         }
  148 
  149         return (0);
  150 }
  151 
  152 
  153 int
  154 sys__lwp_exit(struct lwp *l, void *v, register_t *retval)
  155 {
  156 
  157         lwp_exit(l);
  158         /* NOTREACHED */
  159         return (0);
  160 }
  161 
  162 
  163 int
  164 sys__lwp_self(struct lwp *l, void *v, register_t *retval)
  165 {
  166 
  167         *retval = l->l_lid;
  168 
  169         return (0);
  170 }
  171 
  172 
  173 int
  174 sys__lwp_getprivate(struct lwp *l, void *v, register_t *retval)
  175 {
  176 
  177         *retval = (uintptr_t) l->l_private;
  178 
  179         return (0);
  180 }
  181 
  182 
  183 int
  184 sys__lwp_setprivate(struct lwp *l, void *v, register_t *retval)
  185 {
  186         struct sys__lwp_setprivate_args /* {
  187                 syscallarg(void *) ptr;
  188         } */ *uap = v;
  189 
  190         l->l_private = SCARG(uap, ptr);
  191 
  192         return (0);
  193 }
  194 
  195 
  196 int
  197 sys__lwp_suspend(struct lwp *l, void *v, register_t *retval)
  198 {
  199         struct sys__lwp_suspend_args /* {
  200                 syscallarg(lwpid_t) target;
  201         } */ *uap = v;
  202         int target_lid;
  203         struct proc *p = l->l_proc;
  204         struct lwp *t;
  205         struct lwp *t2;
  206 
  207         if (p->p_flag & P_SA)
  208                 return EINVAL;
  209 
  210         target_lid = SCARG(uap, target);
  211 
  212         LIST_FOREACH(t, &p->p_lwps, l_sibling)
  213                 if (t->l_lid == target_lid)
  214                         break;
  215 
  216         if (t == NULL)
  217                 return (ESRCH);
  218 
  219         if (t == l) {
  220                 /*
  221                  * Check for deadlock, which is only possible
  222                  * when we're suspending ourself.
  223                  */
  224                 LIST_FOREACH(t2, &p->p_lwps, l_sibling) {
  225                         if ((t2 != l) && (t2->l_stat != LSSUSPENDED))
  226                                 break;
  227                 }
  228 
  229                 if (t2 == NULL) /* All other LWPs are suspended */
  230                         return (EDEADLK);
  231         }
  232 
  233         return lwp_suspend(l, t);
  234 }
  235 
  236 inline int
  237 lwp_suspend(struct lwp *l, struct lwp *t)
  238 {
  239         struct proc *p = t->l_proc;
  240         int s;
  241 
  242         if (t == l) {
  243                 SCHED_LOCK(s);
  244                 KASSERT(l->l_stat == LSONPROC);
  245                 l->l_stat = LSSUSPENDED;
  246                 p->p_nrlwps--;
  247                 /* XXX NJWLWP check if this makes sense here: */
  248                 p->p_stats->p_ru.ru_nvcsw++;
  249                 mi_switch(l, NULL);
  250                 SCHED_ASSERT_UNLOCKED();
  251                 splx(s);
  252         } else {
  253                 switch (t->l_stat) {
  254                 case LSSUSPENDED:
  255                         return (0); /* _lwp_suspend() is idempotent */
  256                 case LSRUN:
  257                         SCHED_LOCK(s);
  258                         remrunqueue(t);
  259                         t->l_stat = LSSUSPENDED;
  260                         p->p_nrlwps--;
  261                         SCHED_UNLOCK(s);
  262                         break;
  263                 case LSSLEEP:
  264                         t->l_stat = LSSUSPENDED;
  265                         break;
  266                 case LSIDL:
  267                 case LSZOMB:
  268                         return (EINTR); /* It's what Solaris does..... */
  269                 case LSSTOP:
  270                         panic("_lwp_suspend: Stopped LWP in running process!");
  271                         break;
  272                 case LSONPROC:
  273                         /* XXX multiprocessor LWPs? Implement me! */
  274                         return (EINVAL);
  275                 }
  276         }
  277 
  278         return (0);
  279 }
  280 
  281 
  282 int
  283 sys__lwp_continue(struct lwp *l, void *v, register_t *retval)
  284 {
  285         struct sys__lwp_continue_args /* {
  286                 syscallarg(lwpid_t) target;
  287         } */ *uap = v;
  288         int s, target_lid;
  289         struct proc *p = l->l_proc;
  290         struct lwp *t;
  291 
  292         if (p->p_flag & P_SA)
  293                 return EINVAL;
  294 
  295         target_lid = SCARG(uap, target);
  296 
  297         LIST_FOREACH(t, &p->p_lwps, l_sibling)
  298                 if (t->l_lid == target_lid)
  299                         break;
  300 
  301         if (t == NULL)
  302                 return (ESRCH);
  303 
  304         SCHED_LOCK(s);
  305         lwp_continue(t);
  306         SCHED_UNLOCK(s);
  307 
  308         return (0);
  309 }
  310 
  311 void
  312 lwp_continue(struct lwp *l)
  313 {
  314 
  315         DPRINTF(("lwp_continue of %d.%d (%s), state %d, wchan %p\n",
  316             l->l_proc->p_pid, l->l_lid, l->l_proc->p_comm, l->l_stat,
  317             l->l_wchan));
  318 
  319         if (l->l_stat != LSSUSPENDED)
  320                 return;
  321 
  322         if (l->l_wchan == 0) {
  323                 /* LWP was runnable before being suspended. */
  324                 setrunnable(l);
  325         } else {
  326                 /* LWP was sleeping before being suspended. */
  327                 l->l_stat = LSSLEEP;
  328         }
  329 }
  330 
  331 int
  332 sys__lwp_wakeup(struct lwp *l, void *v, register_t *retval)
  333 {
  334         struct sys__lwp_wakeup_args /* {
  335                 syscallarg(lwpid_t) target;
  336         } */ *uap = v;
  337         lwpid_t target_lid;
  338         struct lwp *t;
  339         struct proc *p;
  340         int error;
  341         int s;
  342 
  343         p = l->l_proc;
  344         target_lid = SCARG(uap, target);
  345 
  346         SCHED_LOCK(s);
  347 
  348         LIST_FOREACH(t, &p->p_lwps, l_sibling)
  349                 if (t->l_lid == target_lid)
  350                         break;
  351 
  352         if (t == NULL) {
  353                 error = ESRCH;
  354                 goto exit;
  355         }
  356 
  357         if (t->l_stat != LSSLEEP) {
  358                 error = ENODEV;
  359                 goto exit;
  360         }
  361 
  362         if ((t->l_flag & L_SINTR) == 0) {
  363                 error = EBUSY;
  364                 goto exit;
  365         }
  366         /*
  367          * Tell ltsleep to wakeup.
  368          */
  369         t->l_flag |= L_CANCELLED;
  370 
  371         setrunnable(t);
  372         error = 0;
  373 exit:
  374         SCHED_UNLOCK(s);
  375 
  376         return error;
  377 }
  378 
  379 int
  380 sys__lwp_wait(struct lwp *l, void *v, register_t *retval)
  381 {
  382         struct sys__lwp_wait_args /* {
  383                 syscallarg(lwpid_t) wait_for;
  384                 syscallarg(lwpid_t *) departed;
  385         } */ *uap = v;
  386         int error;
  387         lwpid_t dep;
  388 
  389         error = lwp_wait1(l, SCARG(uap, wait_for), &dep, 0);
  390         if (error)
  391                 return (error);
  392 
  393         if (SCARG(uap, departed)) {
  394                 error = copyout(&dep, SCARG(uap, departed),
  395                     sizeof(dep));
  396                 if (error)
  397                         return (error);
  398         }
  399 
  400         return (0);
  401 }
  402 
  403 
  404 int
  405 lwp_wait1(struct lwp *l, lwpid_t lid, lwpid_t *departed, int flags)
  406 {
  407         struct proc *p = l->l_proc;
  408         struct lwp *l2, *l3;
  409         int nfound, error, wpri;
  410         static const char waitstr1[] = "lwpwait";
  411         static const char waitstr2[] = "lwpwait2";
  412 
  413         DPRINTF(("lwp_wait1: %d.%d waiting for %d.\n",
  414             p->p_pid, l->l_lid, lid));
  415 
  416         if (lid == l->l_lid)
  417                 return (EDEADLK); /* Waiting for ourselves makes no sense. */
  418 
  419         wpri = PWAIT |
  420             ((flags & LWPWAIT_EXITCONTROL) ? PNOEXITERR : PCATCH);
  421  loop:
  422         nfound = 0;
  423         LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
  424                 if ((l2 == l) || (l2->l_flag & L_DETACHED) ||
  425                     ((lid != 0) && (lid != l2->l_lid)))
  426                         continue;
  427 
  428                 nfound++;
  429                 if (l2->l_stat == LSZOMB) {
  430                         if (departed)
  431                                 *departed = l2->l_lid;
  432 
  433                         simple_lock(&p->p_lock);
  434                         LIST_REMOVE(l2, l_sibling);
  435                         p->p_nlwps--;
  436                         p->p_nzlwps--;
  437                         simple_unlock(&p->p_lock);
  438                         /* XXX decrement limits */
  439 
  440                         pool_put(&lwp_pool, l2);
  441 
  442                         return (0);
  443                 } else if (l2->l_stat == LSSLEEP ||
  444                            l2->l_stat == LSSUSPENDED) {
  445                         /* Deadlock checks.
  446                          * 1. If all other LWPs are waiting for exits
  447                          *    or suspended, we would deadlock.
  448                          */
  449 
  450                         LIST_FOREACH(l3, &p->p_lwps, l_sibling) {
  451                                 if (l3 != l && (l3->l_stat != LSSUSPENDED) &&
  452                                     !(l3->l_stat == LSSLEEP &&
  453                                         l3->l_wchan == (caddr_t) &p->p_nlwps))
  454                                         break;
  455                         }
  456                         if (l3 == NULL) /* Everyone else is waiting. */
  457                                 return (EDEADLK);
  458 
  459                         /* XXX we'd like to check for a cycle of waiting
  460                          * LWPs (specific LID waits, not any-LWP waits)
  461                          * and detect that sort of deadlock, but we don't
  462                          * have a good place to store the lwp that is
  463                          * being waited for. wchan is already filled with
  464                          * &p->p_nlwps, and putting the lwp address in
  465                          * there for deadlock tracing would require
  466                          * exiting LWPs to call wakeup on both their
  467                          * own address and &p->p_nlwps, to get threads
  468                          * sleeping on any LWP exiting.
  469                          *
  470                          * Revisit later. Maybe another auxillary
  471                          * storage location associated with sleeping
  472                          * is in order.
  473                          */
  474                 }
  475         }
  476 
  477         if (nfound == 0)
  478                 return (ESRCH);
  479 
  480         if ((error = tsleep((caddr_t) &p->p_nlwps, wpri,
  481             (lid != 0) ? waitstr1 : waitstr2, 0)) != 0)
  482                 return (error);
  483 
  484         goto loop;
  485 }
  486 
  487 
  488 int
  489 newlwp(struct lwp *l1, struct proc *p2, vaddr_t uaddr, boolean_t inmem,
  490     int flags, void *stack, size_t stacksize,
  491     void (*func)(void *), void *arg, struct lwp **rnewlwpp)
  492 {
  493         struct lwp *l2;
  494         int s;
  495 
  496         l2 = pool_get(&lwp_pool, PR_WAITOK);
  497 
  498         l2->l_stat = LSIDL;
  499         l2->l_forw = l2->l_back = NULL;
  500         l2->l_proc = p2;
  501 
  502         lwp_initspecific(l2);
  503 
  504         memset(&l2->l_startzero, 0,
  505                (unsigned) ((caddr_t)&l2->l_endzero -
  506                            (caddr_t)&l2->l_startzero));
  507         memcpy(&l2->l_startcopy, &l1->l_startcopy,
  508                (unsigned) ((caddr_t)&l2->l_endcopy -
  509                            (caddr_t)&l2->l_startcopy));
  510 
  511 #if !defined(MULTIPROCESSOR)
  512         /*
  513          * In the single-processor case, all processes will always run
  514          * on the same CPU.  So, initialize the child's CPU to the parent's
  515          * now.  In the multiprocessor case, the child's CPU will be
  516          * initialized in the low-level context switch code when the
  517          * process runs.
  518          */
  519         KASSERT(l1->l_cpu != NULL);
  520         l2->l_cpu = l1->l_cpu;
  521 #else
  522         /*
  523          * zero child's CPU pointer so we don't get trash.
  524          */
  525         l2->l_cpu = NULL;
  526 #endif /* ! MULTIPROCESSOR */
  527 
  528         l2->l_flag = inmem ? L_INMEM : 0;
  529         l2->l_flag |= (flags & LWP_DETACHED) ? L_DETACHED : 0;
  530 
  531         lwp_update_creds(l2);
  532         callout_init(&l2->l_tsleep_ch);
  533 
  534         if (rnewlwpp != NULL)
  535                 *rnewlwpp = l2;
  536 
  537         l2->l_addr = UAREA_TO_USER(uaddr);
  538         uvm_lwp_fork(l1, l2, stack, stacksize, func,
  539             (arg != NULL) ? arg : l2);
  540 
  541         simple_lock(&p2->p_lock);
  542         l2->l_lid = ++p2->p_nlwpid;
  543         LIST_INSERT_HEAD(&p2->p_lwps, l2, l_sibling);
  544         p2->p_nlwps++;
  545         simple_unlock(&p2->p_lock);
  546 
  547         /* XXX should be locked differently... */
  548         s = proclist_lock_write();
  549         LIST_INSERT_HEAD(&alllwp, l2, l_list);
  550         proclist_unlock_write(s);
  551 
  552         if (p2->p_emul->e_lwp_fork)
  553                 (*p2->p_emul->e_lwp_fork)(l1, l2);
  554 
  555         return (0);
  556 }
  557 
  558 
  559 /*
  560  * Quit the process. This will call cpu_exit, which will call cpu_switch,
  561  * so this can only be used meaningfully if you're willing to switch away.
  562  * Calling with l!=curlwp would be weird.
  563  */
  564 void
  565 lwp_exit(struct lwp *l)
  566 {
  567         struct proc *p = l->l_proc;
  568         int s;
  569 
  570         DPRINTF(("lwp_exit: %d.%d exiting.\n", p->p_pid, l->l_lid));
  571         DPRINTF((" nlwps: %d nrlwps %d nzlwps: %d\n",
  572             p->p_nlwps, p->p_nrlwps, p->p_nzlwps));
  573 
  574         if (p->p_emul->e_lwp_exit)
  575                 (*p->p_emul->e_lwp_exit)(l);
  576 
  577         /*
  578          * If we are the last live LWP in a process, we need to exit
  579          * the entire process (if that's not already going on). We do
  580          * so with an exit status of zero, because it's a "controlled"
  581          * exit, and because that's what Solaris does.
  582          *
  583          * Note: the last LWP's specificdata will be deleted here.
  584          */
  585         if (((p->p_nlwps - p->p_nzlwps) == 1) && ((p->p_flag & P_WEXIT) == 0)) {
  586                 DPRINTF(("lwp_exit: %d.%d calling exit1()\n",
  587                     p->p_pid, l->l_lid));
  588                 exit1(l, 0);
  589                 /* NOTREACHED */
  590         }
  591 
  592         /* Delete the specificdata while it's still safe to sleep. */
  593         specificdata_fini(lwp_specificdata_domain, &l->l_specdataref);
  594 
  595         s = proclist_lock_write();
  596         LIST_REMOVE(l, l_list);
  597         proclist_unlock_write(s);
  598 
  599         /*
  600          * Release our cached credentials, and collate accounting flags.
  601          */
  602         kauth_cred_free(l->l_cred);
  603         simple_lock(&p->p_lock);
  604         p->p_acflag |= l->l_acflag;
  605         simple_unlock(&p->p_lock);
  606 
  607         /* Free MD LWP resources */
  608 #ifndef __NO_CPU_LWP_FREE
  609         cpu_lwp_free(l, 0);
  610 #endif
  611 
  612         pmap_deactivate(l);
  613 
  614         if (l->l_flag & L_DETACHED) {
  615                 simple_lock(&p->p_lock);
  616                 LIST_REMOVE(l, l_sibling);
  617                 p->p_nlwps--;
  618                 simple_unlock(&p->p_lock);
  619 
  620                 curlwp = NULL;
  621                 l->l_proc = NULL;
  622         }
  623 
  624         SCHED_LOCK(s);
  625         p->p_nrlwps--;
  626         l->l_stat = LSDEAD;
  627         SCHED_UNLOCK(s);
  628 
  629         /* This LWP no longer needs to hold the kernel lock. */
  630         KERNEL_PROC_UNLOCK(l);
  631 
  632         /* cpu_exit() will not return */
  633         cpu_exit(l);
  634 }
  635 
  636 /*
  637  * We are called from cpu_exit() once it is safe to schedule the
  638  * dead process's resources to be freed (i.e., once we've switched to
  639  * the idle PCB for the current CPU).
  640  *
  641  * NOTE: One must be careful with locking in this routine.  It's
  642  * called from a critical section in machine-dependent code, so
  643  * we should refrain from changing any interrupt state.
  644  */
  645 void
  646 lwp_exit2(struct lwp *l)
  647 {
  648         struct proc *p;
  649 
  650         KERNEL_LOCK(LK_EXCLUSIVE);
  651         /*
  652          * Free the VM resources we're still holding on to.
  653          */
  654         uvm_lwp_exit(l);
  655 
  656         if (l->l_flag & L_DETACHED) {
  657                 /* Nobody waits for detached LWPs. */
  658                 pool_put(&lwp_pool, l);
  659                 KERNEL_UNLOCK();
  660         } else {
  661                 l->l_stat = LSZOMB;
  662                 p = l->l_proc;
  663                 p->p_nzlwps++;
  664                 wakeup(&p->p_nlwps);
  665                 KERNEL_UNLOCK();
  666         }
  667 }
  668 
  669 /*
  670  * Pick a LWP to represent the process for those operations which
  671  * want information about a "process" that is actually associated
  672  * with a LWP.
  673  */
  674 struct lwp *
  675 proc_representative_lwp(struct proc *p)
  676 {
  677         struct lwp *l, *onproc, *running, *sleeping, *stopped, *suspended;
  678         struct lwp *signalled;
  679 
  680         /* Trivial case: only one LWP */
  681         if (p->p_nlwps == 1)
  682                 return (LIST_FIRST(&p->p_lwps));
  683 
  684         switch (p->p_stat) {
  685         case SSTOP:
  686         case SACTIVE:
  687                 /* Pick the most live LWP */
  688                 onproc = running = sleeping = stopped = suspended = NULL;
  689                 signalled = NULL;
  690                 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
  691                         if (l->l_lid == p->p_sigctx.ps_lwp)
  692                                 signalled = l;
  693                         switch (l->l_stat) {
  694                         case LSONPROC:
  695                                 onproc = l;
  696                                 break;
  697                         case LSRUN:
  698                                 running = l;
  699                                 break;
  700                         case LSSLEEP:
  701                                 sleeping = l;
  702                                 break;
  703                         case LSSTOP:
  704                                 stopped = l;
  705                                 break;
  706                         case LSSUSPENDED:
  707                                 suspended = l;
  708                                 break;
  709                         }
  710                 }
  711                 if (signalled)
  712                         return signalled;
  713                 if (onproc)
  714                         return onproc;
  715                 if (running)
  716                         return running;
  717                 if (sleeping)
  718                         return sleeping;
  719                 if (stopped)
  720                         return stopped;
  721                 if (suspended)
  722                         return suspended;
  723                 break;
  724         case SZOMB:
  725                 /* Doesn't really matter... */
  726                 return (LIST_FIRST(&p->p_lwps));
  727 #ifdef DIAGNOSTIC
  728         case SDYING:
  729         case SIDL:
  730                 /* We have more than one LWP and we're in SIDL?
  731                  * How'd that happen?
  732                  */
  733                 panic("Too many LWPs (%d) in SIDL process %d (%s)",
  734                     p->p_nrlwps, p->p_pid, p->p_comm);
  735         default:
  736                 panic("Process %d (%s) in unknown state %d",
  737                     p->p_pid, p->p_comm, p->p_stat);
  738 #endif
  739         }
  740 
  741         panic("proc_representative_lwp: couldn't find a lwp for process"
  742                 " %d (%s)", p->p_pid, p->p_comm);
  743         /* NOTREACHED */
  744         return NULL;
  745 }
  746 
  747 /*
  748  * Update an LWP's cached credentials to mirror the process' master copy.
  749  *
  750  * This happens early in the syscall path, on user trap, and on LWP
  751  * creation.  A long-running LWP can also voluntarily choose to update
  752  * it's credentials by calling this routine.  This may be called from
  753  * LWP_CACHE_CREDS(), which checks l->l_cred != p->p_cred beforehand.
  754  */
  755 void
  756 lwp_update_creds(struct lwp *l)
  757 {
  758         kauth_cred_t oc;
  759         struct proc *p;
  760 
  761         p = l->l_proc;
  762         oc = l->l_cred;
  763 
  764         simple_lock(&p->p_lock);
  765         kauth_cred_hold(p->p_cred);
  766         l->l_cred = p->p_cred;
  767         simple_unlock(&p->p_lock);
  768         if (oc != NULL)
  769                 kauth_cred_free(oc);
  770 }
  771 
  772 /*
  773  * lwp_specific_key_create --
  774  *      Create a key for subsystem lwp-specific data.
  775  */
  776 int
  777 lwp_specific_key_create(specificdata_key_t *keyp, specificdata_dtor_t dtor)
  778 {
  779 
  780         return (specificdata_key_create(lwp_specificdata_domain, keyp, dtor));
  781 }
  782 
  783 /*
  784  * lwp_specific_key_delete --
  785  *      Delete a key for subsystem lwp-specific data.
  786  */
  787 void
  788 lwp_specific_key_delete(specificdata_key_t key)
  789 {
  790 
  791         specificdata_key_delete(lwp_specificdata_domain, key);
  792 }
  793 
  794 /*
  795  * lwp_initspecific --
  796  *      Initialize an LWP's specificdata container.
  797  */
  798 void
  799 lwp_initspecific(struct lwp *l)
  800 {
  801         int error;
  802 
  803         error = specificdata_init(lwp_specificdata_domain, &l->l_specdataref);
  804         KASSERT(error == 0);
  805 }
  806 
  807 /*
  808  * lwp_finispecific --
  809  *      Finalize an LWP's specificdata container.
  810  */
  811 void
  812 lwp_finispecific(struct lwp *l)
  813 {
  814 
  815         specificdata_fini(lwp_specificdata_domain, &l->l_specdataref);
  816 }
  817 
  818 /*
  819  * lwp_getspecific --
  820  *      Return lwp-specific data corresponding to the specified key.
  821  *
  822  *      Note: LWP specific data is NOT INTERLOCKED.  An LWP should access
  823  *      only its OWN SPECIFIC DATA.  If it is necessary to access another
  824  *      LWP's specifc data, care must be taken to ensure that doing so
  825  *      would not cause internal data structure inconsistency (i.e. caller
  826  *      can guarantee that the target LWP is not inside an lwp_getspecific()
  827  *      or lwp_setspecific() call).
  828  */
  829 void *
  830 lwp_getspecific(specificdata_key_t key)
  831 {
  832 
  833         return (specificdata_getspecific_unlocked(lwp_specificdata_domain,
  834                                                   &curlwp->l_specdataref, key));
  835 }
  836 
  837 void *
  838 _lwp_getspecific_by_lwp(struct lwp *l, specificdata_key_t key)
  839 {
  840 
  841         return (specificdata_getspecific_unlocked(lwp_specificdata_domain,
  842                                                   &l->l_specdataref, key));
  843 }
  844 
  845 /*
  846  * lwp_setspecific --
  847  *      Set lwp-specific data corresponding to the specified key.
  848  */
  849 void
  850 lwp_setspecific(specificdata_key_t key, void *data)
  851 {
  852 
  853         specificdata_setspecific(lwp_specificdata_domain,
  854                                  &curlwp->l_specdataref, key, data);
  855 }

Cache object: a90e2f5e6d6da81955d0794b6ea8caad


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