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]

[RFC/WIP PATCH v2 02/14] Implement all-stop on top of a target running non-stop mode


This implements all-stop on top of a target running in non-stop mode.
From the user's perspective, the all-stop mode is really just a
special case of being able to stop and resume specific sets of
threads, so it makes sense to do this step first.

This starts by adding a new target method "target_is_non_stop_p",
where targets that can do non-stop can always return true, even if
"set non-stop" is off.  With this, even in all-stop, the target is no
longer in charge of stopping all threads before reporting an event to
the core -- the core takes care of it when it sees fit.  For example,
when "next"- or "step"-ing, we can avoid stopping and resuming every
thread at each internal single-step, but instead stop all threads when
we're about to present the stop to the user.  While developing this, I
progressed in stages.  First I made wait_for_inferior stop all threads
right after the target returning an event, as that's the least
invasive change.  When I got that regression free, I added the
`stop_only_if_needed' global, which when true, means what I mentioned
above -- we only stop all threads when stop_stepping is called, which
means we're reporting an event to the user.  This flag will probably
go away at a later stage.

This forces always-inserted on for such targets that can always do
non-stop.  I think it would make sense to make the "breakpoint
always-inserted" auto mode actually remove breakpoints from the
inferior when all is stopped.  That way, we'd get the classic
behavior, that is a bit safer in that is avoids leaving breakpoints
planted on the target if gdb crashes in most cases, but, it'd also
leave breakpoints always inserted whenever there's a chance a thread
is running.  That'd get us the best of both worlds.


This is in need of a bit of cleanup and commenting throughout.  The
logic around target_pass_signals in do_target_resume may need a bit
more care.  Particularly after the later patch in the series that adds
itsets support to execution commands (apply_execution_command).  All
other !ptrace && !remote targets will need adjustment similar to
inf_ptrace_attach.


v2:

- fixes a bunch of regressions.

 I had the "force target-async on" patch after this one in the
 previous iteration, so I had been testing this patch in a weird mode
 with non-stop mode on, and with async off...  When I reversed the
 patches order, a bunch of problems appeared.

gdb/
2011-11-16  Pedro Alves  <pedro@codesourcery.com>

	* breakpoint.c (breakpoints_always_inserted_mode): Check
	target_is_non_stop_p instead of non_stop.
	(update_global_location_list): Ditto.
	* gdbthread.h (ALL_THREADS, ALL_LIVE_THREADS): New.
	(thread_list): Declare.
	(struct thread_control_state): New field `resumed'.
	(struct thread_suspend_state): New fields `waitstatus' and
	`waitstatus_pending_p'.
	* inf-ptrace.c (inf_ptrace_attach): Set the main thread's resumed
	flag.
	* infcall.c (run_inferior_call): Set the thread's state to
	THREAD_STOPPED while calling clear_proceed_status.
	* infrun.c: Include event-loop.h.
	(infrun_async_inferior_event_token): New global.
	(use_displaced_stepping): Check target_is_non_stop_p instead of
	non_stop.
	(displaced_step_fixup): Change return type to int.  Factor out
	bits into ...
	(displaced_step_next): ... this.  Use do_target_resume.
	(queued_for_displaced_step): New.
	(do_target_resume): New.
	(resume): Return early is the thread has a pending status.  Resume
	all threads if placed in the displaced stepping queue.  Use
	do_target_resume.
	(clear_proceed_status_thread): Bail out if the thread is running.
	(print_target_wait_results): Print the whole ptid.
	(do_target_wait): New.
	(prepare_for_detach): Use do_target_wait.
	(cancel_breakpoints): New.
	(set_executing_from_state): New.
	(stop_only_if_needed): New global.
	(select_event_thread): New.
	(wait_for_inferior): Use do_target_wait.  Call
	set_executing_from_state.  Add the event thread to the thread list
	if not already there.  Stop all threads and select the event
	thread.
	(fetch_inferior_event): Ditto.
	(adjust_pc_after_break): Change prototype.  Use
	target_is_non_stop_p.  Return an indication of whether adjustment
	was necessary.
	(wait_one): New.
	(stop_all_threads): New.
	(handle_inferior_event): Adjust to interface changes.  Use
	target_is_non_stop.
	(stop_stepping): Stop all threads if necessary.
	(keep_going): Stop all threads if starting a step-over.
	(infrun_async_inferior_event_handler): New.
	(_initialize_infrun): Install event source in the event-loop.
	* linux-nat.c (get_pending_status, linux_nat_detach): Use
	target_is_non_stop_p.
	(linux_handle_extended_wait): Set the resumed flag of the new lwp.
	Use target_is_non_stop_p.
	(linux_nat_wait_1, linux_nat_wait): Use target_is_non_stop_p.
	(linux_nat_is_non_stop_p): New.
	(linux_nat_stop): Use target_is_non_stop_p.
	(linux_nat_add_target): Install linux_nat_is_non_stop_p.
	* remote.c (remote_start_remote, extended_remote_attach_1): Set
	the resumed flag of the main thread.
	* target.c (update_current_target): INHERIT and de_fault
	to_is_non_stop_p.
	(target_wait): Return TARGET_WAITKIND_NO_RESUMED by default.
	* target.h (struct target_ops) <to_is_non_stop_p>: New field.
	(target_is_non_stop_p): New.
	* thread.c (thread_list): Make extern.
	(new_thread): Clear the suspend.waitstatus.kind field.
---
 gdb/breakpoint.c |    4 
 gdb/gdbthread.h  |   22 +
 gdb/inf-ptrace.c |    4 
 gdb/infcall.c    |   10 +
 gdb/infrun.c     |  892 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 gdb/linux-nat.c  |   26 +-
 gdb/remote.c     |   10 -
 gdb/target.c     |    6 
 gdb/target.h     |    4 
 gdb/thread.c     |    3 
 10 files changed, 899 insertions(+), 82 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 783b797..ec1565d 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -379,7 +379,7 @@ int
 breakpoints_always_inserted_mode (void)
 {
   return ((always_inserted_mode == always_inserted_on
-	   || (always_inserted_mode == always_inserted_auto && non_stop))
+	   || (always_inserted_mode == always_inserted_auto && target_is_non_stop_p ()))
 	  && !RECORD_IS_USED);
 }
 
