public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Yao Qi <qiyaoltc@gmail.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH v2 00/23] All-stop on top of non-stop
Date: Mon, 13 Apr 2015 15:28:00 -0000	[thread overview]
Message-ID: <552BE0A3.5040001@redhat.com> (raw)
In-Reply-To: <868ue0uyfa.fsf@gmail.com>

On 04/10/2015 10:26 AM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
> 
>> Fun.   TBC, that was only with gdbserver, right?
>>
> 
> Right, I just run non-stop-fair-events.exp on native aarch64-linux gdb,
> they all pass.
> 
>> I suspect the test was only passing by change before though.
> 
> They pass before this change.
> 
>> AFAICS, aarch64 doesn't have a displaced stepping implementation.
> 
> No, aarch64 doesn't have.
> 
>> I'd suspect current master fails other non-stop tests? (and hopefully
>> this series fixes them).
> 
> Current master doesn't fail other non-stop tests on aarch64-linux.  This
> series doesn't change the test result except non-stop-fair-events.exp.
> 
>>
>> So GDB should now be falling back to stopping all threads to
>> step past the breakpoint on aarch64, while before threads were
>> just missing breakpoints.   Likely something wrong with that
>> with remote targets still.
> 
> I'll take a look, and see if I can find anything wrong.

With displaced stepping disabled on x86, I can reproduce it
sometimes here too.  The issue seems to be that we're constantly
bouncing between the events of the same two threads over and over,
and thus the signal event is never processed.  Exactly the sort
of issue the test is meant to catch.   Hurray, I guess?  :-)
I've been testing with the patch below, and it seems to fix it.
Testing against gdbserver + software single-step + displaced
stepping disabled caught a couple other issues too.  I'm testing
this further and cleaning it all up now.

Thanks,
Pedro Alves

commit 9112338313db3a23b9abb4d2176ce6f62498dc08
Author:     Pedro Alves <palves@redhat.com>
AuthorDate: Mon Apr 13 14:16:27 2015 +0100

    better randomization

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 4dd25d6..334d153 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4154,6 +4154,82 @@ switch_to_thread_cleanup (void *ptid_p)
   switch_to_thread (ptid);
 }
 
+/* Save the thread's event and stop reason to process it later.  */
+
+static void
+save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
+{
+  struct regcache *regcache;
+  struct address_space *aspace;
+
+  if (debug_infrun)
+    {
+      char *statstr;
+
+      statstr = target_waitstatus_to_string (ws);
+      fprintf_unfiltered (gdb_stdlog,
+			  "infrun: saving status %s for %d.%ld.%ld\n",
+			  statstr,
+			  ptid_get_pid (tp->ptid),
+			  ptid_get_lwp (tp->ptid),
+			  ptid_get_tid (tp->ptid));
+      xfree (statstr);
+    }
+
+  /* Record for later.  */
+  tp->suspend.waitstatus = *ws;
+  tp->suspend.waitstatus_pending_p = 1;
+
+  regcache = get_thread_regcache (tp->ptid);
+  aspace = get_regcache_aspace (regcache);
+
+  if (ws->kind == TARGET_WAITKIND_STOPPED
+      && ws->value.sig == GDB_SIGNAL_TRAP)
+    {
+      CORE_ADDR pc = regcache_read_pc (regcache);
+
+      adjust_pc_after_break (tp, &tp->suspend.waitstatus);
+
+      if (thread_stopped_by_watchpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_WATCHPOINT;
+	}
+      else if (target_supports_stopped_by_sw_breakpoint ()
+	       && thread_stopped_by_sw_breakpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+	}
+      else if (target_supports_stopped_by_hw_breakpoint ()
+	       && thread_stopped_by_hw_breakpoint (tp->ptid))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+	}
+      else if (!target_supports_stopped_by_hw_breakpoint ()
+	       && hardware_breakpoint_inserted_here_p (aspace,
+						       pc))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_HW_BREAKPOINT;
+	}
+      else if (!target_supports_stopped_by_sw_breakpoint ()
+	       && software_breakpoint_inserted_here_p (aspace,
+						       pc))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SW_BREAKPOINT;
+	}
+      else if (!thread_has_single_step_breakpoints_set (tp)
+	       && currently_stepping (tp))
+	{
+	  tp->suspend.stop_reason
+	    = TARGET_STOPPED_BY_SINGLE_STEP;
+	}
+    }
+}
+
 /* Stop all threads.  */
 
 static void
