This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Add base linux native multi-process support.


This patch adds base multi-process support to linux native GDB.
What this means is that the target side becomes aware of
debugging multiple processes simultaneously.  As for the
gdbserver multiprocess support changes, to take
advantage of this, GDB core also needs to learn about loading
multiple programs/executables (a.k.a., the exec_bfd global),
and all the adjustments and complications behind that.

I don't know of a better way than to push this functionality
into GDB incrementaly, so here goes.  The target still
announces itself to the core as not supporting multi-process,
as otherwise, things wouldn't work that great yet, unfortunately.
I've left in a temporary global `linux_multi_process', and an
undocumented command "set maint linux-multiprocess", for convenience
when working on adding multi-exec support, and testing a multiprocess
GDB.  This has samed me quite some recompile time.  Let me know if
you think this is a bad idea.

Not all is bad though.  If you try debugging a non-threaded app
(one that doesn't load thread-db), you get better results, since
thread event breakpoints aren't in the mix.  I use a a small patch/hack
like this to test multiprocess stuff:

Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c       2009-04-04 01:27:55.000000000 +0100
+++ src/gdb/infcmd.c    2009-04-07 19:49:17.000000000 +0100
@@ -429,6 +429,9 @@ post_create_inferior (struct target_ops
 static void
 kill_if_already_running (int from_tty)
 {
+  if (target_supports_multi_process ())
+    return;
+
   if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
     {
       /* Bail out before killing the program if we will not be able to


Then, issuing "run;run;run" works.  I can sucessully control several
processes simultaneously, step threads in different processes, etc.
Of course, you'll run into a limitations, due to GDB not being
aware that breakpoints need to be inserted in all of the processes.

One thing at a time, I think this part is a step in the right
direction, and good to go.

This patch applies on top of the one I sent a bit earlier today that
rewrites the linux native async support:

 http://sourceware.org/ml/gdb-patches/2009-04/msg00125.html

There are no regressions in the testsuite, sync and async modes.

WDYT?

-- 
Pedro Alves

2009-04-07  Pedro Alves  <pedro@codesourcery.com>

	* fork-child.c (fork_inferior): Only reset the thread list if this
	is the first inferior.
	(startup_inferior): If the target support multi-process, tell it
	to resume only the new process.
	* linux-nat.c (num_lwps): Delete global.
	(purge_lwp_list): New function.
	(num_lwps): New function.
	(add_lwp, delete_lwp): Adjust.
	(ptid_match): New.
	(iterate_over_lwps): Add filter argument.  Handle it.
	(linux_nat_attach): Remove FIXME note.
	(linux_nat_detach): Adjust to iterate over threads of the inferior
	we're detaching from.  Adjust to num_lwps being a function.  Don't
	assume the head of the lwp list is the main thread of the process
	we're detaching from.  Don't destroy the LWP list.
	(resume_callback): Add debug output.
	(linux_nat_resume): Handle resuming a single inferior.  Allow a
	wildcard resume in non-stop mode.
	(linux_handle_extended_wait): Don't assume inferior_ptid is the
	correct inferior of the parent LWP.
	(status_callback): Also check lp->waitstatus.
	(select_event_lwp): Add new filter parameter.  Handle it.
	(linux_nat_filter_event): Adjust to num_lwps being a function.
	(linux_nat_wait_1): When adding the first lwp of the inferior, use
	an is_lwp check instead of checking for the number of lwps.
	(linux_nat_wait_1): Handle waiting for a specific tgid.  Handle
	pending process exit statuses.
	(linux_nat_mourn_inferior): Don't destroy all the LWP info.
	Instead delete LWPs of the inferior that we're mourning.
	(linux_nat_make_corefile_notes): Adjust to walk over lwps of a
	single inferior.
	(linux_multi_process): New global.
	(linux_nat_supports_multi_process): New.
	(show_maint_linux_supports_multi_process): New.
	(linux_nat_stop_lwp): Remove LWP filtering.  It is done by the
	caller.
	(linux_nat_stop): Adjust to make iterate_over_lwps itself do the
	LWP filtering.
	(linux_nat_add_target): Register linux_nat_supports_multi_process.
	Register the undocumented "set maint linux-multiprocess" command.
	* linux-nat.h (iterate_over_lwps): Add filter argument.
	* linux-thread-db.c (using_thread_db): Delete.
	(proc_handle): Delete.
	(struct thread_db_info): New.
	(thread_db_list): New.
	(add_thread_db_info, get_thread_db_info, delete_thread_db_info):
	New.
	(td_create_bp_addr, td_death_bp_addr): Delete.
	(have_threads_callback): Filter out threads of all inferiors but
	the one specified by the ARGS argument.
	(have_threads): Add ptid argument specifying the inferior we're
	interested in.  Handle it.
	(struct thread_get_info_inout): New.
	(thread_get_info_callback, thread_from_lwp): Adjust to use it.
	(thread_db_attach_lwp): Check that inferior of the passed in
	thread is using thread-db.  Adjust.
	(enable_thread_event): Remove thread_agent parameter.  Instead,
	get it from the per-inferior thread-db info.
	(enable_thread_event_reporting): Adjust to use per-inferior
	thread-db info.
	(disable_thread_event_reporting): Ditto.
	(check_for_thread_db): Ditto.
	(thread_db_new_objfile): Add comment about inferior_ptid.
	(thread_db_detach): Adjust to use per-inferior thread-db info.
	Remove thread event breakpoints of the current inferior.  Only
	unpush the thread-db target if there are no more processes using
	it.
	(check_event): Adjust to use per-inferior thread-db info.
	(thread_db_wait): Adjust to use per-inferior thread-db info.  Only
	unpush the thread-db target if there are no more processes using
	it.
	(thread_db_mourn_inferior): Adjust to use per-inferior thread-db
	info.  Mark breakpoints of the current inferior out before
	deleting them.  Only unpush the thread-db target if there are no
	more processes using it.
	(find_new_threads_callback): Use inferior_ptid.
	(thread_db_find_new_threads_1): Add new ptid argument.  Adjust to
	use per-inferior thread-db info.
	(thread_db_find_new_threads): Adjust to use per-inferior thread-db
	info.
	(thread_db_get_thread_local_address): Adjust.
	(thread_db_get_ada_task_ptid): Adjust.

	* mi/mi-interp.c (mi_output_running_pid): New.
	(mi_inferior_count): New.
	(mi_on_resume): For backwards compatibility, if resuming all
	threads of an inferior, and there is only one inferior, output
	"all".
	* thread.c (set_running, set_executing): Handle resuming all
	threads of a single inferior.

---
 gdb/fork-child.c      |   20 +-
 gdb/linux-nat.c       |  434 +++++++++++++++++++++++++++++++++++---------------
 gdb/linux-nat.h       |    3 
 gdb/linux-thread-db.c |  353 ++++++++++++++++++++++++++++------------
 gdb/mi/mi-interp.c    |   41 ++++
 gdb/thread.c          |   24 +-
 6 files changed, 618 insertions(+), 257 deletions(-)

Index: src/gdb/fork-child.c
===================================================================
--- src.orig/gdb/fork-child.c	2009-04-07 20:00:40.000000000 +0100
+++ src/gdb/fork-child.c	2009-04-07 20:01:20.000000000 +0100
@@ -392,7 +392,8 @@ fork_inferior (char *exec_file_arg, char
   /* Restore our environment in case a vforked child clob'd it.  */
   environ = save_our_env;
 
-  init_thread_list ();
+  if (!have_inferiors ())
+    init_thread_list ();
 
   add_inferior (pid);
 
@@ -424,6 +425,12 @@ startup_inferior (int ntraps)
 {
   int pending_execs = ntraps;
   int terminal_initted = 0;
+  ptid_t resume_ptid;
+
+  if (target_supports_multi_process ())
+    resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+  else
+    resume_ptid = minus_one_ptid;
 
   /* The process was started by the fork that created it, but it will
      have stopped one instruction after execing the shell.  Here we
@@ -435,12 +442,11 @@ startup_inferior (int ntraps)
   while (1)
     {
       int resume_signal = TARGET_SIGNAL_0;
-      ptid_t resume_ptid;
       ptid_t event_ptid;
 
       struct target_waitstatus ws;
       memset (&ws, 0, sizeof (ws));
-      event_ptid = target_wait (pid_to_ptid (-1), &ws);
+      event_ptid = target_wait (resume_ptid, &ws);
 
       if (ws.kind == TARGET_WAITKIND_IGNORE)
 	/* The inferior didn't really stop, keep waiting.  */
@@ -489,12 +495,6 @@ startup_inferior (int ntraps)
 	    break;
 	}
 
-      /* In all-stop mode, resume all threads.  */
-      if (!non_stop)
-	resume_ptid = pid_to_ptid (-1);
-      else
-	resume_ptid = event_ptid;
-
       if (resume_signal != TARGET_SIGNAL_TRAP)
 	{
 	  /* Let shell child handle its own signals in its own way.  */
@@ -529,7 +529,7 @@ startup_inferior (int ntraps)
     }
 
   /* Mark all threads non-executing.  */
-  set_executing (pid_to_ptid (-1), 0);
+  set_executing (resume_ptid, 0);
 
   stop_pc = read_pc ();
 }
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-04-07 20:01:08.000000000 +0100
+++ src/gdb/linux-nat.c	2009-04-07 20:01:20.000000000 +0100
@@ -811,9 +811,6 @@ linux_child_insert_exec_catchpoint (int 
 
 /* List of known LWPs.  */
 struct lwp_info *lwp_list;
-
-/* Number of LWPs in the list.  */
-static int num_lwps;
 
 
 /* Original signal mask.  */
@@ -874,7 +871,48 @@ init_lwp_list (void)
     }
 
   lwp_list = NULL;
-  num_lwps = 0;
+}
+
+/* Remove all LWPs belong to PID from the lwp list.  */
+
+static void
+purge_lwp_list (int pid)
+{
+  struct lwp_info *lp, *lpprev, *lpnext;
+
+  lpprev = NULL;
+
+  for (lp = lwp_list; lp; lp = lpnext)
+    {
+      lpnext = lp->next;
+
+      if (ptid_get_pid (lp->ptid) == pid)
+	{
+	  if (lp == lwp_list)
+	    lwp_list = lp->next;
+	  else
+	    lpprev->next = lp->next;
+
+	  xfree (lp);
+	}
+      else
+	lpprev = lp;
+    }
+}
+
+/* Return the number of known LWPs in the tgid given by PID.  */
+
+static int
+num_lwps (int pid)
+{
+  int count = 0;
+  struct lwp_info *lp;
+
+  for (lp = lwp_list; lp; lp = lp->next)
+    if (ptid_get_pid (lp->ptid) == pid)
+      count++;
+
+  return count;
 }
 
 /* Add the LWP specified by PID to the list.  Return a pointer to the
@@ -898,9 +936,8 @@ add_lwp (ptid_t ptid)
 
   lp->next = lwp_list;
   lwp_list = lp;
-  ++num_lwps;
 
-  if (num_lwps > 1 && linux_nat_new_thread != NULL)
+  if (num_lwps (GET_PID (ptid)) > 1 && linux_nat_new_thread != NULL)
     linux_nat_new_thread (ptid);
 
   return lp;
@@ -922,8 +959,6 @@ delete_lwp (ptid_t ptid)
   if (!lp)
     return;
 
-  num_lwps--;
-
   if (lpprev)
     lpprev->next = lp->next;
   else
@@ -953,21 +988,46 @@ find_lwp_pid (ptid_t ptid)
   return NULL;
 }
 
+static int
+ptid_match (ptid_t ptid, ptid_t filter)
+{
+  /* Since both parameters have the same type, prevent easy mistakes
+     from happening.  */
+  gdb_assert (!ptid_equal (ptid, minus_one_ptid)
+	      && !ptid_equal (ptid, null_ptid));
+
+  if (ptid_equal (filter, minus_one_ptid))
+    return 1;
+  if (ptid_is_pid (filter)
+      && ptid_get_pid (ptid) == ptid_get_pid (filter))
+    return 1;
+  else if (ptid_equal (ptid, filter))
+    return 1;
+
+  return 0;
+}
+
 /* Call CALLBACK with its second argument set to DATA for every LWP in
    the list.  If CALLBACK returns 1 for a particular LWP, return a
    pointer to the structure describing that LWP immediately.
    Otherwise return NULL.  */
 
 struct lwp_info *
-iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data)
+iterate_over_lwps (ptid_t filter,
+		   int (*callback) (struct lwp_info *, void *),
+		   void *data)
 {
   struct lwp_info *lp, *lpnext;
 
   for (lp = lwp_list; lp; lp = lpnext)
     {
       lpnext = lp->next;
-      if ((*callback) (lp, data))
-	return lp;
+
+      if (ptid_match (lp->ptid, filter))
+	{
+	  if ((*callback) (lp, data))
+	    return lp;
+	}
     }
 
   return NULL;
@@ -1239,8 +1299,6 @@ linux_nat_attach (struct target_ops *ops
   int status;
   ptid_t ptid;
 
-  /* FIXME: We should probably accept a list of process id's, and
-     attach all of them.  */
   linux_ops->to_attach (ops, args, from_tty);
 
   /* The ptrace base target adds the main thread with (pid,0,0)
@@ -1400,25 +1458,30 @@ linux_nat_detach (struct target_ops *ops
   int pid;
   int status;
   enum target_signal sig;
+  struct lwp_info *main_lwp;
+
+  pid = GET_PID (inferior_ptid);
 
   if (target_can_async_p ())
     linux_nat_async (NULL, 0);
 
   /* Stop all threads before detaching.  ptrace requires that the
      thread is stopped to sucessfully detach.  */
-  iterate_over_lwps (stop_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), stop_callback, NULL);
   /* ... and wait until all of them have reported back that
      they're no longer running.  */
-  iterate_over_lwps (stop_wait_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), stop_wait_callback, NULL);
 
