Handle multiple target events before commit resume concurrent-displaced-stepping-rocm-3.5
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 21 May 2020 22:42:16 +0000 (18:42 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Wed, 10 Jun 2020 21:26:05 +0000 (17:26 -0400)
Modify fetch_inferior_event to fetch (and handle) events from the target
as long as it provides events.

When resuming a thread that has hit a breakpoint (and it was decided
that it should be resumed), don't commit_resume just yet.  Wait until
the target has no more events to provide to do so.

Change-Id: Ia223a7d95dd5a4844c6a96e1125fb03d3e295584

gdb/infrun.c
gdb/target.c
gdb/target.h

index 4139e47139558871a3b85647f1829964f52c2da0..f61e706ef91ee011541aaae400253185ae11be7f 100644 (file)
@@ -91,7 +91,7 @@ static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
 
 static int maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
 
-static void resume (gdb_signal sig);
+static void resume (gdb_signal sig, bool commit = true);
 
 /* Asynchronous signal handler registered as event loop source for
    when we have pending events ready to be passed to the core.  */
@@ -1876,7 +1876,8 @@ reset_ecs (struct execution_control_state *ecs, struct thread_info *tp)
   ecs->ptid = tp->ptid;
 }
 
-static void keep_going_pass_signal (struct execution_control_state *ecs);
+static void keep_going_pass_signal (struct execution_control_state *ecs,
+                                   bool commit = true);
 static void prepare_to_wait (struct execution_control_state *ecs);
 static int keep_going_stepped_thread (struct thread_info *tp);
 static step_over_what thread_still_needs_step_over (struct thread_info *tp);
@@ -2179,7 +2180,8 @@ internal_resume_ptid (int user_step)
    bookkeeping.  */
 
 static void
-do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
+do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig,
+                 bool commit)
 {
   struct thread_info *tp = inferior_thread ();
 
@@ -2219,7 +2221,10 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
 
   target_resume (resume_ptid, step, sig);
 
-  target_commit_resume ();
+  if (commit)
+    target_commit_resume ();
+  else
+    current_top_target ()->pending_commit_resume = true;
 }
 
 /* Resume the inferior.  SIG is the signal to give the inferior
@@ -2227,7 +2232,7 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
    call 'resume', which handles exceptions.  */
 
 static void
-resume_1 (enum gdb_signal sig)
+resume_1 (enum gdb_signal sig, bool commit)
 {
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = regcache->arch ();
@@ -2390,7 +2395,7 @@ resume_1 (enum gdb_signal sig)
              insert_breakpoints ();
 
              resume_ptid = internal_resume_ptid (user_step);
-             do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+             do_target_resume (resume_ptid, 0, GDB_SIGNAL_0, commit);
              tp->resumed = 1;
              return;
            }
@@ -2597,7 +2602,7 @@ resume_1 (enum gdb_signal sig)
       gdb_assert (pc_in_thread_step_range (pc, tp));
     }
 
-  do_target_resume (resume_ptid, step, sig);
+  do_target_resume (resume_ptid, step, sig, commit);
   tp->resumed = 1;
 }
 
@@ -2606,11 +2611,11 @@ resume_1 (enum gdb_signal sig)
    rolls back state on error.  */
 
 static void