@@ -4317,61 +4393,11 @@ stop_all_threads (void)
 		    }
 
 		  /* Record for later.  */
-		  t->suspend.waitstatus = ws;
-		  t->suspend.waitstatus_pending_p = 1;
+		  save_waitstatus (t, &ws);
 
 		  sig = (ws.kind == TARGET_WAITKIND_STOPPED
 			 ? ws.value.sig : GDB_SIGNAL_0);
 
-		  regcache = get_thread_regcache (t->ptid);
-		  aspace = get_regcache_aspace (regcache);
-
-		  if (ws.kind == TARGET_WAITKIND_STOPPED
-		      && ws.value.sig == GDB_SIGNAL_TRAP)
-		    {
-		      CORE_ADDR pc = regcache_read_pc (regcache);
-
-		      adjust_pc_after_break (t, &t->suspend.waitstatus);
-
-		      if (thread_stopped_by_watchpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_WATCHPOINT;
-			}
-		      else if (target_supports_stopped_by_sw_breakpoint ()
-			       && thread_stopped_by_sw_breakpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
-			}
-		      else if (target_supports_stopped_by_hw_breakpoint ()
-			       && thread_stopped_by_hw_breakpoint (t->ptid))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
-			}
-		      else if (!target_supports_stopped_by_hw_breakpoint ()
-			       && hardware_breakpoint_inserted_here_p (aspace,
-								       pc))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_HW_BREAKPOINT;
-			}
-		      else if (!target_supports_stopped_by_sw_breakpoint ()
-			       && software_breakpoint_inserted_here_p (aspace,
-								       pc))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SW_BREAKPOINT;
-			}
-		      else if (!thread_has_single_step_breakpoints_set (t)
-			       && currently_stepping (t))
-			{
-			  t->suspend.stop_reason
-			    = TARGET_STOPPED_BY_SINGLE_STEP;
-			}
-		    }
-
 		  if (displaced_step_fixup (t->ptid, sig) < 0)
 		    {
 		      /* Add it back to the step-over queue.  */
@@ -4379,6 +4405,7 @@ stop_all_threads (void)
 		      thread_step_over_chain_enqueue (t);
 		    }
 
+		  regcache = get_thread_regcache (t->ptid);
 		  t->suspend.stop_pc = regcache_read_pc (regcache);
 
 		  if (debug_infrun)
@@ -5033,7 +5060,13 @@ restart_threads (struct thread_info *event_thread)
       /* If some thread needs to start a step-over at this point, it
 	 should still be in the step-over queue, and thus skipped
 	 above.  */
-      gdb_assert (!thread_still_needs_step_over (tp));
+      if (thread_still_needs_step_over (tp))
+	{
+	  internal_error (__FILE__, __LINE__,
+			  "thread [%s] needs a step-over, but not in "
+			  "step-over queue\n",
+			  target_pid_to_str (tp->ptid));
+	}
 
       if (currently_stepping (tp))
 	{
@@ -5056,10 +5089,24 @@ restart_threads (struct thread_info *event_thread)
     }
 }
 
