2008-03-21 Daniel Jacobowitz <dan@codesourcery.com>
authorDaniel Jacobowitz <drow@false.org>
Fri, 21 Mar 2008 15:44:53 +0000 (15:44 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 21 Mar 2008 15:44:53 +0000 (15:44 +0000)
* gdbthread.h (add_thread_with_info): New.
* linux-thread-db.c: Add some documentation.
(GET_LWP, GET_PID, GET_THREAD, is_lwp, is_thread, BUILD_LWP): Delete.
(struct private_thread_info): Remove th_valid and ti_valid.
Replace ti with tid.
(thread_get_info_callback): Do not add TID to the new ptid.  Do
not cache th or ti.
(thread_db_map_id2thr, lwp_from_thread): Delete functions.
(thread_from_lwp): Assert that the LWP is set.  Do not add TID to the
new PTID.
(attach_thread): Handle an already-existing thread.  Use
add_thread_with_info.  Cache the th and tid.
(detach_thread): Verify that private was set.  Remove verbose
argument and printing.  Update caller.
(thread_db_detach): Do not adjust inferior_ptid.
(clear_lwpid_callback, thread_db_resume, thread_db_kill): Delete.
(check_event, find_new_threads_callback): Do not add TID to the new PTID.
(thread_db_wait): Do not use lwp_from_thread.
(thread_db_pid_to_str): Use the cached TID.
(thread_db_extra_thread_info): Check that private is set.
(same_ptid_callback): Delete.
(thread_db_get_thread_local_address): Do not use it or check
is_thread.  Check that private is set.  Assume that the thread
handle is already cached.
(init_thread_db_ops): Remove to_resume and to_kill.
* thread.c (add_thread_with_info): New.
(add_thread): Use it.
* linux-nat.c (find_thread_from_lwp): Delete.
(exit_lwp): Do not use it.  Check print_thread_events.  Print before
deleting the thread.
(GET_PID, GET_LWP, BUILD_LWP, is_lwp): Move to...
* linux-nat.h (GET_PID, GET_LWP, BUILD_LWP, is_lwp): ...here.
* inf-ttrace.c (inf_ttrace_wait): Use print_thread_events and
printf_unfiltered for thread exits.
* procfs.c (procfs_wait): Likewise.

2008-03-21  Pedro Alves  <pedro@codesourcery.com>

* gdb.threads/fork-child-threads.exp: Test next over fork.

gdb/ChangeLog
gdb/gdbthread.h
gdb/inf-ttrace.c
gdb/linux-nat.c
gdb/linux-nat.h
gdb/linux-thread-db.c
gdb/procfs.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.threads/fork-child-threads.exp
gdb/thread.c

index ef83262..30e8740 100644 (file)
@@ -1,3 +1,41 @@
+2008-03-21  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdbthread.h (add_thread_with_info): New.
+       * linux-thread-db.c: Add some documentation.
+       (GET_LWP, GET_PID, GET_THREAD, is_lwp, is_thread, BUILD_LWP): Delete.
+       (struct private_thread_info): Remove th_valid and ti_valid.
+       Replace ti with tid.
+       (thread_get_info_callback): Do not add TID to the new ptid.  Do
+       not cache th or ti.
+       (thread_db_map_id2thr, lwp_from_thread): Delete functions.
+       (thread_from_lwp): Assert that the LWP is set.  Do not add TID to the
+       new PTID.
+       (attach_thread): Handle an already-existing thread.  Use
+       add_thread_with_info.  Cache the th and tid.
+       (detach_thread): Verify that private was set.  Remove verbose
+       argument and printing.  Update caller.
+       (thread_db_detach): Do not adjust inferior_ptid.
+       (clear_lwpid_callback, thread_db_resume, thread_db_kill): Delete.
+       (check_event, find_new_threads_callback): Do not add TID to the new PTID.
+       (thread_db_wait): Do not use lwp_from_thread.
+       (thread_db_pid_to_str): Use the cached TID.
+       (thread_db_extra_thread_info): Check that private is set.
+       (same_ptid_callback): Delete.
+       (thread_db_get_thread_local_address): Do not use it or check
+       is_thread.  Check that private is set.  Assume that the thread
+       handle is already cached.
+       (init_thread_db_ops): Remove to_resume and to_kill.
+       * thread.c (add_thread_with_info): New.
+       (add_thread): Use it.
+       * linux-nat.c (find_thread_from_lwp): Delete.
+       (exit_lwp): Do not use it.  Check print_thread_events.  Print before
+       deleting the thread.
+       (GET_PID, GET_LWP, BUILD_LWP, is_lwp): Move to...
+       * linux-nat.h (GET_PID, GET_LWP, BUILD_LWP, is_lwp): ...here.
+       * inf-ttrace.c (inf_ttrace_wait): Use print_thread_events and
+       printf_unfiltered for thread exits.
+       * procfs.c (procfs_wait): Likewise.
+
 2008-03-21  Chris Demetriou  <cgd@google.com>
 
        * symtab.c (rbreak_command): Quote symbol name before passing
index 5632af6..f0568e0 100644 (file)
@@ -81,6 +81,10 @@ extern struct thread_info *add_thread (ptid_t ptid);
    about new thread.  */
 extern struct thread_info *add_thread_silent (ptid_t ptid);
 
+/* Same as add_thread, and sets the private info.  */
+extern struct thread_info *add_thread_with_info (ptid_t ptid,
+                                                struct private_thread_info *);
+
 /* Delete an existing thread list entry.  */
 extern void delete_thread (ptid_t);
 
index c3a0bb6..8a8399a 100644 (file)
@@ -964,7 +964,8 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
       break;
 
     case TTEVT_LWP_EXIT:
-      printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
+      if (print_thread_events)
+       printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
       ti = find_thread_pid (ptid);
       gdb_assert (ti != NULL);
       ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
index fc63fa3..770cf31 100644 (file)
@@ -588,11 +588,6 @@ struct lwp_info *lwp_list;
 static int num_lwps;
 \f
 
-#define GET_LWP(ptid)          ptid_get_lwp (ptid)
-#define GET_PID(ptid)          ptid_get_pid (ptid)
-#define is_lwp(ptid)           (GET_LWP (ptid) != 0)
-#define BUILD_LWP(lwp, pid)    ptid_build (pid, lwp, 0)
-
 /* If the last reported event was a SIGTRAP, this variable is set to
    the process id of the LWP/thread that got it.  */
 ptid_t trap_ptid;
@@ -813,20 +808,6 @@ prune_lwps (void)
       p = &(*p)->next;
 }
 
