From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17653 invoked by alias); 17 Feb 2008 15:33:45 -0000 Received: (qmail 17614 invoked by uid 22791); 17 Feb 2008 15:33:43 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 17 Feb 2008 15:33:26 +0000 Received: (qmail 23948 invoked from network); 17 Feb 2008 15:33:23 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 17 Feb 2008 15:33:23 -0000 From: Vladimir Prus To: gdb-patches@sources.redhat.com Subject: [RFA] Implement -thread-info. Date: Sun, 17 Feb 2008 15:33:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200802171833.26673.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-02/txt/msg00277.txt.bz2 Presently, the MI -thread-info and -thread-list-all-threads commands are not implemented, so a frontend wishing to know the state of all threads upon stop is required to manually iterate over threads, or use CLI. This patch implements -thread-info, that prints essentially the same information as 'info thread' in CLI. The new command can either print information for all threads, or for a specific one provided as argument, making -thread-list-all-threads not necessary. The sample output is: ^done, threads=[ {id="2",target-id="Thread 0xb7e1eb90 (LWP 21429)",frame={addr="0xffffe410",func="__kernel_vsyscall",args=[]}}, {id="1",target-id="Thread 0xb7e1f6b0 (LWP 21426)",frame={...}}], current-thread-id="1" I'll provide docs patch if the code patch is approved. OK? - Volodya * gdb.h (mi_info_threads): Declare. * thread.c (mi_info_threads): New. * mi/mi-cmds.c (mi_cmds): Specify a handler for -thread-info. * mi/mi-cmds.h (mi_cmd_thread_info): Declare. * mi/mi-main.c (mi_cmd_thread_info): New. (mi_cmd_list_features): Include 'thread-info'. --- gdb/gdb.h | 2 + gdb/mi/mi-cmds.c | 3 +- gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 19 +++++++++++++++++ gdb/thread.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/gdb/gdb.h b/gdb/gdb.h index fcd3e3b..13523fb 100644 --- a/gdb/gdb.h +++ b/gdb/gdb.h @@ -55,4 +55,6 @@ enum gdb_rc gdb_thread_select (struct ui_out *uiout, char *tidstr, enum gdb_rc gdb_list_thread_ids (struct ui_out *uiout, char **error_message); +extern void mi_info_threads (struct ui_out *uiout, int thread); + #endif diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index c651694..89c6376 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -130,8 +130,7 @@ struct mi_cmd mi_cmds[] = { "target-list-current-targets", { NULL, 0 }, NULL, NULL }, { "target-list-parameters", { NULL, 0 }, NULL, NULL }, { "target-select", { NULL, 0 }, mi_cmd_target_select}, - { "thread-info", { NULL, 0 }, NULL, NULL }, - { "thread-list-all-threads", { NULL, 0 }, NULL, NULL }, + { "thread-info", { NULL, 0 }, NULL, mi_cmd_thread_info }, { "thread-list-ids", { NULL, 0 }, 0, mi_cmd_thread_list_ids}, { "thread-select", { NULL, 0 }, 0, mi_cmd_thread_select}, { "trace-actions", { NULL, 0 }, NULL, NULL }, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 2d0393b..6a033e5 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -105,6 +105,7 @@ extern mi_cmd_argv_ftype mi_cmd_target_file_get; extern mi_cmd_argv_ftype mi_cmd_target_file_put; extern mi_cmd_argv_ftype mi_cmd_target_file_delete; extern mi_cmd_args_ftype mi_cmd_target_select; +extern mi_cmd_argv_ftype mi_cmd_thread_info; extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_var_assign; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 41e12d2..5d89847 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -277,6 +277,24 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) } enum mi_cmd_result +mi_cmd_thread_info (char *command, char **argv, int argc) +{ + int thread = -1; + + if (argc != 0 && argc != 1) + { + mi_error_message = xstrprintf ("Invalid MI command"); + return MI_CMD_ERROR; + } + + if (argc == 1) + thread = atoi (argv[0]); + + mi_info_threads (uiout, thread); + return MI_CMD_DONE; +} + +enum mi_cmd_result mi_cmd_data_list_register_names (char *command, char **argv, int argc) { int regnum, numregs; @@ -1055,6 +1073,7 @@ mi_cmd_list_features (char *command, char **argv, int argc) ui_out_field_string (uiout, NULL, "frozen-varobjs"); ui_out_field_string (uiout, NULL, "pending-breakpoints"); + ui_out_field_string (uiout, NULL, "thread-info"); do_cleanups (cleanup); diff --git a/gdb/thread.c b/gdb/thread.c index 3a39703..d11ef00 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -471,6 +471,66 @@ info_threads_command (char *arg, int from_tty) } } +/* Prints the list of threads and their details on UIOUT. + This is a version of 'info_thread_command' suitable for + use from MI. + If REQESTED_THREAD is not -1, it's the GDB id of the thread + that should be printed. Otherwise, all threads are + printed. */ +void +mi_info_threads (struct ui_out *uiout, int requested_thread) +{ + struct thread_info *tp; + ptid_t current_ptid; + int current_thread = -1; + struct cleanup *cleanup_chain; + char *extra_info; + struct frame_id saved_frame_id; + + saved_frame_id = get_frame_id (get_selected_frame (NULL)); + cleanup_chain = make_cleanup_restore_current_thread (inferior_ptid, + saved_frame_id); + + prune_threads (); + target_find_new_threads (); + current_ptid = inferior_ptid; + cleanup_chain = make_cleanup_ui_out_list_begin_end (uiout, "threads"); + + for (tp = thread_list; tp; tp = tp->next) + { + struct cleanup *cleanup2; + + if (requested_thread != -1 && tp->num != requested_thread) + continue; + + cleanup2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (ptid_equal (tp->ptid, current_ptid)) + current_thread = tp->num; + + ui_out_field_int (uiout, "id", tp->num); + ui_out_field_string (uiout, "target-id", target_tid_to_str (tp->ptid)); + + extra_info = target_extra_thread_info (tp); + if (extra_info) + ui_out_field_string (uiout, "details", extra_info); + + /* That switch put us at the top of the stack (leaf frame). */ + switch_to_thread (tp->ptid); + print_stack_frame (get_selected_frame (NULL), 0, LOCATION); + + do_cleanups (cleanup2); + } + do_cleanups (cleanup_chain); + + if (requested_thread == -1) + { + gdb_assert (current_thread != -1); + ui_out_field_int (uiout, "current-thread-id", current_thread); + } +} + + /* Switch from one thread to another. */ void -- 1.5.3.5