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]

[PATCH v3 1/4] tracepoint multithread and multiprocess support (GDB)


This patch add 3 support to GDB:
1. Multithread tracepoint support.
In remote part, if a tracepoint is special for a thread, send P packet
with ptid of this thread to GDBstub.

2. Multiprocess tracepoint support.
This patch is for the gdbserver.
It will send ";MultiProcessTracepoint+" back to GDB if this gdbserver
support tracepoint.zhe

When cmd_qtdp got a "QTDP" packets that have P@var{thread-id}.
1.  Get ptid from thread-id.
2.  If this ptid's pid is not same with current process, send exx packets
     back to GDB.

Hmm.  Did you sync with Luis?  ISTR he had some multi-process
tracing patches too.  IIRC, he just made it so that tracepoints
apply to the current process, and then GDB made sure to set the
general thread/process (Hg) to the current process before setting
each tracepoint.  So this error seems to go in that direction,
and the main desire here is to make the tracepoints thread-specific,
not really process-specific.  Right?
The v1/v2 patches don't include this part of code.  I merged them in these
verson patch.  Then in defalut, the tracepoint info will saved in inferior
as trace_state.
When tracepoint.c's code want to access the trace_state, it will call
current_trace_state to get it.  current_trace_state will get trace_state
from current_inferior.
This function doesn't need update remote, because a tracepoint is just
for current inferior.  The gdbserver need some change, I will introduce
it clear in gdbserver's patch.

3. Multiprocess tracepoint together support.
It bases old design of GDB that control all the tracepoints together.
In current_trace_state, when target support "MultiProcessTracepointTogether",
It will return together_trace_state as current trace_state.
In remote part, when a tracepoint is not for a special thread (because ptid
for of thread already include pid of a inferior) and the gdbstub support
"MultiProcessTracepointTogether", send Pptid to gdbstub.

The import thing of 2 and 3 is current_trace_state need swith mode between
support "MultiProcessTracepointTogether" and not support it.
For example: when GDB is opened, "MultiProcessTracepointTogether" support
is closed, all the set of tracepoint will set to the trace_state of current
inferior.   When gdb connect to a gdbstub that support
"MultiProcessTracepointTogether", current_trace_state will return
"together_trace_state" instead of the trace_state of current inferior.
If it is not be handled, all of the trace_state will left in the inferior.
This patch handle it with:
"current_trace_state_together" record the last mode when call current_trace_state.
So when current_trace_state is called next time, if the mode is changed,
trace_state will be copyed from inferior to together_trace_state or from
together_trace_state to inferior.

And I added a function that has relation with multithread and multiprocess
tracepoint.
When traceframe changed (tfind), function traceframe_changed_inferior_thread_select
will be called.
GDB will check if this traceframe has $pid, $lwp, $tid.  If so, Try to
select this process and this thread that ptid is $pid, $lwp, $tid.
If not, if this tracepoint has inferior's info or thread's info, try to
select this process and this thread.

Please help me review it.

Thanks,
Hui

2013-12-31  Hui Zhu  <hui@codesourcery.com>
	    Luis Machado  <lgustavo@codesourcery.com>

	* inferior.c (set_inferior): New function.
	(inferior_command): Call set_inferior.
	* inferior.h (set_inferior): New extern.
	* remote.c (PACKET_MultiThreadTracepoint): New enum value.
	(PACKET_MultiProcessTracepointTogether): New enum value.
	(remote_protocol_packets): Support MultiThreadTracepoints
	and MultiProcessTracepointTogether.
	(remote_supports_multi_thread_tracepoint): New function.
	(remote_supports_multi_process_tracepoint_together): New function.
	(remote_download_tracepoint): Send ptid if need.
	(remote_get_tracepoint_status): Ignore a tracepoint if it is not
	for current inferior and curent target doesn't support multiprocess
	tracepoint together.
	(init_remote_ops): Initialize
	remote_ops.to_supports_multi_thread_tracepoint and
	remote_ops.to_supports_multi_process_tracepoint_together.
	(_initialize_remote): Support MultiThreadTracepoints
	and MultiProcessTracepointTogether.
	* target.c (update_current_target): Initialize
	to_supports_multi_thread_tracepoint and
	to_supports_multi_process_tracepoint_together.
	* target.h (target_ops): Add to_supports_multi_thread_tracepoint
	and to_supports_multi_process_tracepoint_together.
	(target_supports_multi_thread_tracepoint): New define.
	(target_supports_multi_process_tracepoint_together): New define.
	* tracepoint.c (tvariables, traceframe_number, tracepoint_number,
	traceframe_info, trace_status): Deleted.
	(trace_state): New struct.
	(current_trace_state_together): New int.
	(together_trace_state): New struct.
	(current_trace_state): New function.
	(current_trace_status): Return trace_status of current
	trace_state.
	(trace_inferior_data): New pointer.
	(trace_inferior_data_cleanup): New function.
	(get_trace_inferior_data): New function.
	(trace_inferior_exit): New function.
	(current_trace_state): New function.
	(clear_traceframe_info): Get tstate from current_trace_state.
	(set_traceframe_num): Ditto.
	(set_tracepoint_num): Ditto.
	(set_traceframe_context): Ditto.
	(create_trace_state_variable): Ditto.
	(find_trace_state_variable): Ditto.
	(find_trace_state_variable_by_number): Ditto.
	(delete_trace_state_variable): Ditto.
	(delete_trace_variable_command): Ditto.
	(tvariables_info_1): Ditto.
	(save_trace_state_variables): Ditto.
	(start_tracing): Ditto.
	(trace_status_command): Ditto.
	(trace_status_mi): Ditto.
	(tfind_1): Ditto.
	(trace_find_command): Ditto.
	(trace_find_tracepoint_command): Ditto.
	(get_traceframe_location): Ditto.
	(trace_dump_command): Ditto.
	(get_traceframe_number): Ditto.
	(get_tracepoint_number): Ditto.
	(set_current_traceframe): Ditto.
	(set_traceframe_number): Ditto.
	(make_cleanup_restore_current_traceframe): Ditto.
	(make_cleanup_restore_traceframe_number): Ditto.
	(create_tsv_from_upload): Ditto.
	(merge_uploaded_trace_state_variables): Ditto.
	(tfile_trace_find): Ditto.
	(tfile_fetch_registers): Ditto.
	(tfile_xfer_partial): Call get_traceframe_number.
	(tfile_has_stack): Ditto.
	(tfile_has_registers): Ditto.
	(get_traceframe_info): Get tstate from current_trace_state.
	(get_trace_state_variable_value): New function.
	(traceframe_changed_inferior_thread_select): New function.
	(_initialize_tracepoint): Initialize together_trace_state.
	Register traceframe_changed_inferior_thread_select. Register
	trace_inferior_exit.  Initialize trace_inferior_data.

--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -688,25 +688,11 @@ kill_inferior_command (char *args, int f
   bfd_cache_close_all ();
 }
-static void
-inferior_command (char *args, int from_tty)
-{
-  struct inferior *inf;
-  int num;
-
-  num = parse_and_eval_long (args);
-
-  inf = find_inferior_id (num);
-  if (inf == NULL)
-    error (_("Inferior ID %d not known."), num);
-
-  printf_filtered (_("[Switching to inferior %d [%s] (%s)]\n"),
-		   inf->num,
-		   inferior_pid_to_str (inf->pid),
-		   (inf->pspace->pspace_exec_filename != NULL
-		    ? inf->pspace->pspace_exec_filename
-		    : _("<noexec>")));
+/* Set INF as current inferior.  */
+void
+set_inferior (struct inferior *inf)
+{
   if (inf->pid != 0)
     {
       if (inf->pid != ptid_get_pid (inferior_ptid))
@@ -719,20 +705,39 @@ inferior_command (char *args, int from_t
switch_to_thread (tp->ptid);
 	}
-
-      printf_filtered (_("[Switching to thread %d (%s)] "),
-		       pid_to_thread_id (inferior_ptid),
-		       target_pid_to_str (inferior_ptid));
     }
   else
     {
-      struct inferior *inf;
-
-      inf = find_inferior_id (num);
       set_current_inferior (inf);
       switch_to_thread (null_ptid);
       set_current_program_space (inf->pspace);
     }
+}
+
+static void
+inferior_command (char *args, int from_tty)
+{
+  struct inferior *inf;
+  int num;
+
+  num = parse_and_eval_long (args);
+
+  inf = find_inferior_id (num);
+  if (inf == NULL)
+    error (_("Inferior ID %d not known."), num);
+
+  printf_filtered (_("[Switching to inferior %d [%s] (%s)]\n"),
+		   inf->num,
+		   inferior_pid_to_str (inf->pid),
+		   (inf->pspace->pspace_exec_filename != NULL
+		    ? inf->pspace->pspace_exec_filename
+		    : _("<noexec>")));
+
+  set_inferior (inf);
+  if (inf->pid != 0)
+    printf_filtered (_("[Switching to thread %d (%s)] "),
+		     pid_to_thread_id (inferior_ptid),
+		     target_pid_to_str (inferior_ptid));
if (inf->pid != 0 && is_running (inferior_ptid))
     ui_out_text (current_uiout, "(running)\n");
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -641,6 +641,8 @@ extern void update_signals_program_targe
extern void signal_catch_update (const unsigned int *); +extern void set_inferior (struct inferior *inf);
+
 /* In some circumstances we allow a command to specify a numeric
    signal.  The idea is to keep these circumstances limited so that
    users (and scripts) develop portable habits.  For comparison,
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1367,6 +1367,8 @@ enum {
   PACKET_Qbtrace_off,
   PACKET_Qbtrace_bts,
   PACKET_qXfer_btrace,
+  PACKET_MultiThreadTracepoint,
+  PACKET_MultiProcessTracepointTogether,
   PACKET_MAX
 };
@@ -4063,7 +4065,11 @@ static const struct protocol_feature rem
   { "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
   { "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
   { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_btrace }
+    PACKET_qXfer_btrace },
+  { "MultiThreadTracepoint", PACKET_DISABLE,
+    remote_supported_packet, PACKET_MultiThreadTracepoint },
+  { "MultiProcessTracepointTogether", PACKET_DISABLE,
+    remote_supported_packet, PACKET_MultiProcessTracepointTogether },
 };
static char *remote_support_xml;
@@ -10437,6 +10443,20 @@ remote_supports_string_tracing (void)
 }
static int
+remote_supports_multi_thread_tracepoint (void)
+{
+  return (remote_protocol_packets[PACKET_MultiThreadTracepoint].support
+	    == PACKET_ENABLE);
+}
+
+static int
+remote_supports_multi_process_tracepoint_together (void)
+{
+  return (remote_protocol_packets[PACKET_MultiProcessTracepointTogether].support
+	    == PACKET_ENABLE);
+}
+
+static int
 remote_can_run_breakpoint_commands (void)
 {
   struct remote_state *rs = get_remote_state ();
@@ -10593,6 +10613,55 @@ remote_download_tracepoint (struct bp_lo
 	   to give up on the trace run.  */
 	error (_("Target does not support static tracepoints"));
     }
+
+  /* If target support multiprocess tracepoint together or tracepoint is
+     special a thread, send ptid of the location's program space with
+     packets if need.  */
+  if (remote_protocol_packets[PACKET_MultiProcessTracepointTogether].support
+	== PACKET_ENABLE
+      || loc->owner->thread != -1)
+    {
+      ptid_t tracepoint_ptid;
+      struct remote_state *rs = get_remote_state ();
+      int got_tracepoint_ptid = 0;
+
+      if (loc->owner->thread != -1)
+        {
+	  if (remote_protocol_packets[PACKET_MultiThreadTracepoint].support
+		!= PACKET_ENABLE)
+	    error (_("Target does not support multithread tracepoint"));
+	  tracepoint_ptid = thread_id_to_pid (loc->owner->thread);
+	  if (!in_thread_list (tracepoint_ptid))
+	    error (_("Cannot find thread %d for tracepoint %d"),
+		   loc->owner->thread, loc->owner->number);
+	  got_tracepoint_ptid = 1;
+	}
+      else if (remote_protocol_packets[PACKET_MultiProcessTracepointTogether].support
+		 == PACKET_ENABLE
+	       && remote_multi_process_p (rs))
+        {
+	  struct inferior *inf;
+
+	  ALL_INFERIORS (inf)
+	    {
+	      if (inf->pspace == loc->pspace)
+		{
+		  tracepoint_ptid = ptid_build (inf->pid, 0, 0);
+		  got_tracepoint_ptid = 1;
+		  break;
+		}
+	    }
+	  if (got_tracepoint_ptid == 0)
+	    error (_("Cannot find inferior for tracepoint %d"),
+		   loc->owner->number);
+	}
+      if (got_tracepoint_ptid)
+        {
+	  strcat (buf, ":P");
+	  write_ptid (buf + strlen (buf), buf + BUF_SIZE, tracepoint_ptid);
+	}
+    }
+
   /* If the tracepoint has a conditional, make it into an agent
      expression and append to the definition.  */
   if (loc->cond)
@@ -10896,6 +10965,7 @@ remote_get_tracepoint_status (struct bre
   struct bp_location *loc;
   struct tracepoint *tp = (struct tracepoint *) bp;
   size_t size = get_remote_packet_size ();
+  struct inferior *inf = current_inferior ();
if (tp)
     {
@@ -10903,6 +10973,11 @@ remote_get_tracepoint_status (struct bre
       tp->traceframe_usage = 0;
       for (loc = tp->base.loc; loc; loc = loc->next)
 	{
+	  if (remote_protocol_packets[PACKET_MultiProcessTracepointTogether].support
+		!= PACKET_ENABLE
+	      && inf->pspace != loc->pspace)
+	    continue;
+
 	  /* If the tracepoint was never downloaded, don't go asking for
 	     any status.  */
 	  if (tp->number_on_target == 0)
@@ -11557,6 +11632,10 @@ Specify the serial device it is connecte
   remote_ops.to_fileio_readlink = remote_hostio_readlink;
   remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
   remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
+  remote_ops.to_supports_multi_thread_tracepoint
+    = remote_supports_multi_thread_tracepoint;
+  remote_ops.to_supports_multi_process_tracepoint_together
+    = remote_supports_multi_process_tracepoint_together;
   remote_ops.to_supports_evaluation_of_breakpoint_conditions = remote_supports_cond_breakpoints;
   remote_ops.to_can_run_breakpoint_commands = remote_can_run_breakpoint_commands;
   remote_ops.to_trace_init = remote_trace_init;
@@ -12183,6 +12262,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
        "qXfer:btrace", "read-btrace", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_MultiThreadTracepoint],
+       "MultiThreadTracepoint", "multi-thread-tracepoint", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_MultiProcessTracepointTogether],
+       "MultiProcessTracepointTogether", "multi-process-tracepoint-together", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -657,6 +657,8 @@ update_current_target (void)
       INHERIT (to_supports_multi_process, t);
       INHERIT (to_supports_enable_disable_tracepoint, t);
       INHERIT (to_supports_string_tracing, t);
+      INHERIT (to_supports_multi_thread_tracepoint, t);
+      INHERIT (to_supports_multi_process_tracepoint_together, t);
       INHERIT (to_trace_init, t);
       INHERIT (to_download_tracepoint, t);
       INHERIT (to_can_download_tracepoint, t);
@@ -838,6 +840,12 @@ update_current_target (void)
   de_fault (to_supports_string_tracing,
 	    (int (*) (void))
 	    return_zero);
+  de_fault (to_supports_multi_thread_tracepoint,
+	    (int (*) (void))
+	    return_zero);
+  de_fault (to_supports_multi_process_tracepoint_together,
+	    (int (*) (void))
+	    return_zero);
   de_fault (to_trace_init,
 	    (void (*) (void))
 	    tcomplain);
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -619,6 +619,12 @@ struct target_ops
     /* Does this target support the tracenz bytecode for string collection?  */
     int (*to_supports_string_tracing) (void);
+ /* Does this target support the multithread tracepoint. */
+    int (*to_supports_multi_thread_tracepoint) (void);
+
+    /* Does this target support the multiprocess tracepoint together.  */
+    int (*to_supports_multi_process_tracepoint_together) (void);
+
     /* Does this target support evaluation of breakpoint conditions on its
        end?  */
     int (*to_supports_evaluation_of_breakpoint_conditions) (void);
@@ -1038,6 +1044,12 @@ int target_supports_disable_randomizatio
 #define target_supports_string_tracing() \
   (*current_target.to_supports_string_tracing) ()
+#define target_supports_multi_thread_tracepoint() \
+  (*current_target.to_supports_multi_thread_tracepoint) ()
+
+#define target_supports_multi_process_tracepoint_together() \
+  (*current_target.to_supports_multi_process_tracepoint_together) ()
+
 /* Returns true if this target can handle breakpoint conditions
    on its end.  */
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -121,23 +121,43 @@ void (*deprecated_trace_start_stop_hook)
 typedef struct trace_state_variable tsv_s;
 DEF_VEC_O(tsv_s);
-static VEC(tsv_s) *tvariables;
+struct trace_state
+{
+  VEC(tsv_s) *tvariables;
-/* The next integer to assign to a variable. */
+  /* Number of last traceframe collected.  */
+  int traceframe_number;
-static int next_tsv_number = 1;
+  /* Tracepoint for last traceframe collected.  */
+  int tracepoint_number;
-/* Number of last traceframe collected. */
-static int traceframe_number;
+  /* Symbol for function for last traceframe collected.  */
+  struct symbol *traceframe_fun;
-/* Tracepoint for last traceframe collected. */
-static int tracepoint_number;
+  /* Symtab and line for last traceframe collected.  */
+  struct symtab_and_line traceframe_sal;
-/* The traceframe info of the current traceframe. NULL if we haven't
-   yet attempted to fetch it, or if the target does not support
-   fetching this object, or if we're not inspecting a traceframe
-   presently.  */
-static struct traceframe_info *traceframe_info;
+  /* The traceframe info of the current traceframe.  NULL if we haven't
+     yet attempted to fetch it, or if the target does not support
+     fetching this object, or if we're not inspecting a traceframe
+     presently.  */
+  struct traceframe_info *traceframe_info;
+
+  /* The load map info for the current process.  */
+  struct load_map_info *load_map;
+
+  struct trace_status trace_status;
+};
+
+/* True if current trace state is together_trace_state.  */
+static int current_trace_state_together = 0;
+
+/* If current target support multiprocess tracepoint together,
+   use this struct as current trace state.  */
+static struct trace_state together_trace_state;
+
+/* The next integer to assign to a variable.  */
+static int next_tsv_number = 1;
/* Tracing command lists. */
 static struct cmd_list_element *tfindlist;
@@ -196,9 +216,9 @@ static void free_uploaded_tsvs (struct u
 static struct command_line *
   all_tracepoint_actions_and_cleanup (struct breakpoint *t);
-extern void _initialize_tracepoint (void);
+static struct trace_state *current_trace_state (void);
-static struct trace_status trace_status;
+extern void _initialize_tracepoint (void);
char *stop_reason_names[] = {
   "tunknown",
@@ -213,7 +233,88 @@ char *stop_reason_names[] = {
 struct trace_status *
 current_trace_status (void)
 {
-  return &trace_status;
+  return &current_trace_state ()->trace_status;
+}
+
+/* Per-inferior trace state data key.  */
+static const struct inferior_data *trace_inferior_data;
+
+/* Clears the inferior-specific trace state fields.  */
+
+static void
+trace_inferior_data_cleanup (struct inferior *inf, void *arg)
+{
+  struct trace_state *tstate;
+
+  tstate = inferior_data (inf, trace_inferior_data);
+  if (tstate != NULL)
+    {
+      xfree (tstate);
+      set_inferior_data (inf, trace_inferior_data, NULL);
+    }
+}
+
+/* Fetch the inferior-specific trace state.  */
+
+static struct trace_state *
+get_trace_inferior_data (struct inferior *inf)
+{
+  struct trace_state *tstate;
+
+  tstate = inferior_data (inf, trace_inferior_data);
+  if (tstate == NULL)
+    {
+      tstate = XZALLOC (struct trace_state);
+      set_inferior_data (inf, trace_inferior_data, tstate);
+      tstate->traceframe_number = -1;
+      tstate->tracepoint_number = -1;
+    }
+
+  return tstate;
+}
+
+/* This is a "inferior_exit" observer.  Releases the TRACE_STATE member
+   of the inferior structure.  This field is private to tracepoint.c, and
+   its type is opaque to the rest of GDB.  */
+
+static void
+trace_inferior_exit (struct inferior *inf)
+{
+  struct trace_state *tstate;
+
+  tstate = inferior_data (inf, trace_inferior_data);
+  if (tstate != NULL)
+    {
+      xfree (tstate);
+      set_inferior_data (inf, trace_inferior_data, NULL);
+    }
+}
+
+/* Fetches the trace state for the current inferior.  */
+
+static struct trace_state *
+current_trace_state (void)
+{
+  if (target_supports_multi_process_tracepoint_together ())
+    {
+      if (!ptid_equal (inferior_ptid, null_ptid)
+	  && current_trace_state_together == 0)
+        {
+	  memcpy (&together_trace_state,
+		  get_trace_inferior_data (current_inferior ()),
+		  sizeof (together_trace_state));
+	  current_trace_state_together = 1;
+	}
+      return &together_trace_state;
+    }
+
+  if (current_trace_state_together == 1)
+    {
+      memcpy (get_trace_inferior_data (current_inferior ()),
+	      &together_trace_state, sizeof (together_trace_state));
+      current_trace_state_together = 0;
+    }
+  return get_trace_inferior_data (current_inferior ());
 }
/* Destroy INFO. */
@@ -236,15 +337,19 @@ free_traceframe_info (struct traceframe_
 static void
 clear_traceframe_info (void)
 {
-  free_traceframe_info (traceframe_info);
-  traceframe_info = NULL;
+  struct trace_state *tstate = current_trace_state ();
+
+  free_traceframe_info (tstate->traceframe_info);
+  tstate->traceframe_info = NULL;
 }
/* Set traceframe number to NUM. */
 static void
 set_traceframe_num (int num)
 {
-  traceframe_number = num;
+  struct trace_state *tstate = current_trace_state ();
+
+  tstate->traceframe_number = num;
   set_internalvar_integer (lookup_internalvar ("trace_frame"), num);
 }
@@ -252,7 +357,9 @@ set_traceframe_num (int num)
 static void
 set_tracepoint_num (int num)
 {
-  tracepoint_number = num;
+  struct trace_state *tstate = current_trace_state ();
+
+  tstate->tracepoint_number = num;
   set_internalvar_integer (lookup_internalvar ("tracepoint"), num);
 }
@@ -265,42 +372,44 @@ set_traceframe_context (struct frame_inf
   CORE_ADDR trace_pc;
   struct symbol *traceframe_fun;
   struct symtab_and_line traceframe_sal;
+  struct trace_state *tstate = current_trace_state ();
/* Save as globals for internal use. */
   if (trace_frame != NULL
       && get_frame_pc_if_available (trace_frame, &trace_pc))
     {
-      traceframe_sal = find_pc_line (trace_pc, 0);
-      traceframe_fun = find_pc_function (trace_pc);
+      tstate->traceframe_sal = find_pc_line (trace_pc, 0);
+      tstate->traceframe_fun = find_pc_function (trace_pc);
/* Save linenumber as "$trace_line", a debugger variable visible to
 	 users.  */
       set_internalvar_integer (lookup_internalvar ("trace_line"),
-			       traceframe_sal.line);
+			       tstate->traceframe_sal.line);
     }
   else
     {
-      init_sal (&traceframe_sal);
-      traceframe_fun = NULL;
+      init_sal (&tstate->traceframe_sal);
+      tstate->traceframe_fun = NULL;
       set_internalvar_integer (lookup_internalvar ("trace_line"), -1);
     }
/* Save func name as "$trace_func", a debugger variable visible to
      users.  */
-  if (traceframe_fun == NULL
-      || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
+  if (tstate->traceframe_fun == NULL
+      || SYMBOL_LINKAGE_NAME (tstate->traceframe_fun) == NULL)
     clear_internalvar (lookup_internalvar ("trace_func"));
   else
     set_internalvar_string (lookup_internalvar ("trace_func"),
-			    SYMBOL_LINKAGE_NAME (traceframe_fun));
+			    SYMBOL_LINKAGE_NAME (tstate->traceframe_fun));
/* Save file name as "$trace_file", a debugger variable visible to
      users.  */
-  if (traceframe_sal.symtab == NULL)
+  if (tstate->traceframe_sal.symtab == NULL)
     clear_internalvar (lookup_internalvar ("trace_file"));
   else
     set_internalvar_string (lookup_internalvar ("trace_file"),
-			symtab_to_filename_for_display (traceframe_sal.symtab));
+			    symtab_to_filename_for_display
+			      (tstate->traceframe_sal.symtab));
 }
/* Create a new trace state variable with the given name. */
@@ -309,11 +418,12 @@ struct trace_state_variable *
 create_trace_state_variable (const char *name)
 {
   struct trace_state_variable tsv;
+  struct trace_state *tstate = current_trace_state ();
memset (&tsv, 0, sizeof (tsv));
   tsv.name = xstrdup (name);
   tsv.number = next_tsv_number++;
-  return VEC_safe_push (tsv_s, tvariables, &tsv);
+  return VEC_safe_push (tsv_s, tstate->tvariables, &tsv);
 }
/* Look for a trace state variable of the given name. */
@@ -323,8 +433,9 @@ find_trace_state_variable (const char *n
 {
   struct trace_state_variable *tsv;
   int ix;
+  struct trace_state *tstate = current_trace_state ();
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     if (strcmp (name, tsv->name) == 0)
       return tsv;
@@ -339,8 +450,9 @@ find_trace_state_variable_by_number (int
 {
   struct trace_state_variable *tsv;
   int ix;
+  struct trace_state *tstate = current_trace_state ();
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     if (tsv->number == number)
       return tsv;
@@ -352,14 +464,15 @@ delete_trace_state_variable (const char
 {
   struct trace_state_variable *tsv;
   int ix;
+  struct trace_state *tstate = current_trace_state ();
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     if (strcmp (name, tsv->name) == 0)
       {
 	observer_notify_tsv_deleted (tsv);
xfree ((void *)tsv->name);
-	VEC_unordered_remove (tsv_s, tvariables, ix);
+	VEC_unordered_remove (tsv_s, tstate->tvariables, ix);
return;
       }
@@ -461,11 +574,12 @@ delete_trace_variable_command (char *arg
   int ix;
   char **argv;
   struct cleanup *back_to;
+  struct trace_state *tstate = current_trace_state ();
if (args == NULL)
     {
       if (query (_("Delete all trace state variables? ")))
-	VEC_free (tsv_s, tvariables);
+	VEC_free (tsv_s, tstate->tvariables);
       dont_repeat ();
       observer_notify_tsv_deleted (NULL);
       return;
@@ -495,15 +609,17 @@ tvariables_info_1 (void)
   int count = 0;
   struct cleanup *back_to;
   struct ui_out *uiout = current_uiout;
+  struct trace_state *tstate = current_trace_state ();
- if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout))
+  if (VEC_length (tsv_s, tstate->tvariables) == 0
+      && !ui_out_is_mi_like_p (uiout))
     {
       printf_filtered (_("No trace state variables.\n"));
       return;
     }
/* Try to acquire values from the target. */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix, ++count)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix, ++count)
     tsv->value_known = target_get_trace_state_variable_value (tsv->number,
 							      &(tsv->value));
@@ -515,7 +631,7 @@ tvariables_info_1 (void) ui_out_table_body (uiout); - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     {
       struct cleanup *back_to2;
       char *c;
@@ -535,7 +651,8 @@ tvariables_info_1 (void)
            omit the field completely.  The difference between unknown and
            undefined does not seem important enough to represent.  */
         c = NULL;
-      else if (current_trace_status ()->running || traceframe_number >= 0)
+      else if (current_trace_status ()->running
+	       || tstate->traceframe_number >= 0)
 	/* The value is/was defined, but we don't have it.  */
         c = "<unknown>";
       else
@@ -566,8 +683,9 @@ save_trace_state_variables (struct ui_fi
 {
   struct trace_state_variable *tsv;
   int ix;
+  struct trace_state *tstate = current_trace_state ();
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     {
       fprintf_unfiltered (fp, "tvariable $%s", tsv->name);
       if (tsv->initial_value)
@@ -1787,6 +1905,7 @@ start_tracing (char *notes)
   struct trace_state_variable *tsv;
   int any_enabled = 0, num_to_download = 0;
   int ret;
+  struct trace_state *tstate = current_trace_state ();
tp_vec = all_tracepoints (); @@ -1876,7 +1995,7 @@ start_tracing (char *notes)
   VEC_free (breakpoint_p, tp_vec);
/* Send down all the trace state variables too. */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     {
       target_download_trace_state_variable (tsv);
     }
@@ -1990,7 +2109,8 @@ trace_status_command (char *args, int fr
   int status, ix;
   VEC(breakpoint_p) *tp_vec = NULL;
   struct breakpoint *t;
-
+  struct trace_state *tstate = current_trace_state ();
+
   status = target_get_trace_status (ts);
if (status == -1)
@@ -2101,9 +2221,9 @@ trace_status_command (char *args, int fr
     printf_filtered (_("Trace notes: %s.\n"), ts->notes);
/* Now report on what we're doing with tfind. */
-  if (traceframe_number >= 0)
+  if (tstate->traceframe_number >= 0)
     printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
-		     traceframe_number, tracepoint_number);
+		     tstate->traceframe_number, tstate->tracepoint_number);
   else
     printf_filtered (_("Not looking at any trace frame.\n"));
@@ -2152,6 +2272,7 @@ trace_status_mi (int on_stop)
   struct ui_out *uiout = current_uiout;
   struct trace_status *ts = current_trace_status ();
   int status;
+  struct trace_state *tstate = current_trace_state ();
status = target_get_trace_status (ts); @@ -2321,6 +2442,7 @@ tfind_1 (enum trace_find_type type, int
   struct frame_id old_frame_id = null_frame_id;
   struct tracepoint *tp;
   struct ui_out *uiout = current_uiout;
+  struct trace_state *tstate = current_trace_state ();
/* Only try to get the current stack frame if we have a chance of
      succeeding.  In particular, if we're trying to get a first trace
@@ -2329,7 +2451,8 @@ tfind_1 (enum trace_find_type type, int
      below (correctly) decide to print out the source location of the
      trace frame.  */
   if (!(type == tfind_number && num == -1)
-      && (has_stack_frames () || traceframe_number >= 0))
+      && (has_stack_frames ()
+	  || tstate->traceframe_number >= 0))
     old_frame_id = get_frame_id (get_current_frame ());
target_frameno = target_trace_find (type, num, addr1, addr2,
@@ -2386,7 +2509,8 @@ tfind_1 (enum trace_find_type type, int
   set_tracepoint_num (tp ? tp->base.number : target_tracept);
if (target_frameno != get_traceframe_number ())
-    observer_notify_traceframe_changed (target_frameno, tracepoint_number);
+    observer_notify_traceframe_changed (target_frameno,
+					tstate->tracepoint_number);
set_current_traceframe (target_frameno); @@ -2395,20 +2519,21 @@ tfind_1 (enum trace_find_type type, int
   else
     set_traceframe_context (get_current_frame ());
- if (traceframe_number >= 0)
+  if (tstate->traceframe_number >= 0)
     {
       /* Use different branches for MI and CLI to make CLI messages
 	 i18n-eable.  */
       if (ui_out_is_mi_like_p (uiout))
 	{
 	  ui_out_field_string (uiout, "found", "1");
-	  ui_out_field_int (uiout, "tracepoint", tracepoint_number);
-	  ui_out_field_int (uiout, "traceframe", traceframe_number);
+	  ui_out_field_int (uiout, "tracepoint", tstate->tracepoint_number);
+	  ui_out_field_int (uiout, "traceframe", tstate->traceframe_number);
 	}
       else
 	{
 	  printf_unfiltered (_("Found trace frame %d, tracepoint %d\n"),
-			     traceframe_number, tracepoint_number);
+			     tstate->traceframe_number,
+			     tstate->tracepoint_number);
 	}
     }
   else
@@ -2425,7 +2550,8 @@ tfind_1 (enum trace_find_type type, int
      frames, there won't be any current frame to go back to and
      display.  */
   if (from_tty
-      && (has_stack_frames () || traceframe_number >= 0))
+      && (has_stack_frames ()
+      || tstate->traceframe_number >= 0))
     {
       enum print_what print_what;
@@ -2465,6 +2591,7 @@ static void
 trace_find_command (char *args, int from_tty)
 { /* This should only be called with a numeric argument.  */
   int frameno = -1;
+  struct trace_state *tstate = current_trace_state ();
if (current_trace_status ()->running
       && current_trace_status ()->filename == NULL)
@@ -2472,20 +2599,20 @@ trace_find_command (char *args, int from
if (args == 0 || *args == 0)
     { /* TFIND with no args means find NEXT trace frame.  */
-      if (traceframe_number == -1)
+      if (tstate->traceframe_number == -1)
 	frameno = 0;	/* "next" is first one.  */
         else
-	frameno = traceframe_number + 1;
+	frameno = tstate->traceframe_number + 1;
     }
   else if (0 == strcmp (args, "-"))
     {
-      if (traceframe_number == -1)
+      if (tstate->traceframe_number == -1)
 	error (_("not debugging trace buffer"));
-      else if (from_tty && traceframe_number == 0)
+      else if (from_tty && tstate->traceframe_number == 0)
 	error (_("already at start of trace buffer"));
- frameno = traceframe_number - 1;
-      }
+      frameno = tstate->traceframe_number - 1;
+    }
   /* A hack to work around eval's need for fp to have been collected.  */
   else if (0 == strcmp (args, "-1"))
     frameno = -1;
@@ -2536,6 +2663,7 @@ trace_find_tracepoint_command (char *arg
 {
   int tdp;
   struct tracepoint *tp;
+  struct trace_state *tstate = current_trace_state ();
if (current_trace_status ()->running
       && current_trace_status ()->filename == NULL)
@@ -2543,10 +2671,10 @@ trace_find_tracepoint_command (char *arg
if (args == 0 || *args == 0)
     {
-      if (tracepoint_number == -1)
+      if (tstate->tracepoint_number == -1)
 	error (_("No current tracepoint -- please supply an argument."));
       else
-	tdp = tracepoint_number;	/* Default is current TDP.  */
+	tdp = tstate->tracepoint_number;	/* default is current TDP */
     }
   else
     tdp = parse_and_eval_long (args);
@@ -2978,15 +3106,16 @@ get_traceframe_location (int *stepping_f
   struct tracepoint *t;
   struct bp_location *tloc;
   struct regcache *regcache;
+  struct trace_state *tstate = current_trace_state ();
- if (tracepoint_number == -1)
+  if (tstate->tracepoint_number == -1)
     error (_("No current trace frame."));
- t = get_tracepoint (tracepoint_number);
+  t = get_tracepoint (tstate->tracepoint_number);
if (t == NULL)
     error (_("No known tracepoint matches 'current' tracepoint #%d."),
-	   tracepoint_number);
+	   tstate->tracepoint_number);
/* The current frame is a trap frame if the frame PC is equal to the
      tracepoint PC.  If not, then the current frame was collected
@@ -3054,12 +3183,13 @@ trace_dump_command (char *args, int from
   struct bp_location *loc;
   struct cleanup *old_chain;
   struct command_line *actions;
+  struct trace_state *tstate = current_trace_state ();
/* This throws an error is not inspecting a trace frame. */
   loc = get_traceframe_location (&stepping_frame);
printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
-		   tracepoint_number, traceframe_number);
+		   tstate->tracepoint_number, tstate->traceframe_number);
old_chain = make_cleanup (null_cleanup, NULL); @@ -3841,13 +3971,13 @@ mem2hex (gdb_byte *mem, char *buf, int c
 int
 get_traceframe_number (void)
 {
-  return traceframe_number;
+  return current_trace_state ()->traceframe_number;
 }
int
 get_tracepoint_number (void)
 {
-  return tracepoint_number;
+  return current_trace_state ()->tracepoint_number;
 }
/* Make the traceframe NUM be the current trace frame. Does nothing
@@ -3857,8 +3987,9 @@ void
 set_current_traceframe (int num)
 {
   int newnum;
+  struct trace_state *tstate = current_trace_state ();
- if (traceframe_number == num)
+  if (tstate->traceframe_number == num)
     {
       /* Nothing to do.  */
       return;
@@ -3884,7 +4015,9 @@ set_current_traceframe (int num)
 void
 set_traceframe_number (int num)
 {
-  traceframe_number = num;
+  struct trace_state *tstate = current_trace_state ();
+
+  tstate->traceframe_number = num;
 }
/* A cleanup used when switching away and back from tfind mode. */
@@ -3915,9 +4048,10 @@ struct cleanup *
 make_cleanup_restore_current_traceframe (void)
 {
   struct current_traceframe_cleanup *old;
+  struct trace_state *tstate = current_trace_state ();
old = xmalloc (sizeof (struct current_traceframe_cleanup));
-  old->traceframe_number = traceframe_number;
+  old->traceframe_number = tstate->traceframe_number;
return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old,
 			    restore_current_traceframe_cleanup_dtor);
@@ -3926,7 +4060,9 @@ make_cleanup_restore_current_traceframe
 struct cleanup *
 make_cleanup_restore_traceframe_number (void)
 {
-  return make_cleanup_restore_integer (&traceframe_number);
+  struct trace_state *tstate = current_trace_state ();
+
+  return make_cleanup_restore_integer (&tstate->traceframe_number);
 }
/* Given a number and address, return an uploaded tracepoint with that
@@ -4143,6 +4279,7 @@ create_tsv_from_upload (struct uploaded_
   int try_num = 0;
   struct trace_state_variable *tsv;
   struct cleanup *old_chain;
+  struct trace_state *tstate = current_trace_state ();
if (utsv->name)
     {
@@ -4187,10 +4324,11 @@ merge_uploaded_trace_state_variables (st
   struct uploaded_tsv *utsv;
   struct trace_state_variable *tsv;
   int highest;
+  struct trace_state *tstate = current_trace_state ();
/* Most likely some numbers will have to be reassigned as part of
      the merge, so clear them all in anticipation.  */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     tsv->number = 0;
for (utsv = *uploaded_tsvs; utsv; utsv = utsv->next)
@@ -4218,12 +4356,12 @@ merge_uploaded_trace_state_variables (st
/* Renumber everything that didn't get a target-assigned number. */
   highest = 0;
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     if (tsv->number > highest)
       highest = tsv->number;
++highest;
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (ix = 0; VEC_iterate (tsv_s, tstate->tvariables, ix, tsv); ++ix)
     if (tsv->number == 0)
       tsv->number = highest++;
@@ -4871,7 +5009,7 @@ tfile_trace_find (enum trace_find_type t
       else
 	{
 	  /* Start from the _next_ trace frame.  */
-	  if (tfnum > traceframe_number)
+	  if (tfnum > current_trace_state ()->traceframe_number)
 	    {
 	      switch (type)
 		{
@@ -5016,6 +5154,7 @@ tfile_fetch_registers (struct target_ops
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   int offset, regn, regsize, pc_regno;
   gdb_byte *regs;
+  struct trace_state *tstate = current_trace_state ();
/* An uninitialized reg size says we're not going to be
      successful at getting register blocks.  */
@@ -5064,7 +5203,7 @@ tfile_fetch_registers (struct target_ops
   pc_regno = gdbarch_pc_regnum (gdbarch);
   if (pc_regno >= 0 && (regno == -1 || regno == pc_regno))
     {
-      struct tracepoint *tp = get_tracepoint (tracepoint_number);
+      struct tracepoint *tp = get_tracepoint (tstate->tracepoint_number);
if (tp && tp->base.loc)
 	{
@@ -5105,7 +5244,7 @@ tfile_xfer_partial (struct target_ops *o
   if (readbuf == NULL)
     error (_("tfile_xfer_partial: trace file is read-only"));
- if (traceframe_number != -1)
+  if (get_traceframe_number () != -1)
     {
       int pos = 0;
@@ -5233,13 +5372,13 @@ tfile_has_memory (struct target_ops *ops
 static int
 tfile_has_stack (struct target_ops *ops)
 {
-  return traceframe_number != -1;
+  return get_traceframe_number () != -1;
 }
static int
 tfile_has_registers (struct target_ops *ops)
 {
-  return traceframe_number != -1;
+  return get_traceframe_number () != -1;
 }
/* Callback for traceframe_walk_blocks. Builds a traceframe_info
@@ -5726,10 +5865,12 @@ parse_traceframe_info (const char *tfram
 struct traceframe_info *
 get_traceframe_info (void)
 {
-  if (traceframe_info == NULL)
-    traceframe_info = target_traceframe_info ();
+  struct trace_state *tstate = current_trace_state ();
- return traceframe_info;
+  if (tstate->traceframe_info == NULL)
+    tstate->traceframe_info = target_traceframe_info ();
+
+  return tstate->traceframe_info;
 }
/* If the target supports the query, return in RESULT the set of
@@ -5785,20 +5926,179 @@ static const struct internalvar_funcs sd
   NULL
 };
+/* Get TSV $name's value from target and put it to valp.
+   Return true if success.  */
+
+static int
+get_trace_state_variable_value (const char *name, LONGEST *valp)
+{
+  struct trace_state_variable *tsv;
+
+  tsv = find_trace_state_variable ("pid");
+  if (tsv)
+    {
+      tsv->value_known = target_get_trace_state_variable_value (tsv->number,
+								&(tsv->value));
+      if (tsv->value_known)
+        {
+	  *valp = tsv->value;
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+/* When traceframe changed, select the inferior and thread of this
+   traceframe.  */
+
+static void
+traceframe_changed_inferior_thread_select (int tfnum, int tpnum)
+{
+  /* This is for the inferior.  */
+  struct inferior *inf;
+  int inf_need_select = 0;
+  /* This is for the thread.  */
+  ptid_t ptid;
+  int ptid_need_select = 0;
+  volatile struct gdb_exception e;
+  struct tracepoint *tp;
+  LONGEST val;
+
+  if (tfnum < 0 || tpnum < 0)
+    return;
+
+  /* Maybe got inferior and thread id from $pid and $tid.  So didn't
+     check if tp is NULL. */
+  tp = get_tracepoint_by_number_on_target (tpnum);
+
+  /* If this traceframe has $pid, try to find a inf for it.  */
+  if (get_trace_state_variable_value ("pid", &val))
+    {
+      int pid = (int) val;
+
+      if (current_inferior ()->pid != pid)
+	{
+	  ALL_INFERIORS (inf)
+	    {
+	      if (inf->pid == pid)
+		{
+		  inf_need_select = 1;
+		  break;
+		}
+	    }
+	}
+    }
+
+  /* If doesn't get inf from $pid and find the tp, try to find inf from
+     tp if need.
+     Just the target that supports multiprocess tracepoint together need
+     select inferior because other target's traceframe is just for current
+     inferior.
+     If the tracepoint's program space is different with current inferior's,
+     select inferior of the tracepoint.*/
+  if (inf_need_select == 0 && tp != NULL
+      && target_supports_multi_process_tracepoint_together ()
+      && current_inferior ()->pspace != tp->base.loc->pspace)
+    {
+      ALL_INFERIORS (inf)
+	{
+	  if (inf->pspace == tp->base.loc->pspace)
+	    {
+	      inf_need_select = 1;
+	      break;
+	    }
+	}
+    }
+
+  /* If this traceframe has $lwp or $tid, set it to ptid.  */
+  if (inf_need_select)
+    ptid = ptid_build (inf->pid, 0, 0);
+  else
+    ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, 0);
+  if (get_trace_state_variable_value ("lwp", &val))
+    {
+      ptid = ptid_build (ptid_get_pid (ptid), (long) val, 0);
+      ptid_need_select = 1;
+    }
+  if (get_trace_state_variable_value ("tid", &val))
+    {
+      ptid = ptid_build (ptid_get_pid (ptid), ptid_get_lwp (ptid),
+			 (long) val);
+      ptid_need_select = 1;
+    }
+  /* If ptid_need_select is true, then the traceframe has $lwp or $tid,
+     Check if ptid is not current thread.  If so, ptid need to be
+     set as current thread.  */
+  if (ptid_need_select && !ptid_equal (ptid, inferior_ptid))
+    ptid_need_select = 1;
+
+  /* If doesn't get a ptid from $lwp and $tid, and tp is not NULL, try
+     to find it from tp->base.thread.  */
+  if (ptid_need_select == 0 && tp != NULL
+      && tp->base.thread != -1
+      && target_supports_multi_thread_tracepoint ())
+    {
+      ptid = thread_id_to_pid (tp->base.thread);
+      if (!in_thread_list (ptid))
+        {
+	  warning (_("Cannot find thread %d for tracepoint %d"),
+		     tp->base.thread, tp->base.number);
+	  return;
+	}
+
+      if (!ptid_equal (ptid, inferior_ptid))
+        ptid_need_select = 1;
+    }
+
+  /* Use this TRY_CATCH to let traceframe_changed function will not be
+     interrupted by a error.  */
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    {
+      if (inf_need_select)
+	{
+	  set_inferior (inf);
+	  printf_filtered (_("[Switching to inferior %d (%s)]\n"),
+			   inf->num,
+			   target_pid_to_str (pid_to_ptid (inf->pid)));
+	}
+      if (ptid_need_select)
+	{
+	  switch_to_thread (ptid);
+	  printf_filtered (_("[Switching to thread %d (%s)]\n"),
+			   tp->base.thread,
+			   target_pid_to_str (inferior_ptid));
+	}
+    }
+  if (e.reason < 0)
+    {
+      warning ("%s", e.message);
+      return;
+    }
+}
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
 {
   struct cmd_list_element *c;
+ memset (&together_trace_state, 0, sizeof (together_trace_state));
+  together_trace_state.traceframe_number = -1;
+  together_trace_state.tracepoint_number = -1;
+
+  observer_attach_traceframe_changed
+    (traceframe_changed_inferior_thread_select);
+
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
      isn't initialized yet.  At this point, we're quite sure there
      isn't another convenience variable of the same name.  */
   create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL);
- traceframe_number = -1;
-  tracepoint_number = -1;
+  observer_attach_inferior_exit (trace_inferior_exit);
+
+  trace_inferior_data
+    = register_inferior_data_with_cleanup (NULL, trace_inferior_data_cleanup);
add_info ("scope", scope_info,
 	    _("List the variables local to a scope"));


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