@@ -10555,7 +10555,7 @@ update_global_location_list (int should_insert)
 
       if (!found_object)
 	{
-	  if (removed && non_stop
+	  if (removed && target_is_non_stop_p ()
 	      && breakpoint_address_is_meaningful (old_loc->owner)
 	      && !is_hardware_watchpoint (old_loc->owner))
 	    {
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index af987f2..97ded57 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -38,6 +38,15 @@ enum thread_state
   THREAD_EXITED,
 };
 
+#define ALL_THREADS(T) \
+  for ((T) = thread_list; (T); (T) = (T)->next)
+
+#define ALL_LIVE_THREADS(T) \
+  for ((T) = thread_list; (T); (T) = (T)->next) \
+    if ((T)->state != THREAD_EXITED)
+
+extern struct thread_info *thread_list;
+
 /* Inferior thread specific part of `struct infcall_control_state'.
 
    Inferior process counterpart is `struct inferior_control_state'.  */
@@ -114,6 +123,14 @@ struct thread_control_state
   /* Chain containing status of breakpoint(s) the thread stopped
      at.  */
   bpstat stop_bpstat;
+
+  /* Non-zero if this thread will be/has been resumed.  Note that a
+     thread can be marked both as stopped and resumed at the same
+     time.  This happens if we try to resume a thread that has a wait
+     status pending.  We shouldn't let the thread run until that wait
+     status has been processed, but we should not report that wait
+     status if GDB didn't try to let the thread run.  */
+  int resumed;
 };
 
 /* Inferior thread specific part of `struct infcall_suspend_state'.
@@ -124,6 +141,11 @@ struct thread_suspend_state
 {
   /* Last signal that the inferior received (why it stopped).  */
   enum target_signal stop_signal;
+
+  /* The waitstatus for this thread's last event.  */
+  struct target_waitstatus waitstatus;
+  /* If true WAITSTATUS hasn't been handled yet.  */
+  int waitstatus_pending_p;
 };
 
 struct thread_info
diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index 110e825..0617631 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -194,6 +194,7 @@ inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
   char *exec_file;
   pid_t pid;
   struct inferior *inf;
+  struct thread_info *tp;
 
   /* Do not change either targets above or the same target if already present.
      The reason is the target stack is shared across multiple inferiors.  */
@@ -243,7 +244,8 @@ inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
 
   /* Always add a main thread.  If some target extends the ptrace
      target, it should decorate the ptid later with more info.  */
-  add_thread_silent (inferior_ptid);
+  tp = add_thread_silent (inferior_ptid);
+  tp->control.resumed = 1;
 
   if (! ops_already_pushed)
     discard_cleanups (back_to);
diff --git a/gdb/infcall.c b/gdb/infcall.c
index b8b7ff5..50f1289 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -389,11 +389,21 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
   volatile struct gdb_exception e;
   int saved_in_infcall = call_thread->control.in_infcall;
   ptid_t call_thread_ptid = call_thread->ptid;
+  int state = call_thread->state;
 
   call_thread->control.in_infcall = 1;
 
+  /* Fudge the thread's state so clear_proceed_status doesn't ignore
+     it.  We may be running an infcall with a THREAD_RUNNING but
+     !executing thread, e.g., when evaluating a breakpoint's
+     condition.  */
+  state = call_thread->state;
+  call_thread->state = THREAD_STOPPED;
+
   clear_proceed_status ();
 
+  call_thread->state = state;
+
   disable_watchpoints_before_interactive_call_start ();
 
   /* We want stop_registers, please...  */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 5a0f1d2..324329f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -57,6 +57,12 @@
 #include "continuations.h"
 #include "interps.h"
 #include "skip.h"
+#include "event-loop.h"
+
+/* Asynchronous signal handle registered as event loop source for
+   when we have pending events ready to be passed to the core.  */
+
+static struct async_event_handler *infrun_async_inferior_event_token;
 
 /* Prototypes for local functions */
 
@@ -1219,7 +1225,7 @@ static int
 use_displaced_stepping (struct gdbarch *gdbarch)
 {
   return (((can_use_displaced_stepping == can_use_displaced_stepping_auto
-	    && non_stop)
+	    && target_is_non_stop_p ())
 	   || can_use_displaced_stepping == can_use_displaced_stepping_on)
 	  && gdbarch_displaced_step_copy_insn_p (gdbarch)
 	  && !RECORD_IS_USED);
@@ -1413,21 +1419,24 @@ displaced_step_restore (struct displaced_step_inferior_state *displaced,
 				  displaced->step_copy));
 }
 
-static void
+static void do_target_resume (ptid_t ptid, int step, enum target_signal signo);
+
+static int
 displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 {
   struct cleanup *old_cleanups;
   struct displaced_step_inferior_state *displaced
     = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+  int ret;
 
   /* Was any thread of this process doing a displaced step?  */
   if (displaced == NULL)
-    return;
+    return 0;
 
   /* Was this event for the pid we displaced?  */
   if (ptid_equal (displaced->step_ptid, null_ptid)
       || ! ptid_equal (displaced->step_ptid, event_ptid))
-    return;
+    return 0;
 
   old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
 
@@ -1442,6 +1451,7 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
                                     displaced->step_original,
                                     displaced->step_copy,
                                     get_thread_regcache (displaced->step_ptid));
+      ret = 1;
     }
   else
     {
@@ -1452,12 +1462,25 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 
       pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
+      ret = -1;
     }
 
   do_cleanups (old_cleanups);
 
   displaced->step_ptid = null_ptid;
 
