summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/thread-db.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver/thread-db.c')
-rw-r--r--gdb/gdbserver/thread-db.c110
1 files changed, 70 insertions, 40 deletions
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index f3b85617ff8..5566e0e8129 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -41,7 +41,7 @@ static struct ps_prochandle proc_handle;
/* Connection to the libthread_db library. */
static td_thragent_t *thread_agent;
-static void thread_db_find_new_threads (void);
+static int find_first_thread (void);
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
static char *
@@ -135,15 +135,11 @@ thread_db_create_event (CORE_ADDR where)
{
td_event_msg_t msg;
td_err_e err;
- struct inferior_linux_data *tdata;
- struct thread_info *inferior;
struct process_info *process;
if (debug_threads)
fprintf (stderr, "Thread creation event.\n");
- tdata = inferior_target_data (current_inferior);
-
/* FIXME: This assumes we don't get another event.
In the LinuxThreads implementation, this is safe,
because all events come from the manager thread
@@ -156,10 +152,9 @@ thread_db_create_event (CORE_ADDR where)
/* If we do not know about the main thread yet, this would be a good time to
find it. We need to do this to pick up the main thread before any newly
created threads. */
- inferior = (struct thread_info *) all_threads.head;
- process = get_thread_process (inferior);
+ process = get_thread_process (current_inferior);
if (process->thread_known == 0)
- thread_db_find_new_threads ();
+ find_first_thread ();
/* msg.event == TD_EVENT_CREATE */
@@ -230,43 +225,73 @@ thread_db_enable_reporting ()
return 1;
}
-static void
-maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
+static int
+find_first_thread (void)
{
+ td_thrhandle_t th;
+ td_thrinfo_t ti;
td_err_e err;
struct thread_info *inferior;
struct process_info *process;
- /* If we are attaching to our first thread, things are a little
- different. */
- if (all_threads.head == all_threads.tail)
+ inferior = (struct thread_info *) all_threads.head;
+ process = get_thread_process (inferior);
+ if (process->thread_known)
+ return 1;
+
+ /* Get information about the one thread we know we have. */
+ err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th);
+ if (err != TD_OK)
+ error ("Cannot get first thread handle: %s", thread_db_err_str (err));
+
+ err = td_thr_get_info (&th, &ti);
+ if (err != TD_OK)
+ error ("Cannot get first thread info: %s", thread_db_err_str (err));
+
+ if (debug_threads)
+ fprintf (stderr, "Found first thread %ld (LWP %d)\n",
+ ti.ti_tid, ti.ti_lid);
+
+ if (process->lwpid != ti.ti_lid)
+ fatal ("PID mismatch! Expected %ld, got %ld",
+ (long) process->lwpid, (long) ti.ti_lid);
+
+ /* If the new thread ID is zero, a final thread ID will be available
+ later. Do not enable thread debugging yet. */
+ if (ti.ti_tid == 0)
{
- inferior = (struct thread_info *) all_threads.head;
- process = get_thread_process (inferior);
-
- if (process->thread_known == 0)
- {
- /* If the new thread ID is zero, a final thread ID will be
- available later. Do not enable thread debugging yet. */
- if (ti_p->ti_tid == 0)
- {
- err = td_thr_event_enable (th_p, 1);
- if (err != TD_OK)
- error ("Cannot enable thread event reporting for %d: %s",
- ti_p->ti_lid, thread_db_err_str (err));
- return;
- }
-
- if (process->lwpid != ti_p->ti_lid)
- fatal ("PID mismatch! Expected %ld, got %ld",
- (long) process->lwpid, (long) ti_p->ti_lid);
-
- /* Switch to indexing the threads list by TID. */
- change_inferior_id (&all_threads, ti_p->ti_tid);
- goto found;
- }
+ err = td_thr_event_enable (&th, 1);
+ if (err != TD_OK)
+ error ("Cannot enable thread event reporting for %d: %s",
+ ti.ti_lid, thread_db_err_str (err));
+ return 0;
}
-
+
+ /* Switch to indexing the threads list by TID. */
+ change_inferior_id (&all_threads, ti.ti_tid);
+
+ new_thread_notify (ti.ti_tid);
+
+ process->tid = ti.ti_tid;
+ process->lwpid = ti.ti_lid;
+ process->thread_known = 1;
+ process->th = th;
+
+ err = td_thr_event_enable (&th, 1);
+ if (err != TD_OK)
+ error ("Cannot enable thread event reporting for %d: %s",
+ ti.ti_lid, thread_db_err_str (err));
+
+ return 1;
+}
+
+static void
+maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
+{
+ td_err_e err;
+ struct thread_info *inferior;
+ struct process_info *process;
+
inferior = (struct thread_info *) find_inferior_id (&all_threads,
ti_p->ti_tid);
if (inferior != NULL)
@@ -287,7 +312,6 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
process = inferior_target_data (inferior);
-found:
new_thread_notify (ti_p->ti_tid);
process->tid = ti_p->ti_tid;
@@ -325,6 +349,12 @@ thread_db_find_new_threads (void)
{
td_err_e err;
+ /* This function is only called when we first initialize thread_db.
+ First locate the initial thread. If it is not ready for
+ debugging yet, then stop. */
+ if (find_first_thread () == 0)
+ return;
+
/* Iterate over all user-space threads to discover new threads. */
err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
@@ -359,7 +389,7 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
process = get_thread_process (thread);
if (!process->thread_known)
- thread_db_find_new_threads ();
+ find_first_thread ();
if (!process->thread_known)
return TD_NOTHR;