* infrun.c (stepping_past_breakpoint): New global variable.
authorUlrich Weigand <uweigand@de.ibm.com>
Mon, 10 Sep 2007 18:49:26 +0000 (18:49 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Mon, 10 Sep 2007 18:49:26 +0000 (18:49 +0000)
(stepping_past_breakpoint_ptid): Likewise.
(prepare_to_proceed): Add STEP parameter.  Do not check for Ctrl-C.
Only switch threads if we need to single-step over a breakpoint hit
in the previously selected thread.  If stepping, remember previous
thread to switch back to in STEPPING_PAST_BREAKPOINT[_PTID].  Call
switch_to_thread instead of copying its contents.
(proceed): Pass STEP to prepare_to_proceed.  Always set ONEPROC if
prepare_to_proceed returns true.
(init_wait_for_inferior): Reset STEPPING_PAST_BREAKPOINT.
(context_switch): Call switch_to_thread.
(handle_inferior_event): Switch back to previous thread if requested
in STEPPING_PAST_BREAKPOINT[_PTID] by prepare_to_proceed.
* gdbthread.h (switch_to_thread): Add prototype.
* thread.c (switch_to_thread): Make global.

gdb/ChangeLog
gdb/gdbthread.h
gdb/infrun.c
gdb/thread.c

index e3c9a81d9b54dcdaace34c120ef86a793dcb644e..5ea94cc5a070ed845f4f1ea92d51bf3d5151494c 100644 (file)
@@ -1,3 +1,21 @@
+2007-09-10  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * infrun.c (stepping_past_breakpoint): New global variable.
+       (stepping_past_breakpoint_ptid): Likewise.
+       (prepare_to_proceed): Add STEP parameter.  Do not check for Ctrl-C.
+       Only switch threads if we need to single-step over a breakpoint hit
+       in the previously selected thread.  If stepping, remember previous
+       thread to switch back to in STEPPING_PAST_BREAKPOINT[_PTID].  Call
+       switch_to_thread instead of copying its contents.
+       (proceed): Pass STEP to prepare_to_proceed.  Always set ONEPROC if
+       prepare_to_proceed returns true.
+       (init_wait_for_inferior): Reset STEPPING_PAST_BREAKPOINT.
+       (context_switch): Call switch_to_thread.
+       (handle_inferior_event): Switch back to previous thread if requested
+       in STEPPING_PAST_BREAKPOINT[_PTID] by prepare_to_proceed.
+       * gdbthread.h (switch_to_thread): Add prototype.
+       * thread.c (switch_to_thread): Make global.
+
 2007-09-07  2007-09-07  Pierre Muller  <muller@ics.u-strasbg.fr>
 
         * p-valprint.c: Fix 7 ARI reported problems.
index d37803368a85df9b27206d4b3c0939c4a289f090..aeb4a408ff2b2c90839d905760dfb96b3f7dd5ef 100644 (file)
@@ -135,6 +135,9 @@ extern void load_infrun_state (ptid_t ptid,
                               int       *current_line,
                               struct symtab **current_symtab);
 
+/* Switch from one thread to another.  */
+extern void switch_to_thread (ptid_t ptid);
+
 /* Commands with a prefix of `thread'.  */
 extern struct cmd_list_element *thread_cmd_list;
 
index 7026d08cf437f61c3e53e741fd01e30b5291ec75..a8297c95ebf44386d3894ee75500b6c21c93eb49 100644 (file)
@@ -78,7 +78,7 @@ static int currently_stepping (struct execution_control_state *ecs);
 
 static void xdb_handle_command (char *args, int from_tty);
 
-static int prepare_to_proceed (void);
+static int prepare_to_proceed (int);
 
 void _initialize_infrun (void);
 
@@ -445,6 +445,11 @@ static CORE_ADDR singlestep_pc;
    thread here so that we can resume single-stepping it later.  */
 static ptid_t saved_singlestep_ptid;
 static int stepping_past_singlestep_breakpoint;
+
+/* Similarly, if we are stepping another thread past a breakpoint,
+   save the original thread here so that we can resume stepping it later.  */
+static ptid_t stepping_past_breakpoint_ptid;
+static int stepping_past_breakpoint;
 \f
 
 /* Things to clean up if we QUIT out of resume ().  */
@@ -642,7 +647,7 @@ clear_proceed_status (void)
 /* This should be suitable for any targets that support threads. */
 
 static int
-prepare_to_proceed (void)
+prepare_to_proceed (int step)
 {
   ptid_t wait_ptid;
   struct target_waitstatus wait_status;
@@ -650,42 +655,35 @@ prepare_to_proceed (void)
   /* Get the last target status returned by target_wait().  */
   get_last_target_status (&wait_ptid, &wait_status);
 
-  /* Make sure we were stopped either at a breakpoint, or because
-     of a Ctrl-C.  */
+  /* Make sure we were stopped at a breakpoint.  */
   if (wait_status.kind != TARGET_WAITKIND_STOPPED
-      || (wait_status.value.sig != TARGET_SIGNAL_TRAP
-         && wait_status.value.sig != TARGET_SIGNAL_INT))
+      || wait_status.value.sig != TARGET_SIGNAL_TRAP)
     {
       return 0;
     }
 
+  /* Switched over from WAIT_PID.  */
   if (!ptid_equal (wait_ptid, minus_one_ptid)
-      && !ptid_equal (inferior_ptid, wait_ptid))
+      && !ptid_equal (inferior_ptid, wait_ptid)
+      && breakpoint_here_p (read_pc_pid (wait_ptid)))
     {
-      /* Switched over from WAIT_PID.  */
-      CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
-
-      if (wait_pc != read_pc ())
+      /* If stepping, remember current thread to switch back to.  */
+      if (step)
        {
-         /* Switch back to WAIT_PID thread.  */
-         inferior_ptid = wait_ptid;
-
-         /* FIXME: This stuff came from switch_to_thread() in
-            thread.c (which should probably be a public function).  */
-         reinit_frame_cache ();
-         registers_changed ();
-         stop_pc = wait_pc;
+         stepping_past_breakpoint = 1;
+         stepping_past_breakpoint_ptid = inferior_ptid;
        }
 
+      /* Switch back to WAIT_PID thread.  */
+      switch_to_thread (wait_ptid);
+
       /* We return 1 to indicate that there is a breakpoint here,
-         so we need to step over it before continuing to avoid
-         hitting it straight away. */
-      if (breakpoint_here_p (wait_pc))
-       return 1;
+        so we need to step over it before continuing to avoid
+        hitting it straight away. */
+      return 1;
     }
 
   return 0;
