[BACK]Return to pthread_dbg.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libpthread_dbg

Annotation of src/lib/libpthread_dbg/pthread_dbg.c, Revision 1.5

1.5     ! lukem       1: /*     $NetBSD: pthread_dbg.c,v 1.4 2003/02/27 00:54:07 nathanw Exp $  */
1.2       thorpej     2:
                      3: /*-
                      4:  * Copyright (c) 2002 Wasabi Systems, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Nathan J. Williams for Wasabi Systems, Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed for the NetBSD Project by
                     20:  *      Wasabi Systems, Inc.
                     21:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific
                     23:  *    prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
1.5     ! lukem      37:
        !            38: #include <sys/cdefs.h>
        !            39: __RCSID("$NetBSD$");
1.2       thorpej    40:
                     41: #include <stddef.h>
                     42: #include <stdlib.h>
                     43: #include <string.h>
                     44: #include <errno.h>
                     45: #include <sys/types.h>
                     46: #include <unistd.h>
                     47:
                     48: #include <pthread.h>
                     49: #include <pthread_int.h>
                     50: #include <pthread_dbg.h>
                     51: #include <pthread_dbg_int.h>
                     52: #include <machine/reg.h>
                     53:
1.4       nathanw    54: #define MIN(a,b)       ((a)<(b) ? (a) : (b))
                     55:
1.2       thorpej    56: static int td__getthread(td_proc_t *proc, caddr_t addr, td_thread_t **threadp);
                     57: static int td__getsync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp);
                     58:
                     59: int
                     60: td_open(struct td_proc_callbacks_t *cb, void *arg, td_proc_t **procp)
                     61: {
                     62:        td_proc_t *proc;
                     63:        caddr_t dbgaddr;
                     64:        int dbg;
                     65:        int val;
                     66:
                     67:        proc = malloc(sizeof(*proc));
                     68:        if (proc == NULL)
                     69:                return TD_ERR_NOMEM;
                     70:
                     71:        proc->cb = cb;
                     72:        proc->arg = arg;
                     73:
                     74:        val = LOOKUP(proc, "pthread__dbg", &dbgaddr);
                     75:        if (val != 0) {
                     76:                if (val == TD_ERR_NOSYM)
                     77:                        val = TD_ERR_NOLIB;
                     78:                goto error;
                     79:        }
                     80:
                     81:        val = READ(proc, dbgaddr, &dbg, sizeof(int));
                     82:        if (val != 0)
                     83:                goto error;
                     84:
                     85:        if (dbg != 0) {
                     86:                /* Another instance of libpthread_dbg is already attached. */
                     87:                val = TD_ERR_INUSE;
                     88:                goto error;
                     89:        }
                     90:
                     91:        dbg = getpid();
                     92:        /*
                     93:         * If this fails it probably means we're debugging a core file and
                     94:         * can't write to it.
                     95:         * If it's something else we'll lose the next time we hit WRITE,
                     96:         * but not before, and that's OK.
                     97:         */
                     98:        WRITE(proc, dbgaddr, &dbg, sizeof(int));
                     99:
                    100:        proc->allqueue = 0;
                    101:        PTQ_INIT(&proc->threads);
                    102:        PTQ_INIT(&proc->syncs);
                    103:
                    104:        *procp = proc;
                    105:
                    106:        return 0;
                    107:
                    108:  error:
                    109:        free(proc);
                    110:        return val;
                    111: }
                    112:
                    113: int
                    114: td_close(td_proc_t *proc)
                    115: {
                    116:        caddr_t dbgaddr;
                    117:        int dbg;
                    118:        int val;
                    119:        td_thread_t *t, *next;
                    120:        td_sync_t *s, *nexts;
                    121:
                    122:        val = LOOKUP(proc, "pthread__dbg", &dbgaddr);
                    123:        if (val != 0)
                    124:                return val;
                    125:
                    126:        dbg = 0;
                    127:        /*
                    128:         * Error returns from this write are mot really a problem;
                    129:         * the process doesn't exist any more.
                    130:         */
                    131:        WRITE(proc, dbgaddr, &dbg, sizeof(int));
                    132:
                    133:        /* Deallocate the list of thread structures */
                    134:        for (t = PTQ_FIRST(&proc->threads); t; t = next) {
                    135:                next = PTQ_NEXT(t, list);
                    136:                PTQ_REMOVE(&proc->threads, t, list);
                    137:                free(t);
                    138:        }
                    139:        /* Deallocate the list of sync objects */
                    140:        for (s = PTQ_FIRST(&proc->syncs); s; s = nexts) {
                    141:                nexts = PTQ_NEXT(s, list);
                    142:                PTQ_REMOVE(&proc->syncs, s, list);
                    143:                free(s);
                    144:        }
                    145:        free(proc);
                    146:        return 0;
                    147: }
                    148:
                    149:
                    150: int
                    151: td_thr_iter(td_proc_t *proc, int (*call)(td_thread_t *, void *), void *callarg)
                    152: {
                    153:        int val;
                    154:        caddr_t allqaddr, next;
                    155:        struct pthread_queue_t allq;
                    156:        td_thread_t *thread;
                    157:
                    158:        if (proc->allqueue == 0) {
                    159:                val = LOOKUP(proc, "pthread__allqueue", &allqaddr);
                    160:                if (val != 0)
                    161:                        return val;
                    162:                proc->allqueue = allqaddr;
                    163:        } else {
                    164:                allqaddr = proc->allqueue;
                    165:        }
                    166:
                    167:        val = READ(proc, allqaddr, &allq, sizeof(allq));
                    168:        if (val != 0)
                    169:                return val;
                    170:
1.3       christos  171:        next = (void *)allq.ptqh_first;
                    172:        while (next != NULL) {
1.2       thorpej   173:                val = td__getthread(proc, next, &thread);
                    174:                if (val != 0)
                    175:                        return val;
                    176:                val = (*call)(thread, callarg);
                    177:                if (val != 0)
                    178:                        return 0;
                    179:
                    180:                val = READ(proc,
                    181:                    next + offsetof(struct pthread_st, pt_allq.ptqe_next),
                    182:                    &next, sizeof(next));
                    183:                if (val != 0)
                    184:                        return val;
                    185:        }
                    186:        return 0;
                    187: }
                    188:
                    189: int
                    190: td_thr_info(td_thread_t *thread, td_thread_info_t *info)
                    191: {
                    192:        int val, tmp;
                    193:        struct pthread_queue_t queue;
                    194:
                    195:        val = READ(thread->proc, thread->addr, &tmp, sizeof(tmp));
                    196:        if (val != 0)
                    197:                return val;
                    198:
                    199:        if (tmp != PT_MAGIC)
                    200:                return TD_ERR_BADTHREAD;
                    201:
                    202:        info->thread_addr = thread->addr;
                    203:        if ((val = READ(thread->proc,
                    204:            thread->addr + offsetof(struct pthread_st, pt_state),
                    205:            &tmp, sizeof(int))) != 0)
                    206:                return val;
                    207:        switch (tmp) {
                    208:        case PT_STATE_RUNNING:
                    209:                info->thread_state = TD_STATE_RUNNING;
                    210:                break;
                    211:        case PT_STATE_RUNNABLE:
                    212:                info->thread_state = TD_STATE_RUNNABLE;
                    213:                break;
                    214:        case PT_STATE_BLOCKED_SYS:
                    215:                info->thread_state = TD_STATE_BLOCKED;
                    216:                break;
                    217:        case PT_STATE_BLOCKED_QUEUE:
                    218:                info->thread_state = TD_STATE_SLEEPING;
                    219:                break;
                    220:        case PT_STATE_ZOMBIE:
                    221:                info->thread_state = TD_STATE_ZOMBIE;
                    222:                break;
                    223:        default:
                    224:                info->thread_state = TD_STATE_UNKNOWN;
                    225:        }
                    226:
                    227:        if ((val = READ(thread->proc,
                    228:            thread->addr + offsetof(struct pthread_st, pt_type),
                    229:            &tmp, sizeof(int))) != 0)
                    230:                return val;
                    231:        switch (tmp) {
                    232:        case PT_THREAD_NORMAL:
                    233:                info->thread_type = TD_TYPE_USER;
                    234:                break;
                    235:        case PT_THREAD_UPCALL:
                    236:        case PT_THREAD_IDLE:
                    237:                info->thread_type = TD_TYPE_SYSTEM;
                    238:                break;
                    239:        default:
                    240:                info->thread_type = TD_TYPE_UNKNOWN;
                    241:        }
                    242:
                    243:        if ((val = READ(thread->proc,
                    244:            thread->addr + offsetof(struct pthread_st, pt_stack),
                    245:            &info->thread_stack, sizeof(stack_t))) != 0)
                    246:                return val;
                    247:
                    248:        if ((val = READ(thread->proc,
                    249:            thread->addr + offsetof(struct pthread_st, pt_joiners),
                    250:            &queue, sizeof(struct pthread_queue_t))) != 0)
                    251:                return val;
                    252:
                    253:        if (PTQ_EMPTY(&queue))
                    254:                info->thread_hasjoiners = 0;
                    255:        else
                    256:                info->thread_hasjoiners = 1;
                    257:
                    258:        if ((val = READ(thread->proc,
                    259:            thread->addr + offsetof(struct pthread_st, pt_errno),
                    260:            &info->thread_errno, sizeof(info->thread_errno))) != 0)
                    261:                return val;
                    262:
                    263:        if ((val = READ(thread->proc,
                    264:            thread->addr + offsetof(struct pthread_st, pt_num),
                    265:            &info->thread_id, sizeof(info->thread_errno))) != 0)
                    266:                return val;
                    267:
                    268:        if ((val = READ(thread->proc,
                    269:            thread->addr + offsetof(struct pthread_st, pt_sigmask),
                    270:            &info->thread_sigmask, sizeof(info->thread_sigmask))) != 0)
                    271:                return val;
                    272:
                    273:        if ((val = READ(thread->proc,
                    274:            thread->addr + offsetof(struct pthread_st, pt_siglist),
                    275:            &info->thread_sigpending, sizeof(info->thread_sigpending))) != 0)
                    276:                return val;
                    277:
                    278:        return 0;
                    279: }
                    280:
                    281: int