-  iterate_over_lwps (detach_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL);
 
   /* Only the initial process should be left right now.  */
-  gdb_assert (num_lwps == 1);
+  gdb_assert (num_lwps (GET_PID (inferior_ptid)) == 1);
+
+  main_lwp = find_lwp_pid (pid_to_ptid (pid));
 
   /* Pass on any pending signal for the last LWP.  */
   if ((args == NULL || *args == '\0')
-      && get_pending_status (lwp_list, &status) != -1
+      && get_pending_status (main_lwp, &status) != -1
       && WIFSTOPPED (status))
     {
       /* Put the signal number in ARGS so that inf_ptrace_detach will
@@ -1428,11 +1491,10 @@ linux_nat_detach (struct target_ops *ops
       fprintf_unfiltered (gdb_stdlog,
 			  "LND: Sending signal %s to %s\n",
 			  args,
-			  target_pid_to_str (lwp_list->ptid));
+ 			  target_pid_to_str (main_lwp->ptid));
     }
 
-  /* Destroy LWP info; it's no longer valid.  */
-  init_lwp_list ();
+  delete_lwp (main_lwp->ptid);
 
   pid = ptid_get_pid (inferior_ptid);
 
@@ -1458,6 +1520,11 @@ resume_callback (struct lwp_info *lp, vo
 {
   if (lp->stopped && lp->status == 0)
     {
+      if (debug_linux_nat)
+	fprintf_unfiltered (gdb_stdlog,
+			    "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
+			    target_pid_to_str (lp->ptid));
+
       linux_ops->to_resume (linux_ops,
 			    pid_to_ptid (GET_LWP (lp->ptid)),
 			    0, TARGET_SIGNAL_0);
@@ -1498,7 +1565,7 @@ linux_nat_resume (struct target_ops *ops
 		  ptid_t ptid, int step, enum target_signal signo)
 {
   struct lwp_info *lp;
-  int resume_all;
+  int resume_many;
 
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
@@ -1509,37 +1576,29 @@ linux_nat_resume (struct target_ops *ops
 			target_pid_to_str (inferior_ptid));
 
   /* A specific PTID means `step only this process id'.  */
-  resume_all = (PIDGET (ptid) == -1);
-
-  if (non_stop && resume_all)
-    internal_error (__FILE__, __LINE__,
-		    "can't resume all in non-stop mode");
+  resume_many = (ptid_equal (minus_one_ptid, ptid)
+		 || ptid_is_pid (ptid));
 
   if (!non_stop)
     {
-      if (resume_all)
-	iterate_over_lwps (resume_set_callback, NULL);
-      else
-	iterate_over_lwps (resume_clear_callback, NULL);
+      /* Mark the lwps we're resuming as resumed.  */
+      iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
+      iterate_over_lwps (ptid, resume_set_callback, NULL);
     }
+  else
+    iterate_over_lwps (minus_one_ptid, resume_set_callback, NULL);
 
-  /* If PID is -1, it's the current inferior that should be
-     handled specially.  */
-  if (PIDGET (ptid) == -1)
-    ptid = inferior_ptid;
-
-  lp = find_lwp_pid (ptid);
+  /* See if it's the current inferior that should be handled
+     specially.  */
+  if (resume_many)
+    lp = find_lwp_pid (inferior_ptid);
+  else
+    lp = find_lwp_pid (ptid);
   gdb_assert (lp != NULL);
 
-  /* Convert to something the lower layer understands.  */
-  ptid = pid_to_ptid (GET_LWP (lp->ptid));
-
   /* Remember if we're stepping.  */
   lp->step = step;
 
-  /* Mark this LWP as resumed.  */
-  lp->resumed = 1;
-
   /* If we have a pending wait status for this thread, there is no
      point in resuming the process.  But first make sure that
      linux_nat_wait won't preemptively handle the event - we
@@ -1553,7 +1612,7 @@ linux_nat_resume (struct target_ops *ops
       int saved_signo;
       struct inferior *inf;
 
-      inf = find_inferior_pid (ptid_get_pid (ptid));
+      inf = find_inferior_pid (ptid_get_pid (lp->ptid));
       gdb_assert (inf);
       saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
 
@@ -1602,8 +1661,11 @@ linux_nat_resume (struct target_ops *ops
      resume_callback.  */
   lp->stopped = 0;
 
-  if (resume_all)
-    iterate_over_lwps (resume_callback, NULL);
+  if (resume_many)
+    iterate_over_lwps (ptid, resume_callback, NULL);
+
+  /* Convert to something the lower layer understands.  */
+  ptid = pid_to_ptid (GET_LWP (lp->ptid));
 
   linux_ops->to_resume (linux_ops, ptid, step, signo);
   memset (&lp->siginfo, 0, sizeof (lp->siginfo));
@@ -1696,7 +1758,7 @@ linux_handle_extended_wait (struct lwp_i
 	  struct cleanup *old_chain;
 
 	  ourstatus->kind = TARGET_WAITKIND_IGNORE;
-	  new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (inferior_ptid)));
+	  new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (lp->ptid)));
 	  new_lp->cloned = 1;
 	  new_lp->stopped = 1;
 
@@ -2120,7 +2182,12 @@ status_callback (struct lwp_info *lp, vo
 {
   /* Only report a pending wait status if we pretend that this has
      indeed been resumed.  */
-  return (lp->status != 0 && lp->resumed);
+  /* We check for lp->waitstatus in addition to lp->status, because we
+     can have pending process exits recorded in lp->waitstatus, and
+     W_EXITCODE(0,0) == 0.  */
+  return ((lp->status != 0
+	   || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
+	  && lp->resumed);
 }
 
 /* Return non-zero if LP isn't stopped.  */
@@ -2242,7 +2309,7 @@ cancel_breakpoints_callback (struct lwp_
 /* Select one LWP out of those that have events pending.  */
 
 static void
-select_event_lwp (struct lwp_info **orig_lp, int *status)
+select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status)
 {
   int num_events = 0;
   int random_selector;
@@ -2252,7 +2319,8 @@ select_event_lwp (struct lwp_info **orig
   (*orig_lp)->status = *status;
 
   /* Give preference to any LWP that is being single-stepped.  */
-  event_lp = iterate_over_lwps (select_singlestep_lwp_callback, NULL);
+  event_lp = iterate_over_lwps (filter,
+				select_singlestep_lwp_callback, NULL);
   if (event_lp != NULL)
     {
       if (debug_linux_nat)
@@ -2266,7 +2334,7 @@ select_event_lwp (struct lwp_info **orig
          which have had SIGTRAP events.  */
 
       /* First see how many SIGTRAP events we have.  */
-      iterate_over_lwps (count_events_callback, &num_events);
+      iterate_over_lwps (filter, count_events_callback, &num_events);
 
       /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
       random_selector = (int)
@@ -2277,7 +2345,8 @@ select_event_lwp (struct lwp_info **orig
 			    "SEL: Found %d SIGTRAP events, selecting #%d\n",
 			    num_events, random_selector);
 
-      event_lp = iterate_over_lwps (select_event_lwp_callback,
+      event_lp = iterate_over_lwps (filter,
+				    select_event_lwp_callback,
 				    &random_selector);
     }
 
@@ -2395,7 +2464,8 @@ linux_nat_filter_event (int lwpid, int s
     }
 
   /* Check if the thread has exited.  */
-  if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1)
+  if ((WIFEXITED (status) || WIFSIGNALED (status))
+      && num_lwps (GET_PID (lp->ptid)))
     {
       /* If this is the main thread, we must stop all threads and verify
 	 if they are still alive.  This is because in the nptl thread model
@@ -2410,7 +2480,8 @@ linux_nat_filter_event (int lwpid, int s
       if (GET_PID (lp->ptid) == GET_LWP (lp->ptid))
 	{
 	  lp->stopped = 1;
-	  iterate_over_lwps (stop_and_resume_callback, NULL);
+	  iterate_over_lwps (pid_to_ptid (GET_PID (lp->ptid)),
+			     stop_and_resume_callback, NULL);
 	}
 
       if (debug_linux_nat)
@@ -2418,7 +2489,7 @@ linux_nat_filter_event (int lwpid, int s
 			    "LLW: %s exited.\n",
 			    target_pid_to_str (lp->ptid));
 
-      if (num_lwps > 1)
+      if (num_lwps (GET_PID (lp->ptid)) > 1)
        {
 	 /* If there is at least one more LWP, then the exit signal
 	    was not the end of the debugged application and should be
@@ -2432,8 +2503,10 @@ linux_nat_filter_event (int lwpid, int s
      thread model, LWPs other than the main thread do not issue
      signals when they exit so we must check whenever the thread has
      stopped.  A similar check is made in stop_wait_callback().  */
-  if (num_lwps > 1 && !linux_thread_alive (lp->ptid))
+  if (num_lwps (GET_PID (lp->ptid)) > 1 && !linux_thread_alive (lp->ptid))
     {
+      ptid_t ptid = pid_to_ptid (GET_PID (lp->ptid));
+
       if (debug_linux_nat)
 	fprintf_unfiltered (gdb_stdlog,
 			    "LLW: %s exited.\n",
@@ -2442,7 +2515,7 @@ linux_nat_filter_event (int lwpid, int s
       exit_lwp (lp);
 
       /* Make sure there is at least one thread running.  */
-      gdb_assert (iterate_over_lwps (running_callback, NULL));
+      gdb_assert (iterate_over_lwps (ptid, running_callback, NULL));
 
       /* Discard the event.  */
       return NULL;
@@ -2522,7 +2595,7 @@ linux_nat_wait_1 (struct target_ops *ops
   struct lwp_info *lp = NULL;
   int options = 0;
   int status = 0;
-  pid_t pid = PIDGET (ptid);
+  pid_t pid;
 
   if (debug_linux_nat_async)
     fprintf_unfiltered (gdb_stdlog, "LLW: enter\n");
@@ -2530,10 +2603,8 @@ linux_nat_wait_1 (struct target_ops *ops
   /* The first time we get here after starting a new inferior, we may
      not have added it to the LWP list yet - this is the earliest
      moment at which we know its PID.  */
-  if (num_lwps == 0)
+  if (!is_lwp (inferior_ptid))
     {
-      gdb_assert (!is_lwp (inferior_ptid));
-
       /* Upgrade the main thread's ptid.  */
       thread_change_ptid (inferior_ptid,
 			  BUILD_LWP (GET_PID (inferior_ptid),
@@ -2550,16 +2621,29 @@ linux_nat_wait_1 (struct target_ops *ops
   /* ... so the sigsuspend below works.  */
   sigprocmask (SIG_BLOCK, &blocked_mask, &prev_mask);
 
+  if (ptid_equal (ptid, minus_one_ptid))
+    pid = -1;
+  else if (ptid_is_pid (ptid))
+    /* A request to wait for a specific tgid.  This is not possible
+       with waitpid, so instead, we wait for any child, and leave
+       children we're not interested in right now with a pending
+       status to report later.  */
+    pid = -1;
+  else
+    pid = GET_LWP (ptid);
+
 retry:
+  lp = NULL;
+  status = 0;
 
   /* Make sure there is at least one LWP that has been resumed.  */
-  gdb_assert (iterate_over_lwps (resumed_callback, NULL));
+  gdb_assert (iterate_over_lwps (ptid, resumed_callback, NULL));
 
   /* First check if there is a LWP with a wait status pending.  */
   if (pid == -1)
     {
       /* Any LWP that's been resumed will do.  */
-      lp = iterate_over_lwps (status_callback, NULL);
+      lp = iterate_over_lwps (ptid, status_callback, NULL);
       if (lp)
 	{
 	  status = lp->status;
@@ -2601,9 +2685,16 @@ retry:
          the layer beneath us can understand.  */
       options = lp->cloned ? __WCLONE : 0;
       pid = GET_LWP (ptid);
+
+      /* We check for lp->waitstatus in addition to lp->status,
+	 because we can have pending process exits recorded in
+	 lp->status and W_EXITCODE(0,0) == 0.  We should probably have
+	 an additional lp->status_p flag.  */
+      if (status == 0 && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE)
+	lp = NULL;
     }
 
-  if (status && lp->signalled)
+  if (lp && lp->signalled)
     {
       /* A pending SIGSTOP may interfere with the normal stream of
          events.  In a typical case where interference is a problem,
@@ -2640,7 +2731,7 @@ retry:
   if (target_can_async_p ())
     options |= WNOHANG; /* In async mode, don't block.  */
 
-  while (status == 0)
+  while (lp == NULL)
     {
       pid_t lwpid;
 
@@ -2658,14 +2749,79 @@ retry:
 	    }
 
 	  lp = linux_nat_filter_event (lwpid, status, options);
-	  if (!lp)
+
+	  if (lp
+	      && ptid_is_pid (ptid)
+	      && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid))
 	    {
-	      /* A discarded event.  */
-	      status = 0;
+	      if (debug_linux_nat)
+		fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
+			 ptid_get_lwp (lp->ptid), status);
+
+	      if (WIFSTOPPED (status))
+		{
+		  if (WSTOPSIG (status) != SIGSTOP)
+		    {
+		      lp->status = status;
+
+		      stop_callback (lp, NULL);
+
+		      /* Resume in order to collect the sigstop.  */
+		      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+
+		      stop_wait_callback (lp, NULL);
+		    }
+		  else
+		    {
+		      lp->stopped = 1;
+		      lp->signalled = 0;
+		    }
+		}
+	      else if (WIFEXITED (status) || WIFSIGNALED (status))
+		{
+		  if (debug_linux_nat)
+		    fprintf (stderr, "Process %ld exited while stopping LWPs\n",
+			     ptid_get_lwp (lp->ptid));
+
+		  /* This was the last lwp in the process.  Since
+		     events are serialized to GDB core, and we can't
+		     report this one right now, but GDB core and the
+		     other target layers will want to be notified
+		     about the exit code/signal, leave the status
+		     pending for the next time we're able to report
+		     it.  */
+		  lp->status = status;
+
+		  /* Prevent trying to stop this thread again.  We'll
+		     never try to resume it because it has a pending
+		     status.  */
+		  lp->stopped = 1;
+
+		  /* Dead LWP's aren't expected to reported a pending
+		     sigstop.  */
+		  lp->signalled = 0;
+
+		  /* Store the pending event in the waitstatus as
+		     well, because W_EXITCODE(0,0) == 0.  */
+		  store_waitstatus (&lp->waitstatus, status);
+		}
+
+	      /* Keep looking.  */
+	      lp = NULL;
 	      continue;
 	    }
 
-	  break;
+	  if (lp)
+	    break;
+	  else
+	    {
+	      if (pid == -1)
+		{
+		  /* waitpid did return something.  Restart over.  */
+		  options |= __WCLONE;
+		}
+	      continue;
+	    }
 	}
 
       if (pid == -1)
@@ -2695,7 +2851,7 @@ retry:
 	}
 
       /* We shouldn't end up here unless we want to try again.  */
-      gdb_assert (status == 0);
+      gdb_assert (lp == NULL);
     }
 
   if (!target_can_async_p ())
@@ -2744,7 +2900,6 @@ retry:
 				target_pid_to_str (lp->ptid),
 				signo ? strsignal (signo) : "0");
 	  lp->stopped = 0;
-	  status = 0;
 	  goto retry;
 	}
 
@@ -2760,7 +2915,8 @@ retry:
 		 will receive it - unless they're using CLONE_THREAD to
 		 share signals.  Since we only want to report it once, we
 		 mark it as ignored for all LWPs except this one.  */
-	      iterate_over_lwps (set_ignore_sigint, NULL);
+	      iterate_over_lwps (pid_to_ptid (ptid_get_pid (ptid)),
+					      set_ignore_sigint, NULL);
 	      lp->ignore_sigint = 0;
 	    }
 	  else
@@ -2778,24 +2934,24 @@ retry:
   if (!non_stop)
     {
       /* Now stop all other LWP's ...  */
-      iterate_over_lwps (stop_callback, NULL);
+      iterate_over_lwps (minus_one_ptid, stop_callback, NULL);
 
       /* ... and wait until all of them have reported back that
 	 they're no longer running.  */
-      iterate_over_lwps (stop_wait_callback, NULL);
+      iterate_over_lwps (minus_one_ptid, stop_wait_callback, NULL);
 
       /* If we're not waiting for a specific LWP, choose an event LWP
 	 from among those that have had events.  Giving equal priority
 	 to all LWPs that have had events helps prevent
 	 starvation.  */
       if (pid == -1)
-	select_event_lwp (&lp, &status);
+	select_event_lwp (ptid, &lp, &status);
     }
 
   /* Now that we've selected our final event LWP, cancel any
      breakpoints in other LWPs that have hit a GDB breakpoint.  See
      the comment in cancel_breakpoints_callback to find out why.  */
-  iterate_over_lwps (cancel_breakpoints_callback, lp);
+  iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
 
   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
     {
@@ -2943,18 +3099,19 @@ linux_nat_kill (struct target_ops *ops)
     linux_fork_killall ();
   else
     {
+      ptid_t ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
       /* Stop all threads before killing them, since ptrace requires
 	 that the thread is stopped to sucessfully PTRACE_KILL.  */
-      iterate_over_lwps (stop_callback, NULL);
+      iterate_over_lwps (ptid, stop_callback, NULL);
       /* ... and wait until all of them have reported back that
 	 they're no longer running.  */
-      iterate_over_lwps (stop_wait_callback, NULL);
+      iterate_over_lwps (ptid, stop_wait_callback, NULL);
 
       /* Kill all LWP's ...  */
-      iterate_over_lwps (kill_callback, NULL);
+      iterate_over_lwps (ptid, kill_callback, NULL);
 
       /* ... and wait until we've flushed all events.  */
-      iterate_over_lwps (kill_wait_callback, NULL);
+      iterate_over_lwps (ptid, kill_wait_callback, NULL);
     }
 
   target_mourn_inferior ();
@@ -2963,8 +3120,7 @@ linux_nat_kill (struct target_ops *ops)
 static void
 linux_nat_mourn_inferior (struct target_ops *ops)
 {
-  /* Destroy LWP info; it's no longer valid.  */
-  init_lwp_list ();
+  purge_lwp_list (ptid_get_pid (inferior_ptid));
 
   if (! forks_exist_p ())
     {
@@ -3395,6 +3551,7 @@ linux_nat_make_corefile_notes (bfd *obfd
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
+  ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid));
   gdb_byte *auxv;
   int auxv_len;
 
@@ -3428,7 +3585,7 @@ linux_nat_make_corefile_notes (bfd *obfd
   thread_args.note_size = note_size;
   thread_args.num_notes = 0;
   thread_args.stop_signal = find_stop_signal ();
-  iterate_over_lwps (linux_nat_corefile_thread_callback, &thread_args);
+  iterate_over_lwps (filter, linux_nat_corefile_thread_callback, &thread_args);
   gdb_assert (thread_args.num_notes != 0);
   note_data = thread_args.note_data;
 
@@ -4065,6 +4222,26 @@ linux_nat_supports_non_stop (void)
   return 1;
 }
 
+/* True if we want to support multi-process.  To be removed when GDB
+   supports multi-exec.  */
+
+int linux_multi_process = 0;
+
+static int
+linux_nat_supports_multi_process (void)
+{
+  return linux_multi_process;
+}
+
+static void
+show_maint_linux_supports_multi_process (struct ui_file *file, int from_tty,
+					 struct cmd_list_element *c,
+					 const char *value)
+{
+  fprintf_filtered (file, _("Debugging of GNU/Linux in multi-process mode is %s.\n"),
+		    value);
+}
+
 /* target_async_mask implementation.  */
 
 static int
@@ -4266,56 +4443,48 @@ linux_nat_async (void (*callback) (enum 
 static int
 linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 {
-  ptid_t ptid = * (ptid_t *) data;
-
-  if (ptid_equal (lwp->ptid, ptid)
-      || ptid_equal (minus_one_ptid, ptid)
-      || (ptid_is_pid (ptid)
-	  && ptid_get_pid (ptid) == ptid_get_pid (lwp->ptid)))
+  if (!lwp->stopped)
     {
-      if (!lwp->stopped)
-	{
-	  int pid, status;
-	  ptid_t ptid = lwp->ptid;
+      int pid, status;
+      ptid_t ptid = lwp->ptid;
 
-	  if (debug_linux_nat)
-	    fprintf_unfiltered (gdb_stdlog,
-				"LNSL: running -> suspending %s\n",
-				target_pid_to_str (lwp->ptid));
+      if (debug_linux_nat)
+	fprintf_unfiltered (gdb_stdlog,
+			    "LNSL: running -> suspending %s\n",
+			    target_pid_to_str (lwp->ptid));
 
 
-	  stop_callback (lwp, NULL);
-	  stop_wait_callback (lwp, NULL);
+      stop_callback (lwp, NULL);
+      stop_wait_callback (lwp, NULL);
 
-	  /* If the lwp exits while we try to stop it, there's nothing
-	     else to do.  */
-	  lwp = find_lwp_pid (ptid);
-	  if (lwp == NULL)
-	    return 0;
-
-	  /* If we didn't collect any signal other than SIGSTOP while
-	     stopping the LWP, push a SIGNAL_0 event.  In either case,
-	     the event-loop will end up calling target_wait which will
-	     collect these.  */
-	  if (lwp->status == 0)
-	    lwp->status = W_STOPCODE (0);
-	  async_file_mark ();
-	}
-      else
-	{
-	  /* Already known to be stopped; do nothing.  */
+      /* If the lwp exits while we try to stop it, there's nothing
+	 else to do.  */
+      lwp = find_lwp_pid (ptid);
+      if (lwp == NULL)
+	return 0;
 
-	  if (debug_linux_nat)
-	    {
-	      if (find_thread_pid (lwp->ptid)->stop_requested)
-		fprintf_unfiltered (gdb_stdlog, "\
+      /* If we didn't collect any signal other than SIGSTOP while
+	 stopping the LWP, push a SIGNAL_0 event.  In either case, the
+	 event-loop will end up calling target_wait which will collect
+	 these.  */
+      if (lwp->status == 0)
+	lwp->status = W_STOPCODE (0);
+      async_file_mark ();
+    }
+  else
+    {
+      /* Already known to be stopped; do nothing.  */
+
+      if (debug_linux_nat)
+	{
+	  if (find_thread_pid (lwp->ptid)->stop_requested)
+	    fprintf_unfiltered (gdb_stdlog, "\
 LNSL: already stopped/stop_requested %s\n",
-				    target_pid_to_str (lwp->ptid));
-	      else
-		fprintf_unfiltered (gdb_stdlog, "\
+				target_pid_to_str (lwp->ptid));
+	  else
+	    fprintf_unfiltered (gdb_stdlog, "\
 LNSL: already stopped/no stop_requested yet %s\n",
-				    target_pid_to_str (lwp->ptid));
-	    }
+				target_pid_to_str (lwp->ptid));
 	}
     }
   return 0;
@@ -4325,7 +4494,7 @@ static void
 linux_nat_stop (ptid_t ptid)
 {
   if (non_stop)
-    iterate_over_lwps (linux_nat_stop_lwp, &ptid);
+    iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
   else
     linux_ops->to_stop (ptid);
 }
@@ -4364,6 +4533,8 @@ linux_nat_add_target (struct target_ops 
   /* Methods for non-stop support.  */
   t->to_stop = linux_nat_stop;
 
+  t->to_supports_multi_process = linux_nat_supports_multi_process;
+
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
@@ -4442,6 +4613,17 @@ Enables printf debugging output."),
 			    show_debug_linux_nat_async,
 			    &setdebuglist, &showdebuglist);
 
+  /* Temporary undocumented command.  To be removed when GDB supports multi-exec.  */
+  add_setshow_zinteger_cmd ("linux-multiprocess", class_maintenance,
+			    &linux_multi_process, _("\
+Enable multi-process support."), _("\
+Shows multi-process support."), _("\
+Enables multi-process support."),
+			    NULL,
+			    show_maint_linux_supports_multi_process,
+			    &maintenance_set_cmdlist,
+			    &maintenance_show_cmdlist);
+
   /* Save this mask as the default.  */
   sigprocmask (SIG_SETMASK, NULL, &normal_mask);
 
Index: src/gdb/linux-nat.h
===================================================================
--- src.orig/gdb/linux-nat.h	2009-04-07 20:00:40.000000000 +0100
+++ src/gdb/linux-nat.h	2009-04-07 20:01:20.000000000 +0100
@@ -105,7 +105,8 @@ extern void linux_enable_event_reporting
 extern int lin_lwp_attach_lwp (ptid_t ptid);
 
 /* Iterator function for lin-lwp's lwp list.  */
-struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *, 
+struct lwp_info *iterate_over_lwps (ptid_t filter,
+				    int (*callback) (struct lwp_info *,
 						     void *), 
 				    void *data);
 
Index: src/gdb/linux-thread-db.c
===================================================================
--- src.orig/gdb/linux-thread-db.c	2009-04-07 20:00:40.000000000 +0100
+++ src/gdb/linux-thread-db.c	2009-04-07 20:01:20.000000000 +0100
@@ -80,21 +80,96 @@
 /* This module's target vector.  */
 static struct target_ops thread_db_ops;
 
-/* Non-zero if we're using this module's target vector.  */
-static int using_thread_db;
-
 /* Non-zero if we have determined the signals used by the threads
    library.  */
 static int thread_signals;
 static sigset_t thread_stop_set;
 static sigset_t thread_print_set;
 
-/* Structure that identifies the child process for the
-   <proc_service.h> interface.  */
-static struct ps_prochandle proc_handle;
+struct thread_db_info
+{
+  struct thread_db_info *next;
+
+  int pid;
+
+  /* Structure that identifies the child process for the
+     <proc_service.h> interface.  */
+  struct ps_prochandle proc_handle;
+
+  /* Connection to the libthread_db library.  */
+  td_thragent_t *thread_agent;
+
+/* Location of the thread creation event breakpoint.  The code at this
+   location in the child process will be called by the pthread library
+   whenever a new thread is created.  By setting a special breakpoint
+   at this location, GDB can detect when a new thread is created.  We
+   obtain this location via the td_ta_event_addr call.  */
+  CORE_ADDR td_create_bp_addr;
+
+/* Location of the thread death event breakpoint.  */
+  CORE_ADDR td_death_bp_addr;
+};
+
+/* List of known processes using thread_db.  */
+struct thread_db_info *thread_db_list;
+
+static void thread_db_find_new_threads_1 (ptid_t ptid);
+
+static struct thread_db_info *
+add_thread_db_info (void)
+{
+  int pid;
+  struct thread_db_info *info;
+
+  info = xcalloc (1, sizeof (*info));
+  info->pid = ptid_get_pid (inferior_ptid);
+
+  info->next = thread_db_list;
+  thread_db_list = info;
+
+  return info;
+}
+
+static struct thread_db_info *
+get_thread_db_info (ptid_t ptid)
+{
+  int pid;
+  struct thread_db_info *info;
+
+  pid = ptid_get_pid (ptid);
+
+  for (info = thread_db_list; info; info = info->next)
+    if (pid == info->pid)
+      return info;
+
+  return NULL;
+}
+
+
+static void
+delete_thread_db_info (ptid_t ptid)
+{
+  int pid;
+  struct thread_db_info *info, *info_prev;
+
+  pid = ptid_get_pid (ptid);
+
+  info_prev = NULL;
+
+  for (info = thread_db_list; info; info_prev = info, info = info->next)
+    if (pid == info->pid)
+      break;
+
+  if (!info)
+    return;
 
-/* Connection to the libthread_db library.  */
-static td_thragent_t *thread_agent;
+  if (info_prev)
+    info_prev->next = info->next;
+  else
+    thread_db_list = info->next;
+
+  xfree (info);
+}
 
 /* Pointers to the libthread_db functions.  */
 
@@ -128,18 +203,7 @@ static td_err_e (*td_thr_tls_get_addr_p)
 					  void *map_address,
 					  size_t offset, void **address);
 
-/* Location of the thread creation event breakpoint.  The code at this
-   location in the child process will be called by the pthread library
-   whenever a new thread is created.  By setting a special breakpoint
-   at this location, GDB can detect when a new thread is created.  We
-   obtain this location via the td_ta_event_addr call.  */
-static CORE_ADDR td_create_bp_addr;
-
-/* Location of the thread death event breakpoint.  */
-static CORE_ADDR td_death_bp_addr;
-
 /* Prototypes for local functions.  */
-static void thread_db_find_new_threads_1 (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);
@@ -230,17 +294,29 @@ thread_db_err_str (td_err_e err)
    the threading library is not fully initialized yet.  */
 
 static int
-have_threads_callback (struct thread_info *thread, void *dummy)
+have_threads_callback (struct thread_info *thread, void *args)
 {
+  int pid = * (int *) args;
+  if (ptid_get_pid (thread->ptid) != pid)
+    return 0;
+
   return thread->private != NULL;
 }
 
 static int
-have_threads (void)
+have_threads (ptid_t ptid)
 {
-  return iterate_over_threads (have_threads_callback, NULL) != NULL;
+  int pid = ptid_get_pid (ptid);
+
+  return iterate_over_threads (have_threads_callback, &pid) != NULL;
 }
 
+struct thread_get_info_inout
+{
+  struct thread_info *thread_info;
+  struct thread_db_info *thread_db_info;
+};
+
 /* A callback function for td_ta_thr_iter, which we use to map all
    threads to LWPs.
 
@@ -252,45 +328,43 @@ have_threads (void)
    zero is returned to indicate success.  */
 
 static int
-thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
+thread_get_info_callback (const td_thrhandle_t *thp, void *argp)
 {
   td_thrinfo_t ti;
   td_err_e err;
-  struct thread_info *thread_info;
   ptid_t thread_ptid;
+  struct thread_get_info_inout *inout;
+  int pid;
 
   err = td_thr_get_info_p (thp, &ti);
   if (err != TD_OK)
     error (_("thread_get_info_callback: cannot get thread info: %s"),
 	   thread_db_err_str (err));
 
+  inout = argp;
+
+  pid = inout->thread_db_info->pid;
+
   /* Fill the cache.  */
-  thread_ptid = ptid_build (GET_PID (proc_handle.ptid), ti.ti_lid, 0);
-  thread_info = find_thread_pid (thread_ptid);
+  thread_ptid = ptid_build (pid, ti.ti_lid, 0);
+  inout->thread_info = find_thread_pid (thread_ptid);
 
   /* In the case of a zombie thread, don't continue.  We don't want to
      attach to it thinking it is a new thread.  */
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
-    {
-      if (infop != NULL)
-        *(struct thread_info **) infop = thread_info;
-      return TD_THR_ZOMBIE;
-    }
+    return TD_THR_ZOMBIE;
 
-  if (thread_info == NULL)
+  if (inout->thread_info == NULL)
     {
       /* New thread.  Attach to it now (why wait?).  */
-      if (!have_threads ())
-	thread_db_find_new_threads_1 ();
+      if (!have_threads (thread_ptid))
+ 	thread_db_find_new_threads_1 (thread_ptid);
       else
 	attach_thread (thread_ptid, thp, &ti);
-      thread_info = find_thread_pid (thread_ptid);
-      gdb_assert (thread_info != NULL);
+      inout->thread_info = find_thread_pid (thread_ptid);
+      gdb_assert (inout->thread_info != NULL);
     }
 
-  if (infop != NULL)
-    *(struct thread_info **) infop = thread_info;
-
   return 0;
 }
 
@@ -301,22 +375,23 @@ thread_from_lwp (ptid_t ptid)
 {
   td_thrhandle_t th;
   td_err_e err;
-  struct thread_info *thread_info;
   ptid_t thread_ptid;
+  struct thread_db_info *info;
+  struct thread_get_info_inout io = {0};
 
   /* This ptid comes from linux-nat.c, which should always fill in the
      LWP.  */
   gdb_assert (GET_LWP (ptid) != 0);
 
+  info = get_thread_db_info (ptid);
+
   /* Access an lwp we know is stopped.  */
-  proc_handle.ptid = ptid;
-  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+  info->proc_handle.ptid = ptid;
+  err = td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th);
   if (err != TD_OK)
     error (_("Cannot find user-level thread for LWP %ld: %s"),
 	   GET_LWP (ptid), thread_db_err_str (err));
 
-  thread_info = NULL;
-
   /* Fetch the thread info.  If we get back TD_THR_ZOMBIE, then the
      event thread has already died.  If another gdb interface has called
      thread_alive() previously, the thread won't be found on the thread list
@@ -325,9 +400,11 @@ thread_from_lwp (ptid_t ptid)
      discovered thread id that we should add to the list.  Thus,
      we return a -1 ptid which is also how the thread list marks a
      dead thread.  */
-  if (thread_get_info_callback (&th, &thread_info) == TD_THR_ZOMBIE
-      && thread_info == NULL)
-    return pid_to_ptid (-1);
+  io.thread_db_info = info;
+  io.thread_info = NULL;
+  if (thread_get_info_callback (&th, &io) == TD_THR_ZOMBIE
+      && io.thread_info == NULL)
+    return minus_one_ptid;
 
   gdb_assert (ptid_get_tid (ptid) == 0);
   return ptid;
@@ -343,8 +420,11 @@ thread_db_attach_lwp (ptid_t ptid)
   td_thrhandle_t th;
   td_thrinfo_t ti;
   td_err_e err;
+  struct thread_db_info *info;
 
-  if (!using_thread_db)
+  info = get_thread_db_info (ptid);
+
+  if (!info)
     return 0;
 
   /* This ptid comes from linux-nat.c, which should always fill in the
@@ -352,15 +432,15 @@ thread_db_attach_lwp (ptid_t ptid)
   gdb_assert (GET_LWP (ptid) != 0);
 
   /* Access an lwp we know is stopped.  */
-  proc_handle.ptid = ptid;
+  info->proc_handle.ptid = ptid;
 
   /* If we have only looked at the first thread before libpthread was
      initialized, we may not know its thread ID yet.  Make sure we do
      before we add another thread to the list.  */
-  if (!have_threads ())
-    thread_db_find_new_threads_1 ();
+  if (!have_threads (ptid))
+    thread_db_find_new_threads_1 (ptid);
 
-  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+  err = td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th);
   if (err != TD_OK)
     /* Cannot find user-level thread.  */
     return 0;
@@ -451,16 +531,19 @@ thread_db_load (void)
 }
 
 static td_err_e
-enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp)
+enable_thread_event (int event, CORE_ADDR *bp)
 {
   td_notify_t notify;
   td_err_e err;
+  struct thread_db_info *info;
+
+  info = get_thread_db_info (inferior_ptid);
 
   /* Access an lwp we know is stopped.  */
-  proc_handle.ptid = inferior_ptid;
+  info->proc_handle.ptid = inferior_ptid;
 
   /* Get the breakpoint address for thread EVENT.  */
-  err = td_ta_event_addr_p (thread_agent, event, &notify);
+  err = td_ta_event_addr_p (info->thread_agent, event, &notify);
   if (err != TD_OK)
     return err;
 
@@ -488,6 +571,7 @@ enable_thread_event_reporting (void)
   const char *libc_version;
   int libc_major, libc_minor;
 #endif
+  struct thread_db_info *info;
 
   /* We cannot use the thread event reporting facility if these
      functions aren't available.  */
@@ -509,7 +593,9 @@ enable_thread_event_reporting (void)
 #endif
     td_event_addset (&events, TD_DEATH);
 
-  err = td_ta_set_event_p (thread_agent, &events);
+  info = get_thread_db_info (inferior_ptid);
+
+  err = td_ta_set_event_p (info->thread_agent, &events);
   if (err != TD_OK)
     {
       warning (_("Unable to set global thread event mask: %s"),
@@ -519,11 +605,11 @@ enable_thread_event_reporting (void)
 
   /* Delete previous thread event breakpoints, if any.  */
   remove_thread_event_breakpoints ();
-  td_create_bp_addr = 0;
-  td_death_bp_addr = 0;
+  info->td_create_bp_addr = 0;
+  info->td_death_bp_addr = 0;
 
   /* Set up the thread creation event.  */
-  err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr);
+  err = enable_thread_event (TD_CREATE, &info->td_create_bp_addr);
   if (err != TD_OK)
     {
       warning (_("Unable to get location for thread creation breakpoint: %s"),
@@ -532,7 +618,7 @@ enable_thread_event_reporting (void)
     }
 
   /* Set up the thread death event.  */
-  err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr);
+  err = enable_thread_event (TD_DEATH, &info->td_death_bp_addr);
   if (err != TD_OK)
     {
       warning (_("Unable to get location for thread death breakpoint: %s"),
@@ -545,16 +631,19 @@ static void
 disable_thread_event_reporting (void)
 {
   td_thr_events_t events;
+  struct thread_db_info *info;
+
+  info = get_thread_db_info (inferior_ptid);
 
   /* Set the process wide mask saying we aren't interested in any
      events anymore.  */
   td_event_emptyset (&events);
-  td_ta_set_event_p (thread_agent, &events);
+  td_ta_set_event_p (info->thread_agent, &events);
 
   /* Delete thread event breakpoints, if any.  */
   remove_thread_event_breakpoints ();
-  td_create_bp_addr = 0;
-  td_death_bp_addr = 0;
+  info->td_create_bp_addr = 0;
+  info->td_death_bp_addr = 0;
 }
 
 static void
@@ -593,6 +682,7 @@ void
 check_for_thread_db (void)
 {
   td_err_e err;
+  struct thread_db_info *info;
   static int already_loaded;
 
   /* Do nothing if we couldn't load libthread_db.so.1.  */
@@ -622,7 +712,9 @@ check_for_thread_db (void)
       already_loaded = 1;
     }
 
-  if (using_thread_db)
+  info = get_thread_db_info (inferior_ptid);
+
+  if (info)
     /* Nothing to do.  The thread library was already detected and the
        target vector was already activated.  */
     return;
@@ -636,29 +728,33 @@ check_for_thread_db (void)
   if (!target_can_run (&current_target))
     return;
 
+  info = add_thread_db_info ();
+
   /* Initialize the structure that identifies the child process.  */
-  proc_handle.ptid = inferior_ptid;
+  info->proc_handle.ptid = inferior_ptid;
 
   /* Now attempt to open a connection to the thread library.  */
-  err = td_ta_new_p (&proc_handle, &thread_agent);
+  err = td_ta_new_p (&info->proc_handle, &info->thread_agent);
   switch (err)
     {
     case TD_NOLIBTHREAD:
       /* No thread library was detected.  */
+      delete_thread_db_info (inferior_ptid);
       break;
 
     case TD_OK:
       printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
 
-      /* The thread library was detected.  Activate the thread_db target.  */
-      push_target (&thread_db_ops);
-      using_thread_db = 1;
+      /* The thread library was detected.  */
+      if (thread_db_list->next == NULL)
+	push_target (&thread_db_ops);
 
       enable_thread_event_reporting ();
-      thread_db_find_new_threads_1 ();
+      thread_db_find_new_threads_1 (inferior_ptid);
       break;
 
     default:
+      delete_thread_db_info (inferior_ptid);
       warning (_("Cannot initialize thread debugging library: %s"),
 	       thread_db_err_str (err));
       break;
@@ -668,6 +764,9 @@ check_for_thread_db (void)
 static void
 thread_db_new_objfile (struct objfile *objfile)
 {
+  /* This observer must always be called with inferior_ptid set
+     correctly.  */
+
   if (objfile != NULL)
     check_for_thread_db ();
 }
@@ -774,18 +873,32 @@ static void
 thread_db_detach (struct target_ops *ops, char *args, int from_tty)
 {
   struct target_ops *target_beneath = find_target_beneath (ops);
+  struct thread_db_info *info;
 
-  disable_thread_event_reporting ();
+  info = get_thread_db_info (inferior_ptid);
 
-  /* Forget about the child's process ID.  We shouldn't need it
-     anymore.  */
-  proc_handle.ptid = null_ptid;
+  if (info)
+    {
+      disable_thread_event_reporting ();
 
-  /* Detach thread_db target ops.  */
-  unpush_target (&thread_db_ops);
-  using_thread_db = 0;
+      /* Delete the old thread event breakpoints.  Note that unlike
+	 when mourning, we can remove them here because there's still
+	 a live inferior to poke at.  In any case, GDB will not try to
+	 insert anything in the inferior when removing a
+	 breakpoint.  */
+      remove_thread_event_breakpoints ();
+
+      delete_thread_db_info (inferior_ptid);
+    }
 
   target_beneath->to_detach (target_beneath, args, from_tty);
+
+  /* NOTE: From this point on, inferior_ptid is null_ptid.  */
+
+  /* If there are no more processes using it, detach the thread_db
+     target ops.  */
+  if (!thread_db_list)
+    unpush_target (&thread_db_ops);
 }
 
 /* Check if PID is currently stopped at the location of a thread event
@@ -802,21 +915,25 @@ check_event (ptid_t ptid)
   td_err_e err;
   CORE_ADDR stop_pc;
   int loop = 0;
+  struct thread_db_info *info;
+
+  info = get_thread_db_info (ptid);
 
   /* Bail out early if we're not at a thread event breakpoint.  */
   stop_pc = regcache_read_pc (regcache)
 	    - gdbarch_decr_pc_after_break (gdbarch);
-  if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
+  if (stop_pc != info->td_create_bp_addr
+      && stop_pc != info->td_death_bp_addr)
     return;
 
   /* Access an lwp we know is stopped.  */
-  proc_handle.ptid = ptid;
+  info->proc_handle.ptid = ptid;
 
   /* If we have only looked at the first thread before libpthread was
      initialized, we may not know its thread ID yet.  Make sure we do
      before we add another thread to the list.  */
-  if (!have_threads ())
-    thread_db_find_new_threads_1 ();
+  if (!have_threads (ptid))
+    thread_db_find_new_threads_1 (ptid);
 
   /* If we are at a create breakpoint, we do not know what new lwp
      was created and cannot specifically locate the event message for it.
@@ -836,7 +953,7 @@ check_event (ptid_t ptid)
 
   do
     {
-      err = td_ta_event_getmsg_p (thread_agent, &msg);
+      err = td_ta_event_getmsg_p (info->thread_agent, &msg);
       if (err != TD_OK)
 	{
 	  if (err == TD_NOMSG)
@@ -881,6 +998,7 @@ static ptid_t
 thread_db_wait (struct target_ops *ops,
 		ptid_t ptid, struct target_waitstatus *ourstatus)
 {
+  struct thread_db_info *info;
   struct target_ops *beneath = find_target_beneath (ops);
 
   ptid = beneath->to_wait (beneath, ptid, ourstatus);
@@ -892,26 +1010,40 @@ thread_db_wait (struct target_ops *ops,
       || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
     return ptid;
 
+  info = get_thread_db_info (ptid);
+
+  /* If this process isn't using thread_db, we're done.  */
+  if (!info)
+    return ptid;
+
   if (ourstatus->kind == TARGET_WAITKIND_EXECD)
     {
+      /* Breakpoints have already been marked non-inserted by the
+	 layer below.  We're safe in knowing that removing them will
+	 not write the shadows of the old image into the new
+	 image.  */
       remove_thread_event_breakpoints ();
-      unpush_target (&thread_db_ops);
-      using_thread_db = 0;
+
+      /* New image, it may or may not end up using thread_db.  Assume
+	 not unless we find otherwise.  */
+      delete_thread_db_info (ptid);
+      if (!thread_db_list)
+ 	unpush_target (&thread_db_ops);
 
       return ptid;
     }
 
   /* If we do not know about the main thread yet, this would be a good time to
      find it.  */
-  if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
-    thread_db_find_new_threads_1 ();
+  if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads (ptid))
+    thread_db_find_new_threads_1 (ptid);
 
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */
     check_event (ptid);
 
-  if (have_threads ())
+  if (have_threads (ptid))
     {
       /* Change ptids back into the higher level PID + TID format.  If
 	 the thread is dead and no longer on the thread list, we will
@@ -932,19 +1064,18 @@ thread_db_mourn_inferior (struct target_
 {
   struct target_ops *target_beneath = find_target_beneath (ops);
 
-  /* Forget about the child's process ID.  We shouldn't need it
-     anymore.  */
-  proc_handle.ptid = null_ptid;
-
-  target_beneath->to_mourn_inferior (target_beneath);
+  delete_thread_db_info (inferior_ptid);
 
-  /* Delete the old thread event breakpoints.  Do this after mourning
-     the inferior, so that we don't try to uninsert them.  */
+  /* Delete the old thread event breakpoints.  Mark breakpoints out,
+     so that we don't try to un-insert them.  */
+  mark_breakpoints_out ();
   remove_thread_event_breakpoints ();
 
+  target_beneath->to_mourn_inferior (target_beneath);
+
   /* Detach thread_db target ops.  */
-  unpush_target (ops);
-  using_thread_db = 0;
+  if (!thread_db_list)
+    unpush_target (ops);
 }
 
 static int
@@ -963,7 +1094,7 @@ find_new_threads_callback (const td_thrh
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
     return 0;			/* A zombie -- ignore.  */
 
-  ptid = ptid_build (GET_PID (proc_handle.ptid), ti.ti_lid, 0);
+  ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
 
   if (ti.ti_tid == 0)
     {
@@ -992,25 +1123,28 @@ find_new_threads_callback (const td_thrh
    PTID.  */
 
 static void
-thread_db_find_new_threads_1 (void)
+thread_db_find_new_threads_1 (ptid_t ptid)
 {
   td_err_e err;
   struct lwp_info *lp;
-  ptid_t ptid;
+  struct thread_db_info *info;
+  int pid = ptid_get_pid (ptid);
 
   /* In linux, we can only read memory through a stopped lwp.  */
   ALL_LWPS (lp, ptid)
-    if (lp->stopped)
+    if (lp->stopped && ptid_get_pid (lp->ptid) == pid)
       break;
 
   if (!lp)
     /* There is no stopped thread.  Bail out.  */
     return;
 
+  info = get_thread_db_info (ptid);
+
   /* Access an lwp we know is stopped.  */
-  proc_handle.ptid = ptid;
+  info->proc_handle.ptid = ptid;
   /* 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 (info->thread_agent, find_new_threads_callback, NULL,
 			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
 			  TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
   if (err != TD_OK)
@@ -1020,7 +1154,14 @@ thread_db_find_new_threads_1 (void)
 static void
 thread_db_find_new_threads (struct target_ops *ops)
 {
-  thread_db_find_new_threads_1 ();
+  struct thread_db_info *info;
+
+  info = get_thread_db_info (inferior_ptid);
+
+  if (!info)
+    return;
+
+  thread_db_find_new_threads_1 (inferior_ptid);
 }
 
 static char *
@@ -1077,8 +1218,8 @@ thread_db_get_thread_local_address (stru
   struct target_ops *beneath;
 
   /* If we have not discovered any threads yet, check now.  */
-  if (!have_threads ())
-    thread_db_find_new_threads_1 ();
+  if (!have_threads (ptid))
+    thread_db_find_new_threads_1 (ptid);
 
   /* Find the matching thread.  */
   thread_info = find_thread_pid (ptid);
@@ -1153,7 +1294,7 @@ thread_db_get_ada_task_ptid (long lwp, l
 {
   struct thread_info *thread_info;
 
-  thread_db_find_new_threads_1 ();
+  thread_db_find_new_threads_1 (inferior_ptid);
   thread_info = iterate_over_threads (thread_db_find_thread_from_tid, &thread);
 
   gdb_assert (thread_info != NULL);
Index: src/gdb/mi/mi-interp.c
===================================================================
--- src.orig/gdb/mi/mi-interp.c	2009-04-07 20:00:40.000000000 +0100
+++ src/gdb/mi/mi-interp.c	2009-04-07 20:01:20.000000000 +0100
@@ -389,6 +389,31 @@ mi_about_to_proceed (void)
   mi_proceeded = 1;
 }
 
+static int
+mi_output_running_pid (struct thread_info *info, void *arg)
+{
+  ptid_t *ptid = arg;
+
+  if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid))
+    fprintf_unfiltered (raw_stdout,
+			"*running,thread-id=\"%d\"\n",
+			info->num);
+
+  return 0;
+}
+
+static int
+mi_inferior_count (struct inferior *inf, void *arg)
+{
+  if (inf->pid != 0)
+    {
+      int *count_p = arg;
+      (*count_p)++;
+    }
+
+  return 0;
+}
+
 static void
 mi_on_resume (ptid_t ptid)
 {
@@ -420,11 +445,19 @@ mi_on_resume (ptid_t ptid)
 
   if (PIDGET (ptid) == -1)
     fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
-  else if (thread_count () == 0)
+  else if (ptid_is_pid (ptid))
     {
-      /* This is a target where for single-threaded programs the thread
-	 table has zero threads.  Don't print any thread-id field.  */
-      fprintf_unfiltered (raw_stdout, "*running\n");
+      int count;
+
+      /* Backwards compatibility.  If there's only one inferior,
+	 output "all", otherwise, output each resumed thread
+	 individually.  */
+      iterate_over_inferiors (mi_inferior_count, &count);
+
+      if (count == 1)
+	fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
+      else
+	iterate_over_threads (mi_output_running_pid, &ptid);
     }
   else
     {
Index: src/gdb/thread.c
===================================================================
--- src.orig/gdb/thread.c	2009-04-07 20:00:40.000000000 +0100
+++ src/gdb/thread.c	2009-04-07 20:01:20.000000000 +0100
@@ -509,21 +509,23 @@ void
 set_running (ptid_t ptid, int running)
 {
   struct thread_info *tp;
+  int all = ptid_equal (ptid, minus_one_ptid);
 
   /* We try not to notify the observer if no thread has actually changed 
      the running state -- merely to reduce the number of messages to 
      frontend.  Frontend is supposed to handle multiple *running just fine.  */
-  if (PIDGET (ptid) == -1)
+  if (all || ptid_is_pid (ptid))
     {
       int any_started = 0;
       for (tp = thread_list; tp; tp = tp->next)
-	{
- 	  if (tp->state_ == THREAD_EXITED)
-  	    continue;
-  	  if (running && tp->state_ == THREAD_STOPPED)
-  	    any_started = 1;
- 	  tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED;
-	}
+	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
+	  {
+	    if (tp->state_ == THREAD_EXITED)
+	      continue;
+	    if (running && tp->state_ == THREAD_STOPPED)
+	      any_started = 1;
+	    tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED;
+	  }
       if (any_started)
 	observer_notify_target_resumed (ptid);
     }
@@ -616,11 +618,13 @@ void
 set_executing (ptid_t ptid, int executing)
 {
   struct thread_info *tp;
+  int all = ptid_equal (ptid, minus_one_ptid);
 
-  if (PIDGET (ptid) == -1)
+  if (all || ptid_is_pid (ptid))
     {
       for (tp = thread_list; tp; tp = tp->next)
-	tp->executing_ = executing;
+	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
+	  tp->executing_ = executing;
     }
   else
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]