Implement all-stop on top of a target running non-stop mode
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 9690a3608f50dfd23bc355a13cc36c68ebe57950..f1d8e7c564ef336668db06f601fdbce7d79a4c7a 100644 (file)
@@ -1630,7 +1630,7 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
     fprintf_filtered (file,
                      _("Debugger's willingness to use displaced stepping "
                        "to step over breakpoints is %s (currently %s).\n"),
-                     value, non_stop ? "on" : "off");
+                     value, target_is_non_stop_p () ? "on" : "off");
   else
     fprintf_filtered (file,
                      _("Debugger's willingness to use displaced stepping "
@@ -1643,7 +1643,8 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
 static int
 use_displaced_stepping (struct gdbarch *gdbarch)
 {
-  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO && non_stop)
+  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO
+           && target_is_non_stop_p ())
           || can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
          && gdbarch_displaced_step_copy_insn_p (gdbarch)
          && find_record_target () == NULL);
@@ -2014,7 +2015,7 @@ start_step_over (void)
         because we wouldn't be able to resume anything else until the
         target stops again.  In non-stop, the resume always resumes
         only TP, so it's OK to let the thread resume freely.  */
-      if (!non_stop && !step_what)
+      if (!target_is_non_stop_p () && !step_what)
        continue;
 
       switch_to_thread (tp->ptid);
@@ -2033,7 +2034,7 @@ start_step_over (void)
          return 1;
        }
 
-      if (!non_stop)
+      if (!target_is_non_stop_p ())
        {
          /* On all-stop, shouldn't have resumed unless we needed a
             step over.  */
@@ -2178,6 +2179,25 @@ user_visible_resume_ptid (int step)
   return resume_ptid;
 }
 
+/* Return a ptid representing the set of threads that we will resume,
+   in the perspective of the target, assuming run control handling
+   does not require leaving some threads stopped (e.g., stepping past
+   breakpoint).  USER_STEP indicates whether we're about to start the
+   target for a stepping command.  */
+
+static ptid_t
+internal_resume_ptid (int user_step)
+{
+  /* In non-stop, we always control threads individually.  Note that
+     the target may always work in non-stop mode even with "set
+     non-stop off", in which case user_visible_resume_ptid could
+     return a wildcard ptid.  */
+  if (target_is_non_stop_p ())
+    return inferior_ptid;
+  else
+    return user_visible_resume_ptid (user_step);
+}
+
 /* Wrapper for target_resume, that handles infrun-specific
    bookkeeping.  */
 
@@ -2389,7 +2409,7 @@ resume (enum gdb_signal sig)
              insert_single_step_breakpoint (gdbarch, aspace, pc);
              insert_breakpoints ();
 
-             resume_ptid = user_visible_resume_ptid (user_step);
+             resume_ptid = internal_resume_ptid (user_step);
              do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
              discard_cleanups (old_cleanups);
              tp->resumed = 1;
@@ -2498,12 +2518,7 @@ resume (enum gdb_signal sig)
      use singlestep breakpoint.  */
   gdb_assert (!(thread_has_single_step_breakpoints_set (tp) && step));
 
-  /* Decide the set of threads to ask the target to resume.  Start
-     by assuming everything will be resumed, than narrow the set
-     by applying increasingly restricting conditions.  */
-  resume_ptid = user_visible_resume_ptid (user_step);
-
-  /* Maybe resume a single thread after all.  */
+  /* Decide the set of threads to ask the target to resume.  */
   if ((step || thread_has_single_step_breakpoints_set (tp))
       && tp->control.trap_expected)
     {
@@ -2514,6 +2529,8 @@ resume (enum gdb_signal sig)
         breakpoint if allowed to run.  */
       resume_ptid = inferior_ptid;
     }
+  else
+    resume_ptid = internal_resume_ptid (user_step);
 
   if (execution_direction != EXEC_REVERSE
       && step && breakpoint_inserted_here_p (aspace, pc))
@@ -2935,11 +2952,52 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
         other thread was already doing one.  In either case, don't
         resume anything else until the step-over is finished.  */
     }
-  else if (started && !non_stop)
+  else if (started && !target_is_non_stop_p ())
     {
       /* A new displaced stepping sequence was started.  In all-stop,
         we can't talk to the target anymore until it next stops.  */
     }
