--- gdb/gdbcmd.h | 2 gdb/inf-loop.c | 12 +++ gdb/infcmd.c | 4 - gdb/inferior.h | 25 +++++-- gdb/infrun.c | 177 +++++++++++++++++++++++++++++++++++++++++----------- gdb/mi/mi-cmd-env.c | 2 gdb/mi/mi-main.c | 65 ++++++++++++++++--- gdb/stack.c | 11 +-- gdb/thread.c | 63 +++++++++++------- gdb/top.c | 46 +++---------- gdb/top.h | 3 11 files changed, 287 insertions(+), 123 deletions(-) Index: src/gdb/inf-loop.c =================================================================== --- src.orig/gdb/inf-loop.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/inf-loop.c 2008-06-29 23:47:19.000000000 +0100 @@ -108,6 +108,14 @@ inferior_event_handler (enum inferior_ev && language_mode == language_mode_auto) language_info (1); /* Print what changed. */ + + /* Run breakpoint commands in a new context. Note: this means + that if a breakpoint command switches threads with "thread + n", that change is discarded after the breakpoint commands + finish. */ + if (non_stop) + push_thread_context (inferior_ptid, get_selected_frame (NULL)); + /* Don't propagate breakpoint commands errors. Either we're stopping or some command resumes the inferior. The user will be informed. */ @@ -116,6 +124,10 @@ inferior_event_handler (enum inferior_ev bpstat_do_actions (&stop_bpstat); } + /* Restore the previous context. */ + if (non_stop) + pop_thread_context (); + /* If no breakpoint command resumed the inferior, prepare for interaction with the user. */ if (!is_running (inferior_ptid)) Index: src/gdb/infcmd.c =================================================================== --- src.orig/gdb/infcmd.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/infcmd.c 2008-06-29 23:44:32.000000000 +0100 @@ -570,7 +570,7 @@ run_command_1 (char *args, int from_tty, environ_vector (inferior_environ), from_tty); /* If no selected thread, select the current one. */ - if (ptid_equal (user_selected_ptid, null_ptid)) + if (is_user_selected_thread (null_ptid)) /* Going to proceed, no need to record a frame. */ store_selected_thread_and_frame (inferior_ptid, NULL); @@ -1971,7 +1971,7 @@ attach_command_post_wait (char *args, in if (async_exec) { /* If no selected thread, select the current one. */ - if (ptid_equal (user_selected_ptid, null_ptid)) + if (is_user_selected_thread (null_ptid)) /* Going to proceed, no need to record a frame. */ store_selected_thread_and_frame (inferior_ptid, NULL); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); Index: src/gdb/inferior.h =================================================================== --- src.orig/gdb/inferior.h 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/inferior.h 2008-06-29 23:44:32.000000000 +0100 @@ -405,12 +405,25 @@ extern int debug_displaced; void displaced_step_dump_bytes (struct ui_file *file, const gdb_byte *buf, size_t len); -/* This points to the user/external selected thread and frame. In - all-stop mode, a stop event changes the external thread to the - thread that got the event (in normal_stop), while in non-stop mode, - GDB never changes the external thread automatically (although the - internal thread may change). */ -extern ptid_t user_selected_ptid; +/* Return true if PTID points to the user/external selected thread of + the current context. */ +extern int is_user_selected_thread (ptid_t ptid); + +/* Returns the current context's user selected thread. */ +extern ptid_t get_user_selected_thread (void); + +/* Push a new context with PTID and FRAME selected into the context + stack. */ +extern void push_thread_context (ptid_t ptid, struct frame_info *frame); + +/* Push a new context cloned from the current context. */ +extern void clone_thread_context (void); + +/* Pop the current context off the context stack. */ +extern void pop_thread_context (void); + +/* Invalidate all contexts that point at PTID. */ +extern void invalidate_contexts_of (ptid_t ptid); /* Records PTID and FRAME as user/frontend/external selected thread and frame. */ Index: src/gdb/infrun.c =================================================================== --- src.orig/gdb/infrun.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/infrun.c 2008-06-29 23:47:07.000000000 +0100 @@ -46,9 +46,10 @@ #include "solib.h" #include "main.h" #include "interps.h" - #include "gdb_assert.h" #include "mi/mi-common.h" +#include "vec.h" +#include "cli/cli-decode.h" /* Prototypes for local functions */ @@ -1694,21 +1695,116 @@ context_switch_to (ptid_t ptid) thread that got the event (in normal_stop), while in non-stop mode, GDB never changes the external thread automatically (although the internal thread (inferior_ptid) may change). */ +struct frontend_context +{ + /* Selected thread/process. If NULL_PTID, there is no selected + thread. */ + ptid_t ptid; + /* Selected frame of the selected thread. We store both frame id + and level. See restore_selected_thread_and_frame. */ + struct frame_id frame; + int frame_level; +}; +typedef struct frontend_context * frontend_context_t; + +DEF_VEC_P(frontend_context_t); +static VEC(frontend_context_t) *thread_context_stack; +static int thread_context_level = -1; + +static struct frontend_context * +get_current_thread_context (void) +{ + struct frontend_context *ctx; + ctx = VEC_index (frontend_context_t, + thread_context_stack, thread_context_level); + gdb_assert (ctx); + return ctx; +} + +void +invalidate_contexts_of (ptid_t ptid) +{ + int ix = 0; + struct frontend_context *ctx; + + for (ix = 0; VEC_iterate (frontend_context_t, thread_context_stack, ix, ctx); ix++) + { + if (ptid_equal (ctx->ptid, ptid)) + { + ctx->ptid = null_ptid; + ctx->frame = null_frame_id; + ctx->frame_level = -1; + } + } +} + +void +push_thread_context (ptid_t ptid, struct frame_info *frame) +{ + struct frontend_context *ctx; + struct frontend_context *new_ctx = XMALLOC (struct frontend_context); -/* Selected thread/process. If NULL_PTID, there is no selected - thread. */ -ptid_t user_selected_ptid; - -/* Selected frame of the selected thread. We store both frame id and - level. See restore_selected_thread_and_frame. */ -static struct frame_id user_selected_frame; -static int user_selected_frame_level; + new_ctx->ptid = null_ptid; + new_ctx->frame = null_frame_id; + new_ctx->frame_level = -1; + + VEC_safe_push (frontend_context_t, thread_context_stack, new_ctx); + thread_context_level++; + + store_selected_thread_and_frame (ptid, frame); +} + +void +clone_thread_context (void) +{ + struct frontend_context *ctx = get_current_thread_context (); + struct frontend_context *new_ctx = XMALLOC (struct frontend_context); + + new_ctx->ptid = ctx->ptid; + new_ctx->frame = ctx->frame; + new_ctx->frame_level = ctx->frame_level; + + VEC_safe_push (frontend_context_t, thread_context_stack, new_ctx); + thread_context_level++; +} + +void +pop_thread_context (void) +{ + struct frontend_context *ctx = get_current_thread_context (); + if (thread_context_level == 0) + return; + + ctx = VEC_last (frontend_context_t, thread_context_stack); + xfree (ctx); + + VEC_pop (frontend_context_t, thread_context_stack); + thread_context_level--; + + /* Restore this context. */ + restore_selected_thread_and_frame (); +} + +ptid_t +get_user_selected_thread (void) +{ + return get_current_thread_context ()->ptid; +} + +int +is_user_selected_thread (ptid_t ptid) +{ + ptid_t selected_ptid = get_user_selected_thread (); + return ptid_equal (selected_ptid, ptid); +} /* Register PTID and FRAME as user selected thread and frame. If PTID is NULL_PTID, FRAME has to be NULL. */ void store_selected_thread_and_frame (ptid_t ptid, struct frame_info *frame) { + struct frontend_context *ctx = get_current_thread_context (); + /* If a frame is passed, we need to be able to build an id from it. GDB only parses frames of inferior_ptid, and frames don't registers which thread they belong to. */ @@ -1719,18 +1815,18 @@ store_selected_thread_and_frame (ptid_t if (ptid_equal (ptid, null_ptid)) gdb_assert (frame == NULL); - user_selected_ptid = ptid; - user_selected_frame = get_frame_id (frame); - user_selected_frame_level = frame_relative_level (frame); + ctx->ptid = ptid; + ctx->frame = get_frame_id (frame); + ctx->frame_level = frame_relative_level (frame); if (debug_infrun) { fprintf_unfiltered (gdb_stdlog, "\ infrun.c: Storing user selected thread and frame [%s], ", - target_pid_to_str (user_selected_ptid)); - fprint_frame_id (gdb_stdlog, user_selected_frame); + target_pid_to_str (ctx->ptid)); + fprint_frame_id (gdb_stdlog, ctx->frame); fprintf_unfiltered (gdb_stdlog, ", #%d.\n", - user_selected_frame_level); + ctx->frame_level); } } @@ -1738,42 +1834,46 @@ infrun.c: Storing user selected thread a void restore_selected_thread_and_frame (void) { + struct frontend_context *ctx; + if (!target_has_registers || !target_has_stack || !target_has_memory) return; + ctx = get_current_thread_context (); + /* Don't switch the internal current thread to the null thread. Too many places require inferior_ptid to point at a valid process (even if the thread component is invalid) currently. */ - if (!ptid_equal (user_selected_ptid, null_ptid)) + if (!ptid_equal (ctx->ptid, null_ptid)) { if (debug_infrun) { fprintf_unfiltered (gdb_stdlog, "\ infrun.c: restoring_selected_thread_and_frame: [%s], ", - target_pid_to_str (user_selected_ptid)); - fprint_frame_id (gdb_stdlog, user_selected_frame); + target_pid_to_str (ctx->ptid)); + fprint_frame_id (gdb_stdlog, ctx->frame); fprintf_unfiltered (gdb_stdlog, ", #%d\n", - user_selected_frame_level); + ctx->frame_level); } if (non_stop) - context_switch_to (user_selected_ptid); + context_switch_to (ctx->ptid); else - switch_to_thread (user_selected_ptid); + switch_to_thread (ctx->ptid); - if (is_stopped (user_selected_ptid)) + if (is_stopped (ctx->ptid)) { struct frame_info *frame; int count; - gdb_assert (user_selected_frame_level >= 0); + gdb_assert (ctx->frame_level >= 0); /* Restore by level first, check if the frame id is the same as expected. If that fails, try restoring by frame id. If that fails, nothing to do, just warn the user. */ - count = user_selected_frame_level; + count = ctx->frame_level; frame = find_relative_frame (get_current_frame (), &count); if (count == 0 && frame != NULL @@ -1782,11 +1882,11 @@ infrun.c: restoring_selected_thread_and_ unlikelly the search by level finds the wrong frame, it's 99.9(9)% of the times (for all practical purposes) safe. */ - && (frame_id_eq (get_frame_id (frame), user_selected_frame) + && (frame_id_eq (get_frame_id (frame), ctx->frame) /* Note: could be better to check every frame_id member for equality here. */ || (!frame_id_p (get_frame_id (frame)) - && !frame_id_p (user_selected_frame)))) + && !frame_id_p (ctx->frame)))) { /* Cool, all is fine. */ select_frame (frame); @@ -1795,7 +1895,7 @@ infrun.c: restoring_selected_thread_and_ return; } - frame = frame_find_by_id (user_selected_frame); + frame = frame_find_by_id (ctx->frame); if (frame != NULL) { /* Cool, refound it. */ @@ -1803,10 +1903,10 @@ infrun.c: restoring_selected_thread_and_ /* The relative level changed, otherwise we would have found it above. */ - user_selected_frame_level = frame_relative_level (frame); + ctx->frame_level = frame_relative_level (frame); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "\ -infrun.c: success (id): new level #%d\n", user_selected_frame_level); +infrun.c: success (id): new level #%d\n", ctx->frame_level); return; } @@ -1819,7 +1919,7 @@ infrun.c: success (id): new level #%d\n" { warning (_("\ Couldn't restore frame #%d in current thread, at reparsed frame #0\n"), - user_selected_frame_level); + ctx->frame_level); /* For MI, we should probably have a notification about current frame change. But this error is not very likely, so don't bother for now. */ @@ -1827,16 +1927,16 @@ Couldn't restore frame #%d in current th } frame = get_selected_frame (NULL); - user_selected_frame = get_frame_id (frame); - user_selected_frame_level = frame_relative_level (frame); + ctx->frame = get_frame_id (frame); + ctx->frame_level = frame_relative_level (frame); if (debug_infrun) { fprintf_unfiltered (gdb_stdlog, "\ infrun.c: user selected frame changed to "); - fprint_frame_id (gdb_stdlog, user_selected_frame); + fprint_frame_id (gdb_stdlog, ctx->frame); fprintf_unfiltered (gdb_stdlog, ", #%d.\n", - user_selected_frame_level); + ctx->frame_level); } } } @@ -1845,7 +1945,7 @@ infrun.c: user selected frame changed to void select_thread_if_no_thread_selected (void) { - if (ptid_equal (user_selected_ptid, null_ptid) + if (is_user_selected_thread (null_ptid) && !ptid_equal (inferior_ptid, null_ptid)) { if (is_stopped (inferior_ptid)) @@ -3892,7 +3992,7 @@ normal_stop (void) Note that SIGNALLED here means "exited with a signal", not "received a signal". */ if (!non_stop - && !ptid_equal (user_selected_ptid, inferior_ptid) + && !is_user_selected_thread (inferior_ptid) && target_has_execution && last.kind != TARGET_WAITKIND_SIGNALLED && last.kind != TARGET_WAITKIND_EXITED) @@ -4076,7 +4176,7 @@ done: { if ((!stop_stack_dummy || !proceed_to_inferior_function_call) && (!non_stop - || ptid_equal (user_selected_ptid, inferior_ptid))) + || is_user_selected_thread (inferior_ptid))) /* Selected thread just stopped. Record the selected frame. In all-stop, the thread that has the event is always made the current. Don't do this on return from a stack dummy @@ -5002,4 +5102,7 @@ breakpoints, even if such is supported b inferior_ptid = null_ptid; target_last_wait_ptid = minus_one_ptid; displaced_step_ptid = null_ptid; + + /* Top level context. */ + push_thread_context (null_ptid, NULL); } Index: src/gdb/mi/mi-main.c =================================================================== --- src.orig/gdb/mi/mi-main.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/mi/mi-main.c 2008-06-29 23:44:32.000000000 +0100 @@ -1056,13 +1056,19 @@ do_restore_selected_thread_and_frame_cle } static void +do_pop_context (void *arg) +{ + pop_thread_context (); +} + +static void mi_cmd_execute (struct mi_parse *parse) { struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); free_all_values (); current_token = xstrdup (parse->token); - cleanup = make_cleanup (free_current_contents, ¤t_token); + make_cleanup (free_current_contents, ¤t_token); /* Switch to the frontend selected thread, before invoking the command, so the command implementation sees the correct @@ -1076,9 +1082,55 @@ mi_cmd_execute (struct mi_parse *parse) if (parse->cmd->argv_func != NULL) { + int i = 0; + for (i = 0; i < parse->argc; ++i) + { + if (strcmp (parse->argv[i], "--thread") == 0) + { + if (i + 1 < parse->argc) + { + enum gdb_rc rc; + char *mi_error_message; + int j, k; + int num; + ptid_t ptid; + + num = value_as_long (parse_and_eval (parse->argv[i + 1])); + + if (!valid_thread_id (num)) + error (_("Thread ID %d not known."), num); + + ptid = thread_id_to_pid (num); + + if (is_exited (ptid)) + error (_("Thread ID %d has terminated."), num); + + clone_thread_context (); + make_cleanup (do_pop_context, NULL); + + /* Silently switch to new thread, and record it as + current in the new context. */ + if (non_stop) + context_switch_to (ptid); + else + switch_to_thread (ptid); + store_selected_thread_and_frame (inferior_ptid, + get_selected_frame (NULL)); + + /* FIXME: should we free the two items? */ + for (j = i, k = i + 2; k < parse->argc; ++k, ++k) + parse->argv[i] = parse->argv[k]; + + parse->argc -= 2; + } + else + error ("The --thread option requires a value"); + } + } + if (target_can_async_p () && target_has_execution - && (ptid_equal (user_selected_ptid, null_ptid)) + && (is_user_selected_thread (null_ptid)) && (strcmp (parse->command, "thread-info") != 0 && strcmp (parse->command, "thread-list-ids") != 0 && strcmp (parse->command, "thread-select") != 0)) @@ -1157,12 +1209,7 @@ mi_execute_cli_command (const char *cmd, fprintf_unfiltered (gdb_stdout, "cli=%s run=%s\n", cmd, run); old_cleanups = make_cleanup (xfree, run); - /* execute_command switches to the user selected thread. We - don't want that switch. We want the command to apply to - inferior_ptid instead, hence use the _internal version. We - don't change temporarily the user selected thread and restore - it with a cleanup, because the command may change it. */ - execute_command_internal ( /*ui */ run, 0 /*from_tty */ ); + execute_command ( /*ui */ run, 0 /*from_tty */ ); do_cleanups (old_cleanups); return; } @@ -1180,7 +1227,7 @@ mi_execute_async_cli_command (char *cli_ run = xstrprintf ("%s %s", cli_command, argc ? *argv : ""); old_cleanups = make_cleanup (xfree, run); - execute_command_internal ( /*ui */ run, 0 /*from_tty */ ); + execute_command ( /*ui */ run, 0 /*from_tty */ ); if (target_can_async_p ()) { Index: src/gdb/stack.c =================================================================== --- src.orig/gdb/stack.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/stack.c 2008-06-29 23:44:32.000000000 +0100 @@ -1699,9 +1699,8 @@ select_frame_command (char *level_exp, i select_frame (parse_frame_specification_1 (level_exp, "No stack.", NULL)); /* Record user selected frame. */ - if (ptid_equal (inferior_ptid, user_selected_ptid)) - store_selected_thread_and_frame (inferior_ptid, - get_selected_frame (NULL)); + store_selected_thread_and_frame (inferior_ptid, + get_selected_frame (NULL)); } /* The "frame" command. With no argument, print the selected frame @@ -1741,8 +1740,7 @@ up_silently_base (char *count_exp) select_frame (frame); /* Record user selected frame. */ - if (ptid_equal (inferior_ptid, user_selected_ptid)) - store_selected_thread_and_frame (inferior_ptid, frame); + store_selected_thread_and_frame (inferior_ptid, frame); } static void @@ -1783,8 +1781,7 @@ down_silently_base (char *count_exp) select_frame (frame); /* Record user selected frame. */ - if (ptid_equal (inferior_ptid, user_selected_ptid)) - store_selected_thread_and_frame (inferior_ptid, frame); + store_selected_thread_and_frame (inferior_ptid, frame); } static void Index: src/gdb/thread.c =================================================================== --- src.orig/gdb/thread.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/thread.c 2008-06-30 01:06:22.000000000 +0100 @@ -244,10 +244,12 @@ delete_thread (ptid_t ptid) if (!tp) return; - if (ptid_equal (tp->ptid, user_selected_ptid)) + if (is_user_selected_thread (tp->ptid)) /* User selected thread no longer exists. */ store_selected_thread_and_frame (null_ptid, NULL); + invalidate_contexts_of (tp->ptid); + if (ptid_equal (tp->ptid, inferior_ptid)) { /* Can't delete yet. Mark it as exited, and notify it. */ @@ -740,6 +742,12 @@ set_executing (ptid_t ptid, int executin } } +static void +do_pop_context (void *arg) +{ + pop_thread_context (); +} + /* Prints the list of threads and their details on UIOUT. This is a version of 'info_thread_command' suitable for use from MI. @@ -759,6 +767,9 @@ print_thread_info (struct ui_out *uiout, old_chain = make_cleanup_ui_out_list_begin_end (uiout, "threads"); + clone_thread_context (); + make_cleanup (do_pop_context, NULL); + for (tp = thread_list; tp; tp = tp->next) { struct cleanup *chain2; @@ -772,7 +783,7 @@ print_thread_info (struct ui_out *uiout, chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - if (ptid_equal (tp->ptid, user_selected_ptid)) + if (is_user_selected_thread (tp->ptid)) { current_thread = tp->num; ui_out_text (uiout, "* "); @@ -812,15 +823,13 @@ print_thread_info (struct ui_out *uiout, do_cleanups (chain2); } - /* Restores the current thread and the frame selected before - the "info threads" command. */ do_cleanups (old_chain); if (requested_thread == -1) { gdb_assert (current_thread != -1 || !thread_list - || ptid_equal (user_selected_ptid, null_ptid)); + || is_user_selected_thread (null_ptid)); if (current_thread != -1 && ui_out_is_mi_like_p (uiout)) ui_out_field_int (uiout, "current-thread-id", current_thread); @@ -940,6 +949,9 @@ thread_apply_all_command (char *cmd, int prune_threads (); target_find_new_threads (); + clone_thread_context (); + make_cleanup (do_pop_context, NULL); + /* Save a copy of the command in case it is clobbered by execute_command */ saved_cmd = xstrdup (cmd); @@ -947,20 +959,19 @@ thread_apply_all_command (char *cmd, int for (tp = thread_list; tp; tp = tp->next) if (thread_alive (tp)) { + /* Silently switch to new thread, and record it as current in + the new context. */ if (non_stop) context_switch_to (tp->ptid); else switch_to_thread (tp->ptid); + store_selected_thread_and_frame (inferior_ptid, + get_selected_frame (NULL)); printf_filtered (_("\nThread %d (%s):\n"), tp->num, target_tid_to_str (inferior_ptid)); - /* execute_command switches to the user selected thread. We - don't want that switch. We want the command to apply to - inferior_ptid instead, hence use the _internal version. We - don't change temporarily the user selected thread and - restore it with a cleanup, because the command may change - it. */ - execute_command_internal (cmd, from_tty); + /* Now execute the command in this new context. */ + execute_command (cmd, from_tty); strcpy (cmd, saved_cmd); /* Restore exact command used previously */ } @@ -1024,20 +1035,25 @@ thread_apply_command (char *tidlist, int warning (_("Thread %d has terminated."), start); else { + clone_thread_context (); + make_cleanup (do_pop_context, NULL); + + /* Silently switch to new thread, and record it as current in + the new context. */ if (non_stop) context_switch_to (tp->ptid); else switch_to_thread (tp->ptid); + store_selected_thread_and_frame (inferior_ptid, + get_selected_frame (NULL)); + printf_filtered (_("\nThread %d (%s):\n"), tp->num, target_tid_to_str (inferior_ptid)); - /* execute_command switches to the user selected thread. - We don't want that switch. We want the command to - apply to inferior_ptid instead, hence use the - _internal version. We don't change temporarily the - user selected thread and restore it with a cleanup, - because the command may change it. */ - execute_command_internal (cmd, from_tty); - strcpy (cmd, saved_cmd); /* Restore exact command used previously */ + /* Now execute the command in this new context. */ + execute_command (cmd, from_tty); + + /* Restore exact command used previously. */ + strcpy (cmd, saved_cmd); } } } @@ -1055,14 +1071,15 @@ thread_command (char *tidstr, int from_t { if (target_has_stack) { + ptid_t ptid = get_user_selected_thread (); /* Don't generate an error, just say which thread is current. */ - if (ptid_equal (user_selected_ptid, null_ptid)) + if (ptid_equal (ptid, null_ptid)) printf_filtered (_("No selected thread.\n")); else printf_filtered (_("[Current thread is %d (%s)]\n"), - pid_to_thread_id (user_selected_ptid), - target_tid_to_str (user_selected_ptid)); + pid_to_thread_id (ptid), + target_tid_to_str (ptid)); } else error (_("No stack.")); Index: src/gdb/top.c =================================================================== --- src.orig/gdb/top.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/top.c 2008-06-29 23:44:32.000000000 +0100 @@ -368,8 +368,10 @@ do_restore_selected_thread_and_frame_cle /* Execute the line P as a command. Pass FROM_TTY as second argument to the defining function. */ +/* Execute command P, in the current user context. */ + void -execute_command_1 (char *p, int from_tty, int internal) +execute_command (char *p, int from_tty) { struct cmd_list_element *c; enum language flang; @@ -422,25 +424,21 @@ execute_command_1 (char *p, int from_tty c = lookup_cmd (&p, cmdlist, "", 0, 1); - if (!internal) - { - /* Command applies to the external thread. Switch the - internal thread to it before invoking the command, so the - command implementation sees the correct context. */ - restore_selected_thread_and_frame (); - /* Switch to the external thread again after invoking the - command, so if for some reason restoring the selected - frame fails, the user notices immediatelly. Note that - the command may change the selected thread. */ - make_cleanup (do_restore_selected_thread_and_frame_cleanup, NULL); - } + /* Make sure the internal thread points to the user selected + thread, so the command implementation sees the correct + context. */ + restore_selected_thread_and_frame (); + /* Switch to the external thread again after invoking the + command, so if for some reason restoring the selected frame + fails, the user notices immediatelly. Note that the command + may change the selected thread and/or frame */ + make_cleanup (do_restore_selected_thread_and_frame_cleanup, NULL); /* If there is no selected thread, we allow only a limited set of commands. */ if (target_can_async_p () && target_has_execution - && (!internal - && ptid_equal (user_selected_ptid, null_ptid)) + && is_user_selected_thread (null_ptid) && !get_cmd_no_selected_thread_ok (c)) error (_("\ Cannot execute this command without a selected thread. See `help thread'")); @@ -528,24 +526,6 @@ Cannot execute this command without a se } } -/* Execute command P, and use the already selected internal thread - (inferior_ptid) as current context. Use in situations like the - "thread apply" command. */ - -void -execute_command_internal (char *p, int from_tty) -{ - execute_command_1 (p, from_tty, 1); -} - -/* Execute command P, with the user/frontend/external thread as - context. */ -void -execute_command (char *p, int from_tty) -{ - execute_command_1 (p, from_tty, 0); -} - /* Read commands from `instream' and execute them until end of file or error reading instream. */ Index: src/gdb/gdbcmd.h =================================================================== --- src.orig/gdb/gdbcmd.h 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/gdbcmd.h 2008-06-29 23:44:32.000000000 +0100 @@ -122,8 +122,6 @@ extern struct cmd_list_element *showchec extern void execute_command (char *, int); -extern void execute_command_internal (char *, int); - enum command_control_type execute_control_command (struct command_line *); extern void print_command_line (struct command_line *, unsigned int, Index: src/gdb/mi/mi-cmd-env.c =================================================================== --- src.orig/gdb/mi/mi-cmd-env.c 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/mi/mi-cmd-env.c 2008-06-29 23:44:32.000000000 +0100 @@ -56,7 +56,7 @@ env_execute_cli_command (const char *cmd else run = xstrdup (cmd); old_cleanups = make_cleanup (xfree, run); - execute_command_internal ( /*ui */ run, 0 /*from_tty */ ); + execute_command ( /*ui */ run, 0 /*from_tty */ ); do_cleanups (old_cleanups); return; } Index: src/gdb/top.h =================================================================== --- src.orig/gdb/top.h 2008-06-29 23:44:19.000000000 +0100 +++ src/gdb/top.h 2008-06-29 23:44:32.000000000 +0100 @@ -51,9 +51,6 @@ extern int quit_cover (void *); /* Execute command, after changing to the user selected thread. */ extern void execute_command (char *, int); -/* Execute command, without changing to the user selected thread. */ -extern void execute_command_internal (char *, int); - /* This function returns a pointer to the string that is used by gdb for its command prompt. */ extern char *get_prompt (void);