+/* Callback for iterate_over_threads.  Find a resumed thread that has
+   a pending waitstatus.  */
+
+static int
+resumed_thread_with_pending_status (struct thread_info *tp,
+				    void *arg)
+{
+  return (tp->resumed
+	  && tp->suspend.waitstatus_pending_p);
+}
+
 /* Called when we get an event that may finish an in-line or
-   out-of-line (displaced stepping) step-over started previously.  */
+   out-of-line (displaced stepping) step-over started previously.
+   Return true if the event is processed and we should go back to the
+   event loop; false if the caller should continue processing the
+   event.  */
 
-static void
+static int
 finish_step_over (struct execution_control_state *ecs)
 {
   int had_step_over_info;
@@ -5081,7 +5128,7 @@ finish_step_over (struct execution_control_state *ecs)
     }
 
   if (!target_is_non_stop_p ())
-    return;
+    return 0;
 
   /* Start a new step-over in another thread if there's one that
      needs it.  */
@@ -5094,10 +5141,67 @@ finish_step_over (struct execution_control_state *ecs)
      these other threads stop.  */
   if (had_step_over_info && !step_over_info_valid_p ())
     {
+      struct thread_info *pending;
+
       restart_threads (ecs->event_thread);
 
-      gdb_assert (!ecs->event_thread->resumed);
+      /* If we have events pending, go through handle_inferior_event
+	 again, picking up a pending event at random.  This avoids
+	 thread starvation.  */
+      pending = iterate_over_threads (resumed_thread_with_pending_status,
+				      NULL);
+      if (pending != NULL)
+	{
+	  struct thread_info *tp = ecs->event_thread;
+	  struct regcache *regcache;
+
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: found resumed threads with "
+				  "pending events, saving status\n");
+	    }
+
+	  gdb_assert (pending != tp);
+
+	  /* Record the event thread's event for later.  */
+	  save_waitstatus (tp, &ecs->ws);
+	  /* This was cleared early, by handle_inferior_event.  Set it
+	     so this pending event is considered by
+	     do_target_wait.  */
+	  tp->resumed = 1;
+
+	  gdb_assert (!tp->executing);
+
+	  regcache = get_thread_regcache (tp->ptid);
+	  tp->suspend.stop_pc = regcache_read_pc (regcache);
+
+	  if (debug_infrun)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: saved stop_pc=%s for %s "
+				  "(currently_stepping=%d)\n",
+				  paddress (target_gdbarch (),
+					    tp->suspend.stop_pc),
+				  target_pid_to_str (tp->ptid),
+				  currently_stepping (tp));
+	    }
+
+	  /* This in-line step-over finished; clear this so we won't
+	     start a new one.  This is what handle_signal_stop would
+	     do, if we returned false.  */
+	  tp->stepping_over_breakpoint = 0;
+	  tp->stepping_over_watchpoint = 0;
+
+	  /* Wake up the event loop again.  */
+	  mark_async_event_handler (infrun_async_inferior_event_token);
+
+	  prepare_to_wait (ecs);
+	  return 1;
+	}
     }
+
+  return 0;
 }
 
 /* Come here when the program has stopped with a signal.  */