-resume (gdb_signal sig)
+resume (gdb_signal sig, bool commit)
 {
   try
     {
-      resume_1 (sig);
+      resume_1 (sig, commit);
     }
   catch (const gdb_exception &ex)
     {
@@ -3120,7 +3125,8 @@ static void check_exception_resume (struct execution_control_state *,
 
 static void end_stepping_range (struct execution_control_state *ecs);
 static void stop_waiting (struct execution_control_state *ecs);
-static void keep_going (struct execution_control_state *ecs);
+static void keep_going (struct execution_control_state *ecs,
+                       bool commit = true);
 static void process_event_stop_test (struct execution_control_state *ecs);
 static int switch_back_to_stepped_thread (struct execution_control_state *ecs);
 
@@ -3681,8 +3687,6 @@ fetch_inferior_event (void *client_data)
   int cmd_done = 0;
   ptid_t waiton_ptid = minus_one_ptid;
 
-  memset (ecs, 0, sizeof (*ecs));
-
   /* Events are always processed with the main UI as current UI.  This
      way, warnings, debug output, etc. are always consistently sent to
      the main console.  */
@@ -3723,78 +3727,92 @@ fetch_inferior_event (void *client_data)
       = make_scoped_restore (&execution_direction,
                             target_execution_direction ());
 
-    ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
-                               target_can_async_p () ? TARGET_WNOHANG : 0);
-
-    if (debug_infrun)
-      print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+    int iter = 0;
+    while (true)
+      {
+       memset (ecs, 0, sizeof (*ecs));
 
-    /* If an error happens while handling the event, propagate GDB's
-       knowledge of the executing state to the frontend/user running
-       state.  */
-    ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
-    scoped_finish_thread_state finish_state (finish_ptid);
+       ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
+                                   target_can_async_p () ? TARGET_WNOHANG : 0);
+       if (ecs->ws.kind == TARGET_WAITKIND_IGNORE
+           || ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED)
+         break;
 
-    /* Get executed before scoped_restore_current_thread above to apply
-       still for the thread which has thrown the exception.  */
-    auto defer_bpstat_clear
-      = make_scope_exit (bpstat_clear_actions);
-    auto defer_delete_threads
-      = make_scope_exit (delete_just_stopped_threads_infrun_breakpoints);
+       if (debug_infrun)
+         print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
-    /* Now figure out what to do with the result of the result.  */
-    handle_inferior_event (ecs);
+       /* If an error happens while handling the event, propagate GDB's
+          knowledge of the executing state to the frontend/user running
+          state.  */
+       ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
+       scoped_finish_thread_state finish_state (finish_ptid);
 
-    if (!ecs->wait_some_more)
-      {
-       struct inferior *inf = find_inferior_ptid (ecs->ptid);
-       int should_stop = 1;
-       struct thread_info *thr = ecs->event_thread;
+       /* Get executed before scoped_restore_current_thread above to apply
+          still for the thread which has thrown the exception.  */
+       auto defer_bpstat_clear
+         = make_scope_exit (bpstat_clear_actions);
+       auto defer_delete_threads
+         = make_scope_exit (delete_just_stopped_threads_infrun_breakpoints);
 
-       delete_just_stopped_threads_infrun_breakpoints ();
+       /* Now figure out what to do with the result of the result.  */
+       handle_inferior_event (ecs);
 
-       if (thr != NULL)
+       if (!ecs->wait_some_more)
          {
-           struct thread_fsm *thread_fsm = thr->thread_fsm;
+           struct inferior *inf = find_inferior_ptid (ecs->ptid);
+           int should_stop = 1;
+           struct thread_info *thr = ecs->event_thread;
 
-           if (thread_fsm != NULL)
-             should_stop = thread_fsm->should_stop (thr);
-         }
+           delete_just_stopped_threads_infrun_breakpoints ();
 
-       if (!should_stop)
-         {
-           keep_going (ecs);
-         }
-       else
-         {
-           bool should_notify_stop = true;
-           int proceeded = 0;
-
-           clean_up_just_stopped_threads_fsms (ecs);
+           if (thr != NULL)
+             {
+               struct thread_fsm *thread_fsm = thr->thread_fsm;
 
-           if (thr != NULL && thr->thread_fsm != NULL)
-             should_notify_stop = thr->thread_fsm->should_notify_stop ();
+               if (thread_fsm != NULL)
+                 should_stop = thread_fsm->should_stop (thr);
+             }
 
-           if (should_notify_stop)
+           if (!should_stop)
              {
-               /* We may not find an inferior if this was a process exit.  */
-               if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
-                 proceeded = normal_stop ();
+               keep_going (ecs);
              }
-
-           if (!proceeded)
+           else
              {
-               inferior_event_handler (INF_EXEC_COMPLETE, NULL);
-               cmd_done = 1;
+               bool should_notify_stop = true;
+               int proceeded = 0;
+
+               clean_up_just_stopped_threads_fsms (ecs);
+
+               if (thr != NULL && thr->thread_fsm != NULL)
+                 should_notify_stop = thr->thread_fsm->should_notify_stop ();
+
+               if (should_notify_stop)
+                 {
+                   /* We may not find an inferior if this was a process exit.  */
+                   if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
+                     proceeded = normal_stop ();
+                 }
+
+               if (!proceeded)
+                 {
+                   inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+                   cmd_done = 1;
+                 }
              }
          }
-      }
 
-    defer_delete_threads.release ();
-    defer_bpstat_clear.release ();
+       defer_delete_threads.release ();
+       defer_bpstat_clear.release ();
 
-    /* No error, don't finish the thread states yet.  */
-    finish_state.release ();
+       /* No error, don't finish the thread states yet.  */
+       finish_state.release ();
+
+       iter++;
+      }
+
+    if (current_top_target ()->pending_commit_resume)
+      current_top_target ()->commit_resume ();
 
     /* This scope is used to ensure that readline callbacks are
        reinstalled here.  */
@@ -6244,7 +6262,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
       /* Likewise if we aren't even stepping.  */
-      keep_going (ecs);
+      keep_going (ecs, false /* don't commit */);
       return;
     }
 
