summaryrefslogtreecommitdiff
path: root/devel/gdb/files/fbsd-threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/gdb/files/fbsd-threads.c')
-rw-r--r--devel/gdb/files/fbsd-threads.c88
1 files changed, 63 insertions, 25 deletions
diff --git a/devel/gdb/files/fbsd-threads.c b/devel/gdb/files/fbsd-threads.c
index 7ee69c20c5cf..68ebfad6d5a2 100644
--- a/devel/gdb/files/fbsd-threads.c
+++ b/devel/gdb/files/fbsd-threads.c
@@ -18,11 +18,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <err.h>
-
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
@@ -151,7 +146,7 @@ static CORE_ADDR td_death_bp_addr;
/* Prototypes for local functions. */
static void fbsd_find_lwp_name(long lwpid, struct private_thread_info *info);
-static void fbsd_thread_find_new_threads (struct target_ops *ops);
+static void fbsd_thread_update_thread_list (struct target_ops *ops);
static int fbsd_thread_alive (struct target_ops *ops, ptid_t ptid);
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose);
@@ -446,7 +441,7 @@ fbsd_thread_activate (void)
fbsd_thread_active = 1;
if (target_has_execution)
enable_thread_event_reporting ();
- fbsd_thread_find_new_threads (NULL);
+ fbsd_thread_update_thread_list (NULL);
get_current_thread ();
}
@@ -809,6 +804,7 @@ fbsd_thread_fetch_registers (struct target_ops *ops,
prgregset_t gregset;
prfpregset_t fpregset;
td_thrhandle_t th;
+ td_thrinfo_t ti;
td_err_e err;
#ifdef PT_GETXMMREGS
char xmmregs[512];
@@ -828,6 +824,25 @@ fbsd_thread_fetch_registers (struct target_ops *ops,
pid_to_thread_id (inferior_ptid),
GET_THREAD (inferior_ptid), thread_db_err_str (err));
+ err = td_thr_get_info_p (&th, &ti);
+ if (err != TD_OK)
+ error ("Cannot get thread info, Thread ID=%ld, %s",
+ GET_THREAD (inferior_ptid), thread_db_err_str (err));
+
+ if (ti.ti_lid != 0)
+ {
+ struct target_ops *beneath = find_target_beneath (ops);
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_ptid ();
+
+ inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid));
+ beneath->to_fetch_registers (ops, regcache, regnum);
+
+ do_cleanups (old_chain);
+ return;
+ }
+
err = td_thr_getgregs_p (&th, gregset);
if (err != TD_OK)
error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s",
@@ -862,6 +877,7 @@ fbsd_thread_store_registers (struct target_ops *ops,
prgregset_t gregset;
prfpregset_t fpregset;
td_thrhandle_t th;
+ td_thrinfo_t ti;
td_err_e err;
#ifdef PT_GETXMMREGS
char xmmregs[512];
@@ -882,6 +898,25 @@ fbsd_thread_store_registers (struct target_ops *ops,
GET_THREAD (inferior_ptid),
thread_db_err_str (err));
+ err = td_thr_get_info_p (&th, &ti);
+ if (err != TD_OK)
+ error ("Cannot get thread info, Thread ID=%ld, %s",
+ GET_THREAD (inferior_ptid), thread_db_err_str (err));
+
+ if (ti.ti_lid != 0)
+ {
+ struct target_ops *beneath = find_target_beneath (ops);
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_ptid ();
+
+ inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid));
+ beneath->to_store_registers (ops, regcache, regnum);
+
+ do_cleanups (old_chain);
+ return;
+ }
+
if (regnum != -1)
{
char old_value[MAX_REGISTER_SIZE];
@@ -1013,7 +1048,7 @@ fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
}
static int
-find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
+update_thread_list_callback (const td_thrhandle_t *th_p, void *data)
{
td_thrinfo_t ti;
td_err_e err;
@@ -1033,12 +1068,15 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
}
static void
-fbsd_thread_find_new_threads (struct target_ops *ops)
+fbsd_thread_update_thread_list (struct target_ops *ops)
{
td_err_e err;
+ /* Delete dead threads. */
+ prune_threads();
+
/* Iterate over all user-space threads to discover new threads. */
- err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
+ err = td_ta_thr_iter_p (thread_agent, update_thread_list_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
if (err != TD_OK)
@@ -1048,6 +1086,7 @@ fbsd_thread_find_new_threads (struct target_ops *ops)
static void
fbsd_find_lwp_name(long lwpid, struct private_thread_info *info)
{
+ struct cleanup *old_chain;
int error, name[4];
unsigned int i;
struct kinfo_proc *kipp, *kip;
@@ -1061,21 +1100,22 @@ fbsd_find_lwp_name(long lwpid, struct private_thread_info *info)
name[3] = pid;
error = sysctl(name, 4, NULL, &len, NULL, 0);
- if (error < 0 && errno != ESRCH) {
- warn("sysctl: kern.proc.pid: %d", pid);
- return;
- }
- if (error < 0)
+ if (error < 0) {
+ if (errno != ESRCH)
+ warning (_("sysctl: kern.proc.pid: %d: %s"), pid,
+ safe_strerror (errno));
return;
+ }
- kip = malloc(len);
+ kip = xmalloc(len);
if (kip == NULL)
- err(-1, "malloc");
+ return;
+ old_chain = make_cleanup(xfree, kip);
if (sysctl(name, 4, kip, &len, NULL, 0) < 0) {
- warn("sysctl: kern.proc.pid: %d", pid);
- free(kip);
- return;
+ warning (_("sysctl: kern.proc.pid: %d: %s"), pid, safe_strerror(errno));
+ do_cleanups(old_chain);
+ return;
}
for (i = 0; i < len / sizeof(*kipp); i++) {
@@ -1097,15 +1137,13 @@ fbsd_find_lwp_name(long lwpid, struct private_thread_info *info)
}
}
- len = strlen(kipp->ki_ocomm) + 1;
- lwpstr = xmalloc(len);
- strncpy(lwpstr, kipp->ki_ocomm, len);
+ lwpstr = xstrdup(kipp->ki_ocomm);
info->lwp_name = lwpstr;
break;
}
}
- free(kip);
+ do_cleanups(old_chain);
}
static char *
@@ -1316,7 +1354,7 @@ init_fbsd_thread_ops (void)
fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers;
fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior;
fbsd_thread_ops.to_thread_alive = fbsd_thread_alive;
- fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads;
+ fbsd_thread_ops.to_update_thread_list = fbsd_thread_update_thread_list;
fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str;
fbsd_thread_ops.to_stratum = thread_stratum;
fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address;