@@ -5116,7 +5220,8 @@ handle_signal_stop (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.)  */
-  finish_step_over (ecs);
+  if (finish_step_over (ecs))
+    return;
 
   /* If we either finished a single-step or hit a breakpoint, but
      the user wanted this thread to be stopped, pretend we got a

  reply	other threads:[~2015-04-13 15:28 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-07 12:49 Pedro Alves
2015-04-07 12:50 ` [PATCH v2 10/23] PPC64: Fix step-over-trips-on-watchpoint.exp with displaced stepping on Pedro Alves
2015-04-07 12:50 ` [PATCH v2 05/23] remote.c/all-stop: Implement TARGET_WAITKIND_NO_RESUMED and TARGET_WNOHANG Pedro Alves
2015-04-07 12:50 ` [PATCH v2 09/23] Make gdb.threads/step-over-trips-on-watchpoint.exp effective on !x86 Pedro Alves
2015-04-07 12:50 ` [PATCH v2 23/23] native Linux: enable always non-stop by default Pedro Alves
2015-04-07 12:50 ` [PATCH v2 03/23] PR13858 - Can't do displaced stepping with no symbols Pedro Alves
2015-04-09 12:46   ` Pedro Alves
2015-04-07 12:50 ` [PATCH v2 01/23] Fix gdb.base/sigstep.exp with displaced stepping on software single-step targets Pedro Alves
2015-04-10  9:56   ` Pedro Alves
2015-04-07 12:50 ` [PATCH v2 19/23] Disable displaced stepping if trying it fails Pedro Alves
2015-04-07 12:50 ` [PATCH v2 16/23] Fix signal-while-stepping-over-bp-other-thread.exp on targets always in non-stop Pedro Alves
2015-04-07 12:50 ` [PATCH v2 15/23] Implement all-stop on top of a target running non-stop mode Pedro Alves
2015-04-07 13:36   ` Eli Zaretskii
2015-04-08  9:34   ` Yao Qi
2015-04-08  9:53     ` Pedro Alves
2015-04-08 11:08       ` Pedro Alves
2015-04-08 19:35         ` Pedro Alves
2015-04-08 19:41           ` Pedro Alves
2015-04-07 12:50 ` [PATCH v2 02/23] Fix and test "checkpoint" in " Pedro Alves
2015-04-07 12:50 ` [PATCH v2 11/23] Use keep_going in proceed and start_step_over too Pedro Alves
2015-04-07 12:50 ` [PATCH v2 04/23] Change adjust_pc_after_break's prototype Pedro Alves
2015-04-07 12:50 ` [PATCH v2 12/23] Misc switch_back_to_stepped_thread cleanups Pedro Alves
2015-04-07 12:50 ` [PATCH v2 20/23] PPC64: symbol-file + exec-file results in broken displaced stepping Pedro Alves
2015-04-07 12:50 ` [PATCH v2 21/23] PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with " Pedro Alves
2015-04-07 12:50 ` [PATCH v2 22/23] S/390: displaced stepping and PC-relative RIL-b/RIL-c instructions Pedro Alves
2015-04-07 12:55 ` [PATCH v2 17/23] Fix interrupt-noterm.exp on targets always in non-stop Pedro Alves
2015-04-07 12:57 ` [PATCH v2 08/23] Test step-over-{lands-on-breakpoint|trips-on-watchpoint}.exp with displaced stepping Pedro Alves
2015-04-10 14:54   ` Pedro Alves
2015-04-07 12:59 ` [PATCH v2 14/23] Teach non-stop to do in-line step-overs (stop all, step, restart) Pedro Alves
2015-04-07 12:59 ` [PATCH v2 07/23] Embed the pending step-over chain in thread_info objects Pedro Alves
2015-04-07 12:59 ` [PATCH v2 13/23] Factor out code to re-resume stepped thread Pedro Alves
2015-04-07 13:30 ` [PATCH v2 06/23] Make thread_still_needs_step_over consider stepping_over_watchpoint too Pedro Alves
2015-04-08  9:28   ` Yao Qi
2015-04-13 10:47     ` Pedro Alves
2015-04-07 13:30 ` [PATCH v2 18/23] Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race Pedro Alves
2015-04-08  9:45 ` [PATCH v2 00/23] All-stop on top of non-stop Yao Qi
2015-04-08 10:17   ` Pedro Alves
2015-04-08 10:30     ` Pedro Alves
2015-04-10  8:41     ` Yao Qi
2015-04-10  8:50       ` Pedro Alves
2015-04-10  8:22 ` Yao Qi
2015-04-10  8:34   ` Pedro Alves
2015-04-10  9:26     ` Yao Qi
2015-04-13 15:28       ` Pedro Alves [this message]
2015-04-13 16:16         ` Yao Qi
2015-04-13 16:23           ` Pedro Alves
2015-04-13 16:23           ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=552BE0A3.5040001@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=qiyaoltc@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).