+  return ret;
+}
+
+static void
+displaced_step_next (ptid_t event_ptid)
+{
+  struct displaced_step_inferior_state *displaced
+    = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+
+  if (displaced == NULL)
+    return;
+
   /* Are there any pending displaced stepping requests?  If so, run
      one now.  Leave the state object around, since we're likely to
      need it again soon.  */
@@ -1469,6 +1492,7 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
       struct gdbarch *gdbarch;
       CORE_ADDR actual_pc;
       struct address_space *aspace;
+      struct thread_info *tp;
 
       head = displaced->step_request_queue;
       ptid = head->ptid;
@@ -1481,6 +1505,11 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
       actual_pc = regcache_read_pc (regcache);
       aspace = get_regcache_aspace (regcache);
 
+      tp = inferior_thread ();
+
+      gdb_assert (!tp->control.resumed);
+      gdb_assert (!tp->executing);
+
       if (breakpoint_here_p (aspace, actual_pc))
 	{
 	  if (debug_displaced)
@@ -1505,9 +1534,9 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 
 	  if (gdbarch_displaced_step_hw_singlestep (gdbarch,
 						    displaced->step_closure))
-	    target_resume (ptid, 1, TARGET_SIGNAL_0);
+	    do_target_resume (ptid, 1, TARGET_SIGNAL_0);
 	  else
-	    target_resume (ptid, 0, TARGET_SIGNAL_0);
+	    do_target_resume (ptid, 0, TARGET_SIGNAL_0);
 
 	  /* Done, we're stepping a thread.  */
 	  break;
@@ -1526,10 +1555,10 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 
 	  if (debug_displaced)
 	    fprintf_unfiltered (gdb_stdlog,
-				"breakpoint is gone %s: step(%d)\n",
+				"displaced: breakpoint is gone: %s, step(%d)\n",
 				target_pid_to_str (tp->ptid), step);
 
-	  target_resume (ptid, step, TARGET_SIGNAL_0);
+	  do_target_resume (ptid, step, TARGET_SIGNAL_0);
 	  tp->suspend.stop_signal = TARGET_SIGNAL_0;
 
 	  /* This request was discarded.  See if there's any other
@@ -1677,6 +1706,212 @@ user_visible_resume_ptid (int step)
   return resume_ptid;
 }
 
+static int
+queued_for_displaced_step (ptid_t ptid)
+{
+  struct displaced_step_inferior_state *displaced
+    = get_displaced_stepping_state (ptid_get_pid (ptid));
+  struct displaced_step_request *head;
+
+  if (displaced != NULL)
+    for (head = displaced->step_request_queue; head != NULL; head = head->next)
+      if (ptid_equal (head->ptid, ptid))
+	return 1;
+
+  return 0;
+}
+
+static void
+do_target_resume (ptid_t ptid, int step, enum target_signal signo)
+{
+  int resume_many;
+  struct thread_info *tp;
+  struct regcache *regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int want_all_signals;
+  int can_wildcard;
+  int any_to_resume;
+  ptid_t leader_ptid = inferior_ptid;
+
+  /* A specific PTID means `step only this process id'.  */
+  resume_many = (ptid_equal (minus_one_ptid, ptid)
+		 || ptid_is_pid (ptid));
+
+  /* See if it's the current inferior that should be handled
+     specially.  */
+  if (resume_many)
+    tp = find_thread_ptid (inferior_ptid);
+  else
+    tp = find_thread_ptid (ptid);
+  gdb_assert (tp != NULL);
+  gdb_assert (tp->state != THREAD_EXITED);
+
+  /* Advise target which signals may be handled silently.  If we have
+     removed breakpoints because we are stepping over one (which can
+     happen only if we are not using displaced stepping), we need to
+     receive all signals to avoid accidentally skipping a breakpoint
+     during execution of a signal handler.  */
+  want_all_signals = ((step || singlestep_breakpoints_inserted_p)
+		      && tp->control.trap_expected
+		      && !use_displaced_stepping (gdbarch));
+  if (want_all_signals)
+    target_pass_signals (0, NULL);
+  else
+    target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass);
+
+  can_wildcard = 1;
+
+  ALL_LIVE_THREADS (tp)
+    {
+      if (ptid_match (tp->ptid, ptid))
+	{
+	  if (tp->executing)
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: do_target_resume: executing\n");
+
+	      /* Need to prevent wildcard; the target may want to read
+		 PC for example.  And, we may have set EXECUTING
+		 temporarily true, while the thread really isn't
+		 executing, which would mean it's not safe to assume
+		 the target ignores this thread.  */
+	      can_wildcard = 0;
+	      continue;
+	    }
+
+	  if (queued_for_displaced_step (tp->ptid))
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: do_target_resume: queued for displaced step\n");
+	      can_wildcard = 0;
+	      continue;
+	    }
+
+	  /* Avoid confusing the next resume, if the next stop/resume
+	     happens to apply to another thread.  */
+	  tp->suspend.stop_signal = TARGET_SIGNAL_0;
+	  tp->control.resumed = 1;
+
+	  if (tp->suspend.waitstatus_pending_p)
+	    {
+	      /* FIXME: What should we do if we are supposed to
+		 continue this thread with a signal?  */
+	      gdb_assert (signo == TARGET_SIGNAL_0);
+
+	      if (!step
+		  && tp->suspend.waitstatus.kind == TARGET_WAITKIND_STOPPED
+		  && !want_all_signals
+		  && signal_pass[signo])
+		{
+		  if (debug_infrun)
+		    {
+		      char *statstr;
+
+		      statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+		      fprintf_unfiltered (gdb_stdlog,
+					  "infrun: Not short circuiting for ignored "
+					  "status %s\n",
+					  statstr);
+		      xfree (statstr);
+		    }
+
+		  signo = tp->suspend.waitstatus.value.sig;
+		  tp->suspend.waitstatus_pending_p = 0;
+		}
+	      else
+		{
+		  can_wildcard = 0;
+
+		  if (target_can_async_p ())
+		    {
+		      target_async (inferior_event_handler, 0);
+
+		      /* Tell the event loop we have something to
+			 process.  */
+		      mark_async_event_handler (infrun_async_inferior_event_token);
+		    }
+		  return; /// XXX why?
+		}
+	    }
+
+	  if (!tp->suspend.waitstatus_pending_p)
+	    any_to_resume = 1;
+	}
+    }
+
+  if (can_wildcard)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: managed a wildcard target_resume\n");
+      target_resume (ptid, step, signo);
+    }
+  else
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: resuming threads individually\n");
+      ALL_LIVE_THREADS (tp)
+        {
+	  if (ptid_match (tp->ptid, ptid))
+	    {
+	      if (tp->executing)
+		{
+		  if (debug_infrun)
+		    fprintf_unfiltered (gdb_stdlog,
+					"infrun: Not resuming %s (executing)\n",
+					target_pid_to_str (tp->ptid));
+		}
+	      else if (queued_for_displaced_step (tp->ptid))
+		{
+		  if (debug_infrun)
+		    fprintf_unfiltered (gdb_stdlog,
+					"infrun: Not resuming %s (queued for displaced step)\n",
+					target_pid_to_str (tp->ptid));
+		}
+	      else if (!tp->suspend.waitstatus_pending_p)
+		{
+		  if (debug_infrun)
+		    fprintf_unfiltered (gdb_stdlog,
+					"infrun: resuming %s (no pending status)\n",
+					target_pid_to_str (tp->ptid));
+		  switch_to_thread (tp->ptid);
+
+		  if (ptid_equal (tp->ptid, leader_ptid))
+		    target_resume (tp->ptid, step, signo);
+		  else
+		    target_resume (tp->ptid, 0, TARGET_SIGNAL_0);
+		}
+	      else
+		{
+		  if (debug_infrun)
+		    {
+		      char *statstr;
+
+		      statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+		      fprintf_unfiltered (gdb_stdlog,
+					  "infrun: not resuming %s, has pending status %s\n",
+					  target_pid_to_str (tp->ptid), statstr);
+		      xfree (statstr);
+		    }
+		}
+	    }
+	}
+
+      set_running (ptid, 1);
+      clear_inline_frame_state (ptid);
+    }
+
+  if (target_can_async_p ())
+    {
+      target_async (inferior_event_handler, 0);
+      /* Tell the event loop we have something to process.  */
+      mark_async_event_handler (infrun_async_inferior_event_token);
+    }
+}
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
@@ -1698,6 +1933,26 @@ resume (int step, enum target_signal sig)
 
   QUIT;
 
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      /* Avoid confusing the next resume, if the next stop/resume
+	 happens to apply to another thread.  */
+      tp->suspend.stop_signal = TARGET_SIGNAL_0;
+      tp->control.resumed = 1;
+
+      set_running (inferior_ptid, 1);
+      clear_inline_frame_state (inferior_ptid);
+      discard_cleanups (old_cleanups);
+
+      if (target_can_async_p ())
+	{
+	  target_async (inferior_event_handler, 0);
+	  /* Tell the event loop we have something to process.  */
+	  mark_async_event_handler (infrun_async_inferior_event_token);
+	}
+      return;
+    }
+
   if (current_inferior ()->waiting_for_vfork_done)
     {
       /* Don't try to single-step a vfork parent that is waiting for
@@ -1761,14 +2016,34 @@ a command like `return' or `jump' to continue execution."));
 
       if (!displaced_step_prepare (inferior_ptid))
 	{
+	  ptid_t resume_ptid;
+
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"Got placed in displaced stepping queue\n");
+
 	  /* Got placed in displaced stepping queue.  Will be resumed
 	     later when all the currently queued displaced stepping
 	     requests finish.  The thread is not executing at this point,
 	     and the call to set_executing will be made later.  But we
 	     need to call set_running here, since from frontend point of view,
 	     the thread is running.  */
+
+	  tp->suspend.stop_signal = TARGET_SIGNAL_0;
 	  set_running (inferior_ptid, 1);
+	  clear_inline_frame_state (inferior_ptid);
 	  discard_cleanups (old_cleanups);
+
+	  resume_ptid = user_visible_resume_ptid (step);
+
+	  gdb_assert (!tp->control.resumed);
+
+	  /* Resume others.  */
+	  tp->executing = 1;
+	  do_target_resume (resume_ptid, 0, TARGET_SIGNAL_0);
+	  tp->executing = 0;
+
+	  gdb_assert (!tp->control.resumed);
 	  return;
 	}
 