-/* Callback for iterate_over_threads that finds a thread corresponding
-   to the given LWP.  */
-
-static int
-find_thread_from_lwp (struct thread_info *thr, void *dummy)
-{
-  ptid_t *ptid_p = dummy;
-
-  if (GET_LWP (thr->ptid) && GET_LWP (thr->ptid) == GET_LWP (*ptid_p))
-    return 1;
-  else
-    return 0;
-}
-
 /* Handle the exit of a single thread LP.  */
 
 static void
@@ -834,32 +815,14 @@ exit_lwp (struct lwp_info *lp)
 {
   if (in_thread_list (lp->ptid))
     {
+      if (print_thread_events)
+       printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (lp->ptid));
+
       /* Core GDB cannot deal with us deleting the current thread.  */
       if (!ptid_equal (lp->ptid, inferior_ptid))
        delete_thread (lp->ptid);
       else
        record_dead_thread (lp->ptid);
-      printf_unfiltered (_("[%s exited]\n"),
-                        target_pid_to_str (lp->ptid));
-    }
-  else
-    {
-      /* Even if LP->PTID is not in the global GDB thread list, the
-        LWP may be - with an additional thread ID.  We don't need
-        to print anything in this case; thread_db is in use and
-        already took care of that.  But it didn't delete the thread
-        in order to handle zombies correctly.  */
-
-      struct thread_info *thr;
-
-      thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid);
-      if (thr)
-       {
-         if (!ptid_equal (thr->ptid, inferior_ptid))
-           delete_thread (thr->ptid);
-         else
-           record_dead_thread (thr->ptid);
-       }
     }
 
   delete_lwp (lp->ptid);
