[BACK]Return to kern_lwp.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_lwp.c, Revision 1.17

1.17    ! manu        1: /*     $NetBSD: kern_lwp.c,v 1.16 2003/12/20 18:22:17 manu Exp $       */
1.2       thorpej     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:  */
1.9       lukem      38:
                     39: #include <sys/cdefs.h>
1.17    ! manu       40: __KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.16 2003/12/20 18:22:17 manu Exp $");
1.8       martin     41:
                     42: #include "opt_multiprocessor.h"
1.2       thorpej    43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/pool.h>
                     47: #include <sys/lock.h>
                     48: #include <sys/proc.h>
                     49: #include <sys/sa.h>
                     50: #include <sys/savar.h>
                     51: #include <sys/types.h>
                     52: #include <sys/ucontext.h>
                     53: #include <sys/resourcevar.h>
                     54: #include <sys/mount.h>
                     55: #include <sys/syscallargs.h>
                     56:
                     57: #include <uvm/uvm_extern.h>
                     58:
                     59: struct lwplist alllwp;
                     60: struct lwplist deadlwp;
                     61: struct lwplist zomblwp;
                     62:
                     63: #define LWP_DEBUG
                     64:
                     65: #ifdef LWP_DEBUG
                     66: int lwp_debug = 0;
                     67: #define DPRINTF(x) if (lwp_debug) printf x
                     68: #else
                     69: #define DPRINTF(x)
                     70: #endif
                     71: /* ARGSUSED */
                     72: int
                     73: sys__lwp_create(struct lwp *l, void *v, register_t *retval)
                     74: {
                     75:        struct sys__lwp_create_args /* {
                     76:                syscallarg(const ucontext_t *) ucp;
                     77:                syscallarg(u_long) flags;
                     78:                syscallarg(lwpid_t *) new_lwp;
                     79:        } */ *uap = v;
                     80:        struct proc *p = l->l_proc;
                     81:        struct lwp *l2;
                     82:        vaddr_t uaddr;
                     83:        boolean_t inmem;
                     84:        ucontext_t *newuc;
                     85:        int s, error;
                     86:
                     87:        newuc = pool_get(&lwp_uc_pool, PR_WAITOK);
                     88:
                     89:        error = copyin(SCARG(uap, ucp), newuc, sizeof(*newuc));
                     90:        if (error)
                     91:                return (error);
                     92:
                     93:        /* XXX check against resource limits */
                     94:
                     95:        inmem = uvm_uarea_alloc(&uaddr);
                     96:        if (__predict_false(uaddr == 0)) {
                     97:                return (ENOMEM);
                     98:        }
                     99:
                    100:        /* XXX flags:
                    101:         * __LWP_ASLWP is probably needed for Solaris compat.
                    102:         */
                    103:
                    104:        newlwp(l, p, uaddr, inmem,
                    105:            SCARG(uap, flags) & LWP_DETACHED,
1.7       kristerw  106:            NULL, 0, startlwp, newuc, &l2);
1.2       thorpej   107:
                    108:        if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0) {
                    109:                SCHED_LOCK(s);
                    110:                l2->l_stat = LSRUN;
                    111:                setrunqueue(l2);
                    112:                SCHED_UNLOCK(s);
1.15      dsl       113:                simple_lock(&p->p_lock);
1.2       thorpej   114:                p->p_nrlwps++;
1.15      dsl       115:                simple_unlock(&p->p_lock);
1.2       thorpej   116:        } else {
                    117:                l2->l_stat = LSSUSPENDED;
                    118:        }
                    119:
                    120:        error = copyout(&l2->l_lid, SCARG(uap, new_lwp),
                    121:            sizeof(l2->l_lid));
                    122:        if (error)
                    123:                return (error);
                    124:
                    125:        return (0);
                    126: }
                    127:
                    128:
                    129: int
                    130: sys__lwp_exit(struct lwp *l, void *v, register_t *retval)
                    131: {
                    132:
                    133:        lwp_exit(l);
                    134:        /* NOTREACHED */
                    135:        return (0);
                    136: }
                    137:
                    138:
                    139: int
                    140: sys__lwp_self(struct lwp *l, void *v, register_t *retval)
                    141: {
                    142:
                    143:        *retval = l->l_lid;
                    144:
                    145:        return (0);
                    146: }
                    147:
                    148:
                    149: int
                    150: sys__lwp_getprivate(struct lwp *l, void *v, register_t *retval)
                    151: {
                    152:
                    153:        *retval = (uintptr_t) l->l_private;
                    154:
                    155:        return (0);
                    156: }
                    157:
                    158:
                    159: int
                    160: sys__lwp_setprivate(struct lwp *l, void *v, register_t *retval)
                    161: {
                    162:        struct sys__lwp_setprivate_args /* {
                    163:                syscallarg(void *) ptr;
                    164:        } */ *uap = v;
                    165:
                    166:        l->l_private = SCARG(uap, ptr);
                    167:
                    168:        return (0);
                    169: }
                    170:
                    171:
                    172: int
                    173: sys__lwp_suspend(struct lwp *l, void *v, register_t *retval)
                    174: {
                    175:        struct sys__lwp_suspend_args /* {
                    176:                syscallarg(lwpid_t) target;
                    177:        } */ *uap = v;
                    178:        int target_lid;
                    179:        struct proc *p = l->l_proc;
1.17    ! manu      180:        struct lwp *t;
        !           181:        struct lwp *t2;
1.2       thorpej   182:
                    183:        target_lid = SCARG(uap, target);
                    184:
                    185:        LIST_FOREACH(t, &p->p_lwps, l_sibling)
                    186:                if (t->l_lid == target_lid)
                    187:                        break;
                    188:
                    189:        if (t == NULL)
                    190:                return (ESRCH);
                    191:
                    192:        if (t == l) {
                    193:                /*
                    194:                 * Check for deadlock, which is only possible
                    195:                 * when we're suspending ourself.
                    196:                 */
                    197:                LIST_FOREACH(t2, &p->p_lwps, l_sibling) {
                    198:                        if ((t2 != l) && (t2->l_stat != LSSUSPENDED))
                    199:                                break;
                    200:                }
                    201:
                    202:                if (t2 == NULL) /* All other LWPs are suspended */
                    203:                        return (EDEADLK);
1.17    ! manu      204:        }
        !           205:
        !           206:        return lwp_suspend(l, t);
        !           207: }