@@ -1900,23 +2175,7 @@ a command like `return' or `jump' to continue execution."));
       /* Install inferior's terminal modes.  */
       target_terminal_inferior ();
 
-      /* Avoid confusing the next resume, if the next stop/resume
-	 happens to apply to another thread.  */
-      tp->suspend.stop_signal = TARGET_SIGNAL_0;
-
-      /* Advise target which signals may be handled silently.  If we have
-	 removed breakpoints because we are stepping over one (which can
-	 happen only if we are not using displaced stepping), we need to
-	 receive all signals to avoid accidentally skipping a breakpoint
-	 during execution of a signal handler.  */
-      if ((step || singlestep_breakpoints_inserted_p)
-	  && tp->control.trap_expected
-	  && !use_displaced_stepping (gdbarch))
-	target_pass_signals (0, NULL);
-      else
-	target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass);
-
-      target_resume (resume_ptid, step, sig);
+      do_target_resume (resume_ptid, step, sig);
     }
 
   discard_cleanups (old_cleanups);
@@ -1930,6 +2189,15 @@ a command like `return' or `jump' to continue execution."));
 static void
 clear_proceed_status_thread (struct thread_info *tp)
 {
+  if (tp->state == THREAD_RUNNING)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: clear_proceed_status_thread (%s): ignored, thread is running\n",
+			    target_pid_to_str (tp->ptid));
+      return;
+    }
+
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
 			"infrun: clear_proceed_status_thread (%s)\n",
@@ -2558,14 +2826,20 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
      is set.  */
 
   fprintf_unfiltered (tmp_stream,
-		      "infrun: target_wait (%d", PIDGET (waiton_ptid));
+		      "infrun: target_wait (%d.%ld.%ld",
+		      ptid_get_pid (waiton_ptid),
+		      ptid_get_lwp (waiton_ptid),
+		      ptid_get_tid (waiton_ptid));
   if (PIDGET (waiton_ptid) != -1)
     fprintf_unfiltered (tmp_stream,
 			" [%s]", target_pid_to_str (waiton_ptid));
   fprintf_unfiltered (tmp_stream, ", status) =\n");
   fprintf_unfiltered (tmp_stream,
-		      "infrun:   %d [%s],\n",
-		      PIDGET (result_ptid), target_pid_to_str (result_ptid));
+		      "infrun:   %d.%ld.%ld [%s],\n",
+		      ptid_get_pid (result_ptid),
+		      ptid_get_lwp (result_ptid),
+		      ptid_get_tid (result_ptid),
+		      target_pid_to_str (result_ptid));
   fprintf_unfiltered (tmp_stream,
 		      "infrun:   %s\n",
 		      status_string);
@@ -2581,6 +2855,88 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
   ui_file_delete (tmp_stream);
 }
 