-
 }
 
 /* Record the pc of the program the last time it stopped.  This is
@@ -751,7 +749,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      prepare_to_proceed checks the current thread against the thread
      that reported the most recent event.  If a step-over is required
      it returns TRUE and sets the current thread to the old thread. */
-  if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
+  if (prepare_to_proceed (step))
     oneproc = 1;
 
   if (oneproc)
@@ -872,6 +870,7 @@ init_wait_for_inferior (void)
   clear_proceed_status ();
 
   stepping_past_singlestep_breakpoint = 0;
+  stepping_past_breakpoint = 0;
 }
 \f
 /* This enum encodes possible reasons for doing a target_wait, so that
@@ -1141,8 +1140,8 @@ context_switch (struct execution_control_state *ecs)
                         &ecs->stepping_through_solib_catchpoints,
                         &ecs->current_line, &ecs->current_symtab);
     }
-  inferior_ptid = ecs->ptid;
-  reinit_frame_cache ();
+
+  switch_to_thread (ecs->ptid);
 }
 
 static void
@@ -1604,6 +1603,37 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   stepping_past_singlestep_breakpoint = 0;
 
+  if (stepping_past_breakpoint)
+    {
+      stepping_past_breakpoint = 0;
+
+      /* If we stopped for some other reason than single-stepping, ignore
+        the fact that we were supposed to switch back.  */
+      if (stop_signal == TARGET_SIGNAL_TRAP)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: stepping_past_breakpoint\n");
+
+         /* Pull the single step breakpoints out of the target.  */
+         if (singlestep_breakpoints_inserted_p)
+           {
+             remove_single_step_breakpoints ();
+             singlestep_breakpoints_inserted_p = 0;
+           }
+
+         /* Note: We do not call context_switch at this point, as the
+            context is already set up for stepping the original thread.  */
+         switch_to_thread (stepping_past_breakpoint_ptid);
+         /* Suppress spurious "Switching to ..." message.  */
+         previous_inferior_ptid = inferior_ptid;
+
+         resume (1, TARGET_SIGNAL_0);
+         prepare_to_wait (ecs);
+         return;
+       }
+    }
+
   /* See if a thread hit a thread-specific breakpoint that was meant for
      another thread.  If so, then step that thread past the breakpoint,
      and continue it.  */
index 8853e9105b18d25c5bce35e7d5fa38e0c39934a5..563d18a8afa4e67217592ddbc500c142d6f8b181 100644 (file)
@@ -59,7 +59,6 @@ static int thread_alive (struct thread_info *);
 static void info_threads_command (char *, int);
 static void thread_apply_command (char *, int);
 static void restore_current_thread (ptid_t);
-static void switch_to_thread (ptid_t ptid);
 static void prune_threads (void);
 static struct cleanup *make_cleanup_restore_current_thread (ptid_t,
                                                             struct frame_id);
@@ -452,7 +451,7 @@ info_threads_command (char *arg, int from_tty)
 
 /* Switch from one thread to another. */
 
-static void
+void
 switch_to_thread (ptid_t ptid)
 {
   if (ptid_equal (ptid, inferior_ptid))