1.4       nathanw   282: td_thr_getname(td_thread_t *thread, char *name, int len)
                    283: {
                    284:        int val, tmp;
                    285:        caddr_t nameaddr;
                    286:
                    287:
                    288:        val = READ(thread->proc, thread->addr, &tmp, sizeof(tmp));
                    289:        if (val != 0)
                    290:                return val;
                    291:
                    292:        if (tmp != PT_MAGIC)
                    293:                return TD_ERR_BADTHREAD;
                    294:
                    295:        if ((val = READ(thread->proc,
                    296:            thread->addr + offsetof(struct pthread_st, pt_name),
                    297:            &nameaddr, sizeof(nameaddr))) != 0)
                    298:                return val;
                    299:
                    300:        if (nameaddr == 0)
                    301:                name[0] = '\0';
                    302:        else if ((val = READ(thread->proc, nameaddr,
                    303:            name, MIN(PTHREAD_MAX_NAMELEN_NP, len))) != 0)
                    304:                return val;
                    305:
                    306:        return 0;
                    307: }
                    308:
                    309: int
1.2       thorpej   310: td_thr_getregs(td_thread_t *thread, int regset, void *buf)
                    311: {
                    312:        int tmp, val;
                    313:        caddr_t addr;
                    314:        ucontext_t uc;
                    315:
                    316:        val = READ(thread->proc,
                    317:            thread->addr + offsetof(struct pthread_st, pt_state),
                    318:            &tmp, sizeof(int));
                    319:        if (val != 0)
                    320:                return val;
                    321:
                    322:        switch (tmp) {
                    323:        case PT_STATE_RUNNING:
                    324:                /*
                    325:                 * The register state of the thread is live in the
                    326:                 * inferior process's register state.
                    327:                 */
                    328:                val = GETREGS(thread->proc, regset, thread->lwp, buf);
                    329:                if (val != 0)
                    330:                        return val;
                    331:                break;
                    332:        case PT_STATE_RUNNABLE:
                    333:        case PT_STATE_BLOCKED_SYS:
                    334:        case PT_STATE_BLOCKED_QUEUE:
                    335:                /*
                    336:                 * The register state of the thread is in the ucontext_t
                    337:                 * of the thread structure.
                    338:                 */
                    339:                val = READ(thread->proc,
                    340:                    thread->addr + offsetof(struct pthread_st, pt_uc),
                    341:                    &addr, sizeof(addr));
                    342:                if (val != 0)
                    343:                        return val;
                    344:                val = READ(thread->proc,
                    345:                    addr, &uc, sizeof(uc));
                    346:                if (val != 0)
                    347:                        return val;
                    348:
                    349:                switch (regset) {
                    350:                case 0:
                    351:                        PTHREAD_UCONTEXT_TO_REG((struct reg *)buf, &uc);
                    352:                        break;
                    353:                case 1:
                    354:                        PTHREAD_UCONTEXT_TO_FPREG((struct fpreg *)buf, &uc);
                    355:                        break;
                    356:                case 2:
                    357:                        return TD_ERR_INVAL;
                    358:                }
                    359:                break;
                    360:        case PT_STATE_ZOMBIE:
                    361:        default:
                    362:                return TD_ERR_BADTHREAD;
                    363:        }
                    364:
                    365:        return 0;
                    366: }
                    367:
                    368: int
                    369: td_thr_setregs(td_thread_t *thread, int regset, void *buf)
                    370: {
                    371:
                    372:        int tmp, val;
                    373:        caddr_t addr;
                    374:        ucontext_t uc;
                    375:
                    376:        val = READ(thread->proc,
                    377:            thread->addr + offsetof(struct pthread_st, pt_state),
                    378:            &tmp, sizeof(int));
                    379:        if (val != 0)
                    380:                return val;
                    381:
                    382:        switch (tmp) {
                    383:        case PT_STATE_RUNNING:
                    384:                /*
                    385:                 * The register state of the thread is live in the
                    386:                 * inferior process's register state.
                    387:                 */
                    388:                val = SETREGS(thread->proc, regset, thread->lwp, buf);
                    389:                if (val != 0)
                    390:                        return val;
                    391:                break;
                    392:        case PT_STATE_RUNNABLE:
                    393:        case PT_STATE_BLOCKED_SYS:
                    394:        case PT_STATE_BLOCKED_QUEUE:
                    395:                /*
                    396:                 * The register state of the thread is in the ucontext_t
                    397:                 * of the thread structure.
                    398:                 *
                    399:                 * Fetch the uc first, since there is state in it
                    400:                 * besides the registers that should be preserved.
                    401:                 */
                    402:                val = READ(thread->proc,
                    403:                    thread->addr + offsetof(struct pthread_st, pt_uc),
                    404:                    &addr, sizeof(addr));
                    405:                if (val != 0)
                    406:                        return val;
                    407:                val = READ(thread->proc,
                    408:                    addr, &uc, sizeof(uc));
                    409:                if (val != 0)
                    410:                        return val;
                    411:
                    412:                switch (regset) {
                    413:                case 0:
1.3       christos  414:                        PTHREAD_REG_TO_UCONTEXT(&uc,
                    415:                            (struct reg *)(void *)buf);
1.2       thorpej   416:                        break;
                    417:                case 1:
1.3       christos  418:                        PTHREAD_FPREG_TO_UCONTEXT(&uc,
                    419:                            (struct fpreg *)(void *)buf);
1.2       thorpej   420:                        break;
                    421:                case 2:
                    422:                        return TD_ERR_INVAL;
                    423:                }
                    424:
                    425:                val = WRITE(thread->proc,
                    426:                    addr, &uc, sizeof(uc));
                    427:                if (val != 0)
                    428:                        return val;
                    429:
                    430:                break;
                    431:        case PT_STATE_ZOMBIE:
                    432:        default:
                    433:                return TD_ERR_BADTHREAD;
                    434:        }
                    435:
                    436:        return 0;
                    437: }
                    438:
                    439: int
                    440: td_thr_join_iter(td_thread_t *thread, int (*call)(td_thread_t *, void *),
                    441:     void *arg)
                    442: {
                    443:        int val;
                    444:        caddr_t next;
                    445:        td_thread_t *thread2;
                    446:        struct pthread_queue_t queue;
                    447:
                    448:        if ((val = READ(thread->proc,
                    449:            thread->addr + offsetof(struct pthread_st, pt_joiners),
                    450:            &queue, sizeof(struct pthread_queue_t))) != 0)
                    451:                return val;
                    452:
1.3       christos  453:        next = (void *)queue.ptqh_first;
                    454:        while (next != NULL) {
1.2       thorpej   455:                val = td__getthread(thread->proc, next, &thread2);
                    456:                if (val != 0)
                    457:                        return val;
1.4       nathanw   458:                val = (*call)(thread2, arg);
1.2       thorpej   459:                if (val != 0)
                    460:                        return 0;
                    461:
                    462:                val = READ(thread->proc,
                    463:                    next + offsetof(struct pthread_st, pt_sleep.ptqe_next),
                    464:                    &next, sizeof(next));
                    465:                if (val != 0)
                    466:                        return val;
                    467:        }
                    468:
                    469:        return 0;
                    470: }
                    471:
                    472: int
                    473: td_sync_info(td_sync_t *s, td_sync_info_t *info)
                    474: {
                    475:        int val, magic, n;
                    476:        struct pthread_queue_t queue;
                    477:        pthread_spin_t slock;
                    478:        pthread_t taddr;
                    479:
                    480:        val = READ(s->proc, s->addr, &magic, sizeof(magic));
                    481:        if (val != 0)
                    482:                return val;
                    483:
                    484:        info->sync_type = TD_SYNC_UNKNOWN;
                    485:        info->sync_size = 0;
                    486:        info->sync_haswaiters = 0;
                    487:        switch (magic) {
                    488:        case _PT_MUTEX_MAGIC:
                    489:                info->sync_type = TD_SYNC_MUTEX;
                    490:                info->sync_size = sizeof(struct pthread_mutex_st);
                    491:                if ((val = READ(s->proc,
                    492:                    s->addr + offsetof(struct pthread_mutex_st, ptm_blocked),
                    493:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    494:                return val;
                    495:
                    496:                if (!PTQ_EMPTY(&queue))
                    497:                        info->sync_haswaiters = 1;
                    498:                /*
                    499:                 * The cast to (void *) is to explicitly throw away the
                    500:                 * volatile qualifier on pthread_spin_t,
                    501:                 * from __cpu_simple_lock_t.
                    502:                 */
                    503:                if ((val = READ(s->proc,
                    504:                    s->addr + offsetof(struct pthread_mutex_st, ptm_lock),
                    505:                    (void *)&slock, sizeof(struct pthread_spinlock_st))) != 0)
                    506:                        return val;
                    507:                if (slock == __SIMPLELOCK_LOCKED) {
                    508:                        info->sync_data.mutex.locked = 1;
                    509:                        if ((val = READ(s->proc,
                    510:                            s->addr + offsetof(struct pthread_mutex_st,
                    511:                                ptm_owner),
                    512:                            &taddr, sizeof(pthread_t))) != 0)
                    513:                                return val;
                    514:                        taddr = pthread__id(taddr);
1.3       christos  515:                        td__getthread(s->proc, (void *)taddr,
1.2       thorpej   516:                            &info->sync_data.mutex.owner);
                    517:                } else
                    518:                        info->sync_data.mutex.locked = 0;
                    519:                break;
                    520:        case _PT_COND_MAGIC:
                    521:                info->sync_type = TD_SYNC_COND;
                    522:                info->sync_size = sizeof(struct pthread_cond_st);
                    523:                if ((val = READ(s->proc,
                    524:                    s->addr + offsetof(struct pthread_cond_st, ptc_waiters),
                    525:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    526:                        return val;
                    527:                if (!PTQ_EMPTY(&queue))
                    528:                        info->sync_haswaiters = 1;
                    529:                break;
                    530:        case _PT_SPINLOCK_MAGIC:
                    531:                info->sync_type = TD_SYNC_SPIN;
                    532:                info->sync_size = sizeof(struct pthread_spinlock_st);
                    533:                if ((val = READ(s->proc,
                    534:                    s->addr + offsetof(struct pthread_spinlock_st, pts_spin),
                    535:                    (void *)&slock, sizeof(struct pthread_spinlock_st))) != 0)
                    536:                        return val;
                    537:                if (slock == __SIMPLELOCK_LOCKED)
                    538:                        info->sync_data.spin.locked = 1;
                    539:                break;
                    540:        case PT_MAGIC:
                    541:                info->sync_type = TD_SYNC_JOIN;
                    542:                info->sync_size = sizeof(struct pthread_st);
                    543:                td__getthread(s->proc, s->addr,
                    544:                    &info->sync_data.join.thread);
                    545:                if ((val = READ(s->proc,
                    546:                    s->addr + offsetof(struct pthread_st, pt_joiners),
                    547:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    548:                        return val;
                    549:
                    550:                if (!PTQ_EMPTY(&queue))
                    551:                        info->sync_haswaiters = 1;
                    552:                break;
1.3       christos  553:        case (int)_PT_RWLOCK_MAGIC:
1.2       thorpej   554:                info->sync_type = TD_SYNC_RWLOCK;
                    555:                info->sync_size = sizeof(struct pthread_rwlock_st);
                    556:                if ((val = READ(s->proc,
                    557:                    s->addr + offsetof(struct pthread_rwlock_st, ptr_rblocked),
                    558:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    559:                        return val;
                    560:                if (!PTQ_EMPTY(&queue))
                    561:                        info->sync_haswaiters = 1;
                    562:
                    563:                if ((val = READ(s->proc,
                    564:                    s->addr + offsetof(struct pthread_rwlock_st, ptr_wblocked),
                    565:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    566:                        return val;
                    567:                if (!PTQ_EMPTY(&queue))
                    568:                        info->sync_haswaiters = 1;
                    569:
                    570:
                    571:                info->sync_data.rwlock.locked = 0;
                    572:                if ((val = READ(s->proc,
                    573:                    s->addr + offsetof(struct pthread_rwlock_st, ptr_nreaders),
                    574:                    &n, sizeof(int))) != 0)
                    575:                        return val;
                    576:                info->sync_data.rwlock.readlocks = n;
                    577:                if (n > 0)
                    578:                        info->sync_data.rwlock.locked = 1;
                    579:
                    580:                if ((val = READ(s->proc,
                    581:                    s->addr + offsetof(struct pthread_rwlock_st, ptr_writer),
                    582:                    &taddr, sizeof(pthread_t))) != 0)
                    583:                        return val;
                    584:                if (taddr != 0) {
                    585:                        info->sync_data.rwlock.locked = 1;
1.3       christos  586:                        td__getthread(s->proc, (void *)taddr,
1.2       thorpej   587:                            &info->sync_data.rwlock.writeowner);
                    588:                }
1.3       christos  589:                /*FALLTHROUGH*/
1.2       thorpej   590:        default:
                    591:                return (0);
                    592:        }
                    593:
                    594:        info->sync_addr = s->addr;
                    595:
                    596:        return 0;
                    597: }
                    598:
                    599:
                    600: int
                    601: td_sync_waiters_iter(td_sync_t *s, int (*call)(td_thread_t *, void *),
                    602:     void *arg)
                    603: {
                    604:        int val, magic;
                    605:        caddr_t next;
                    606:        struct pthread_queue_t queue;
                    607:        td_thread_t *thread;
                    608:
                    609:        val = READ(s->proc, s->addr, &magic, sizeof(magic));
                    610:        if (val != 0)
                    611:                return val;
                    612:
                    613:        switch (magic) {
                    614:        case _PT_MUTEX_MAGIC:
                    615:                if ((val = READ(s->proc,
                    616:                    s->addr + offsetof(struct pthread_mutex_st, ptm_blocked),
                    617:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    618:                        return val;
                    619:                break;
                    620:        case _PT_COND_MAGIC:
                    621:                if ((val = READ(s->proc,
                    622:                    s->addr + offsetof(struct pthread_cond_st, ptc_waiters),
                    623:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    624:                        return val;
                    625:                break;
                    626:        case PT_MAGIC:
                    627:                /* Redundant with join_iter, but what the hell... */
                    628:                if ((val = READ(s->proc,
                    629:                    s->addr + offsetof(struct pthread_st, pt_joiners),
                    630:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    631:                        return val;
                    632:                break;
                    633:        default:
                    634:                return (0);
                    635:        }
                    636:
1.3       christos  637:        next = (void *)queue.ptqh_first;
                    638:        while (next != NULL) {
1.2       thorpej   639:                val = td__getthread(s->proc, next, &thread);
                    640:                if (val != 0)
                    641:                        return val;
                    642:                val = (*call)(thread, arg);
                    643:                if (val != 0)
                    644:                        return 0;
                    645:
                    646:                val = READ(s->proc,
                    647:                    next + offsetof(struct pthread_st, pt_sleep.ptqe_next),
                    648:                    &next, sizeof(next));
                    649:                if (val != 0)
                    650:                        return val;
                    651:        }
                    652:        return 0;
                    653: }
                    654:
                    655:
                    656: int
                    657: td_map_addr2sync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp)
                    658: {
                    659:        int magic, val;
                    660:
                    661:        val = READ(proc, addr, &magic, sizeof(magic));
                    662:        if (val != 0)
                    663:                return val;
                    664:
                    665:        if ((magic != _PT_MUTEX_MAGIC) &&
                    666:            (magic != _PT_COND_MAGIC) &&
                    667:            (magic != _PT_SPINLOCK_MAGIC))
                    668:                return TD_ERR_NOOBJ;
                    669:
                    670:        val = td__getsync(proc, addr, syncp);
                    671:        if (val != 0)
                    672:                return val;
                    673:
                    674:        return 0;
                    675: }
                    676:
                    677:
                    678: int
                    679: td_map_pth2thr(td_proc_t *proc, pthread_t thread, td_thread_t **threadp)
                    680: {
                    681:        int magic, val;
                    682:
1.3       christos  683:        val = READ(proc, (void *)thread, &magic, sizeof(magic));
1.2       thorpej   684:        if (val != 0)
                    685:                return val;
                    686:
                    687:        if (magic != PT_MAGIC)
                    688:                return TD_ERR_NOOBJ;
                    689:
1.3       christos  690:        val = td__getthread(proc, (void *)thread, threadp);
1.2       thorpej   691:        if (val != 0)
                    692:                return val;
                    693:
                    694:        return 0;
                    695: }
                    696:
                    697: int
                    698: td_map_id2thr(td_proc_t *proc, int threadid, td_thread_t **threadp)
                    699: {
                    700:        int val, num;
                    701:        caddr_t allqaddr, next;
                    702:        struct pthread_queue_t allq;
                    703:        td_thread_t *thread;
                    704:
                    705:
                    706:        if (proc->allqueue == 0) {
                    707:                val = LOOKUP(proc, "pthread__allqueue", &allqaddr);
                    708:                if (val != 0)
                    709:                        return val;
                    710:                proc->allqueue = allqaddr;
                    711:        } else {
                    712:                allqaddr = proc->allqueue;
                    713:        }
                    714:
                    715:        val = READ(proc, allqaddr, &allq, sizeof(allq));
                    716:        if (val != 0)
                    717:                return val;
                    718:
1.3       christos  719:        next = (void *)allq.ptqh_first;
                    720:        while (next != NULL) {
1.2       thorpej   721:                val = READ(proc,
                    722:                    next + offsetof(struct pthread_st, pt_num),
                    723:                    &num, sizeof(num));
                    724:
                    725:                if (num == threadid)
                    726:                        break;
                    727:
                    728:                val = READ(proc,
                    729:                    next + offsetof(struct pthread_st, pt_allq.ptqe_next),
                    730:                    &next, sizeof(next));
                    731:                if (val != 0)
                    732:                        return val;
                    733:        }
                    734:
                    735:        if (next == 0) {
                    736:                /* A matching thread was not found. */
                    737:                return TD_ERR_NOOBJ;
                    738:        }
                    739:
                    740:        val = td__getthread(proc, next, &thread);
                    741:        if (val != 0)
                    742:                return val;
                    743:        *threadp = thread;
                    744:
                    745:        return 0;
                    746: }
                    747:
                    748: /* Return the thread handle of the thread running on the given LWP */
                    749: int
                    750: td_map_lwp2thr(td_proc_t *proc, int lwp, td_thread_t **threadp)
                    751: {
                    752:        int val, magic;
                    753:        struct reg gregs;
                    754:        ucontext_t uc;
1.3       christos  755:        void *th;
1.2       thorpej   756:
                    757:        val = GETREGS(proc, 0, lwp, &gregs);
                    758:        if (val != 0)
                    759:                return val;
                    760:
                    761:        PTHREAD_REG_TO_UCONTEXT(&uc, &gregs);
                    762:
1.3       christos  763:        th = pthread__id(pthread__uc_sp(&uc));
1.2       thorpej   764:
                    765:        val = READ(proc, th, &magic, sizeof(magic));
                    766:        if (val != 0)
                    767:                return val;
                    768:
                    769:        if (magic != PT_MAGIC)
                    770:                return TD_ERR_NOOBJ;
                    771:
                    772:        val = td__getthread(proc, th, threadp);
                    773:        if (val != 0)
                    774:                return val;
                    775:
                    776:        (*threadp)->lwp = lwp;
                    777:
                    778:        return 0;
                    779: }
                    780:
                    781: int
                    782: td_map_lwps(td_proc_t *proc)
                    783: {
                    784:        int i, val, nlwps;
                    785:        caddr_t addr;
                    786:        td_thread_t *thread;
                    787:
                    788:        val = LOOKUP(proc, "pthread__maxlwps", &addr);
                    789:        if (val != 0)
                    790:                return val;
                    791:
                    792:        val = READ(proc, addr, &nlwps, sizeof(int));
                    793:        if (val != 0)
                    794:                return val;
                    795:
                    796:        for (i = 1; i <= nlwps; i++) {
                    797:                /*
                    798:                 * Errors are deliberately ignored for the call to
                    799:                 * td_map_lwp2thr(); it is entirely likely that not
                    800:                 * all LWPs in the range 1..nlwps exist, and that's
                    801:                 * not a problem.
                    802:                 */
                    803:                td_map_lwp2thr(proc, i, &thread);
                    804:        }
                    805:        return 0;
                    806: }
                    807:
                    808: int
                    809: td_tsd_iter(td_proc_t *proc,
                    810:     int (*call)(pthread_key_t, void (*)(void *), void *), void *arg)
                    811: {
                    812:        caddr_t desaddr, allocaddr;
                    813:        int val;
                    814:        int i, allocated;
                    815:        void (*destructor)(void *);
                    816:
                    817:        val = LOOKUP(proc, "pthread__tsd_alloc", &allocaddr);
                    818:        if (val != 0)
                    819:                return val;
                    820:        val = LOOKUP(proc, "pthread__tsd_destructors", &desaddr);
                    821:        if (val != 0)
                    822:                return val;
                    823:
                    824:        for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
                    825:                val = READ(proc, allocaddr + i * sizeof(int),
                    826:                    &allocated, sizeof(int));
                    827:                if (val != 0)
                    828:                        return val;
                    829:
                    830:                if (allocated) {
                    831:                        val = READ(proc,  desaddr + i * sizeof(destructor),
                    832:                            &destructor, sizeof(destructor));
                    833:                        if (val != 0)
                    834:                                return val;
                    835:
                    836:                        val = (call)(i, destructor, arg);
                    837:                        if (val != 0)
                    838:                                return val;
                    839:                }
                    840:        }
                    841:
                    842:        return 0;
                    843: }
                    844:
                    845: /* Get the synchronization object that the thread is sleeping on */
                    846: int
                    847: td_thr_sleepinfo(td_thread_t *thread, td_sync_t **s)
                    848: {
                    849:        int val;
                    850:        caddr_t addr;
                    851:
                    852:        if ((val = READ(thread->proc,
                    853:            thread->addr + offsetof(struct pthread_st, pt_sleepobj),
                    854:            &addr, sizeof(caddr_t))) != 0)
                    855:                return val;
                    856:
                    857:        td__getsync(thread->proc, addr, s);
                    858:
                    859:        return 0;
                    860:
                    861: }
                    862:
                    863:
                    864:
                    865: static int
                    866: td__getthread(td_proc_t *proc, caddr_t addr, td_thread_t **threadp)
                    867: {
                    868:        td_thread_t *thread;
                    869:
                    870:        /*
                    871:         * Check if we've allocated a descriptor for this thread.
                    872:         * Sadly, this makes iterating over a set of threads O(N^2)
                    873:         * in the number of threads. More sophisticated data structures
                    874:         * can wait.
                    875:                 */
                    876:        PTQ_FOREACH(thread, &proc->threads, list) {
                    877:                if (thread->addr == addr)
                    878:                        break;
                    879:        }
                    880:        if (thread == NULL) {
                    881:                thread = malloc(sizeof(*thread));
                    882:                if (thread == NULL)
                    883:                        return TD_ERR_NOMEM;
                    884:                thread->proc = proc;
                    885:                thread->addr = addr;
                    886:                thread->lwp  = 0;
                    887:                PTQ_INSERT_HEAD(&proc->threads, thread, list);
                    888:        }
                    889:
                    890:        *threadp = thread;
                    891:        return 0;
                    892: }
                    893:
                    894:
                    895: static int
                    896: td__getsync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp)
                    897: {
                    898:        td_sync_t *s;
                    899:
                    900:        /* Check if we've allocated a descriptor for this object. */
                    901:        PTQ_FOREACH(s, &proc->syncs, list) {
                    902:                if (s->addr == addr)
                    903:                        break;
                    904:        }
                    905:        /* Allocate a fresh one */
                    906:        if (s == NULL) {
                    907:                s = malloc(sizeof(*s));
                    908:                if (s == NULL)
                    909:                        return TD_ERR_NOMEM;
                    910:                s->proc = proc;
                    911:                s->addr = addr;
                    912:                PTQ_INSERT_HEAD(&proc->syncs, s, list);
                    913:        }
                    914:
                    915:        *syncp = s;
                    916:        return 0;
                    917: }
                    918:
                    919:
                    920: int
                    921: td_thr_tsd(td_thread_t *thread, pthread_key_t key, void **value)
                    922: {
                    923:        int val;
                    924:
                    925:        val = READ(thread->proc, thread->addr +
                    926:            offsetof(struct pthread_st, pt_specific) +
                    927:            key * sizeof(void *), &value, sizeof(void *));
                    928:
                    929:        return val;
                    930: }
                    931:

CVSweb <webmaster@jp.NetBSD.org>