index 8ae5ab3..48c9a0c 100644 (file)
@@ -83,6 +83,11 @@ extern struct lwp_info *lwp_list;
        (LP) != NULL;                                                   \
        (LP) = (LP)->next, (PTID) = (LP) ? (LP)->ptid : (PTID))
 
+#define GET_LWP(ptid)          ptid_get_lwp (ptid)
+#define GET_PID(ptid)          ptid_get_pid (ptid)
+#define is_lwp(ptid)           (GET_LWP (ptid) != 0)
+#define BUILD_LWP(lwp, pid)    ptid_build (pid, lwp, 0)
+
 /* Attempt to initialize libthread_db.  */
 void check_for_thread_db (void);
 
index a653bed..a222d8b 100644 (file)
 #define LIBTHREAD_DB_SO "libthread_db.so.1"
 #endif
 
+/* GNU/Linux libthread_db support.
+
+   libthread_db is a library, provided along with libpthread.so, which
+   exposes the internals of the thread library to a debugger.  It
+   allows GDB to find existing threads, new threads as they are
+   created, thread IDs (usually, the result of pthread_self), and
+   thread-local variables.
+
+   The libthread_db interface originates on Solaris, where it is
+   both more powerful and more complicated.  This implementation
+   only works for LinuxThreads and NPTL, the two glibc threading
+   libraries.  It assumes that each thread is permanently assigned
+   to a single light-weight process (LWP).
+
+   libthread_db-specific information is stored in the "private" field
+   of struct thread_info.  When the field is NULL we do not yet have
+   information about the new thread; this could be temporary (created,
+   but the thread library's data structures do not reflect it yet)
+   or permanent (created using clone instead of pthread_create).
+
+   Process IDs managed by linux-thread-db.c match those used by
+   linux-nat.c: a common PID for all processes, an LWP ID for each
+   thread, and no TID.  We save the TID in private.  Keeping it out
+   of the ptid_t prevents thread IDs changing when libpthread is
+   loaded or unloaded.  */
+
 /* If we're running on GNU/Linux, we must explicitly attach to any new
    threads.  */
 
@@ -119,19 +145,7 @@ static CORE_ADDR td_death_bp_addr;
 static void thread_db_find_new_threads (void);
 static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
                           const td_thrinfo_t *ti_p);
-static void detach_thread (ptid_t ptid, int verbose);
-\f
-
-/* Building process ids.  */
-
-#define GET_PID(ptid)          ptid_get_pid (ptid)
-#define GET_LWP(ptid)          ptid_get_lwp (ptid)
-#define GET_THREAD(ptid)       ptid_get_tid (ptid)
-
-#define is_lwp(ptid)           (GET_LWP (ptid) != 0)
-#define is_thread(ptid)                (GET_THREAD (ptid) != 0)
-
-#define BUILD_LWP(lwp, pid)    ptid_build (pid, lwp, 0)
+static void detach_thread (ptid_t ptid);
 \f
 
 /* Use "struct private_thread_info" to cache thread state.  This is
@@ -143,11 +157,8 @@ struct private_thread_info
   unsigned int dying:1;
 
   /* Cached thread state.  */
-  unsigned int th_valid:1;
-  unsigned int ti_valid:1;
-
   td_thrhandle_t th;
-  td_thrinfo_t ti;
+  thread_t tid;
 };
 \f
 
@@ -257,7 +268,7 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
           thread_db_err_str (err));
 
   /* Fill the cache.  */
