diff options
author | davidxu <davidxu@FreeBSD.org> | 2004-07-15 03:36:35 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2004-07-15 03:36:35 +0000 |
commit | f64cd4bec9b12cafda2f341065400c877cd8c4f5 (patch) | |
tree | 5391cf6197c761aa0db16e260592bd92535e5ba9 /lib/libthread_db/include | |
parent | 61f27b8eb8fc6a29ff1468552ebbdc11a509ce7d (diff) | |
download | FreeBSD-src-f64cd4bec9b12cafda2f341065400c877cd8c4f5.zip FreeBSD-src-f64cd4bec9b12cafda2f341065400c877cd8c4f5.tar.gz |
Add my initial work of libthread_db. The library is used by gdb to debug
threaded process. Current, only libpthread is supported, but macrel will
work on it to support libthr and libc_r.
Diffstat (limited to 'lib/libthread_db/include')
-rw-r--r-- | lib/libthread_db/include/thread_db.h | 287 | ||||
-rw-r--r-- | lib/libthread_db/include/thread_db_int.h | 93 |
2 files changed, 380 insertions, 0 deletions
diff --git a/lib/libthread_db/include/thread_db.h b/lib/libthread_db/include/thread_db.h new file mode 100644 index 0000000..e5f0c32 --- /dev/null +++ b/lib/libthread_db/include/thread_db.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2004 David Xu <davidxu@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _THREAD_DB_H_ +#define _THREAD_DB_H_ + +#include <sys/types.h> +#include <pthread.h> + +typedef enum +{ + TD_OK, + TD_ERR, + TD_NOTHR, + TD_NOSV, + TD_NOLWP, + TD_BADPH, + TD_BADTH, + TD_BADSH, + TD_BADTA, + TD_BADKEY, + TD_NOMSG, + TD_NOFPREGS, + TD_NOLIBTHREAD, + TD_NOEVENT, + TD_NOCAPAB, + TD_DBERR, + TD_NOAPLIC, + TD_NOTSD, + TD_MALLOC, + TD_PARTIALREG, + TD_NOXREGS +} td_err_e; + +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + +typedef long thread_t; +typedef pthread_key_t thread_key_t; +typedef struct td_thragent td_thragent_t; + +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + thread_t th_unique; + int th_ta_data; +} td_thrhandle_t; + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY 0 +#define TD_SIGNO_MASK NULL + +typedef uint32_t td_thr_events_t; + +typedef enum +{ + TD_ALL_EVENTS, + TD_EVENT_NONE = TD_ALL_EVENTS, + TD_CREATE, + TD_DEATH, + TD_REAP, + TD_READY, + TD_SLEEP, + TD_SWITCHTO, + TD_SWITCHFROM, + TD_LOCK_TRY, + TD_CATCHSIG, + TD_IDLE, + TD_PREEMPT, + TD_PRI_INHERIT, + TD_CONCURRENCY, + TD_TIMEOUT, + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 +} td_event_e; + +typedef enum +{ + NOTIFY_BPT, + NOTIFY_AUTOBPT, + NOTIFY_SYSCALL +} td_notify_e; + +typedef struct td_notify +{ + td_notify_e type; + union { + psaddr_t bptaddr; + int syscallno; + } u; +} td_notify_t; + +typedef struct td_event_msg +{ + td_event_e event; + const td_thrhandle_t *th_p; + union { +#if 0 + td_synchandle_t *sh; +#endif + uintptr_t data; + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + +static inline void +td_event_emptyset(td_thr_events_t *setp) +{ + *setp = 0; +} + +static inline void +td_event_fillset(td_thr_events_t *setp) +{ + *setp = 0xFFFFFFFF; +} + +static inline void +td_event_addset(td_thr_events_t *setp, int n) +{ + *setp |= (1 << (n-1)); +} + +static inline void +td_event_delset(td_thr_events_t *setp, int n) +{ + *setp &= ~(1 << (n-1)); +} + +static inline int +td_eventismember(td_thr_events_t *setp, int n) +{ + return (*setp & (1 << (n-1)) ? 1 : 0); +} + +static inline int +td_eventisempty(td_thr_events_t *setp) +{ + return (*setp == 0); +} + +typedef int td_thr_iter_f(const td_thrhandle_t *, void *); +typedef int td_key_iter_f(thread_key_t, void (*) (void *), void *); + +struct ps_prochandle; + +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; + unsigned int ti_user_flags; + thread_t ti_tid; + char *ti_tls; + psaddr_t ti_startfunc; + psaddr_t ti_stkbase; + long int ti_stksize; + psaddr_t ti_ro_area; + int ti_ro_size; + td_thr_state_e ti_state; + unsigned char ti_db_suspended; + td_thr_type_e ti_type; + intptr_t ti_pc; + intptr_t ti_sp; + short int ti_flags; + int ti_pri; + lwpid_t ti_lid; + sigset_t ti_sigmask; + unsigned char ti_traceme; + unsigned char ti_preemptflag; + unsigned char ti_pirecflag; + sigset_t ti_pending; + td_thr_events_t ti_events; +} td_thrinfo_t; + +td_err_e td_init(void); +td_err_e td_log(void); +td_err_e td_ta_new(struct ps_prochandle *, td_thragent_t **); +td_err_e td_ta_delete(td_thragent_t *); +td_err_e td_ta_get_nthreads(const td_thragent_t *, int *); +td_err_e td_ta_get_ph(const td_thragent_t *, struct ps_prochandle **); +td_err_e td_ta_map_id2thr(const td_thragent_t *, thread_t, td_thrhandle_t *); +td_err_e td_ta_map_lwp2thr(const td_thragent_t *, lwpid_t lwpid, + td_thrhandle_t *); +td_err_e td_ta_thr_iter(const td_thragent_t *, td_thr_iter_f *, void *, + td_thr_state_e, int, sigset_t *, unsigned int); +td_err_e td_ta_tsd_iter(const td_thragent_t *, td_key_iter_f *, void *); +td_err_e td_ta_event_addr(const td_thragent_t *, td_event_e , td_notify_t *); +td_err_e td_ta_set_event(const td_thragent_t *, td_thr_events_t *); +td_err_e td_ta_clear_event(const td_thragent_t *, td_thr_events_t *); +td_err_e td_ta_event_getmsg(const td_thragent_t *, td_event_msg_t *); +td_err_e td_ta_setconcurrency(const td_thragent_t *, int); +td_err_e td_ta_enable_stats(const td_thragent_t *, int); +td_err_e td_ta_reset_stats(const td_thragent_t *); +td_err_e td_ta_get_stats(const td_thragent_t *, td_ta_stats_t *); +td_err_e td_thr_validate(const td_thrhandle_t *); +td_err_e td_thr_get_info(const td_thrhandle_t *, td_thrinfo_t *); +td_err_e td_thr_getfpregs(const td_thrhandle_t *, prfpregset_t *); +td_err_e td_thr_getgregs(const td_thrhandle_t *, prgregset_t); +td_err_e td_thr_getxregs(const td_thrhandle_t *, void *); +td_err_e td_thr_getxregsize(const td_thrhandle_t *, int *); +td_err_e td_thr_setfpregs(const td_thrhandle_t *, const prfpregset_t *); +td_err_e td_thr_setgregs(const td_thrhandle_t *, prgregset_t); +td_err_e td_thr_setxregs(const td_thrhandle_t *, const void *); +td_err_e td_thr_event_enable(const td_thrhandle_t *, int); +td_err_e td_thr_set_event(const td_thrhandle_t *, td_thr_events_t *); +td_err_e td_thr_clear_event(const td_thrhandle_t *, td_thr_events_t *); +td_err_e td_thr_event_getmsg(const td_thrhandle_t *, td_event_msg_t *); +td_err_e td_thr_setprio(const td_thrhandle_t *, int); +td_err_e td_thr_setsigpending(const td_thrhandle_t *, unsigned char, + const sigset_t *); +td_err_e td_thr_sigsetmask(const td_thrhandle_t *, const sigset_t *); +td_err_e td_thr_tsd(const td_thrhandle_t *, const thread_key_t, void **); +td_err_e td_thr_dbsuspend(const td_thrhandle_t *); +td_err_e td_thr_dbresume(const td_thrhandle_t *); +td_err_e td_get_ta(int pid, td_thragent_t **); +td_err_e td_ta_activated(td_thragent_t *, int *); +td_err_e td_thr_sstep(td_thrhandle_t *, int); + +#endif diff --git a/lib/libthread_db/include/thread_db_int.h b/lib/libthread_db/include/thread_db_int.h new file mode 100644 index 0000000..177cb4a --- /dev/null +++ b/lib/libthread_db/include/thread_db_int.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2004 David Xu <davidxu@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _THREAD_DB_INT_H +#define _THREAD_DB_INT_H + +#include <sys/types.h> +#include <sys/queue.h> + +struct td_thragent { + struct ta_ops *ta_ops; + TAILQ_ENTRY(td_thragent) ta_next; +}; + +struct ta_ops { + td_err_e (*to_init)(void); + td_err_e (*to_ta_new)(struct ps_prochandle *, td_thragent_t **); + td_err_e (*to_ta_delete)(td_thragent_t *); + td_err_e (*to_ta_get_nthreads)(const td_thragent_t *, int *); + td_err_e (*to_ta_get_ph)(const td_thragent_t *, struct ps_prochandle **); + td_err_e (*to_ta_map_id2thr)(const td_thragent_t *, thread_t, td_thrhandle_t *); + td_err_e (*to_ta_map_lwp2thr)(const td_thragent_t *, lwpid_t lwpid, + td_thrhandle_t *); + td_err_e (*to_ta_thr_iter)(const td_thragent_t *, td_thr_iter_f *, void *, + td_thr_state_e, int, sigset_t *, unsigned int); + td_err_e (*to_ta_tsd_iter)(const td_thragent_t *, td_key_iter_f *, void *); + td_err_e (*to_ta_event_addr)(const td_thragent_t *, td_event_e , td_notify_t *); + td_err_e (*to_ta_set_event)(const td_thragent_t *, td_thr_events_t *); + td_err_e (*to_ta_clear_event)(const td_thragent_t *, td_thr_events_t *); + td_err_e (*to_ta_event_getmsg)(const td_thragent_t *, td_event_msg_t *); + td_err_e (*to_ta_setconcurrency)(const td_thragent_t *, int); + td_err_e (*to_ta_enable_stats)(const td_thragent_t *, int); + td_err_e (*to_ta_reset_stats)(const td_thragent_t *); + td_err_e (*to_ta_get_stats)(const td_thragent_t *, td_ta_stats_t *); + td_err_e (*to_thr_validate)(const td_thrhandle_t *); + td_err_e (*to_thr_get_info)(const td_thrhandle_t *, td_thrinfo_t *); + td_err_e (*to_thr_getfpregs)(const td_thrhandle_t *, prfpregset_t *); + td_err_e (*to_thr_getgregs)(const td_thrhandle_t *, prgregset_t); + td_err_e (*to_thr_getxregs)(const td_thrhandle_t *, void *); + td_err_e (*to_thr_getxregsize)(const td_thrhandle_t *, int *); + td_err_e (*to_thr_setfpregs)(const td_thrhandle_t *, const prfpregset_t *); + td_err_e (*to_thr_setgregs)(const td_thrhandle_t *, prgregset_t); + td_err_e (*to_thr_setxregs)(const td_thrhandle_t *, const void *); + td_err_e (*to_thr_event_enable)(const td_thrhandle_t *, int); + td_err_e (*to_thr_set_event)(const td_thrhandle_t *, td_thr_events_t *); + td_err_e (*to_thr_clear_event)(const td_thrhandle_t *, td_thr_events_t *); + td_err_e (*to_thr_event_getmsg)(const td_thrhandle_t *, td_event_msg_t *); + td_err_e (*to_thr_setprio)(const td_thrhandle_t *, int); + td_err_e (*to_thr_setsigpending)(const td_thrhandle_t *, unsigned char, + const sigset_t *); + td_err_e (*to_thr_sigsetmask)(const td_thrhandle_t *, const sigset_t *); + td_err_e (*to_thr_tsd)(const td_thrhandle_t *, const thread_key_t, void **); + td_err_e (*to_thr_dbsuspend)(const td_thrhandle_t *); + td_err_e (*to_thr_dbresume)(const td_thrhandle_t *); + td_err_e (*to_get_ta)(int pid, td_thragent_t **); + td_err_e (*to_ta_activated)(td_thragent_t *, int *); + td_err_e (*to_thr_sstep)(td_thrhandle_t *, int step); +}; + +#ifdef TD_DEBUG +#define TDBG(...) ps_plog(__VA_ARGS__) +#define TDBG_FUNC() ps_plog(__func__); ps_plog("\n") +#else +#define TDBG(...) +#define TDBG_FUNC() +#endif + +#endif |