@@ -7022,7 +7040,7 @@ keep_going_stepped_thread (struct thread_info *tp)
 
       tp->resumed = 1;
       resume_ptid = internal_resume_ptid (tp->control.stepping_command);
-      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0, true);
     }
   else
     {
@@ -7443,7 +7461,7 @@ stop_waiting (struct execution_control_state *ecs)
    signal is set to nopass.  */
 
 static void
-keep_going_pass_signal (struct execution_control_state *ecs)
+keep_going_pass_signal (struct execution_control_state *ecs, bool commit)
 {
   gdb_assert (ecs->event_thread->ptid == inferior_ptid);
   gdb_assert (!ecs->event_thread->resumed);
@@ -7562,7 +7580,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
-      resume (ecs->event_thread->suspend.stop_signal);
+      resume (ecs->event_thread->suspend.stop_signal, commit);
     }
 
   prepare_to_wait (ecs);
@@ -7573,7 +7591,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
    resuming part; waiting for the next event is done elsewhere.  */
 
 static void
-keep_going (struct execution_control_state *ecs)
+keep_going (struct execution_control_state *ecs, bool commit)
 {
   if (ecs->event_thread->control.trap_expected
       && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
@@ -7581,7 +7599,7 @@ keep_going (struct execution_control_state *ecs)
 
   if (!signal_program[ecs->event_thread->suspend.stop_signal])
     ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-  keep_going_pass_signal (ecs);
+  keep_going_pass_signal (ecs, commit);
 }
 
 /* This function normally comes after a resume, before
index e3e30afd7a5450b65101ac2c90d8be7190bd65dd..093f74759a3563d16806ef0987cd112bc7ed419f 100644 (file)
@@ -2123,8 +2123,12 @@ void
 target_commit_resume (void)
 {
   if (defer_target_commit_resume)
-    return;
+    {
+      current_top_target ()->pending_commit_resume = true;
+      return;
+    }
 
+  current_top_target ()->pending_commit_resume = false;
   current_top_target ()->commit_resume ();
 }
 
index 7469e6bee7a61c76e91b422451ed425832488a45..1ce1ab8cc47d147ee10f569f704fd751e45c78b7 100644 (file)
@@ -429,6 +429,8 @@ struct target_info
 
 struct target_ops
   {
+    bool pending_commit_resume = false;
+
     /* Return this target's stratum.  */
     virtual strata stratum () const = 0;
 
This page took 0.032139 seconds and 4 git commands to generate.