-  thread_ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
+  thread_ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
   thread_info = find_thread_pid (thread_ptid);
 
   /* In the case of a zombie thread, don't continue.  We don't want to
@@ -266,13 +277,6 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
     {
       if (infop != NULL)
         *(struct thread_info **) infop = thread_info;
-      if (thread_info != NULL)
-       {
-         memcpy (&thread_info->private->th, thp, sizeof (*thp));
-         thread_info->private->th_valid = 1;
-         memcpy (&thread_info->private->ti, &ti, sizeof (ti));
-         thread_info->private->ti_valid = 1;
-       }
       return TD_THR_ZOMBIE;
     }
 
@@ -284,39 +288,11 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
       gdb_assert (thread_info != NULL);
     }
 
-  memcpy (&thread_info->private->th, thp, sizeof (*thp));
-  thread_info->private->th_valid = 1;
-  memcpy (&thread_info->private->ti, &ti, sizeof (ti));
-  thread_info->private->ti_valid = 1;
-
   if (infop != NULL)
     *(struct thread_info **) infop = thread_info;
 
   return 0;
 }
-
-/* Accessor functions for the thread_db information, with caching.  */
-
-static void
-thread_db_map_id2thr (struct thread_info *thread_info, int fatal)
-{
-  td_err_e err;
-
-  if (thread_info->private->th_valid)
-    return;
-
-  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
-                           &thread_info->private->th);
-  if (err != TD_OK)
-    {
-      if (fatal)
-       error (_("Cannot find thread %ld: %s"),
-              (long) GET_THREAD (thread_info->ptid),
-              thread_db_err_str (err));
-    }
-  else
-    thread_info->private->th_valid = 1;
-}
 \f
 /* Convert between user-level thread ids and LWP ids.  */
 
@@ -328,10 +304,9 @@ thread_from_lwp (ptid_t ptid)
   struct thread_info *thread_info;
   ptid_t thread_ptid;
 
-  if (GET_LWP (ptid) == 0)
-    ptid = BUILD_LWP (GET_PID (ptid), GET_PID (ptid));
-
-  gdb_assert (is_lwp (ptid));
+  /* This ptid comes from linux-nat.c, which should always fill in the
+     LWP.  */
+  gdb_assert (GET_LWP (ptid) != 0);
 
   err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
   if (err != TD_OK)
@@ -352,16 +327,8 @@ thread_from_lwp (ptid_t ptid)
       && thread_info == NULL)
     return pid_to_ptid (-1);
 
-  gdb_assert (thread_info && thread_info->private->ti_valid);
-
-  return ptid_build (GET_PID (ptid), GET_LWP (ptid),
-                    thread_info->private->ti.ti_tid);
-}
-
-static ptid_t
-lwp_from_thread (ptid_t ptid)
-{
-  return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid));
+  gdb_assert (ptid_get_tid (ptid) == 0);
+  return ptid;
 }
 \f
 
@@ -672,7 +639,8 @@ static void
 attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
               const td_thrinfo_t *ti_p)
 {
-  struct thread_info *tp;
+  struct private_thread_info *private;
+  struct thread_info *tp = NULL;
   td_err_e err;
 
   /* If we're being called after a TD_CREATE event, we may already
@@ -690,10 +658,21 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
       tp = find_thread_pid (ptid);
       gdb_assert (tp != NULL);
 
-      if (!tp->private->dying)
-        return;
+      /* If tp->private is NULL, then GDB is already attached to this
+        thread, but we do not know anything about it.  We can learn
+        about it here.  This can only happen if we have some other
+        way besides libthread_db to notice new threads (i.e.
+        PTRACE_EVENT_CLONE); assume the same mechanism notices thread
+        exit, so this can not be a stale thread recreated with the
+        same ID.  */
+      if (tp->private != NULL)
+       {
+         if (!tp->private->dying)
+           return;
 
-      delete_thread (ptid);
+         delete_thread (ptid);
+         tp = NULL;
+       }
     }
 
   check_thread_signals ();