1.2       thorpej   208:
1.17    ! manu      209: inline int
        !           210: lwp_suspend(l, t)
        !           211:        struct lwp *l;
        !           212:        struct lwp *t;
        !           213: {
        !           214:        struct proc *p = t->l_proc;
        !           215:        int s;
        !           216:
        !           217:        if (t == l) {
1.2       thorpej   218:                SCHED_LOCK(s);
                    219:                l->l_stat = LSSUSPENDED;
                    220:                /* XXX NJWLWP check if this makes sense here: */
1.17    ! manu      221:                p->p_stats->p_ru.ru_nvcsw++;
1.2       thorpej   222:                mi_switch(l, NULL);
                    223:                SCHED_ASSERT_UNLOCKED();
                    224:                splx(s);
                    225:        } else {
                    226:                switch (t->l_stat) {
                    227:                case LSSUSPENDED:
                    228:                        return (0); /* _lwp_suspend() is idempotent */
                    229:                case LSRUN:
                    230:                        SCHED_LOCK(s);
                    231:                        remrunqueue(t);
                    232:                        t->l_stat = LSSUSPENDED;
                    233:                        SCHED_UNLOCK(s);
1.15      dsl       234:                        simple_lock(&p->p_lock);
1.2       thorpej   235:                        p->p_nrlwps--;
1.15      dsl       236:                        simple_unlock(&p->p_lock);
1.2       thorpej   237:                        break;
                    238:                case LSSLEEP:
                    239:                        t->l_stat = LSSUSPENDED;
                    240:                        break;
                    241:                case LSIDL:
                    242:                case LSDEAD:
                    243:                case LSZOMB:
                    244:                        return (EINTR); /* It's what Solaris does..... */
                    245:                case LSSTOP:
                    246:                        panic("_lwp_suspend: Stopped LWP in running process!");
                    247:                        break;
                    248:                case LSONPROC:
                    249:                        panic("XXX multiprocessor LWPs? Implement me!");
                    250:                        break;
                    251:                }
                    252:        }
                    253:
                    254:        return (0);
                    255: }
                    256:
                    257:
                    258: int
                    259: sys__lwp_continue(struct lwp *l, void *v, register_t *retval)
                    260: {
                    261:        struct sys__lwp_continue_args /* {
                    262:                syscallarg(lwpid_t) target;
                    263:        } */ *uap = v;
1.14      cl        264:        int s, target_lid;
1.2       thorpej   265:        struct proc *p = l->l_proc;
                    266:        struct lwp *t;
                    267:
                    268:        target_lid = SCARG(uap, target);
                    269:
                    270:        LIST_FOREACH(t, &p->p_lwps, l_sibling)
                    271:                if (t->l_lid == target_lid)
                    272:                        break;
                    273:
                    274:        if (t == NULL)
                    275:                return (ESRCH);
                    276:
1.14      cl        277:        SCHED_LOCK(s);
1.2       thorpej   278:        lwp_continue(t);
1.14      cl        279:        SCHED_UNLOCK(s);
1.2       thorpej   280:
                    281:        return (0);
                    282: }
                    283:
                    284: void
                    285: lwp_continue(struct lwp *l)
                    286: {
                    287:
                    288:        DPRINTF(("lwp_continue of %d.%d (%s), state %d, wchan %p\n",
                    289:            l->l_proc->p_pid, l->l_lid, l->l_proc->p_comm, l->l_stat,
                    290:            l->l_wchan));
                    291:
                    292:        if (l->l_stat != LSSUSPENDED)
                    293:                return;
                    294:
                    295:        if (l->l_wchan == 0) {
                    296:                /* LWP was runnable before being suspended. */
                    297:                setrunnable(l);
                    298:        } else {
                    299:                /* LWP was sleeping before being suspended. */
                    300:                l->l_stat = LSSLEEP;
                    301:        }
                    302: }
                    303:
                    304: int
                    305: sys__lwp_wakeup(struct lwp *l, void *v, register_t *retval)
                    306: {
                    307:        struct sys__lwp_wakeup_args /* {
                    308:                syscallarg(lwpid_t) wakeup;
                    309:        } */ *uap = v;
                    310:        lwpid_t target_lid;
                    311:        struct lwp *t;
                    312:        struct proc *p;
1.10      fvdl      313:        int error;
                    314:        int s;
1.2       thorpej   315:
                    316:        p = l->l_proc;
                    317:        target_lid = SCARG(uap, target);
                    318:
1.10      fvdl      319:        SCHED_LOCK(s);
                    320:
                    321:
1.2       thorpej   322:        LIST_FOREACH(t, &p->p_lwps, l_sibling)
                    323:                if (t->l_lid == target_lid)
                    324:                        break;
                    325:
1.10      fvdl      326:        if (t == NULL) {
                    327:                error = ESRCH;
                    328:                goto exit;
                    329:        }
1.2       thorpej   330:
1.10      fvdl      331:        if (t->l_stat != LSSLEEP) {
                    332:                error = ENODEV;
                    333:                goto exit;
                    334:        }
1.2       thorpej   335:
1.10      fvdl      336:        if ((t->l_flag & L_SINTR) == 0) {
                    337:                error = EBUSY;
                    338:                goto exit;
                    339:        }
1.12      matt      340:        /*
                    341:         * Tell ltsleep to wakeup.
                    342:         */
                    343:        t->l_flag |= L_CANCELLED;
1.2       thorpej   344:
1.4       nathanw   345:        setrunnable(t);
1.10      fvdl      346:        error = 0;
                    347: exit:
                    348:        SCHED_UNLOCK(s);
                    349:
1.2       thorpej   350:
1.11      fvdl      351:        return error;
1.2       thorpej   352: }
                    353:
                    354: int
                    355: sys__lwp_wait(struct lwp *l, void *v, register_t *retval)
                    356: {
                    357:        struct sys__lwp_wait_args /* {
                    358:                syscallarg(lwpid_t) wait_for;
                    359:                syscallarg(lwpid_t *) departed;
                    360:        } */ *uap = v;
                    361:        int error;
                    362:        lwpid_t dep;
                    363:
                    364:        error = lwp_wait1(l, SCARG(uap, wait_for), &dep, 0);
                    365:        if (error)
                    366:                return (error);
                    367:
                    368:        if (SCARG(uap, departed)) {
                    369:                error = copyout(&dep, SCARG(uap, departed),
                    370:                    sizeof(dep));
                    371:                if (error)
                    372:                        return (error);
                    373:        }
                    374:
                    375:        return (0);
                    376: }
                    377:
                    378:
                    379: int
                    380: lwp_wait1(struct lwp *l, lwpid_t lid, lwpid_t *departed, int flags)
                    381: {
                    382:
                    383:        struct proc *p = l->l_proc;
                    384:        struct lwp *l2, *l3;
                    385:        int nfound, error, s, wpri;
                    386:        static char waitstr1[] = "lwpwait";
                    387:        static char waitstr2[] = "lwpwait2";
                    388:
                    389:        DPRINTF(("lwp_wait1: %d.%d waiting for %d.\n",
                    390:            p->p_pid, l->l_lid, lid));
                    391:
                    392:        if (lid == l->l_lid)
                    393:                return (EDEADLK); /* Waiting for ourselves makes no sense. */
                    394:
                    395:        wpri = PWAIT |
                    396:            ((flags & LWPWAIT_EXITCONTROL) ? PNOEXITERR : PCATCH);
                    397:  loop:
                    398:        nfound = 0;
                    399:        LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
                    400:                if ((l2 == l) || (l2->l_flag & L_DETACHED) ||
                    401:                    ((lid != 0) && (lid != l2->l_lid)))
                    402:                        continue;
                    403:
                    404:                nfound++;
                    405:                if (l2->l_stat == LSZOMB) {
                    406:                        if (departed)
                    407:                                *departed = l2->l_lid;
                    408:
                    409:                        s = proclist_lock_write();
                    410:                        LIST_REMOVE(l2, l_zlist); /* off zomblwp */
                    411:                        proclist_unlock_write(s);
                    412:
1.15      dsl       413:                        simple_lock(&p->p_lock);
1.2       thorpej   414:                        LIST_REMOVE(l2, l_sibling);
                    415:                        p->p_nlwps--;
                    416:                        p->p_nzlwps--;
1.15      dsl       417:                        simple_unlock(&p->p_lock);
1.2       thorpej   418:                        /* XXX decrement limits */
                    419:
                    420:                        pool_put(&lwp_pool, l2);
                    421:
                    422:                        return (0);
                    423:                } else if (l2->l_stat == LSSLEEP ||
                    424:                           l2->l_stat == LSSUSPENDED) {
                    425:                        /* Deadlock checks.
                    426:                         * 1. If all other LWPs are waiting for exits
                    427:                         *    or suspended, we would deadlock.
                    428:                         */
                    429:
                    430:                        LIST_FOREACH(l3, &p->p_lwps, l_sibling) {
                    431:                                if (l3 != l && (l3->l_stat != LSSUSPENDED) &&
                    432:                                    !(l3->l_stat == LSSLEEP &&
                    433:                                        l3->l_wchan == (caddr_t) &p->p_nlwps))
                    434:                                        break;
                    435:                        }
                    436:                        if (l3 == NULL) /* Everyone else is waiting. */
                    437:                                return (EDEADLK);
                    438:
                    439:                        /* XXX we'd like to check for a cycle of waiting
                    440:                         * LWPs (specific LID waits, not any-LWP waits)
                    441:                         * and detect that sort of deadlock, but we don't
                    442:                         * have a good place to store the lwp that is
                    443:                         * being waited for. wchan is already filled with
                    444:                         * &p->p_nlwps, and putting the lwp address in
                    445:                         * there for deadlock tracing would require
                    446:                         * exiting LWPs to call wakeup on both their
                    447:                         * own address and &p->p_nlwps, to get threads
                    448:                         * sleeping on any LWP exiting.
                    449:                         *
                    450:                         * Revisit later. Maybe another auxillary
                    451:                         * storage location associated with sleeping
                    452:                         * is in order.
                    453:                         */
                    454:                }
                    455:        }
                    456:
                    457:        if (nfound == 0)
                    458:                return (ESRCH);
                    459:
                    460:        if ((error = tsleep((caddr_t) &p->p_nlwps, wpri,
                    461:            (lid != 0) ? waitstr1 : waitstr2, 0)) != 0)
                    462:                return (error);
                    463:
                    464:        goto loop;
                    465: }
                    466:
                    467:
                    468: int
                    469: newlwp(struct lwp *l1, struct proc *p2, vaddr_t uaddr, boolean_t inmem,
                    470:     int flags, void *stack, size_t stacksize,
                    471:     void (*func)(void *), void *arg, struct lwp **rnewlwpp)
                    472: {
                    473:        struct lwp *l2;
                    474:        int s;
                    475:
                    476:        l2 = pool_get(&lwp_pool, PR_WAITOK);
                    477:
                    478:        l2->l_stat = LSIDL;
                    479:        l2->l_forw = l2->l_back = NULL;
                    480:        l2->l_proc = p2;
                    481:
                    482:
                    483:        memset(&l2->l_startzero, 0,
                    484:               (unsigned) ((caddr_t)&l2->l_endzero -
                    485:                           (caddr_t)&l2->l_startzero));
                    486:        memcpy(&l2->l_startcopy, &l1->l_startcopy,
                    487:               (unsigned) ((caddr_t)&l2->l_endcopy -
                    488:                           (caddr_t)&l2->l_startcopy));
                    489:
                    490: #if !defined(MULTIPROCESSOR)
                    491:        /*
                    492:         * In the single-processor case, all processes will always run
                    493:         * on the same CPU.  So, initialize the child's CPU to the parent's
                    494:         * now.  In the multiprocessor case, the child's CPU will be
                    495:         * initialized in the low-level context switch code when the
                    496:         * process runs.
                    497:         */
1.5       matt      498:        KASSERT(l1->l_cpu != NULL);
1.2       thorpej   499:        l2->l_cpu = l1->l_cpu;
                    500: #else
                    501:        /*
                    502:         * zero child's cpu pointer so we don't get trash.
                    503:         */
                    504:        l2->l_cpu = NULL;
                    505: #endif /* ! MULTIPROCESSOR */
                    506:
                    507:        l2->l_flag = inmem ? L_INMEM : 0;
                    508:        l2->l_flag |= (flags & LWP_DETACHED) ? L_DETACHED : 0;
                    509:
                    510:        callout_init(&l2->l_tsleep_ch);
                    511:
                    512:        if (rnewlwpp != NULL)
                    513:                *rnewlwpp = l2;
                    514:
                    515:        l2->l_addr = (struct user *)uaddr;
                    516:        uvm_lwp_fork(l1, l2, stack, stacksize, func,
                    517:            (arg != NULL) ? arg : l2);
                    518:
                    519:
1.15      dsl       520:        simple_lock(&p2->p_lock);
1.2       thorpej   521:        l2->l_lid = ++p2->p_nlwpid;
                    522:        LIST_INSERT_HEAD(&p2->p_lwps, l2, l_sibling);
                    523:        p2->p_nlwps++;
1.15      dsl       524:        simple_unlock(&p2->p_lock);
1.2       thorpej   525:
                    526:        /* XXX should be locked differently... */
                    527:        s = proclist_lock_write();
                    528:        LIST_INSERT_HEAD(&alllwp, l2, l_list);
                    529:        proclist_unlock_write(s);
                    530:
1.16      manu      531:        if (p2->p_emul->e_lwp_fork)
                    532:                (*p2->p_emul->e_lwp_fork)(l1, l2);
                    533:
1.2       thorpej   534:        return (0);
                    535: }
                    536:
                    537:
                    538: /*
                    539:  * Quit the process. This will call cpu_exit, which will call cpu_switch,
                    540:  * so this can only be used meaningfully if you're willing to switch away.
                    541:  * Calling with l!=curlwp would be weird.
                    542:  */
                    543: void
                    544: lwp_exit(struct lwp *l)
                    545: {
                    546:        struct proc *p = l->l_proc;
                    547:        int s;
                    548:
                    549:        DPRINTF(("lwp_exit: %d.%d exiting.\n", p->p_pid, l->l_lid));
                    550:        DPRINTF((" nlwps: %d nrlwps %d nzlwps: %d\n",
                    551:            p->p_nlwps, p->p_nrlwps, p->p_nzlwps));
                    552:
1.16      manu      553:        if (p->p_emul->e_lwp_exit)
                    554:                (*p->p_emul->e_lwp_exit)(l);
                    555:
1.2       thorpej   556:        /*
                    557:         * If we are the last live LWP in a process, we need to exit
                    558:         * the entire process (if that's not already going on). We do
                    559:         * so with an exit status of zero, because it's a "controlled"
                    560:         * exit, and because that's what Solaris does.
                    561:         */
                    562:        if (((p->p_nlwps - p->p_nzlwps) == 1) && ((p->p_flag & P_WEXIT) == 0)) {
                    563:                DPRINTF(("lwp_exit: %d.%d calling exit1()\n",
                    564:                    p->p_pid, l->l_lid));
                    565:                exit1(l, 0);
                    566:        }
                    567:
                    568:        s = proclist_lock_write();
                    569:        LIST_REMOVE(l, l_list);
                    570:        if ((l->l_flag & L_DETACHED) == 0) {
                    571:                DPRINTF(("lwp_exit: %d.%d going on zombie list\n", p->p_pid,
                    572:                    l->l_lid));
                    573:                LIST_INSERT_HEAD(&zomblwp, l, l_zlist);
                    574:        }
                    575:        proclist_unlock_write(s);
                    576:
1.15      dsl       577:        simple_lock(&p->p_lock);
1.2       thorpej   578:        p->p_nrlwps--;
1.15      dsl       579:        simple_unlock(&p->p_lock);
1.2       thorpej   580:
                    581:        l->l_stat = LSDEAD;
                    582:
                    583:        /* This LWP no longer needs to hold the kernel lock. */
                    584:        KERNEL_PROC_UNLOCK(l);
                    585:
                    586:        /* cpu_exit() will not return */
                    587:        cpu_exit(l, 0);
                    588:
                    589: }
                    590:
                    591:
                    592: void
                    593: lwp_exit2(struct lwp *l)
                    594: {
                    595:
                    596:        simple_lock(&deadproc_slock);
                    597:        LIST_INSERT_HEAD(&deadlwp, l, l_list);
                    598:        simple_unlock(&deadproc_slock);
                    599:
1.6       dsl       600:        wakeup(&deadprocs);
1.2       thorpej   601: }
                    602:
                    603: /*
                    604:  * Pick a LWP to represent the process for those operations which
                    605:  * want information about a "process" that is actually associated
                    606:  * with a LWP.
                    607:  */
                    608: struct lwp *
                    609: proc_representative_lwp(p)
                    610:        struct proc *p;
                    611: {
                    612:        struct lwp *l, *onproc, *running, *sleeping, *stopped, *suspended;
                    613:
                    614:        /* Trivial case: only one LWP */
                    615:        if (p->p_nlwps == 1)
                    616:                return (LIST_FIRST(&p->p_lwps));
                    617:
                    618:        switch (p->p_stat) {
                    619:        case SSTOP:
                    620:        case SACTIVE:
                    621:                /* Pick the most live LWP */
                    622:                onproc = running = sleeping = stopped = suspended = NULL;
                    623:                LIST_FOREACH(l, &p->p_lwps, l_sibling) {
                    624:                        switch (l->l_stat) {
                    625:                        case LSONPROC:
                    626:                                onproc = l;
                    627:                                break;
                    628:                        case LSRUN:
                    629:                                running = l;
                    630:                                break;
                    631:                        case LSSLEEP:
                    632:                                sleeping = l;
                    633:                                break;
                    634:                        case LSSTOP:
                    635:                                stopped = l;
                    636:                                break;
                    637:                        case LSSUSPENDED:
                    638:                                suspended = l;
                    639:                                break;
                    640:                        }
                    641:                }
1.3       nathanw   642:                if (onproc)
                    643:                        return onproc;
                    644:                if (running)
                    645:                        return running;
                    646:                if (sleeping)
                    647:                        return sleeping;
                    648:                if (stopped)
                    649:                        return stopped;
                    650:                if (suspended)
                    651:                        return suspended;
1.2       thorpej   652:                break;
                    653:        case SDEAD:
                    654:        case SZOMB:
                    655:                /* Doesn't really matter... */
                    656:                return (LIST_FIRST(&p->p_lwps));
                    657: #ifdef DIAGNOSTIC
                    658:        case SIDL:
                    659:                /* We have more than one LWP and we're in SIDL?
                    660:                 * How'd that happen?
                    661:                 */
                    662:                panic("Too many LWPs (%d) in SIDL process %d (%s)",
                    663:                    p->p_nrlwps, p->p_pid, p->p_comm);
                    664:        default:
                    665:                panic("Process %d (%s) in unknown state %d",
                    666:                    p->p_pid, p->p_comm, p->p_stat);
                    667: #endif
                    668:        }
                    669:
                    670:        panic("proc_representative_lwp: couldn't find a lwp for process"
                    671:                " %d (%s)", p->p_pid, p->p_comm);
                    672:        /* NOTREACHED */
                    673:        return NULL;
                    674: }

CVSweb <webmaster@jp.NetBSD.org>