+static ptid_t
+do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
+{
+  ptid_t event_ptid;
+  struct thread_info *tp;
+
+  /* First check if there is a thread with a wait status pending.  */
+  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+    {
+      ALL_LIVE_THREADS (tp)
+        {
+	  /* Only report a pending wait status if we pretend that this
+	     has indeed been resumed.  */
+	  if (ptid_match (tp->ptid, ptid)
+	      && tp->control.resumed
+	      && tp->suspend.waitstatus_pending_p)
+	    {
+	      gdb_assert (!tp->executing);
+	      break;
+	    }
+	}
+    }
+  else
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: Waiting for specific thread %s.\n",
+			    target_pid_to_str (ptid));
+
+      /* We have a specific thread to check.  */
+      tp = find_thread_ptid (ptid);
+      gdb_assert (tp);
+      if (!tp->suspend.waitstatus_pending_p)
+	tp = NULL;
+    }
+
+  if (tp)
+    {
+      if (debug_infrun)
+	{
+	  char *statstr;
+
+	  statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
+	  fprintf_unfiltered (gdb_stdlog,
+			      "infrun: Using pending wait status %s for %s.\n",
+			      statstr,
+			      target_pid_to_str (tp->ptid));
+	  xfree (statstr);
+	}
+
+      *status = tp->suspend.waitstatus;
+      tp->suspend.waitstatus_pending_p = 0;
+      return tp->ptid;
+    }
+
+  /* But if we don't find one, we'll have to wait.  */
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (ptid, status, options);
+  else
+    event_ptid = target_wait (ptid, status, options);
+
+  if (status->kind != TARGET_WAITKIND_EXITED
+      && status->kind != TARGET_WAITKIND_SIGNALLED
+      /* If a thread not the main thread execl's, we'll see the event
+	 happening on the main thread, even if it was stopped.  It's
+	 as if the pre-exec thread changes its thread id (well, it
+	 really is that way on the Linux kernel).  */
+      && status->kind != TARGET_WAITKIND_EXECD
+      && status->kind != TARGET_WAITKIND_IGNORE)
+    {
+      tp = find_thread_ptid (event_ptid);
+      if (tp)
+	{
+	  gdb_assert (tp->control.resumed);
+	  tp->suspend.waitstatus = *status;
+	}
+    }
+
+  return event_ptid;
+}
+
 /* Prepare and stabilize the inferior for detaching it.  E.g.,
    detaching while a thread is displaced stepping is a recipe for
    crashing it, as nothing would readjust the PC out of the scratch
@@ -2619,10 +2975,7 @@ prepare_for_detach (void)
 
       overlay_cache_invalid = 1;
 
-      if (deprecated_target_wait_hook)
-	ecs->ptid = deprecated_target_wait_hook (pid_ptid, &ecs->ws, 0);
-      else
-	ecs->ptid = target_wait (pid_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (pid_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
 	print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
@@ -2660,6 +3013,189 @@ prepare_for_detach (void)
   discard_cleanups (old_chain_1);
 }
 
+static void stop_all_threads (void);
+static int adjust_pc_after_break (struct thread_info *thread,
+				  struct target_waitstatus *ws);
+
+static void
+cancel_breakpoints (void)
+{
+  struct thread_info *t;
+
+  /* Cancel any breakpoints in other threads that have hit a
+     breakpoint.  If we do not do this, then we run the risk that the
+     user will delete or disable the breakpoint, but the thread will
+     have already tripped on it.  */
+  ALL_LIVE_THREADS (t)
+    if (t->control.resumed
+	&& t->suspend.waitstatus_pending_p)
+      {
+	if (adjust_pc_after_break (t, &t->suspend.waitstatus))
+	  {
+	    /* Throw away the trap.  The thread will re-trap if
+	       re-resumed and the breakpoint is still
+	       installed.  */
+	    t->suspend.waitstatus_pending_p = 0;
+	    t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+
+	    /* Need to call displaced_step_fixup here too, for SSS
+	       targets?  */
+	  }
+	else if (t->suspend.waitstatus.kind == TARGET_WAITKIND_STOPPED
+		 && displaced_step_fixup (t->ptid,
+					  t->suspend.waitstatus.value.sig) > 0)
+	  {
+	    /* Throw away the trap.  */
+	    t->suspend.waitstatus_pending_p = 0;
+	    t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+	  }
+	else if (t->suspend.waitstatus.kind == TARGET_WAITKIND_STOPPED
+		 && t->suspend.waitstatus.value.sig == TARGET_SIGNAL_TRAP
+		 && currently_stepping (t))
+	  {
+	    /* Throw away the step trap.  */
+	    t->suspend.waitstatus_pending_p = 0;
+	    t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+	  }
+      }
+}
+
+static void
+set_executing_from_state (struct execution_control_state *ecs)
+{
+  if (ecs->ws.kind == TARGET_WAITKIND_IGNORE
+      || ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED)
+    ;
+  else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
+	   || ecs->ws.kind == TARGET_WAITKIND_EXITED)
+    {
+      int exited_pid = ptid_get_pid (ecs->ptid);
+      struct thread_info *t;
+
+      ALL_THREADS (t)
+	if (ptid_get_pid (t->ptid) == exited_pid)
+	  t->executing = 0;
+    }
+  else
+    set_executing (ecs->ptid, 0);
+}
+
+int stop_only_if_needed = 1;
+
+static void
+select_event_thread (struct execution_control_state *ecs)
+{
+  if (!non_stop && target_is_non_stop_p () && !stop_only_if_needed)
+    {
+      stop_all_threads ();
+
+      if (ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
+	  && ecs->ws.kind != TARGET_WAITKIND_EXITED
+	  && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+	  && (ptid_equal (waiton_ptid, minus_one_ptid)
+	      || ptid_is_pid (waiton_ptid)))
+	{
+	  /* If we're not waiting for a specific thread, choose an
+	     event thread from among those that have had events.
+	     Giving equal priority to all threads that have had events
+	     helps prevent starvation.  */
+
+	  int num_events = 0;
+	  int random_selector;
+	  struct thread_info *event_tp;
+
+	  ecs->event_thread = find_thread_ptid (ecs->ptid);
+	  /* Record the wait status for the original thread.  */
+	  ecs->event_thread->suspend.waitstatus = ecs->ws;
+
+	  /* Give preference to any thread that is being
+	     single-stepped.  */
+	  ALL_LIVE_THREADS (event_tp)
+	    if (ptid_match (event_tp->ptid, waiton_ptid)
+		&& event_tp->control.resumed
+		&& event_tp->suspend.waitstatus_pending_p
+		&& currently_stepping (event_tp))
+	      break;
+
+	  if (event_tp != NULL)
+	    {
+	      if (debug_infrun)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: Select single-step %s\n",
+				    target_pid_to_str (event_tp->ptid));
+	    }
+	  else
+	    {
+	      /* No single-stepping thread.  Select one at random,
+		 out of those which have had events.
+
+		 First see how many events we have.  Count only
+		 resumed threads that have an event pending.  */
+	      ALL_LIVE_THREADS (event_tp)
+		if (ptid_match (event_tp->ptid, waiton_ptid)
+		    && event_tp->control.resumed
+		    && event_tp->suspend.waitstatus_pending_p)
+		  num_events++;
+
+	      /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
+	      random_selector = (int)
+		((num_events * (double) rand ()) / (RAND_MAX + 1.0));
+
+	      if (debug_infrun && num_events > 1)
+		fprintf_unfiltered (gdb_stdlog,
+				    "infrun: Found %d events, selecting #%d\n",
+				    num_events, random_selector);
+
+	      /* Select the Nth thread that has had an event.  */
+	      ALL_LIVE_THREADS (event_tp)
+		if (ptid_match (event_tp->ptid, waiton_ptid)
+		    && event_tp->control.resumed
+		    && event_tp->suspend.waitstatus_pending_p)
+		  if (random_selector-- == 0)
+		    break;
+	    }
+
+	  if (event_tp != NULL)
+	    {
+	      /* Switch the event thread.  */
+	      ecs->ptid = event_tp->ptid;
+	      ecs->event_thread = event_tp;
+	      ecs->ws = event_tp->suspend.waitstatus;
+	    }
+
+	  /* Flush the wait status for the event thread.  */
+	  ecs->event_thread->suspend.waitstatus_pending_p = 0;
+	}
+
+      {
+	struct thread_info *t;
+
+	/* Now that we've selected our final event thread, cancel
+	   any breakpoints in other threads that have hit a
+	   breakpoint.  If we do not do this, then we run the risk
+	   that the user will delete or disable the breakpoint,
+	   but the thread will have already tripped on it.  */
+	cancel_breakpoints ();
+
+	/* In all-stop, from the core's perspective, all threads
+	   are now stopped until a new resume action is sent
+	   over.  */
+	ALL_LIVE_THREADS (t)
+	  t->control.resumed = 0;
+      }
+    }
+  else
+    {
+      if (ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
+	  && ecs->ws.kind != TARGET_WAITKIND_EXITED
+	  && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
+	{
+	  ecs->event_thread = find_thread_ptid (ecs->ptid);
+	  ecs->event_thread->control.resumed = 0;
+	}
+    }
+}
+
 /* Wait for control to return from inferior to debugger.
 
    If inferior gets a signal, we may decide to start it up again
@@ -2690,14 +3226,13 @@ wait_for_inferior (void)
 
       overlay_cache_invalid = 1;
 
-      if (deprecated_target_wait_hook)
-	ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws, 0);
-      else
-	ecs->ptid = target_wait (waiton_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
 	print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
+      set_executing_from_state (ecs);
+
       /* If an error happens while handling the event, propagate GDB's
 	 knowledge of the executing state to the frontend/user running
 	 state.  */
@@ -2707,6 +3242,14 @@ wait_for_inferior (void)
           || ecs->ws.kind == TARGET_WAITKIND_SYSCALL_RETURN)
         ecs->ws.value.syscall_number = UNKNOWN_SYSCALL;
 
+      if (ecs->ws.kind != TARGET_WAITKIND_EXITED
+	  && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+	  && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
+	  && !in_thread_list (ecs->ptid))
+	add_thread (ecs->ptid);
+
+      select_event_thread (ecs);
+
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
 
@@ -2763,15 +3306,23 @@ fetch_inferior_event (void *client_data)
   make_cleanup_restore_integer (&execution_direction);
   execution_direction = target_execution_direction ();
 