@@ -702,13 +681,28 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
     return;                    /* A zombie thread -- do not attach.  */
 
   /* Under GNU/Linux, we have to attach to each and every thread.  */
-  if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
+  if (tp == NULL
+      && lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
     return;
 
+  /* Construct the thread's private data.  */
+  private = xmalloc (sizeof (struct private_thread_info));
+  memset (private, 0, sizeof (struct private_thread_info));
+
+  /* A thread ID of zero may mean the thread library has not initialized
+     yet.  But we shouldn't even get here if that's the case.  FIXME:
+     if we change GDB to always have at least one thread in the thread
+     list this will have to go somewhere else; maybe private == NULL
+     until the thread_db target claims it.  */
+  gdb_assert (ti_p->ti_tid != 0);
+  private->th = *th_p;
+  private->tid = ti_p->ti_tid;
+
   /* Add the thread to GDB's thread list.  */
-  tp = add_thread (ptid);
-  tp->private = xmalloc (sizeof (struct private_thread_info));
-  memset (tp->private, 0, sizeof (struct private_thread_info));
+  if (tp == NULL)
+    tp = add_thread_with_info (ptid, private);
+  else
+    tp->private = private;
 
   /* Enable thread event reporting for this thread.  */
   err = td_thr_event_enable_p (th_p, 1);
@@ -718,22 +712,20 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
 }
 
 static void
-detach_thread (ptid_t ptid, int verbose)
+detach_thread (ptid_t ptid)
 {
   struct thread_info *thread_info;
 
-  if (verbose)
-    printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
-
   /* Don't delete the thread now, because it still reports as active
      until it has executed a few instructions after the event
      breakpoint - if we deleted it now, "info threads" would cause us
      to re-attach to it.  Just mark it as having had a TD_DEATH
      event.  This means that we won't delete it from our thread list
      until we notice that it's dead (via prune_threads), or until
-     something re-uses its thread ID.  */
+     something re-uses its thread ID.  We'll report the thread exit
+     when the underlying LWP dies.  */
   thread_info = find_thread_pid (ptid);
-  gdb_assert (thread_info != NULL);
+  gdb_assert (thread_info != NULL && thread_info->private != NULL);
   thread_info->private->dying = 1;
 }
 
@@ -742,47 +734,12 @@ thread_db_detach (char *args, int from_tty)
 {
   disable_thread_event_reporting ();
 
-  /* There's no need to save & restore inferior_ptid here, since the
-     inferior is not supposed to survive this function call.  */
-  inferior_ptid = lwp_from_thread (inferior_ptid);
-
   target_beneath->to_detach (args, from_tty);
 
   /* Should this be done by detach_command?  */
   target_mourn_inferior ();
 }
 
-static int
-clear_lwpid_callback (struct thread_info *thread, void *dummy)
-{
-  /* If we know that our thread implementation is 1-to-1, we could save
-     a certain amount of information; it's not clear how much, so we
-     are always conservative.  */
-
-  thread->private->th_valid = 0;
-  thread->private->ti_valid = 0;
-
-  return 0;
-}
-
-static void
-thread_db_resume (ptid_t ptid, int step, enum target_signal signo)
-{
-  struct cleanup *old_chain = save_inferior_ptid ();
-
-  if (GET_PID (ptid) == -1)
-    inferior_ptid = lwp_from_thread (inferior_ptid);
-  else if (is_thread (ptid))
-    ptid = lwp_from_thread (ptid);
-
-  /* Clear cached data which may not be valid after the resume.  */
-  iterate_over_threads (clear_lwpid_callback, NULL);
-
-  target_beneath->to_resume (ptid, step, signo);
-
-  do_cleanups (old_chain);
-}
-
 /* Check if PID is currently stopped at the location of a thread event
    breakpoint location.  If it is, read the event message and act upon
    the event.  */
@@ -833,7 +790,7 @@ check_event (ptid_t ptid)
       if (err != TD_OK)
        error (_("Cannot get thread info: %s"), thread_db_err_str (err));
 
