From: Aaron Gamble <agamble@google.com>
To: Tom Tromey <tromey@redhat.com>
Cc: Sergio Durigan Junior <sergiodj@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [patch] info threads sort by name and name regex matching
Date: Fri, 24 Aug 2012 01:09:00 -0000 [thread overview]
Message-ID: <CAHX8C+L=iiicRcprm7ixcxn2ykd+3aePR7r0=XsrvB1-kbLv2g@mail.gmail.com> (raw)
In-Reply-To: <87pq6hppiz.fsf@fleche.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1165 bytes --]
Here is an updated patch. I have changed the options to be as follows.
'info threads [-a] [ id ... | -r regex ]'
-a enables sorting by thread name
-r regex matches regex with thread names.
I have not changed the threads array to a VEC as of yet. At this point
it seems like more trouble than it's worth. But I suppose it could be
done if people think it's necessary.
On Thu, Aug 23, 2012 at 9:00 AM, Tom Tromey <tromey@redhat.com> wrote:
>
> Sergio> Why not `-r regex'? I think it would be more clear.
>
> Me too.
>
> Sergio> Other commands (`sharedlibrary', `info variables', etc) take a regex as
> Sergio> their first argument, without requiring a modifier like `-r'. If the
> Sergio> "pipe" patch were already in, this alphabetical sorting would not be
> Sergio> needed... Anyway, just thinking here.
>
> Piping is nice but I think it is also good to have options for common
> cases.
>
> Sergio> I guess Tom did not suggest this because of performance per se, but
> Sergio> rather because if you have to make a list in GDB then it is already a
> Sergio> convention to use VEC for these things.
>
> Yeah. I thought it would make the code simpler.
>
> Tom
[-- Attachment #2: thread_sorting_regex_with-a-r-options.patch --]
[-- Type: application/octet-stream, Size: 22268 bytes --]
From efef7b796f528835d18bb778304805e6228695fd Mon Sep 17 00:00:00 2001
From: Aaron Gamble <agamble@google.com>
Date: Thu, 23 Aug 2012 18:04:03 -0700
Subject: [PATCH] sorting with -a -r regex options
---
gdb/doc/gdb.texinfo | 11 +-
gdb/gdbthread.h | 6 +-
gdb/testsuite/gdb.threads/Makefile.in | 2 +-
gdb/testsuite/gdb.threads/info-thread-sort-regex.c | 122 +++++++
.../gdb.threads/info-thread-sort-regex.exp | 58 +++
gdb/thread.c | 374 +++++++++++++-------
6 files changed, 441 insertions(+), 132 deletions(-)
create mode 100644 gdb/testsuite/gdb.threads/info-thread-sort-regex.c
create mode 100644 gdb/testsuite/gdb.threads/info-thread-sort-regex.exp
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 08ba92d..3e6c108 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2751,10 +2751,13 @@ number---always a single integer---with each thread in your program.
@table @code
@kindex info threads
-@item info threads @r{[}@var{id}@dots{}@r{]}
-Display a summary of all threads currently in your program. Optional
-argument @var{id}@dots{} is one or more thread ids separated by spaces, and
-means to print information only about the specified thread or threads.
+@item info threads @r{[}-a@r{]} @r{[}@var{id}@dots{}@b{|}-r @var{regex}@r{]}
+Display a summary of all threads currently in your program. Use the option
+-a to sort threads alphabetically by name. Selection of threads can be done
+by supplying a list or ranges of thread ID's, or by using the -r @var{regex}
+option to display only threads with names matching @var{regex}. Spaces
+between the -r and @var{regex} are ignored.
+
@value{GDBN} displays for each thread (in this order):
@enumerate
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 0250555..2463cea 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -138,6 +138,10 @@ struct thread_info
if the thread does not have a user-given name. */
char *name;
+ /* The name of the thread, as cached by print_thread_info.
+ Used for sorting info threads output. */
+ char *cached_name;
+
/* Non-zero means the thread is executing. Note: this is different
from saying that there is an active target and we are stopped at
a breakpoint, for instance. This is a real indicator whether the
@@ -385,7 +389,7 @@ extern struct cmd_list_element *thread_cmd_list;
`set print thread-events'. */
extern int print_thread_events;
-extern void print_thread_info (struct ui_out *uiout, char *threads,
+extern void print_thread_info (struct ui_out *uiout, char *args,
int pid);
extern struct cleanup *make_cleanup_restore_current_thread (void);
diff --git a/gdb/testsuite/gdb.threads/Makefile.in b/gdb/testsuite/gdb.threads/Makefile.in
index 8f9f867..2d24ba4 100644
--- a/gdb/testsuite/gdb.threads/Makefile.in
+++ b/gdb/testsuite/gdb.threads/Makefile.in
@@ -5,7 +5,7 @@ EXECUTABLES = attach-into-signal-nothr attach-into-signal-thr \
attach-stopped attachstop-mt \
bp_in_thread current-lwp-dead execl execl1 fork-child-threads \
fork-thread-pending gcore-pthreads hand-call-in-threads \
- ia64-sigill interrupted-hand-call killed linux-dp \
+ ia64-sigill info-thread-sort-regex interrupted-hand-call killed linux-dp \
local-watch-wrong-thread manythreads multi-create pending-step \
print-threads pthreads pthread_cond_wait schedlock sigthread \
staticthreads switch-threads thread-execl thread-specific \
diff --git a/gdb/testsuite/gdb.threads/info-thread-sort-regex.c b/gdb/testsuite/gdb.threads/info-thread-sort-regex.c
new file mode 100644
index 0000000..98979ce
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-thread-sort-regex.c
@@ -0,0 +1,122 @@
+/* Test case for info threads sort and regex matching.
+
+ Copyright 2008, 2010-2012 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef NR_THREADS
+#define NR_THREADS 4
+#endif
+
+int thread_count;
+
+pthread_mutex_t thread_count_mutex;
+
+pthread_cond_t thread_count_condvar;
+
+void
+incr_thread_count (void)
+{
+ pthread_mutex_lock (&thread_count_mutex);
+ ++thread_count;
+ if (thread_count == NR_THREADS)
+ pthread_cond_signal (&thread_count_condvar);
+ pthread_mutex_unlock (&thread_count_mutex);
+}
+
+void
+cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut)
+{
+ pthread_mutex_lock (mut);
+ pthread_cond_wait (cond, mut);
+ pthread_mutex_unlock (mut);
+}
+
+void
+noreturn (void)
+{
+ pthread_mutex_t mut;
+ pthread_cond_t cond;
+
+ pthread_mutex_init (&mut, NULL);
+ pthread_cond_init (&cond, NULL);
+
+ /* Wait for a condition that will never be signaled, so we effectively
+ block the thread here. */
+ cond_wait (&cond, &mut);
+}
+
+void *
+forever_pthread (void *unused)
+{
+ incr_thread_count ();
+ noreturn ();
+}
+
+/* Wait until all threads are running. */
+
+void
+wait_all_threads_running (void)
+{
+ pthread_mutex_lock (&thread_count_mutex);
+ if (thread_count == NR_THREADS)
+ {
+ pthread_mutex_unlock (&thread_count_mutex);
+ return;
+ }
+ pthread_cond_wait (&thread_count_condvar, &thread_count_mutex);
+ if (thread_count == NR_THREADS)
+ {
+ pthread_mutex_unlock (&thread_count_mutex);
+ return;
+ }
+ pthread_mutex_unlock (&thread_count_mutex);
+ printf ("failed waiting for all threads to start\n");
+ abort ();
+}
+
+/* Called when all threads are running.
+ Easy place for a breakpoint. */
+
+void
+all_threads_running (void)
+{
+}
+
+int
+main (void)
+{
+ pthread_t forever[NR_THREADS];
+ int i;
+
+ pthread_mutex_init (&thread_count_mutex, NULL);
+ pthread_cond_init (&thread_count_condvar, NULL);
+
+ for (i = 0; i < NR_THREADS; ++i)
+ pthread_create (&forever[i], NULL, forever_pthread, NULL);
+
+ wait_all_threads_running ();
+ all_threads_running ();
+
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.threads/info-thread-sort-regex.exp b/gdb/testsuite/gdb.threads/info-thread-sort-regex.exp
new file mode 100644
index 0000000..a49eedf
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-thread-sort-regex.exp
@@ -0,0 +1,58 @@
+# Copyright (C) 2004, 2007-2008, 2010-2012 Free Software Foundation,
+# Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test sorting and regex matching in info threads.
+
+set NR_THREADS 4
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-DNR_THREADS=$NR_THREADS"]] != "" } {
+ return -1
+}
+
+clean_restart ${binfile}
+
+if { ![runto_main] } {
+ fail "Can't run to main"
+ return 0
+}
+
+gdb_test "break all_threads_running" \
+ "Breakpoint 2 at .*: file .*${srcfile}, line .*" \
+ "breakpoint on all_threads_running"
+
+# Run the program and make sure GDB reports that we stopped after
+# hitting breakpoint 2 in all_threads_running().
+
+gdb_test "continue" \
+ ".*Breakpoint 2, all_threads_running ().*" \
+ "run to all_threads_running"
+
+# Test that the no threads match message prints correctly.
+gdb_test "info threads -r \$foo" \
+ "No threads match '\\\$foo'\." \
+ "info thread no match test"
+
+gdb_test_no_output "thread name a" "set thread name to a"
+
+gdb_test "info threads -a" \
+ "\\s+Id\\s+Target\\s+Id\\s+Frame \r\n\\*\\\s+\\\d+\\\s+Thread\\\s+0x\[A-Fa-f0-9\]+ \\\(LWP \\\d+\\\) \"a\".*" \
+ "check thread a is first"
+
+gdb_test "info threads -r ^info" \
+ "\\s+Id\\s+Target\\s+Id\\s+Frame \r\n\\\s+\\\d+\\\s+Thread\\\s+0x\[A-Fa-f0-9\]+ \\\(LWP \\\d+\\\) \"info.*\".*" \
+ "filter out thread named a"
diff --git a/gdb/thread.c b/gdb/thread.c
index 7e8eec5..68b2dac 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -55,6 +55,7 @@ void _initialize_thread (void);
/* Prototypes for local functions. */
struct thread_info *thread_list = NULL;
+static int thread_list_size = 0;
static int highest_thread_num;
static void thread_command (char *tidstr, int from_tty);
@@ -132,6 +133,7 @@ free_thread (struct thread_info *tp)
xfree (tp->private);
}
+ thread_list_size--;
xfree (tp->name);
xfree (tp);
}
@@ -153,6 +155,7 @@ init_thread_list (void)
}
thread_list = NULL;
+ thread_list_size = 0;
}
/* Allocate a new thread with target id PTID and add it to the thread
@@ -169,6 +172,7 @@ new_thread (ptid_t ptid)
tp->num = ++highest_thread_num;
tp->next = thread_list;
thread_list = tp;
+ thread_list_size++;
/* Nothing to follow yet. */
tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
@@ -748,25 +752,195 @@ finish_thread_state_cleanup (void *arg)
finish_thread_state (*ptid_p);
}
+/* Returns true if user requested the thread. */
+
+static int
+print_thread_filter_check (struct thread_info *tp, char *requested_threads,
+ int pid, regex_t *preg)
+{
+ if (preg)
+ {
+ int err = regexec (preg, tp->cached_name ? tp->cached_name : "",
+ 0, NULL, 0);
+ if (err == 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ /* No regular expression was supplied, see if there's a match the list
+ of thread id's. */
+ if (!number_is_in_list (requested_threads, tp->num))
+ return FALSE;
+
+ if (pid != -1 && PIDGET (tp->ptid) != pid)
+ {
+ if (requested_threads != NULL && *requested_threads != '\0')
+ error (_("Requested thread not found in requested process"));
+ return FALSE;
+ }
+
+ if (tp->state == THREAD_EXITED)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/* Used to Sort threads in lexicographic order by name. */
+
+static int
+print_thread_sort_cmp (const void *p1, const void *p2)
+{
+ const char *name1 = (*(struct thread_info **) p1)->cached_name;
+ const char *name2 = (*(struct thread_info **) p2)->cached_name;
+ if (name1 && name2)
+ return strcmp (name1, name2);
+
+ /* In case we receive NULL pointers instead of strings.
+ NULL pointers are sorted as empty strings. */
+ if (!name1 && name2)
+ return -1;
+ if (!name2 && name1)
+ return 1;
+
+ return 0;
+}
+
+/* Prints the info for a single thread.
+ Called by print_thread_info for each thread. */
+
+static void
+print_thread_info_single (struct ui_out *uiout, struct thread_info *tp,
+ ptid_t current_ptid)
+{
+ struct cleanup *uiout_cleanup
+ = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+ int core;
+ char *extra_info, *name, *target_id;
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ /* Compatibility. */
+ if (ptid_equal (tp->ptid, current_ptid))
+ ui_out_text (uiout, "* ");
+ else
+ ui_out_text (uiout, " ");
+ }
+ else
+ {
+ if (ptid_equal (tp->ptid, current_ptid))
+ ui_out_field_string (uiout, "current", "*");
+ else
+ ui_out_field_skip (uiout, "current");
+ }
+
+ ui_out_field_int (uiout, "id", tp->num);
+
+ /* For the CLI, we stuff everything into the target-id field.
+ This is a gross hack to make the output come out looking
+ correct. The underlying problem here is that ui-out has no
+ way to specify that a field's space allocation should be
+ shared by several fields. For MI, we do the right thing
+ instead. */
+
+ target_id = target_pid_to_str (tp->ptid);
+ extra_info = target_extra_thread_info (tp);
+ if (tp->cached_name)
+ name = tp->cached_name;
+ else
+ name = tp->name ? tp->name : target_thread_name (tp);
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ ui_out_field_string (uiout, "target-id", target_id);
+ if (extra_info)
+ ui_out_field_string (uiout, "details", extra_info);
+ if (name)
+ ui_out_field_string (uiout, "name", name);
+ }
+ else
+ {
+ struct cleanup *str_cleanup;
+ char *contents;
+
+ if (extra_info && name)
+ contents = xstrprintf ("%s \"%s\" (%s)", target_id,
+ name, extra_info);
+ else if (extra_info)
+ contents = xstrprintf ("%s (%s)", target_id, extra_info);
+ else if (name)
+ contents = xstrprintf ("%s \"%s\"", target_id, name);
+ else
+ contents = xstrdup (target_id);
+ str_cleanup = make_cleanup (xfree, contents);
+
+ ui_out_field_string (uiout, "target-id", contents);
+ do_cleanups (str_cleanup);
+ }
+
+ if (tp->state == THREAD_RUNNING)
+ ui_out_text (uiout, "(running)\n");
+ else
+ {
+ /* The switch below puts us at the top of the stack (leaf
+ frame). */
+ switch_to_thread (tp->ptid);
+ print_stack_frame (get_selected_frame (NULL),
+ /* For MI output, print frame level. */
+ ui_out_is_mi_like_p (uiout),
+ LOCATION);
+ }
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ char *state = "stopped";
+
+ if (tp->state == THREAD_RUNNING)
+ state = "running";
+ ui_out_field_string (uiout, "state", state);
+ }
+
+ core = target_core_of_thread (tp->ptid);
+ if (ui_out_is_mi_like_p (uiout) && core != -1)
+ ui_out_field_int (uiout, "core", core);
+
+ do_cleanups (uiout_cleanup);
+}
+
+/* Caches the name that will be shown to the user for a thread.
+ We keep track of this for sorting purposes. */
+
+static void
+thread_cache_name (struct thread_info *tp)
+{
+ /* Does not need to be freed, is only transient. */
+ tp->cached_name = tp->name ? tp->name : target_thread_name (tp);
+}
+
/* Prints the list of threads and their details on UIOUT.
This is a version of 'info_threads_command' suitable for
use from MI.
- If REQUESTED_THREAD is not -1, it's the GDB id of the thread
- that should be printed. Otherwise, all threads are
- printed.
- If PID is not -1, only print threads from the process PID.
- Otherwise, threads from all attached PIDs are printed.
- If both REQUESTED_THREAD and PID are not -1, then the thread
- is printed if it belongs to the specified process. Otherwise,
- an error is raised. */
+ REQUESTED_THREADS is either a list of numeric thread Id's
+ or the character 'r' followed by a regular expression to
+ match with each thread's name. Any spaces between the 'r' and
+ the regular expression are ignored.
+ If neither is supplied then all threads are printed.
+ Threads are sorted by name unless we are sending to MI. */
+
void
-print_thread_info (struct ui_out *uiout, char *requested_threads, int pid)
+print_thread_info (struct ui_out *uiout, char *args, int pid)
{
struct thread_info *tp;
ptid_t current_ptid;
struct cleanup *old_chain;
- char *extra_info, *name, *target_id;
int current_thread = -1;
+ struct thread_info **threads = NULL;
+ int n_threads, i, ret;
+ int enable_sort = FALSE;
+ regex_t preg_buffer;
+ regex_t *preg = NULL;
+ char *requested_threads = args;
update_thread_list ();
current_ptid = inferior_ptid;
@@ -774,27 +948,75 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid)
/* We'll be switching threads temporarily. */
old_chain = make_cleanup_restore_current_thread ();
+ /* Process argument string args for options. */
+ args = skip_spaces (args);
+ while (args && *args != '\0')
+ {
+ if (*args != '-')
+ break;
+ if (args[1] == 'a')
+ {
+ enable_sort = TRUE;
+ args = skip_spaces (args + 2);
+ requested_threads = args;
+ continue;
+ }
+ if (args[1] == 'r')
+ {
+ args = skip_spaces (&args[2]);
+ ret = regcomp (&preg_buffer, args, REG_NOSUB);
+ if (ret == 0)
+ {
+ preg = &preg_buffer;
+ make_regfree_cleanup (preg);
+ }
+ else
+ {
+ char *err = get_regcomp_error (ret, &preg_buffer);
+ make_cleanup (xfree, err);
+ error (_("Invalid regexp (%s): %s"), err, requested_threads);
+ }
+ break;
+ }
+ error (_("Bad option (%s)"), &args[1]);
+ break;
+ }
+
/* For backward compatibility, we make a list for MI. A table is
preferable for the CLI, though, because it shows table
- headers. */
+ headers.
+ We do not sort the list for MI. */
if (ui_out_is_mi_like_p (uiout))
- make_cleanup_ui_out_list_begin_end (uiout, "threads");
- else
{
- int n_threads = 0;
+ make_cleanup_ui_out_list_begin_end (uiout, "threads");
for (tp = thread_list; tp; tp = tp->next)
{
- if (!number_is_in_list (requested_threads, tp->num))
- continue;
+ if (ptid_equal (tp->ptid, current_ptid))
+ current_thread = tp->num;
+
+ if (print_thread_filter_check (tp, requested_threads, pid, NULL))
+ print_thread_info_single (uiout, tp, current_ptid);
+ }
+ }
+ else
+ {
+ threads = xmalloc (sizeof (*threads) * thread_list_size);
+ make_cleanup (free, threads);
- if (pid != -1 && PIDGET (tp->ptid) != pid)
- continue;
+ n_threads = 0;
+ for (i = 0, tp = thread_list; tp; tp = tp->next, ++i)
+ {
+ thread_cache_name (tp);
+ if (print_thread_filter_check (tp, requested_threads, pid, preg))
+ {
+ threads[n_threads] = tp;
+ ++n_threads;
+ }
- if (tp->state == THREAD_EXITED)
- continue;
+ if (ptid_equal (tp->ptid, current_ptid))
+ current_thread = tp->num;
- ++n_threads;
}
if (n_threads == 0)
@@ -803,7 +1025,7 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid)
ui_out_message (uiout, 0, _("No threads.\n"));
else
ui_out_message (uiout, 0, _("No threads match '%s'.\n"),
- requested_threads);
+ args);
do_cleanups (old_chain);
return;
}
@@ -815,115 +1037,15 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid)
ui_out_table_header (uiout, 17, ui_left, "target-id", "Target Id");
ui_out_table_header (uiout, 1, ui_left, "frame", "Frame");
ui_out_table_body (uiout);
- }
- for (tp = thread_list; tp; tp = tp->next)
- {
- struct cleanup *chain2;
- int core;
- if (!number_is_in_list (requested_threads, tp->num))
- continue;
+ if (enable_sort)
+ qsort (threads, n_threads, sizeof (*threads), print_thread_sort_cmp);
- if (pid != -1 && PIDGET (tp->ptid) != pid)
+ for (i = 0; i < n_threads; i++)
{
- if (requested_threads != NULL && *requested_threads != '\0')
- error (_("Requested thread not found in requested process"));
- continue;
+ print_thread_info_single (uiout, threads[i], current_ptid);
}
-
- if (ptid_equal (tp->ptid, current_ptid))
- current_thread = tp->num;
-
- if (tp->state == THREAD_EXITED)
- continue;
-
- chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
-
- if (ui_out_is_mi_like_p (uiout))
- {
- /* Compatibility. */
- if (ptid_equal (tp->ptid, current_ptid))
- ui_out_text (uiout, "* ");
- else
- ui_out_text (uiout, " ");
- }
- else
- {
- if (ptid_equal (tp->ptid, current_ptid))
- ui_out_field_string (uiout, "current", "*");
- else
- ui_out_field_skip (uiout, "current");
- }
-
- ui_out_field_int (uiout, "id", tp->num);
-
- /* For the CLI, we stuff everything into the target-id field.
- This is a gross hack to make the output come out looking
- correct. The underlying problem here is that ui-out has no
- way to specify that a field's space allocation should be
- shared by several fields. For MI, we do the right thing
- instead. */
-
- target_id = target_pid_to_str (tp->ptid);
- extra_info = target_extra_thread_info (tp);
- name = tp->name ? tp->name : target_thread_name (tp);
-
- if (ui_out_is_mi_like_p (uiout))
- {
- ui_out_field_string (uiout, "target-id", target_id);
- if (extra_info)
- ui_out_field_string (uiout, "details", extra_info);
- if (name)
- ui_out_field_string (uiout, "name", name);
- }
- else
- {
- struct cleanup *str_cleanup;
- char *contents;
-
- if (extra_info && name)
- contents = xstrprintf ("%s \"%s\" (%s)", target_id,
- name, extra_info);
- else if (extra_info)
- contents = xstrprintf ("%s (%s)", target_id, extra_info);
- else if (name)
- contents = xstrprintf ("%s \"%s\"", target_id, name);
- else
- contents = xstrdup (target_id);
- str_cleanup = make_cleanup (xfree, contents);
-
- ui_out_field_string (uiout, "target-id", contents);
- do_cleanups (str_cleanup);
- }
-
- if (tp->state == THREAD_RUNNING)
- ui_out_text (uiout, "(running)\n");
- else
- {
- /* The switch below puts us at the top of the stack (leaf
- frame). */
- switch_to_thread (tp->ptid);
- print_stack_frame (get_selected_frame (NULL),
- /* For MI output, print frame level. */
- ui_out_is_mi_like_p (uiout),
- LOCATION);
- }
-
- if (ui_out_is_mi_like_p (uiout))
- {
- char *state = "stopped";
-
- if (tp->state == THREAD_RUNNING)
- state = "running";
- ui_out_field_string (uiout, "state", state);
- }
-
- core = target_core_of_thread (tp->ptid);
- if (ui_out_is_mi_like_p (uiout) && core != -1)
- ui_out_field_int (uiout, "core", core);
-
- do_cleanups (chain2);
}
/* Restores the current thread and the frame selected before
--
1.7.7.3
next prev parent reply other threads:[~2012-08-24 1:09 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-21 21:19 Aaron Gamble
2012-08-22 10:06 ` Abid, Hafiz
2012-08-22 17:15 ` Eli Zaretskii
2012-08-22 18:52 ` Tom Tromey
2012-08-22 22:37 ` Aaron Gamble
2012-08-22 23:30 ` Sergio Durigan Junior
2012-08-23 16:00 ` Tom Tromey
2012-08-24 1:09 ` Aaron Gamble [this message]
2012-08-24 17:58 ` Tom Tromey
2012-08-24 22:23 ` Aaron Gamble
2012-08-24 22:32 ` Sergio Durigan Junior
2012-08-24 23:21 ` Aaron Gamble
2012-08-24 23:28 ` Aaron Gamble
2012-08-25 3:12 ` Sergio Durigan Junior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAHX8C+L=iiicRcprm7ixcxn2ykd+3aePR7r0=XsrvB1-kbLv2g@mail.gmail.com' \
--to=agamble@google.com \
--cc=gdb-patches@sourceware.org \
--cc=sergiodj@redhat.com \
--cc=tromey@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox