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] 05/10 Expose context_switch


In non-stop mode, whenever we switch threads, and because each
is handled independently of the others, we need to context-switch
outside of infrun.c (e.g., "thread n" command, thread apply 
all, "continue --all").

This patch adds the base support for that.

-- 
Pedro Alves
2008-05-06  Pedro Alves  <pedro@codesourcery.com>

	* inferior.h (context_switch_to): Declare.
	* infrun.c (ecss): New global.
	(wait_for_inferior): Use global ecss.
	(async_ecss, async_ecs): Delete.
	(fetch_inferior_event): Use global ecss.
	(context_switch_to): New.

---
 gdb/inferior.h |    2 ++
 gdb/infrun.c   |   49 +++++++++++++++++++++++++++++--------------------
 2 files changed, 31 insertions(+), 20 deletions(-)

Index: src/gdb/inferior.h
===================================================================
--- src.orig/gdb/inferior.h	2008-05-06 03:29:04.000000000 +0100
+++ src/gdb/inferior.h	2008-05-06 03:30:10.000000000 +0100
@@ -132,6 +132,8 @@ extern void clear_proceed_status (void);
 
 extern void proceed (CORE_ADDR, enum target_signal, int);
 
+extern ptid_t context_switch_to (ptid_t ptid);
+
 /* When set, stop the 'step' command if we enter a function which has
    no line number information.  The normal behavior is that we step
    over such function.  */
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2008-05-06 03:24:59.000000000 +0100
+++ src/gdb/infrun.c	2008-05-06 03:27:31.000000000 +0100
@@ -288,6 +288,8 @@ static struct breakpoint *step_resume_br
 static ptid_t target_last_wait_ptid;
 static struct target_waitstatus target_last_waitstatus;
 
+struct execution_control_state ecss;
+
 /* This is used to remember when a fork, vfork or exec event
    was caught by a catchpoint, and thus the event is to be
    followed at the next resume of the inferior, and not
@@ -1426,7 +1428,6 @@ void
 wait_for_inferior (int treat_exec_as_sigtrap)
 {
   struct cleanup *old_cleanups;
-  struct execution_control_state ecss;
   struct execution_control_state *ecs;
 
   if (debug_infrun)
@@ -1437,8 +1438,6 @@ wait_for_inferior (int treat_exec_as_sig
   old_cleanups = make_cleanup (delete_step_resume_breakpoint,
 			       &step_resume_breakpoint);
 
-  /* wfi still stays in a loop, so it's OK just to take the address of
-     a local to get the ecs pointer.  */
   ecs = &ecss;
 
   /* Fill in with reasonable starting values.  */
@@ -1484,25 +1483,20 @@ wait_for_inferior (int treat_exec_as_sig
    event loop whenever a change of state is detected on the file
    descriptor corresponding to the target. It can be called more than
    once to complete a single execution command. In such cases we need
-   to keep the state in a global variable ASYNC_ECSS. If it is the
-   last time that this function is called for a single execution
-   command, then report to the user that the inferior has stopped, and
-   do the necessary cleanups. */
-
-struct execution_control_state async_ecss;
-struct execution_control_state *async_ecs;
+   to keep the state in a global variable ECSS. If it is the last time
+   that this function is called for a single execution command, then
+   report to the user that the inferior has stopped, and do the
+   necessary cleanups. */
 
 void
 fetch_inferior_event (void *client_data)
 {
-  static struct cleanup *old_cleanups;
-
-  async_ecs = &async_ecss;
+  struct execution_control_state *ecs = &ecss;
 
-  if (!async_ecs->wait_some_more)
+  if (!ecs->wait_some_more)
     {
       /* Fill in with reasonable starting values.  */
-      init_execution_control_state (async_ecs);
+      init_execution_control_state (ecs);
 
       /* We'll update this if & when we switch to a new thread. */
       previous_inferior_ptid = inferior_ptid;
@@ -1519,15 +1513,15 @@ fetch_inferior_event (void *client_data)
     }
 
   if (deprecated_target_wait_hook)
-    async_ecs->ptid =
-      deprecated_target_wait_hook (async_ecs->waiton_ptid, async_ecs->wp);
+    ecs->ptid =
+      deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
   else
-    async_ecs->ptid = target_wait (async_ecs->waiton_ptid, async_ecs->wp);
+    ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
 
   /* Now figure out what to do with the result of the result.  */
-  handle_inferior_event (async_ecs);
+  handle_inferior_event (ecs);
 
-  if (!async_ecs->wait_some_more)
+  if (!ecs->wait_some_more)
     {
       delete_step_resume_breakpoint (&step_resume_breakpoint);
 
@@ -1633,6 +1627,21 @@ context_switch (struct execution_control
   switch_to_thread (ecs->ptid);
 }
 
+/* Context switch to thread PTID.  */
+ptid_t
+context_switch_to (ptid_t ptid)
+{
+  ptid_t current_ptid = inferior_ptid;
+
+  /* Context switch to the new thread.	*/
+  if (!ptid_equal (ptid, inferior_ptid))
+    {
+      ecss.ptid = ptid;
+      context_switch (&ecss);
+    }
+  return current_ptid;
+}
+
 static void
 adjust_pc_after_break (struct execution_control_state *ecs)
 {

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