-  if (deprecated_target_wait_hook)
-    ecs->ptid =
-      deprecated_target_wait_hook (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
-  else
-    ecs->ptid = target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
+  ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
 
   if (debug_infrun)
     print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
+  if (ecs->ws.kind != TARGET_WAITKIND_EXITED
+      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+      && ecs->ws.kind != TARGET_WAITKIND_IGNORE
+      && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
+      && !in_thread_list (ecs->ptid))
+    add_thread (ecs->ptid);
+
+  set_executing_from_state (ecs);
+
+  if (ecs->ws.kind != TARGET_WAITKIND_IGNORE)
+    select_event_thread (ecs);
+
   if (non_stop
       && ecs->ws.kind != TARGET_WAITKIND_IGNORE
       && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
@@ -2897,13 +3448,15 @@ context_switch (ptid_t ptid)
   switch_to_thread (ptid);
 }
 
-static void
-adjust_pc_after_break (struct execution_control_state *ecs)
+static int
+adjust_pc_after_break (struct thread_info *thread,
+		       struct target_waitstatus *ws)
 {
   struct regcache *regcache;
   struct gdbarch *gdbarch;
   struct address_space *aspace;
   CORE_ADDR breakpoint_pc;
+  int ret = 0;
 
   /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
      we aren't, just return.
@@ -2926,11 +3479,11 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      target with both of these set in GDB history, and it seems unlikely to be
      correct, so gdbarch_have_nonsteppable_watchpoint is not checked here.  */
 
-  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
-    return;
+  if (ws->kind != TARGET_WAITKIND_STOPPED)
+    return 0;
 
-  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
-    return;
+  if (ws->value.sig != TARGET_SIGNAL_TRAP)
+    return 0;
 
   /* In reverse execution, when a breakpoint is hit, the instruction
      under it has already been de-executed.  The reported PC always
@@ -2959,14 +3512,14 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      INSN1 hadn't been de-executed yet.  Doing nothing is the correct
      behaviour.  */
   if (execution_direction == EXEC_REVERSE)
-    return;
+    return 0;
 
   /* If this target does not decrement the PC after breakpoints, then
      we have nothing to do.  */
-  regcache = get_thread_regcache (ecs->ptid);
+  regcache = get_thread_regcache (thread->ptid);
   gdbarch = get_regcache_arch (regcache);
   if (gdbarch_decr_pc_after_break (gdbarch) == 0)
-    return;
+    return 0;
 
   aspace = get_regcache_aspace (regcache);
 
@@ -2984,7 +3537,8 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      SIGTRAPs, we keep a list of such breakpoint locations for a bit,
      and retire them after a number of stop events are reported.  */
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
-      || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
+      || (target_is_non_stop_p ()
+	  && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
       struct cleanup *old_cleanups = NULL;
 
@@ -3010,14 +3564,19 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 	 we also need to back up to the breakpoint address.  */
 
       if (singlestep_breakpoints_inserted_p
-	  || !ptid_equal (ecs->ptid, inferior_ptid)
-	  || !currently_stepping (ecs->event_thread)
-	  || ecs->event_thread->prev_pc == breakpoint_pc)
-	regcache_write_pc (regcache, breakpoint_pc);
+	  || !ptid_equal (thread->ptid, inferior_ptid)
+	  || !currently_stepping (thread)
+	  || thread->prev_pc == breakpoint_pc)
+	{
+	  regcache_write_pc (regcache, breakpoint_pc);
+	  ret = 1;
+	}
 
       if (RECORD_IS_USED)
 	do_cleanups (old_cleanups);
     }
+
+  return ret;
 }
 
 void
@@ -3136,6 +3695,165 @@ fill_in_stop_func (struct gdbarch *gdbarch,
     }
 }
 
+static ptid_t
+wait_one (ptid_t wait_ptid, struct target_waitstatus *ws)
+{
+  struct cleanup *old_chain;
+  ptid_t event_ptid;
+
+  /* We have to invalidate the registers BEFORE calling target_wait
+     because they can be loaded from the target while in target_wait.
+     This makes remote debugging a bit more efficient for those
+     targets that provide critical registers as part of their normal
+     status mechanism.  */
+
+  overlay_cache_invalid = 1;
+  registers_changed ();
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (wait_ptid, ws, 0);
+  else
+    event_ptid = target_wait (wait_ptid, ws, 0);
+
+  if (debug_infrun)
+    print_target_wait_results (wait_ptid, event_ptid, ws);
+
+  if (ws->kind == TARGET_WAITKIND_SYSCALL_ENTRY
+      || ws->kind == TARGET_WAITKIND_SYSCALL_RETURN)
+    ws->value.syscall_number = UNKNOWN_SYSCALL;
+
+  return event_ptid;
+}
+
+static void
+stop_all_threads (void)
+{
+  /* We may need multiple passes to discover all threads.  */
+  int pass;
+  int iterations = 0;
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun.c: stop_all_threads\n");
+
+  /* Stop threads in two passes since threads could be spawning as we
+     go through the first pass.  In the second pass, we will stop such
+     spawned threads.  */
+  for (pass = 0; pass < 2; pass++, iterations++)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun.c: stop_all_threads, pass=%d, iterations=%d\n",
+			    pass, iterations);
+      while (1)
+	{
+	  ptid_t event_ptid;
+	  struct target_waitstatus ws;
+	  int need_wait = 0;
+	  struct thread_info *t = NULL;
+
+	  update_thread_list ();
+
+	  /* Go through all threads looking for threads that we need
+	     to tell the target to stop.  */
+	  ALL_LIVE_THREADS (t)
+	    {
+	      if (t->executing)
+		{
+		  /* If already stopping, don't request a stop again.
+		     We just haven't seen the notification yet.  */
+		  if (!t->stop_requested)
+		    {
+		      if (debug_infrun)
+			fprintf_unfiltered (gdb_stdlog,
+					    "infrun.c:   %s executing, need stop\n",
+					    target_pid_to_str (t->ptid));
+		      target_stop (t->ptid);
+		      t->stop_requested = 1;
+		    }
+		  else
+		    {
+		      if (debug_infrun)
+			fprintf_unfiltered (gdb_stdlog,
+					    "infrun.c:   %s executing, already stopping\n",
+					    target_pid_to_str (t->ptid));
+		    }
+
+		  if (t->stop_requested)
+		    need_wait = 1;
+		}
+	      else
+		{
+		  if (debug_infrun)
+		    fprintf_unfiltered (gdb_stdlog,
+					"infrun.c:   %s not executing\n",
+					target_pid_to_str (t->ptid));
+		}
+	    }
+
+	  if (!need_wait)
+	    break;
+
+	  /* If we find new threads on the second iteration, restart
+	     over.  We want to see two iterations in a row with all
+	     threads stopped.  */
+	  if (pass > 0)
+	    pass = -1;
+
+	  event_ptid = wait_one (minus_one_ptid, &ws);
+	  if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
+	    /* All resumed threads exited.  */
+	    ;
+	  else if (ws.kind == TARGET_WAITKIND_EXITED
+	      || ws.kind == TARGET_WAITKIND_SIGNALLED)
+	    warning ("exited while stopping threads\n");
+	  else
+	    {
+	      if (!in_thread_list (event_ptid))
+		t = add_thread (event_ptid);
+	      else
+		t = find_thread_ptid (event_ptid);
+
+	      t->stop_requested = 0;
+	      t->executing = 0;
+
+	      if (ws.kind == TARGET_WAITKIND_STOPPED && ws.value.sig == TARGET_SIGNAL_0)
+		{
+		  /* We caught the event that we intended to catch, so
+		     there's no event pending.  */
+		  t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+		  t->suspend.waitstatus_pending_p = 0;
+		}
+	      else
+		{
+		  if (debug_infrun)
+		    {
+		      char *statstr;
+
+		      statstr = target_waitstatus_to_string (&ws);
+		      fprintf_unfiltered (gdb_stdlog,
+					  "infrun: target_wait %s, saving "
+					  "status for %d.%ld.%ld\n",
+					  statstr,
+					  ptid_get_pid (t->ptid),
+					  ptid_get_lwp (t->ptid),
+					  ptid_get_tid (t->ptid));
+		      xfree (statstr);
+		    }
+
+		  /* Record for later.  */
+		  t->suspend.waitstatus = ws;
+		  t->suspend.waitstatus_pending_p = 1;
+		}
+
+	      set_running (event_ptid, 0);
+	    }
+	}
+    }
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun.c: stop_all_threads done\n");
+}
+
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
@@ -3226,7 +3944,7 @@ handle_inferior_event (struct execution_control_state *ecs)
   ecs->event_thread = find_thread_ptid (ecs->ptid);
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
-  adjust_pc_after_break (ecs);
+  adjust_pc_after_break (ecs->event_thread, &ecs->ws);
 
   /* Dependent on the current PC value modified by adjust_pc_after_break.  */
   reinit_frame_cache ();
