From 9532eb67a4a92baab960d8d37bfa28048285dabb Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 5 Nov 1999 02:26:16 +0000 Subject: Update. 1999-11-03 Ulrich Drepper * Versions.def: Add version for libthread_db. --- ChangeLog | 4 ++ Versions.def | 3 ++ linuxthreads_db/ChangeLog | 25 ++++++++++++ linuxthreads_db/Versions | 15 ++++++++ linuxthreads_db/td_ta_clear_event.c | 4 ++ linuxthreads_db/td_ta_delete.c | 23 ++++++++++++ linuxthreads_db/td_ta_enable_stats.c | 5 +++ linuxthreads_db/td_ta_event_addr.c | 4 ++ linuxthreads_db/td_ta_event_getmsg.c | 4 ++ linuxthreads_db/td_ta_get_nthreads.c | 4 ++ linuxthreads_db/td_ta_get_ph.c | 4 ++ linuxthreads_db/td_ta_get_stats.c | 5 +++ linuxthreads_db/td_ta_map_id2thr.c | 22 +++++++++-- linuxthreads_db/td_ta_map_lwp2thr.c | 69 ++++++++++++++++++++++------------ linuxthreads_db/td_ta_new.c | 20 ++++++++++ linuxthreads_db/td_ta_reset_stats.c | 5 +++ linuxthreads_db/td_ta_set_event.c | 4 ++ linuxthreads_db/td_ta_setconcurrency.c | 5 +++ linuxthreads_db/td_ta_thr_iter.c | 28 +++++++++++--- linuxthreads_db/td_ta_tsd_iter.c | 32 +++++++++------- linuxthreads_db/td_thr_get_info.c | 1 + linuxthreads_db/thread_dbP.h | 25 ++++++++++++ 22 files changed, 263 insertions(+), 48 deletions(-) create mode 100644 linuxthreads_db/Versions diff --git a/ChangeLog b/ChangeLog index 86ffc43..54e379d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +1999-11-03 Ulrich Drepper + + * Versions.def: Add version for libthread_db. + 1999-11-02 Andreas Jaeger * manual/header.texi (Library Summary): The command @indexfonts diff --git a/Versions.def b/Versions.def index 4a3ee42..82b0f1d 100644 --- a/Versions.def +++ b/Versions.def @@ -81,3 +81,6 @@ ld.so { GLIBC_2.1 GLIBC_2.0 GLIBC_2.1.1 GLIBC_2.1 } +libthread_db { + GLIBC_2.1.3 +} diff --git a/linuxthreads_db/ChangeLog b/linuxthreads_db/ChangeLog index 0922e9e..f2286c9 100644 --- a/linuxthreads_db/ChangeLog +++ b/linuxthreads_db/ChangeLog @@ -1,3 +1,28 @@ +1999-11-03 Ulrich Drepper + + * thread_dbP.h (ta_ok): New function. + * td_ta_new.c: Add new handle to list. + * td_ta_delete.c: Remove handle from list. + * td_ta_clear_event.c: Use ta_ok to check for correct ta parameter. + * td_ta_enable_stats.c: Likewise. + * td_ta_event_addr.c: Likewise. + * td_ta_event_getmsg.c: Likewise. + * td_ta_get_nthreads.c: Likewise. + * td_ta_get_ph.c: Likewise. + * td_ta_get_stats.c: Likewise. + * td_ta_map_id2thr.c: Likewise. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_reset_stats.c: Likewise. + * td_ta_set_event.c: Likewise. + * td_ta_setconcurrency.c: Likewise. + * td_ta_thr_iter.c: Likewise. + + * td_ta_tsd_iter.c: Optimize memory retrieving. + + * Versions: New file. + + * td_thr_get_info.c (td_thr_get_info): Initialize ti_traceme. + 1999-11-02 Ulrich Drepper * td_ta_thr_iter.c (td_ta_thr_iter): Optimize a bit. Read all diff --git a/linuxthreads_db/Versions b/linuxthreads_db/Versions new file mode 100644 index 0000000..83b30ee --- /dev/null +++ b/linuxthreads_db/Versions @@ -0,0 +1,15 @@ +libthread_db { + GLIBC_2.1.3 { + # t* + td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; + td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; + td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; + td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; + td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; + td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; + td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; + td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; + td_thr_tsd; td_thr_validate; + } +} diff --git a/linuxthreads_db/td_ta_clear_event.c b/linuxthreads_db/td_ta_clear_event.c index ec7770e..02d8336 100644 --- a/linuxthreads_db/td_ta_clear_event.c +++ b/linuxthreads_db/td_ta_clear_event.c @@ -31,6 +31,10 @@ td_ta_clear_event (ta, event) LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + /* Write the new value into the thread data structure. */ if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, &old_event, sizeof (td_thrhandle_t)) != PS_OK) diff --git a/linuxthreads_db/td_ta_delete.c b/linuxthreads_db/td_ta_delete.c index a8031f2..e983577 100644 --- a/linuxthreads_db/td_ta_delete.c +++ b/linuxthreads_db/td_ta_delete.c @@ -28,6 +28,29 @@ td_ta_delete (td_thragent_t *ta) { LOG (__FUNCTION__); + /* Safety check. */ + if (ta == NULL || __td_agent_list == NULL) + return TD_BADTA; + + /* Remove the handle from the list. */ + if (ta == __td_agent_list->ta) + /* It's the first element of the list. */ + __td_agent_list = __td_agent_list->next; + else + { + /* We have to search for it. */ + struct agent_list *runp = __td_agent_list; + + while (runp->next != NULL && runp->next->ta != ta) + runp = runp->next; + + if (runp->next == NULL) + /* It's not a valid decriptor since it is not in the list. */ + return TD_BADTA; + + runp->next = runp->next->next; + } + /* The handle was allocated in `td_ta_new'. */ free (ta); diff --git a/linuxthreads_db/td_ta_enable_stats.c b/linuxthreads_db/td_ta_enable_stats.c index eb3a338..abf4d20 100644 --- a/linuxthreads_db/td_ta_enable_stats.c +++ b/linuxthreads_db/td_ta_enable_stats.c @@ -26,5 +26,10 @@ td_ta_enable_stats (const td_thragent_t *ta, int enable) { /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + return TD_OK; } diff --git a/linuxthreads_db/td_ta_event_addr.c b/linuxthreads_db/td_ta_event_addr.c index 4edd54c..7f217f1 100644 --- a/linuxthreads_db/td_ta_event_addr.c +++ b/linuxthreads_db/td_ta_event_addr.c @@ -31,6 +31,10 @@ td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + switch (event) { case TD_CREATE: diff --git a/linuxthreads_db/td_ta_event_getmsg.c b/linuxthreads_db/td_ta_event_getmsg.c index 6b56e0d..4c635dc 100644 --- a/linuxthreads_db/td_ta_event_getmsg.c +++ b/linuxthreads_db/td_ta_event_getmsg.c @@ -34,6 +34,10 @@ td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg) LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + /* Get the pointer to the thread descriptor with the last event. */ if (ps_pdread (ta->ph, ta->pthread_last_event, &addr, sizeof (void *)) != PS_OK) diff --git a/linuxthreads_db/td_ta_get_nthreads.c b/linuxthreads_db/td_ta_get_nthreads.c index 13d5032..9396250 100644 --- a/linuxthreads_db/td_ta_get_nthreads.c +++ b/linuxthreads_db/td_ta_get_nthreads.c @@ -28,6 +28,10 @@ td_ta_get_nthreads (const td_thragent_t *ta, int *np) LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + /* Access the variable `__pthread_handles_num'. */ if (ps_pglobal_lookup (ta->ph, LIBPTHREAD_SO, "__pthread_handles_num", &addr) != PS_OK) diff --git a/linuxthreads_db/td_ta_get_ph.c b/linuxthreads_db/td_ta_get_ph.c index 538990f..b748916 100644 --- a/linuxthreads_db/td_ta_get_ph.c +++ b/linuxthreads_db/td_ta_get_ph.c @@ -26,6 +26,10 @@ td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) { LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + *ph = ta->ph; return TD_OK; diff --git a/linuxthreads_db/td_ta_get_stats.c b/linuxthreads_db/td_ta_get_stats.c index d8f5fe2..1741d81 100644 --- a/linuxthreads_db/td_ta_get_stats.c +++ b/linuxthreads_db/td_ta_get_stats.c @@ -26,5 +26,10 @@ td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) { /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + return TD_OK; } diff --git a/linuxthreads_db/td_ta_map_id2thr.c b/linuxthreads_db/td_ta_map_id2thr.c index ffbc8b2..6fb1ba9 100644 --- a/linuxthreads_db/td_ta_map_id2thr.c +++ b/linuxthreads_db/td_ta_map_id2thr.c @@ -24,14 +24,21 @@ td_err_e td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) { - struct pthread_handle_struct *handles = ta->handles; struct pthread_handle_struct phc; - int pthread_threads_max = ta->pthread_threads_max; + struct _pthread_descr_struct pds; + int pthread_threads_max; LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Make the following expression a bit smaller. */ + pthread_threads_max = ta->pthread_threads_max; + /* We can compute the entry in the handle array we want. */ - if (ps_pdread (ta->ph, handles + pt % pthread_threads_max, &phc, + if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc, sizeof (struct pthread_handle_struct)) != PS_OK) return TD_ERR; /* XXX Other error value? */ @@ -39,6 +46,15 @@ td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) if (phc.h_descr == NULL) return TD_BADTH; + /* Next test: get the descriptor to see whether this is not an old + thread handle. */ + if (ps_pdread (ta->ph, phc.h_descr, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_tid != pt) + return TD_BADTH; + /* Create the `td_thrhandle_t' object. */ th->th_ta_p = (td_thragent_t *) ta; th->th_unique = phc.h_descr; diff --git a/linuxthreads_db/td_ta_map_lwp2thr.c b/linuxthreads_db/td_ta_map_lwp2thr.c index 995620f..f51bc18 100644 --- a/linuxthreads_db/td_ta_map_lwp2thr.c +++ b/linuxthreads_db/td_ta_map_lwp2thr.c @@ -24,38 +24,57 @@ td_err_e td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) { - struct pthread_handle_struct *handles = ta->handles; int pthread_threads_max = ta->pthread_threads_max; + size_t sizeof_descr = ta->sizeof_descr; + struct pthread_handle_struct phc[pthread_threads_max]; size_t cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * pthread_threads_max) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + /* Get the entries one after the other and find out whether the ID matches. */ - for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles) - { - struct pthread_handle_struct phc; - struct _pthread_descr_struct pds; - - if (ps_pdread (ta->ph, handles, &phc, - sizeof (struct pthread_handle_struct)) != PS_OK) - return TD_ERR; /* XXX Other error value? */ - - if (phc.h_descr != NULL) - { - if (ps_pdread (ta->ph, phc.h_descr, &pds, - sizeof (struct _pthread_descr_struct)) != PS_OK) - return TD_ERR; /* XXX Other error value? */ - - if (pds.p_pid == lwpid) - { - /* Found it. Now fill in the `td_thrhandle_t' object. */ - th->th_ta_p = (td_thragent_t *) ta; - th->th_unique = phc.h_descr; - - return TD_OK; - } - } + for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { + struct _pthread_descr_struct pds; + +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_pid == lwpid) + { + /* Found it. Now fill in the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc[cnt].h_descr; + + return TD_OK; + } } return TD_NOLWP; diff --git a/linuxthreads_db/td_ta_new.c b/linuxthreads_db/td_ta_new.c index 65535f8..8d6ee9a 100644 --- a/linuxthreads_db/td_ta_new.c +++ b/linuxthreads_db/td_ta_new.c @@ -25,10 +25,16 @@ #include "thread_dbP.h" +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +struct agent_list *__td_agent_list; + + td_err_e td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) { psaddr_t addr; + struct agent_list *elemp; LOG (__FUNCTION__); @@ -130,5 +136,19 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) goto free_return; } + /* Now add the new agent descriptor to the list. */ + elemp = (struct agent_list *) malloc (sizeof (struct agent_list)); + if (elemp == NULL) + { + /* Argh, now that everything else worked... */ + free (*ta); + return TD_MALLOC; + } + + /* We don't care for thread-safety here. */ + elemp->ta = *ta; + elemp->next = __td_agent_list; + __td_agent_list = elemp; + return TD_OK; } diff --git a/linuxthreads_db/td_ta_reset_stats.c b/linuxthreads_db/td_ta_reset_stats.c index 1ea1e71..11401b9 100644 --- a/linuxthreads_db/td_ta_reset_stats.c +++ b/linuxthreads_db/td_ta_reset_stats.c @@ -26,5 +26,10 @@ td_ta_reset_stats (const td_thragent_t *ta) { /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + return TD_OK; } diff --git a/linuxthreads_db/td_ta_set_event.c b/linuxthreads_db/td_ta_set_event.c index f783d75..4d87fe1 100644 --- a/linuxthreads_db/td_ta_set_event.c +++ b/linuxthreads_db/td_ta_set_event.c @@ -31,6 +31,10 @@ td_ta_set_event (ta, event) LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + /* Write the new value into the thread data structure. */ if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, &old_event, sizeof (td_thrhandle_t)) != PS_OK) diff --git a/linuxthreads_db/td_ta_setconcurrency.c b/linuxthreads_db/td_ta_setconcurrency.c index eec9968..5bb2601 100644 --- a/linuxthreads_db/td_ta_setconcurrency.c +++ b/linuxthreads_db/td_ta_setconcurrency.c @@ -26,5 +26,10 @@ td_ta_setconcurrency (const td_thragent_t *ta, int level) { /* This is something LinuxThreads does not support. */ LOG (__FUNCTION__); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + return TD_NOCAPAB; } diff --git a/linuxthreads_db/td_ta_thr_iter.c b/linuxthreads_db/td_ta_thr_iter.c index 1fe871f..ecc86c7 100644 --- a/linuxthreads_db/td_ta_thr_iter.c +++ b/linuxthreads_db/td_ta_thr_iter.c @@ -26,24 +26,38 @@ td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, unsigned int ti_user_flags) { - int pthread_threads_max = ta->pthread_threads_max; - size_t sizeof_descr = ta->sizeof_descr; - struct pthread_handle_struct phc[pthread_threads_max]; - int num; + int pthread_threads_max; + size_t sizeof_descr; + struct pthread_handle_struct *phc; int cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif LOG (__FUNCTION__); + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_threads_max = ta->pthread_threads_max; + sizeof_descr = ta->sizeof_descr; + phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) + * pthread_threads_max); + /* Read all the descriptors. */ if (ps_pdread (ta->ph, ta->handles, phc, sizeof (struct pthread_handle_struct) * pthread_threads_max) != PS_OK) return TD_ERR; /* XXX Other error value? */ +#ifdef ALL_THREADS_STOPPED /* Read the number of currently active threads. */ - if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) - != PS_OK) + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) return TD_ERR; /* XXX Other error value? */ +#endif /* Now get all descriptors, one after the other. */ for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) @@ -52,8 +66,10 @@ td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, struct _pthread_descr_struct pds; td_thrhandle_t th; +#ifdef ALL_THREADS_STOPPED /* First count this active thread. */ --num; +#endif if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) diff --git a/linuxthreads_db/td_ta_tsd_iter.c b/linuxthreads_db/td_ta_tsd_iter.c index 4eada2b..c58928c 100644 --- a/linuxthreads_db/td_ta_tsd_iter.c +++ b/linuxthreads_db/td_ta_tsd_iter.c @@ -25,27 +25,31 @@ td_err_e td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback, void *cbdata_p) { - struct pthread_key_struct *keys = ta->keys; - int pthread_keys_max = ta->pthread_keys_max; + struct pthread_key_struct *keys; + int pthread_keys_max; int cnt; - /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); - /* Now get all descriptors, one after the other. */ - for (cnt = 0; cnt < pthread_keys_max; ++cnt, ++keys) - { - struct pthread_key_struct key; + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_keys_max = ta->pthread_keys_max; + keys = (struct pthread_key_struct *) alloca (sizeof (keys[0]) + * pthread_keys_max); - if (ps_pdread (ta->ph, keys, &key, - sizeof (struct pthread_key_struct)) != PS_OK) + /* Read all the information about the keys. */ + if (ps_pdread (ta->ph, ta->keys, keys, + sizeof (keys[0]) * pthread_keys_max) != PS_OK) return TD_ERR; /* XXX Other error value? */ - if (key.in_use - /* Return with an error if the callback returns a nonzero value. */ - && callback (cnt, key.destr, cbdata_p) != 0) - return TD_DBERR; - } + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_keys_max; ++cnt) + if (keys[cnt].in_use + /* Return with an error if the callback returns a nonzero value. */ + && callback (cnt, keys[cnt].destr, cbdata_p) != 0) + return TD_DBERR; return TD_OK; } diff --git a/linuxthreads_db/td_thr_get_info.c b/linuxthreads_db/td_thr_get_info.c index 1e05d4c..21f9f68 100644 --- a/linuxthreads_db/td_thr_get_info.c +++ b/linuxthreads_db/td_thr_get_info.c @@ -69,6 +69,7 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) infop->ti_startfunc = pds.p_start_args.start_routine; memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask, sizeof (td_thr_events_t)); + infop->ti_traceme = pds.p_report_events != 0; return TD_OK; } diff --git a/linuxthreads_db/thread_dbP.h b/linuxthreads_db/thread_dbP.h index 6092183..7e9fb48 100644 --- a/linuxthreads_db/thread_dbP.h +++ b/linuxthreads_db/thread_dbP.h @@ -50,4 +50,29 @@ struct td_thragent }; +/* Type used internally to keep track of thread agent descriptors. */ +struct agent_list +{ + td_thragent_t *ta; + struct agent_list *next; +}; + +/* List of all known descriptors. */ +extern struct agent_list *__td_agent_list; + +/* Function used to test for correct thread agent pointer. */ +static inline int +ta_ok (const td_thragent_t *ta) +{ + struct agent_list *runp = __td_agent_list; + + if (ta == NULL) + return 0; + + while (runp != NULL && runp->ta != ta) + runp = runp->next; + + return runp != NULL; +} + #endif /* thread_dbP.h */ -- cgit v1.1