+  else if (!non_stop && target_is_non_stop_p ())
+    {
+      /* In all-stop, but the target is always in non-stop mode.
+        Start all other threads that are implicitly resumed too.  */
+      ALL_NON_EXITED_THREADS (tp)
+        {
+         /* Ignore threads of processes we're not resuming.  */
+         if (!ptid_match (tp->ptid, resume_ptid))
+           continue;
+
+         if (tp->resumed)
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] resumed\n",
+                                   target_pid_to_str (tp->ptid));
+             gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p);
+             continue;
+           }
+
+         if (thread_is_in_step_over_chain (tp))
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] needs step-over\n",
+                                   target_pid_to_str (tp->ptid));
+             continue;
+           }
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: proceed: resuming %s\n",
+                               target_pid_to_str (tp->ptid));
+
+         reset_ecs (ecs, tp);
+         switch_to_thread (tp->ptid);
+         keep_going_pass_signal (ecs);
+         if (!ecs->wait_some_more)
+           error ("Command aborted.");
+       }
+    }
   else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
     {
       /* The thread wasn't started, and isn't queued, run it now.  */
@@ -3151,7 +3209,7 @@ for_each_just_stopped_thread (for_each_just_stopped_thread_callback_func func)
   if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid))
     return;
 
-  if (non_stop)
+  if (target_is_non_stop_p ())
     {
       /* If in non-stop mode, only the current thread stopped.  */
       func (inferior_thread ());
@@ -3632,7 +3690,7 @@ fetch_inferior_event (void *client_data)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
   else
     ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
@@ -3871,7 +3929,8 @@ adjust_pc_after_break (struct thread_info *thread,
      to get the "stopped by SW BP and needs adjustment" info out of
      the target/kernel (and thus never reach here; see above).  */
   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 = make_cleanup (null_cleanup, NULL);
 
@@ -4148,7 +4207,7 @@ stop_all_threads (void)
   ptid_t entry_ptid;
   struct cleanup *old_chain;
 
-  gdb_assert (non_stop);
+  gdb_assert (target_is_non_stop_p ());
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
@@ -4460,7 +4519,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
   {
     ptid_t mark_ptid;
 
-    if (!non_stop)
+    if (!target_is_non_stop_p ())
       mark_ptid = minus_one_ptid;
     else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
             || ecs->ws.kind == TARGET_WAITKIND_EXITED)
@@ -4774,7 +4833,8 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
          child = ecs->ws.value.related_pid;
 
          /* In non-stop mode, also resume the other branch.  */
-         if (non_stop && !detach_fork)
+         if (!detach_fork && (non_stop
+                              || (sched_multi && target_is_non_stop_p ())))
            {
              if (follow_child)
                switch_to_thread (parent);
@@ -5058,7 +5118,7 @@ finish_step_over (struct execution_control_state *ecs)
        clear_step_over_info ();
     }
 
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     return 0;
 
   /* Start a new step-over in another thread if there's one that
@@ -5638,15 +5698,17 @@ handle_signal_stop (struct execution_control_state *ecs)
          /* Reset trap_expected to ensure breakpoints are re-inserted.  */
          ecs->event_thread->control.trap_expected = 0;
 
-         if (non_stop)
+         if (target_is_non_stop_p ())
            {
+             /* Either "set non-stop" is "on", or the target is
+                always in non-stop mode.  In this case, we have a bit
+                more work to do.  Resume the current thread, and if
+                we had paused all threads, restart them while the
+                signal handler runs.  */
              keep_going (ecs);
 
-             /* The step-over has been canceled temporarily while the
-                signal handler executes.  */
              if (was_in_line)
                {
-                 /* We had paused all threads, restart them.  */
                  restart_threads (ecs->event_thread);
                }
              else if (debug_infrun)
@@ -6541,7 +6603,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 static int
 switch_back_to_stepped_thread (struct execution_control_state *ecs)
 {
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       struct thread_info *tp;
       struct thread_info *stepping_thread;
@@ -6632,7 +6694,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
       ALL_NON_EXITED_THREADS (tp)
         {
-         /* Ignore threads of processes we're not resuming.  */
+         /* Ignore threads of processes the caller is not
+            resuming.  */
          if (!sched_multi
              && ptid_get_pid (tp->ptid) != ptid_get_pid (ecs->ptid))
            continue;
@@ -6778,7 +6841,7 @@ keep_going_stepped_thread (struct thread_info *tp)
                                     stop_pc);
 
       tp->resumed = 1;
-      resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+      resume_ptid = internal_resume_ptid (tp->control.stepping_command);
       do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
     }
   else
@@ -7199,6 +7262,11 @@ stop_waiting (struct execution_control_state *ecs)
 
   /* Let callers know we don't want to wait for the inferior anymore.  */
   ecs->wait_some_more = 0;
+
+  /* If all-stop, but the target is always in non-stop mode, stop all
+     threads now that we're presenting the stop to the user.  */
+  if (!non_stop && target_is_non_stop_p ())
+    stop_all_threads ();
 }
 
 /* Like keep_going, but passes the signal to the inferior, even if the
@@ -7313,7 +7381,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
         insert_breakpoints below, because that removes the breakpoint
         we're about to step over, otherwise other threads could miss
         it.  */
-      if (step_over_info_valid_p () && non_stop)
+      if (step_over_info_valid_p () && target_is_non_stop_p ())
        stop_all_threads ();
 
       /* Stop stepping if inserting breakpoints fails.  */
This page took 0.028578 seconds and 4 git commands to generate.