@@ -3266,7 +3984,7 @@ handle_inferior_event (struct execution_control_state *ecs)
      we're handling a process exit in non-stop mode, there's nothing
      to do, as threads of the dead process are gone, and threads of
      any other process were left running.  */
-  if (!non_stop)
+  if (!non_stop && !(target_is_non_stop_p () && stop_only_if_needed))
     set_executing (minus_one_ptid, 0);
   else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
 	   && ecs->ws.kind != TARGET_WAITKIND_EXITED)
@@ -3463,7 +4181,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 	       has been done.  Perform cleanup for parent process here.  Note
 	       that this operation also cleans up the child process for vfork,
 	       because their pages are shared.  */
-	    displaced_step_fixup (ecs->ptid, TARGET_SIGNAL_TRAP);
+	    if (displaced_step_fixup (ecs->ptid, TARGET_SIGNAL_TRAP))
+	      displaced_step_next (ecs->ptid);
 
 	    if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
 	      {
@@ -3698,7 +4417,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   if (ecs->new_thread_event)
     {
-      if (non_stop)
+      if (target_is_non_stop_p ())
 	/* Non-stop assumes that the target handles adding new threads
 	   to the thread list.  */
 	internal_error (__FILE__, __LINE__,
@@ -3725,8 +4444,9 @@ handle_inferior_event (struct execution_control_state *ecs)
       /* Do we need to clean up the state of a thread that has
 	 completed a displaced single-step?  (Doing so usually affects
 	 the PC, so do it here, before we set stop_pc.)  */
-      displaced_step_fixup (ecs->ptid,
-			    ecs->event_thread->suspend.stop_signal);
+      if (displaced_step_fixup (ecs->ptid,
+				ecs->event_thread->suspend.stop_signal))
+	displaced_step_next (ecs->ptid);
 
       /* If we either finished a single-step or hit a breakpoint, but
 	 the user wanted this thread to be stopped, pretend we got a
@@ -4600,7 +5320,7 @@ process_event_stop_test:
 
   /* In all-stop mode, if we're currently stepping but have stopped in
      some other thread, we need to switch back to the stepped thread.  */
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       struct thread_info *tp;
 
@@ -5583,6 +6303,23 @@ stop_stepping (struct execution_control_state *ecs)
 
   /* Let callers know we don't want to wait for the inferior anymore.  */
   ecs->wait_some_more = 0;
+
+  if (!non_stop
+      && target_is_non_stop_p ()
+      && stop_only_if_needed)
+    {
+      struct thread_info *t;
+
+      stop_all_threads ();
+
+      cancel_breakpoints ();
+
+      /* In all-stop, from the core's perspective, all threads
+	 are now stopped until a new resume action is sent
+	 over.  */
+      ALL_LIVE_THREADS (t)
+	t->control.resumed = 0;
+    }
 }
 
 /* This function handles various cases where we need to continue
@@ -5634,10 +6371,23 @@ keep_going (struct execution_control_state *ecs)
 	  struct regcache *thread_regcache = get_thread_regcache (ecs->ptid);
 
 	  if (!use_displaced_stepping (get_regcache_arch (thread_regcache)))
-	    /* Since we can't do a displaced step, we have to remove
-	       the breakpoint while we step it.  To keep things
-	       simple, we remove them all.  */
-	    remove_breakpoints ();
+	    {
+	      struct thread_info *t;
+
+	      /* Since we can't do a displaced step, we have to remove
+		 the breakpoint while we step it.  To keep things
+		 simple, we remove them all.  */
+	      stop_all_threads ();
+
+	      cancel_breakpoints ();
+	      /* In all-stop, from the core's perspective, all threads
+		 are now stopped until a new resume action is sent
+		 over.  */
+	      ALL_LIVE_THREADS (t)
+		t->control.resumed = 0;
+
+	      remove_breakpoints ();
+	    }
 	}
       else
 	{
@@ -7060,12 +7810,22 @@ show_schedule_multiple (struct ui_file *file, int from_tty,
 			    "of all processes is %s.\n"), value);
 }
 
+static void
+infrun_async_inferior_event_handler (gdb_client_data data)
+{
+  inferior_event_handler (INF_REG_EVENT, NULL);
+}
+
 void
 _initialize_infrun (void)
 {
   int i;
   int numsigs;
 
+  /* Register extra event sources in the event loop.  */
+  infrun_async_inferior_event_token
+    = create_async_event_handler (infrun_async_inferior_event_handler, NULL);
+
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 1cbfc44..3383609 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1652,13 +1652,13 @@ get_pending_status (struct lwp_info *lp, int *status)
     signo = TARGET_SIGNAL_0; /* a pending ptrace event, not a real signal.  */
   else if (lp->status)
     signo = target_signal_from_host (WSTOPSIG (lp->status));
-  else if (non_stop && !is_executing (lp->ptid))
+  else if (target_is_non_stop_p () && !is_executing (lp->ptid))
     {
       struct thread_info *tp = find_thread_ptid (lp->ptid);
 
       signo = tp->suspend.stop_signal;
     }
-  else if (!non_stop)
+  else if (!target_is_non_stop_p ())
     {
       struct target_waitstatus last;
       ptid_t last_ptid;
@@ -1810,7 +1810,7 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
 	 available.  */
       linux_fork_detach (args, from_tty);
 
-      if (non_stop && target_can_async_p ())
+      if (target_is_non_stop_p ())
  	target_async (inferior_event_handler, 0);
     }
   else
@@ -2288,7 +2288,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
 		status = 0;
 	    }
 