-      ptid = ptid_build (GET_PID (ptid), ti.ti_lid, ti.ti_tid);
+      ptid = ptid_build (GET_PID (ptid), ti.ti_lid, 0);
 
       switch (msg.event)
        {
@@ -849,7 +806,7 @@ check_event (ptid_t ptid)
          if (!in_thread_list (ptid))
            error (_("Spurious thread death event."));
 
-         detach_thread (ptid, print_thread_events);
+         detach_thread (ptid);
 
          break;
 
@@ -865,9 +822,6 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 {
   extern ptid_t trap_ptid;
 
-  if (GET_PID (ptid) != -1 && is_thread (ptid))
-    ptid = lwp_from_thread (ptid);
-
   ptid = target_beneath->to_wait (ptid, ourstatus);
 
   if (ourstatus->kind == TARGET_WAITKIND_EXITED
@@ -913,15 +867,6 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 }
 
 static void
-thread_db_kill (void)
-{
-  /* There's no need to save & restore inferior_ptid here, since the
-     inferior isn't supposed to survive this function call.  */
-  inferior_ptid = lwp_from_thread (inferior_ptid);
-  target_beneath->to_kill ();
-}
-
-static void
 thread_db_mourn_inferior (void)
 {
   /* Forget about the child's process ID.  We shouldn't need it
@@ -954,7 +899,7 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
     return 0;                  /* A zombie -- ignore.  */
 
-  ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
+  ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
 
   if (ti.ti_tid == 0)
     {
@@ -994,18 +939,17 @@ thread_db_find_new_threads (void)
 static char *
 thread_db_pid_to_str (ptid_t ptid)
 {
-  if (is_thread (ptid))
+  struct thread_info *thread_info = find_thread_pid (ptid);
+
+  if (thread_info != NULL && thread_info->private != NULL)
     {
       static char buf[64];
-      struct thread_info *thread_info;
+      thread_t tid;
 
+      tid = thread_info->private->tid;
       thread_info = find_thread_pid (ptid);
-      if (thread_info == NULL)
-       snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld) (Missing)",
-                 GET_THREAD (ptid), GET_LWP (ptid));
-      else
-       snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
-                 GET_THREAD (ptid), GET_LWP (ptid));
+      snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
+               tid, GET_LWP (ptid));
 
       return buf;
     }
@@ -1022,22 +966,15 @@ thread_db_pid_to_str (ptid_t ptid)
 static char *
 thread_db_extra_thread_info (struct thread_info *info)
 {
+  if (info->private == NULL)
+    return NULL;
+
   if (info->private->dying)
     return "Exiting";
 
   return NULL;
 }
 
-/* Return 1 if this thread has the same LWP as the passed PTID.  */
-
-static int
-same_ptid_callback (struct thread_info *thread, void *arg)
-{
-  ptid_t *ptid_p = arg;
-
-  return GET_LWP (thread->ptid) == GET_LWP (*ptid_p);
-}
-
 /* Get the address of the thread local variable in load module LM which
    is stored at OFFSET within the thread local storage for thread PTID.  */
 
@@ -1046,26 +983,19 @@ thread_db_get_thread_local_address (ptid_t ptid,
                                    CORE_ADDR lm,
                                    CORE_ADDR offset)
 {
+  struct thread_info *thread_info;
+
   /* If we have not discovered any threads yet, check now.  */
-  if (!is_thread (ptid) && !have_threads ())
+  if (!have_threads ())
     thread_db_find_new_threads ();
 
-  /* Try to find a matching thread if we still have the LWP ID instead
-     of the thread ID.  */
-  if (!is_thread (ptid))
-    {
-      struct thread_info *thread;
-
-      thread = iterate_over_threads (same_ptid_callback, &ptid);
-      if (thread != NULL)
-       ptid = thread->ptid;
-    }
+  /* Find the matching thread.  */
+  thread_info = find_thread_pid (ptid);
 
-  if (is_thread (ptid))
+  if (thread_info != NULL && thread_info->private != NULL)
     {
       td_err_e err;
       void *address;
-      struct thread_info *thread_info;
 
       /* glibc doesn't provide the needed interface.  */
       if (!td_thr_tls_get_addr_p)
@@ -1075,11 +1005,6 @@ thread_db_get_thread_local_address (ptid_t ptid,
       /* Caller should have verified that lm != 0.  */
       gdb_assert (lm != 0);
 
-      /* Get info about the thread.  */
-      thread_info = find_thread_pid (ptid);
-      gdb_assert (thread_info);
-      thread_db_map_id2thr (thread_info, 1);
-
       /* Finally, get the address of the variable.  */
       err = td_thr_tls_get_addr_p (&thread_info->private->th,
                                   (void *)(size_t) lm,
@@ -1122,9 +1047,7 @@ init_thread_db_ops (void)
   thread_db_ops.to_longname = "multi-threaded child process.";
   thread_db_ops.to_doc = "Threads and pthreads support.";
   thread_db_ops.to_detach = thread_db_detach;
-  thread_db_ops.to_resume = thread_db_resume;
   thread_db_ops.to_wait = thread_db_wait;
-  thread_db_ops.to_kill = thread_db_kill;
   thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
   thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
   thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
index 72d72cc..f40b388 100644 (file)
@@ -4034,8 +4034,9 @@ wait_again:
              case PR_SYSENTRY:
                if (syscall_is_lwp_exit (pi, what))
                  {
-                   printf_filtered (_("[%s exited]\n"),
-                                    target_pid_to_str (retval));
+                   if (print_thread_events)
+                     printf_unfiltered (_("[%s exited]\n"),
+                                        target_pid_to_str (retval));
                    delete_thread (retval);
                    status->kind = TARGET_WAITKIND_SPURIOUS;
                    return retval;
@@ -4165,8 +4166,9 @@ wait_again:
                  }
                else if (syscall_is_lwp_exit (pi, what))
                  {
-                   printf_filtered (_("[%s exited]\n"),
-                                    target_pid_to_str (retval));
+                   if (print_thread_events)
+                     printf_unfiltered (_("[%s exited]\n"),
+                                        target_pid_to_str (retval));
                    delete_thread (retval);
                    status->kind = TARGET_WAITKIND_SPURIOUS;
                    return retval;
index d72ef2b..2f9ee94 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-21  Pedro Alves  <pedro@codesourcery.com>
+
+       * gdb.threads/fork-child-threads.exp: Test next over fork.
+
 2008-03-21  Chris Demetriou  <cgd@google.com>
 
        * gdb.base/break.exp (rbreak junk): New test for rbreak
index b0b4e7f..ba03028 100644 (file)
@@ -38,6 +38,10 @@ if ![runto_main] then {
 
 gdb_test "set follow-fork-mode child"
 gdb_breakpoint "start"
+
+# Make sure we can step over fork without losing our breakpoint.
+gdb_test "next" ".*pthread_create \\(&thread, NULL, start, NULL\\);.*" "next over fork"
+
 gdb_test "continue" "Breakpoint 2, start.*" "get to the spawned thread"
 
 # Wrong:
index 87dcbd7..e2ec2cd 100644 (file)
@@ -132,10 +132,12 @@ add_thread_silent (ptid_t ptid)
 }
 
 struct thread_info *
-add_thread (ptid_t ptid)
+add_thread_with_info (ptid_t ptid, struct private_thread_info *private)
 {
   struct thread_info *result = add_thread_silent (ptid);
 
+  result->private = private;
+
   if (print_thread_events)
     printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
 
@@ -144,6 +146,12 @@ add_thread (ptid_t ptid)
   return result;
 }
 
+struct thread_info *
+add_thread (ptid_t ptid)
+{
+  return add_thread_with_info (ptid, NULL);
+}
+
 void
 delete_thread (ptid_t ptid)
 {