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

1.1.2.3 ! nathanw     1: /*     $NetBSD: pthread_dbg.c,v 1.1.2.2 2002/08/06 06:10:59 thorpej Exp $      */
1.1.2.1   nathanw     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:  */
                     37:
                     38: #include <stddef.h>
                     39: #include <stdlib.h>
1.1.2.3 ! nathanw    40: #include <string.h>
1.1.2.1   nathanw    41: #include <errno.h>
                     42: #include <sys/types.h>
                     43: #include <unistd.h>
                     44:
                     45: #include <pthread.h>
                     46: #include <pthread_int.h>
                     47: #include <pthread_dbg.h>
                     48: #include <pthread_dbg_int.h>
                     49: #include <machine/reg.h>
                     50:
                     51: static int td__getthread(td_proc_t *proc, caddr_t addr, td_thread_t **threadp);
                     52: static int td__getsync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp);
                     53:
                     54: int
                     55: td_open(struct td_proc_callbacks_t *cb, void *arg, td_proc_t **procp)
                     56: {
                     57:        td_proc_t *proc;
                     58:        caddr_t dbgaddr;
                     59:        int dbg;
                     60:        int val;
                     61:
                     62:        proc = malloc(sizeof(*proc));
                     63:        if (proc == NULL)
                     64:                return TD_ERR_NOMEM;
                     65:
                     66:        proc->cb = cb;
                     67:        proc->arg = arg;
                     68:
                     69:        val = LOOKUP(proc, "pthread__dbg", &dbgaddr);
                     70:        if (val != 0) {
                     71:                if (val == TD_ERR_NOSYM)
                     72:                        val = TD_ERR_NOLIB;
                     73:                goto error;
                     74:        }
                     75:
                     76:        val = READ(proc, dbgaddr, &dbg, sizeof(int));
                     77:        if (val != 0)
                     78:                goto error;
                     79:
                     80:        if (dbg != 0) {
                     81:                /* Another instance of libpthread_dbg is already attached. */
                     82:                val = TD_ERR_INUSE;
                     83:                goto error;
                     84:        }
                     85:
                     86:        dbg = getpid();
                     87:        /* If this fails it probably means we're debugging a core file and
                     88:         * can't write to it.
                     89:         * If it's something else we'll lose the next time we hit WRITE,
                     90:         * but not before, and that's OK.
                     91:         */
                     92:        WRITE(proc, dbgaddr, &dbg, sizeof(int));
                     93:
                     94:        proc->allqueue = 0;
                     95:        PTQ_INIT(&proc->threads);
                     96:        PTQ_INIT(&proc->syncs);
                     97:
                     98:        *procp = proc;
                     99:
                    100:        return 0;
                    101:
                    102:  error:
                    103:        free(proc);
                    104:        return val;
                    105: }
                    106:
                    107: int
                    108: td_close(td_proc_t *proc)
                    109: {
                    110:        caddr_t dbgaddr;
                    111:        int dbg;
                    112:        int val;
                    113:        td_thread_t *t, *next;
                    114:        td_sync_t *s, *nexts;
                    115:
                    116:        val = LOOKUP(proc, "pthread__dbg", &dbgaddr);
                    117:        if (val != 0)
                    118:                return val;
                    119:
                    120:        dbg = 0;
                    121:        /*
                    122:         * Error returns from this write are mot really a problem;
                    123:         * the process doesn't exist any more.
                    124:         */
                    125:        WRITE(proc, dbgaddr, &dbg, sizeof(int));
                    126:
                    127:        /* Deallocate the list of thread structures */
                    128:        for (t = PTQ_FIRST(&proc->threads); t; t = next) {
                    129:                next = PTQ_NEXT(t, list);
                    130:                PTQ_REMOVE(&proc->threads, t, list);
                    131:                free(t);
                    132:        }
                    133:        /* Deallocate the list of sync objects */
                    134:        for (s = PTQ_FIRST(&proc->syncs); s; s = nexts) {
                    135:                nexts = PTQ_NEXT(s, list);
                    136:                PTQ_REMOVE(&proc->syncs, s, list);
                    137:                free(s);
                    138:        }
                    139:        free(proc);
                    140:        return 0;
                    141: }
                    142:
                    143:
                    144: int
                    145: td_thr_iter(td_proc_t *proc, int (*call)(td_thread_t *, void *), void *callarg)
                    146: {
                    147:        int val;
                    148:        caddr_t allqaddr, next;
                    149:        struct pthread_queue_t allq;
                    150:        td_thread_t *thread;
                    151:
                    152:        if (proc->allqueue == 0) {
                    153:                val = LOOKUP(proc, "allqueue", &allqaddr);
                    154:                if (val != 0)
                    155:                        return val;
                    156:                proc->allqueue = allqaddr;
                    157:        } else {
                    158:                allqaddr = proc->allqueue;
                    159:        }
                    160:
                    161:        val = READ(proc, allqaddr, &allq, sizeof(allq));
                    162:        if (val != 0)
                    163:                return val;
                    164:
                    165:        next = (caddr_t) allq.ptqh_first;
                    166:        while (next != 0) {
                    167:                val = td__getthread(proc, next, &thread);
                    168:                if (val != 0)
                    169:                        return val;
                    170:                val = (*call)(thread, callarg);
                    171:                if (val != 0)
                    172:                        return 0;
                    173:
                    174:                val = READ(proc,
                    175:                    next + offsetof(struct pthread_st, pt_allq.ptqe_next),
                    176:                    &next, sizeof(next));
                    177:                if (val != 0)
                    178:                        return val;
                    179:        }
                    180:        return 0;
                    181: }
                    182:
                    183: int
                    184: td_thr_info(td_thread_t *thread, td_thread_info_t *info)
                    185: {
                    186:        int val, tmp;
                    187:        struct pthread_queue_t queue;
                    188:
                    189:        val = READ(thread->proc, thread->addr, &tmp, sizeof(tmp));
                    190:        if (val != 0)
                    191:                return val;
                    192:
                    193:        if (tmp != PT_MAGIC)
                    194:                return TD_ERR_BADTHREAD;
                    195:
                    196:        info->thread_addr = thread->addr;
                    197:        if ((val = READ(thread->proc,
                    198:            thread->addr + offsetof(struct pthread_st, pt_state),
                    199:            &tmp, sizeof(int))) != 0)
                    200:                return val;
                    201:        switch (tmp) {
                    202:        case PT_STATE_RUNNING:
                    203:                info->thread_state = TD_STATE_RUNNING;
                    204:                break;
                    205:        case PT_STATE_RUNNABLE:
                    206:                info->thread_state = TD_STATE_RUNNABLE;
                    207:                break;
                    208:        case PT_STATE_BLOCKED_SYS:
                    209:                info->thread_state = TD_STATE_BLOCKED;
                    210:                break;
                    211:        case PT_STATE_BLOCKED_QUEUE:
                    212:                info->thread_state = TD_STATE_SLEEPING;
                    213:                break;
                    214:        case PT_STATE_ZOMBIE:
                    215:                info->thread_state = TD_STATE_ZOMBIE;
                    216:                break;
                    217:        default:
                    218:                info->thread_state = TD_STATE_UNKNOWN;
                    219:        }
                    220:
                    221:        if ((val = READ(thread->proc,
                    222:            thread->addr + offsetof(struct pthread_st, pt_type),
                    223:            &tmp, sizeof(int))) != 0)
                    224:                return val;
                    225:        switch (tmp) {
                    226:        case PT_THREAD_NORMAL:
                    227:                info->thread_type = TD_TYPE_USER;
                    228:                break;
                    229:        case PT_THREAD_UPCALL:
                    230:        case PT_THREAD_IDLE:
                    231:                info->thread_type = TD_TYPE_SYSTEM;
                    232:                break;
                    233:        default:
                    234:                info->thread_type = TD_TYPE_UNKNOWN;
                    235:        }
                    236:
                    237:        if ((val = READ(thread->proc,
                    238:            thread->addr + offsetof(struct pthread_st, pt_stack),
                    239:            &info->thread_stack, sizeof(stack_t))) != 0)
                    240:                return val;
                    241:
                    242:        if ((val = READ(thread->proc,
                    243:            thread->addr + offsetof(struct pthread_st, pt_joiners),
                    244:            &queue, sizeof(struct pthread_queue_t))) != 0)
                    245:                return val;
                    246:
                    247:        if (PTQ_EMPTY(&queue))
                    248:                info->thread_hasjoiners = 0;
                    249:        else
                    250:                info->thread_hasjoiners = 1;
                    251:
                    252:        if ((val = READ(thread->proc,
                    253:            thread->addr + offsetof(struct pthread_st, pt_errno),
                    254:            &info->thread_errno, sizeof(info->thread_errno))) != 0)
                    255:                return val;
                    256:
                    257:        if ((val = READ(thread->proc,
                    258:            thread->addr + offsetof(struct pthread_st, pt_num),
                    259:            &info->thread_id, sizeof(info->thread_errno))) != 0)
                    260:                return val;
                    261:
                    262:        if ((val = READ(thread->proc,
                    263:            thread->addr + offsetof(struct pthread_st, pt_sigmask),
                    264:            &info->thread_sigmask, sizeof(info->thread_sigmask))) != 0)
                    265:                return val;
                    266:
                    267:        if ((val = READ(thread->proc,
                    268:            thread->addr + offsetof(struct pthread_st, pt_siglist),
                    269:            &info->thread_sigpending, sizeof(info->thread_sigpending))) != 0)
                    270:                return val;
                    271:
                    272:        return 0;
                    273: }
                    274:
                    275: int
                    276: td_thr_getregs(td_thread_t *thread, int regset, void *buf)
                    277: {
                    278:        int tmp, val;
                    279:        caddr_t addr;
                    280:        ucontext_t uc;
                    281:
                    282:        val = READ(thread->proc,
                    283:            thread->addr + offsetof(struct pthread_st, pt_state),
                    284:            &tmp, sizeof(int));
                    285:        if (val != 0)
                    286:                return val;
                    287:
                    288:        switch (tmp) {
                    289:        case PT_STATE_RUNNING:
                    290:                /* The register state of the thread is live in the
                    291:                 * inferior process's register state.
                    292:                 * XXX we don't have a thread->LWP mapping, and the
                    293:                 * XXX layer we're calling doesn't have a way to feed
                    294:                 * XXX a LWP ID to ptrace.... fortunately, it's a moot
                    295:                 * XXX issue on a uniprocessor box.
                    296:                 */
                    297:                val = GETREGS(thread->proc, regset, -1, buf);
                    298:                if (val != 0)
                    299:                        return val;
                    300:                break;
                    301:        case PT_STATE_RUNNABLE:
                    302:        case PT_STATE_BLOCKED_SYS:
                    303:        case PT_STATE_BLOCKED_QUEUE:
                    304:                /* The register state of the thread is in the ucontext_t
                    305:                 * of the thread structure.
                    306:                 */
                    307:                val = READ(thread->proc,
                    308:                    thread->addr + offsetof(struct pthread_st, pt_uc),
                    309:                    &addr, sizeof(addr));
                    310:                if (val != 0)
                    311:                        return val;
                    312:                val = READ(thread->proc,
                    313:                    addr, &uc, sizeof(uc));
                    314:                if (val != 0)
                    315:                        return val;
                    316:
                    317:                switch (regset) {
                    318:                case 0:
                    319:                        PTHREAD_UCONTEXT_TO_REG((struct reg *)buf, &uc);
                    320:                        break;
                    321:                case 1:
                    322:                        PTHREAD_UCONTEXT_TO_FPREG((struct fpreg *)buf, &uc);
                    323:                        break;
                    324:                case 2:
                    325:                        return TD_ERR_INVAL;
                    326:                }
                    327:                break;
                    328:        case PT_STATE_ZOMBIE:
                    329:        default:
                    330:                return TD_ERR_BADTHREAD;
                    331:        }
                    332:
                    333:        return 0;
                    334: }
                    335:
                    336: int
                    337: td_thr_setregs(td_thread_t *thread, int regset, void *buf)
                    338: {
                    339:
                    340:        int tmp, val;
                    341:        caddr_t addr;
                    342:        ucontext_t uc;
                    343:
                    344:        val = READ(thread->proc,
                    345:            thread->addr + offsetof(struct pthread_st, pt_state),
                    346:            &tmp, sizeof(int));
                    347:        if (val != 0)
                    348:                return val;
                    349:
                    350:        switch (tmp) {
                    351:        case PT_STATE_RUNNING:
                    352:                /* The register state of the thread is live in the
                    353:                 * inferior process's register state.
                    354:                 * XXX we don't have a thread->LWP mapping, and the
                    355:                 * XXX layer we're calling doesn't have a way to feed
                    356:                 * XXX a LWP ID to ptrace.... fortunately, it's a moot
                    357:                 * XXX issue on a uniprocessor box.
                    358:                 */
                    359:                val = SETREGS(thread->proc, regset, -1, buf);
                    360:                if (val != 0)
                    361:                        return val;
                    362:                break;
                    363:        case PT_STATE_RUNNABLE:
                    364:        case PT_STATE_BLOCKED_SYS:
                    365:        case PT_STATE_BLOCKED_QUEUE:
                    366:                /* The register state of the thread is in the ucontext_t
                    367:                 * of the thread structure.
                    368:                 */
                    369:                /* Fetch the uc first, since there is state in it
                    370:                 * besides the registers that should be preserved.
                    371:                 */
                    372:                val = READ(thread->proc,
                    373:                    thread->addr + offsetof(struct pthread_st, pt_uc),
                    374:                    &addr, sizeof(addr));
                    375:                if (val != 0)
                    376:                        return val;
                    377:                val = READ(thread->proc,
                    378:                    addr, &uc, sizeof(uc));
                    379:                if (val != 0)
                    380:                        return val;
                    381:
                    382:                switch (regset) {
                    383:                case 0:
                    384:                        PTHREAD_REG_TO_UCONTEXT(&uc, (struct reg *)buf);
                    385:                        break;
                    386:                case 1:
                    387:                        PTHREAD_FPREG_TO_UCONTEXT(&uc, (struct fpreg *)buf);
                    388:                        break;
                    389:                case 2:
                    390:                        return TD_ERR_INVAL;
                    391:                }
                    392:
                    393:                val = WRITE(thread->proc,
                    394:                    addr, &uc, sizeof(uc));
                    395:                if (val != 0)
                    396:                        return val;
                    397:
                    398:                break;
                    399:        case PT_STATE_ZOMBIE:
                    400:        default:
                    401:                return TD_ERR_BADTHREAD;
                    402:        }
                    403:
                    404:        return 0;
                    405: }
                    406:
                    407: int
                    408: td_thr_join_iter(td_thread_t *thread, int (*call)(td_thread_t *, void *),
                    409:     void *arg)
                    410: {
                    411:        int val;
                    412:        caddr_t next;
                    413:        td_thread_t *thread2;
                    414:        struct pthread_queue_t queue;
                    415:
                    416:        if ((val = READ(thread->proc,
                    417:            thread->addr + offsetof(struct pthread_st, pt_joiners),
                    418:            &queue, sizeof(struct pthread_queue_t))) != 0)
                    419:                return val;
                    420:
                    421:        next = (caddr_t) queue.ptqh_first;
                    422:        while (next != 0) {
                    423:                val = td__getthread(thread->proc, next, &thread2);
                    424:                if (val != 0)
                    425:                        return val;
                    426:                val = (*call)(thread, arg);
                    427:                if (val != 0)
                    428:                        return 0;
                    429:
                    430:                val = READ(thread->proc,
                    431:                    next + offsetof(struct pthread_st, pt_sleep.ptqe_next),
                    432:                    &next, sizeof(next));
                    433:                if (val != 0)
                    434:                        return val;
                    435:        }
                    436:
                    437:        return 0;
                    438: }
                    439:
                    440: int
                    441: td_sync_info(td_sync_t *s, td_sync_info_t *info)
                    442: {
                    443:        int val, magic;
                    444:        struct pthread_queue_t queue;
                    445:        pthread_spin_t slock;
                    446:        pthread_t taddr;
                    447:
                    448:        val = READ(s->proc, s->addr, &magic, sizeof(magic));
                    449:        if (val != 0)
                    450:                return val;
                    451:
                    452:        info->sync_type = TD_SYNC_UNKNOWN;
                    453:        info->sync_size = 0;
                    454:        info->sync_haswaiters = 0;
                    455:        switch (magic) {
                    456:        case _PT_MUTEX_MAGIC:
                    457:                info->sync_type = TD_SYNC_MUTEX;
                    458:                info->sync_size = sizeof(struct pthread_mutex_st);
                    459:                if ((val = READ(s->proc,
                    460:                    s->addr + offsetof(struct pthread_mutex_st, ptm_blocked),
                    461:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    462:                return val;
                    463:
                    464:                if (!PTQ_EMPTY(&queue))
                    465:                        info->sync_haswaiters = 1;
                    466:                /* The cast to (void *) is to explicitly throw away the
                    467:                 * volatile qualifier on pthread_spin_t,
                    468:                 * from __cpu_simple_lock_t.
                    469:                 */
                    470:                if ((val = READ(s->proc,
                    471:                    s->addr + offsetof(struct pthread_mutex_st, ptm_lock),
                    472:                    (void *)&slock, sizeof(struct pthread_spinlock_st))) != 0)
                    473:                        return val;
                    474:                if (slock == __SIMPLELOCK_LOCKED) {
                    475:                        info->sync_data.mutex.locked = 1;
                    476:                        if ((val = READ(s->proc,
                    477:                            s->addr + offsetof(struct pthread_mutex_st,
                    478:                                ptm_owner),
                    479:                            &taddr, sizeof(pthread_t))) != 0)
                    480:                                return val;
                    481:                        td__getthread(s->proc, (caddr_t)taddr,
                    482:                            &info->sync_data.mutex.owner);
                    483:                } else
                    484:                        info->sync_data.mutex.locked = 0;
                    485:                break;
                    486:        case _PT_COND_MAGIC:
                    487:                info->sync_type = TD_SYNC_COND;
                    488:                info->sync_size = sizeof(struct pthread_cond_st);
                    489:                if ((val = READ(s->proc,
                    490:                    s->addr + offsetof(struct pthread_cond_st, ptc_waiters),
                    491:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    492:                        return val;
                    493:                if (!PTQ_EMPTY(&queue))
                    494:                        info->sync_haswaiters = 1;
                    495:                break;
                    496:        case _PT_SPINLOCK_MAGIC:
                    497:                info->sync_type = TD_SYNC_SPIN;
                    498:                info->sync_size = sizeof(struct pthread_spinlock_st);
                    499:                if ((val = READ(s->proc,
                    500:                    s->addr + offsetof(struct pthread_spinlock_st, pts_spin),
                    501:                    (void *)&slock, sizeof(struct pthread_spinlock_st))) != 0)
                    502:                        return val;
                    503:                if (slock == __SIMPLELOCK_LOCKED)
                    504:                        info->sync_data.spin.locked = 1;
                    505:                break;
                    506:        case PT_MAGIC:
                    507:                info->sync_type = TD_SYNC_JOIN;
                    508:                info->sync_size = sizeof(struct pthread_st);
                    509:                td__getthread(s->proc, s->addr,
                    510:                    &info->sync_data.join.thread);
                    511:                if ((val = READ(s->proc,
                    512:                    s->addr + offsetof(struct pthread_st, pt_joiners),
                    513:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    514:                        return val;
                    515:
                    516:                if (!PTQ_EMPTY(&queue))
                    517:                        info->sync_haswaiters = 1;
                    518:                break;
                    519:        default:
                    520:                return (0);
                    521:        }
                    522:
                    523:        info->sync_addr = s->addr;
                    524:
                    525:        return 0;
                    526: }
                    527:
                    528:
                    529: int
                    530: td_sync_waiters_iter(td_sync_t *s, int (*call)(td_thread_t *, void *),
                    531:     void *arg)
                    532: {
                    533:        int val, magic;
                    534:        caddr_t next;
                    535:        struct pthread_queue_t queue;
                    536:        td_thread_t *thread;
                    537:
                    538:        val = READ(s->proc, s->addr, &magic, sizeof(magic));
                    539:        if (val != 0)
                    540:                return val;
                    541:
                    542:        switch (magic) {
                    543:        case _PT_MUTEX_MAGIC:
                    544:                if ((val = READ(s->proc,
                    545:                    s->addr + offsetof(struct pthread_mutex_st, ptm_blocked),
                    546:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    547:                        return val;
                    548:                break;
                    549:        case _PT_COND_MAGIC:
                    550:                if ((val = READ(s->proc,
                    551:                    s->addr + offsetof(struct pthread_cond_st, ptc_waiters),
                    552:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    553:                        return val;
                    554:                break;
                    555:        case PT_MAGIC:
                    556:                /* Redundant with join_iter, but what the hell... */
                    557:                if ((val = READ(s->proc,
                    558:                    s->addr + offsetof(struct pthread_st, pt_joiners),
                    559:                    &queue, sizeof(struct pthread_queue_t))) != 0)
                    560:                        return val;
                    561:                break;
                    562:        default:
                    563:                return (0);
                    564:        }
                    565:
                    566:        next = (caddr_t) queue.ptqh_first;
                    567:        while (next != 0) {
                    568:                val = td__getthread(s->proc, next, &thread);
                    569:                if (val != 0)
                    570:                        return val;
                    571:                val = (*call)(thread, arg);
                    572:                if (val != 0)
                    573:                        return 0;
                    574:
                    575:                val = READ(s->proc,
                    576:                    next + offsetof(struct pthread_st, pt_sleep.ptqe_next),
                    577:                    &next, sizeof(next));
                    578:                if (val != 0)
                    579:                        return val;
                    580:        }
                    581:        return 0;
                    582: }
                    583:
                    584:
                    585: int
                    586: td_map_addr2sync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp)
                    587: {
                    588:        int magic, val;
                    589:
                    590:        val = READ(proc, addr, &magic, sizeof(magic));
                    591:        if (val != 0)
                    592:                return val;
                    593:
                    594:        if ((magic != _PT_MUTEX_MAGIC) &&
                    595:            (magic != _PT_COND_MAGIC) &&
                    596:            (magic != _PT_SPINLOCK_MAGIC))
                    597:                return TD_ERR_NOOBJ;
                    598:
                    599:        val = td__getsync(proc, addr, syncp);
                    600:        if (val != 0)
                    601:                return val;
                    602:
                    603:        return 0;
                    604: }
                    605:
                    606:
                    607: int
                    608: td_map_pth2thr(td_proc_t *proc, pthread_t thread, td_thread_t **threadp)
                    609: {
                    610:        int magic, val;
                    611:
                    612:        val = READ(proc, (caddr_t)thread, &magic, sizeof(magic));
                    613:        if (val != 0)
                    614:                return val;
                    615:
                    616:        if (magic != PT_MAGIC)
                    617:                return TD_ERR_NOOBJ;
                    618:
                    619:        val = td__getthread(proc, (caddr_t)thread, threadp);
                    620:        if (val != 0)
                    621:                return val;
                    622:
                    623:        return 0;
                    624: }
                    625:
                    626: int
                    627: td_map_id2thr(td_proc_t *proc, int threadid, td_thread_t **threadp)
                    628: {
                    629:        int val, num;
                    630:        caddr_t allqaddr, next;
                    631:        struct pthread_queue_t allq;
                    632:        td_thread_t *thread;
                    633:
                    634:
                    635:        if (proc->allqueue == 0) {
                    636:                val = LOOKUP(proc, "allqueue", &allqaddr);
                    637:                if (val != 0)
                    638:                        return val;
                    639:                proc->allqueue = allqaddr;
                    640:        } else {
                    641:                allqaddr = proc->allqueue;
                    642:        }
                    643:
                    644:        val = READ(proc, allqaddr, &allq, sizeof(allq));
                    645:        if (val != 0)
                    646:                return val;
                    647:
                    648:        next = (caddr_t) allq.ptqh_first;
                    649:        while (next != 0) {
                    650:                val = READ(proc,
                    651:                    next + offsetof(struct pthread_st, pt_num),
                    652:                    &num, sizeof(num));
                    653:
                    654:                if (num == threadid)
                    655:                        break;
                    656:
                    657:                val = READ(proc,
                    658:                    next + offsetof(struct pthread_st, pt_allq.ptqe_next),
                    659:                    &next, sizeof(next));
                    660:                if (val != 0)
                    661:                        return val;
                    662:        }
                    663:
                    664:        if (next == 0) {
                    665:                /* A matching thread was not found. */
                    666:                return TD_ERR_NOOBJ;
                    667:        }
                    668:
                    669:        val = td__getthread(proc, next, &thread);
                    670:        if (val != 0)
                    671:                return val;
                    672:        *threadp = thread;
                    673:
                    674:        return 0;
                    675: }
                    676:
                    677: /* Return the thread handle of the thread running on the given LWP */
                    678: int
                    679: td_map_lwp2thr(td_proc_t *proc, int lwp, td_thread_t **threadp)
                    680: {
                    681:        int val, magic;
                    682:        struct reg gregs;
                    683:        ucontext_t uc;
                    684:        caddr_t th;
                    685:
                    686:        val = GETREGS(proc, 0, lwp, &gregs);
                    687:        if (val != 0)
                    688:                return val;
                    689:
                    690:        PTHREAD_REG_TO_UCONTEXT(&uc, &gregs);
                    691:
                    692:        th = (caddr_t) pthread__id(pthread__uc_sp(&uc));
                    693:
                    694:        val = READ(proc, th, &magic, sizeof(magic));
                    695:        if (val != 0)
                    696:                return val;
                    697:
                    698:        if (magic != PT_MAGIC)
                    699:                return TD_ERR_NOOBJ;
                    700:
                    701:        val = td__getthread(proc, th, threadp);
                    702:        if (val != 0)
                    703:                return val;
                    704:
                    705:        return 0;
                    706: }
                    707:
                    708:
                    709: int
                    710: td_tsd_iter(td_proc_t *proc,
                    711:     int (*call)(pthread_key_t, void (*)(void *), void *), void *arg)
                    712: {
                    713:        caddr_t desaddr, allocaddr;
                    714:        int val;
                    715:        int i, allocated;
                    716:        void (*destructor)(void *);
                    717:
                    718:        val = LOOKUP(proc, "pthread__tsd_alloc", &allocaddr);
                    719:        if (val != 0)
                    720:                return val;
                    721:        val = LOOKUP(proc, "pthread__tsd_destructors", &desaddr);
                    722:        if (val != 0)
                    723:                return val;
                    724:
                    725:        for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
                    726:                val = READ(proc, allocaddr + i * sizeof(int),
                    727:                    &allocated, sizeof(int));
                    728:                if (val != 0)
                    729:                        return val;
                    730:
                    731:                if (allocated) {
                    732:                        val = READ(proc,  desaddr + i * sizeof(destructor),
                    733:                            &destructor, sizeof(destructor));
                    734:                        if (val != 0)
                    735:                                return val;
                    736:
                    737:                        val = (call)(i, destructor, arg);
                    738:                        if (val != 0)
                    739:                                return val;
                    740:                }
                    741:        }
                    742:
                    743:        return 0;
                    744: }
                    745:
                    746: /* Get the synchronization object that the thread is sleeping on */
                    747: int
                    748: td_thr_sleepinfo(td_thread_t *thread, td_sync_t **s)
                    749: {
                    750:        int val;
                    751:        caddr_t addr;
                    752:
                    753:        if ((val = READ(thread->proc,
                    754:            thread->addr + offsetof(struct pthread_st, pt_sleepobj),
                    755:            &addr, sizeof(caddr_t))) != 0)
                    756:                return val;
                    757:
                    758:        td__getsync(thread->proc, addr, s);
                    759:
                    760:        return 0;
                    761:
                    762: }
                    763:
                    764:
                    765:
                    766: static int
                    767: td__getthread(td_proc_t *proc, caddr_t addr, td_thread_t **threadp)
                    768: {
                    769:        td_thread_t *thread;
                    770:
                    771:
                    772:        /* Check if we've allocated a descriptor for this thread.
                    773:         * Sadly, this makes iterating over a set of threads O(N^2)
                    774:         * in the number of threads. More sophisticated data structures
                    775:         * can wait.
                    776:                 */
                    777:        PTQ_FOREACH(thread, &proc->threads, list) {
                    778:                if (thread->addr == addr)
                    779:                        break;
                    780:        }
                    781:        if (thread == NULL) {
                    782:                thread = malloc(sizeof(*thread));
                    783:                if (thread == NULL)
                    784:                        return TD_ERR_NOMEM;
                    785:                thread->proc = proc;
                    786:                thread->addr = addr;
                    787:                PTQ_INSERT_HEAD(&proc->threads, thread, list);
                    788:        }
                    789:
                    790:        *threadp = thread;
                    791:        return 0;
                    792: }
                    793:
                    794:
                    795: static int
                    796: td__getsync(td_proc_t *proc, caddr_t addr, td_sync_t **syncp)
                    797: {
                    798:        td_sync_t *s;
                    799:
                    800:        /* Check if we've allocated a descriptor for this object. */
                    801:        PTQ_FOREACH(s, &proc->syncs, list) {
                    802:                if (s->addr == addr)
                    803:                        break;
                    804:        }
                    805:        /* Allocate a fresh one */
                    806:        if (s == NULL) {
                    807:                s = malloc(sizeof(*s));
                    808:                if (s == NULL)
                    809:                        return TD_ERR_NOMEM;
                    810:                s->proc = proc;
                    811:                s->addr = addr;
                    812:                PTQ_INSERT_HEAD(&proc->syncs, s, list);
                    813:        }
                    814:
                    815:        *syncp = s;
                    816:        return 0;
                    817: }
                    818:
                    819:
                    820: int
                    821: td_thr_tsd(td_thread_t *thread, pthread_key_t key, void **value)
                    822: {
                    823:        int val;
                    824:
                    825:        val = READ(thread->proc, thread->addr +
                    826:            offsetof(struct pthread_st, pt_specific) +
                    827:            key * sizeof(void *), &value, sizeof(void *));
                    828:
                    829:        return val;
                    830: }
                    831:

CVSweb <webmaster@jp.NetBSD.org>