-	  if (non_stop)
+	  if (target_is_non_stop_p ())
 	    {
 	      /* Add the new thread to GDB's lists as soon as possible
 		 so that:
@@ -2312,6 +2312,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
 		{
 		  set_running (new_lp->ptid, 1);
 		  set_executing (new_lp->ptid, 1);
+		  find_thread_ptid (new_lp->ptid)->control.resumed = 1;
 		  /* thread_db_attach_lwp -> lin_lwp_attach_lwp forced
 		     resume_stop.  */
 		  new_lp->last_resume_kind = resume_continue;
@@ -3685,7 +3686,7 @@ retry:
 			 core before this one is handled.  All-stop
 			 always cancels breakpoint hits in all
 			 threads.  */
-		      if (non_stop
+		      if (target_is_non_stop_p ()
 			  && linux_nat_lp_status_is_event (lp)
 			  && cancel_breakpoint (lp))
 			{
@@ -3844,7 +3845,7 @@ retry:
 	  goto retry;
 	}
 
-      if (!non_stop)
+      if (!target_is_non_stop_p ())
 	{
 	  /* Only do the below in all-stop, as we currently use SIGINT
 	     to implement target_stop (see linux_nat_stop) in
@@ -3872,7 +3873,7 @@ retry:
     fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
 			status_to_str (status), target_pid_to_str (lp->ptid));
 
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       /* Now stop all other LWP's ...  */
       iterate_over_lwps (minus_one_ptid, stop_callback, NULL);
@@ -4019,7 +4020,7 @@ linux_nat_wait (struct target_ops *ops,
      specific_process, for example, see linux_nat_wait_1), and
      meanwhile the event became uninteresting.  Don't bother resuming
      LWPs we're not going to wait for if they'd stop immediately.  */
-  if (non_stop)
+  if (target_is_non_stop_p ())
     iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid);
 
   event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options);
@@ -5478,6 +5479,12 @@ linux_nat_supports_non_stop (void)
   return 1;
 }
 
+static int
+linux_nat_is_non_stop_p (void)
+{
+  return 1;
+}
+
 /* True if we want to support multi-process.  To be removed when GDB
    supports multi-exec.  */
 
@@ -5700,7 +5707,7 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 static void
 linux_nat_stop (ptid_t ptid)
 {
-  if (non_stop)
+  if (target_is_non_stop_p ())
     iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
   else
     linux_ops->to_stop (ptid);
@@ -5858,6 +5865,7 @@ linux_nat_add_target (struct target_ops *t)
   t->to_can_async_p = linux_nat_can_async_p;
   t->to_is_async_p = linux_nat_is_async_p;
   t->to_supports_non_stop = linux_nat_supports_non_stop;
+  t->to_is_non_stop_p = linux_nat_is_non_stop_p;
   t->to_async = linux_nat_async;
   t->to_terminal_inferior = linux_nat_terminal_inferior;
   t->to_terminal_ours = linux_nat_terminal_ours;
diff --git a/gdb/remote.c b/gdb/remote.c
index 9bfebd2..a9f8f6f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -3255,6 +3255,8 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
 
   if (!non_stop)
     {
+      struct thread_info *tp;
+
       if (rs->buf[0] == 'W' || rs->buf[0] == 'X')
 	{
 	  if (!extended_p)
@@ -3289,7 +3291,8 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
       remote_add_inferior (ptid_get_pid (inferior_ptid), -1);
 
       /* Always add the main thread.  */
-      add_thread_silent (inferior_ptid);
+      tp = add_thread_silent (inferior_ptid);
+      tp->control.resumed = 1;
 
       /* init_wait_for_inferior should be called before get_offsets in order
 	 to manage `inserted' flag in bp loc in a correct state.
@@ -4302,11 +4305,14 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
     }
   else
     {
+      struct thread_info *tp;
+
       /* Now, if we have thread information, update inferior_ptid.  */
       inferior_ptid = remote_current_thread (inferior_ptid);
 
       /* Add the main thread to the thread list.  */
-      add_thread_silent (inferior_ptid);
+      tp = add_thread_silent (inferior_ptid);
+      tp->control.resumed = 1;
     }
 
   /* Next, if the target can specify a description, read it.  We do
diff --git a/gdb/target.c b/gdb/target.c
index a6e146d..ca00912 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -659,6 +659,8 @@ update_current_target (void)
       INHERIT (to_can_async_p, t);
       INHERIT (to_is_async_p, t);
       INHERIT (to_async, t);
+      /* Do not inherit to_supports_non_stop.  */
+      INHERIT (to_is_non_stop_p, t);
       INHERIT (to_find_memory_regions, t);
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_bookmark, t);
@@ -927,6 +929,7 @@ update_current_target (void)
 	    (struct traceframe_info * (*) (void))
 	    tcomplain);
   de_fault (to_execution_direction, default_execution_direction);
+  de_fault (to_is_non_stop_p, return_zero);
 
 #undef de_fault
 
@@ -2619,7 +2622,8 @@ target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 	}
     }
 
-  noprocess ();
+  status->kind = TARGET_WAITKIND_NO_RESUMED;
+  return minus_one_ptid;
 }
 
 char *
diff --git a/gdb/target.h b/gdb/target.h
index fd488d6..6e079e8 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -534,6 +534,7 @@ struct target_ops
     int (*to_is_async_p) (void);
     void (*to_async) (void (*) (enum inferior_event_type, void *), void *);
     int (*to_supports_non_stop) (void);
+    int (*to_is_non_stop_p) (void);
     /* find_memory_regions support method for gcore */
     int (*to_find_memory_regions) (find_memory_region_ftype func, void *data);
     /* make_corefile_notes support method for gcore */
@@ -1292,6 +1293,9 @@ extern int target_async_permitted;
 
 int target_supports_non_stop (void);
 
+/* Is the target in non-stop mode?  */
+#define target_is_non_stop_p() (current_target.to_is_non_stop_p ())
+
 /* Put the target in async mode with the specified callback function.  */
 #define target_async(CALLBACK,CONTEXT) \
      (current_target.to_async ((CALLBACK), (CONTEXT)))
diff --git a/gdb/thread.c b/gdb/thread.c
index 8cca83d..0777887 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -55,7 +55,7 @@ void _initialize_thread (void);
 
 /* Prototypes for local functions.  */
 
-static struct thread_info *thread_list = NULL;
+struct thread_info *thread_list = NULL;
 static int highest_thread_num;
 
 static void thread_command (char *tidstr, int from_tty);
@@ -174,6 +174,7 @@ new_thread (ptid_t ptid)
   /* Nothing to follow yet.  */
   tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
   tp->state = THREAD_STOPPED;
+  tp->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
 
   return tp;
 }


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