From 8ea051c51f64f1f720b12a7424c56ac31ff9a58b Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 9 Jul 2008 22:16:15 +0000 Subject: [PATCH] Add "executing" property to threads. * inferior.h (target_executing): Delete. * gdbthread.h (struct thread_info): Add executing_ field. (set_executing, is_executing): New. * thread.c (main_thread_executing): New. (init_thread_list): Clear it and also main_thread_running. (is_running): Return false if target has no execution. (any_running, is_executing, set_executing): New. * top.c: Include "gdbthread.h". (target_executing): Delete. (execute_command): Replace target_executing check by any_running. * event-top.c: Include "gdbthread.h". (display_gdb_prompt, command_handler): Replace target_executing by is_running. * inf-loop.c: Include "gdbthread.h". Don't mark as not executing here. Replace target_executing by is_running. * infrun.c (handle_inferior_event): Mark all threads as not-executing. * linux-nat.c (linux_nat_resume): Don't mark thread as executing here. * stack.c (get_selected_block): Return null if inferior is executing. * target.c (target_resume): Mark resumed ptid as executing. * breakpoint.c (until_break_command): Replace target_executing check by is_executing. * remote.c (remote_async_resume): Don't mark inferior as executing here. * mi/mi-interp.c (mi_cmd_interpreter_exec): Replace target_executing by any_running. * mi/mi-main.c (mi_cmd_exec_interrupt, mi_cmd_execute) (mi_execute_async_cli_command): Replace target_executing by is_running. * frame.c (get_current_frame): Error out if the current thread is executing. (has_stack_frames): New. (get_selected_frame, deprecated_safe_get_selected_frame): Check has_stack_frames. * Makefile.in (event-top.o, frame.o, inf-loop.o, top.o): Depend on $(gdbthread_h). --- gdb/ChangeLog | 47 +++++++++++++++++++++++++++++++ gdb/Makefile.in | 9 +++--- gdb/breakpoint.c | 2 +- gdb/event-top.c | 5 ++-- gdb/frame.c | 24 +++++++++++++--- gdb/gdbthread.h | 35 +++++++++++++++++++---- gdb/inf-loop.c | 13 ++------- gdb/inferior.h | 6 ---- gdb/infrun.c | 5 ++++ gdb/linux-nat.c | 5 +--- gdb/mi/mi-main.c | 8 +++--- gdb/remote.c | 7 ----- gdb/stack.c | 4 +++ gdb/target.c | 2 +- gdb/thread.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- gdb/top.c | 13 ++++----- 16 files changed, 199 insertions(+), 58 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b85fcec29ca..bde0c5700d0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,50 @@ +2008-07-09 Pedro Alves + + Add "executing" property to threads. + + * inferior.h (target_executing): Delete. + * gdbthread.h (struct thread_info): Add executing_ field. + (set_executing, is_executing): New. + * thread.c (main_thread_executing): New. + (init_thread_list): Clear it and also main_thread_running. + (is_running): Return false if target has no execution. + (any_running, is_executing, set_executing): New. + + * top.c: Include "gdbthread.h". + (target_executing): Delete. + (execute_command): Replace target_executing check by any_running. + * event-top.c: Include "gdbthread.h". + (display_gdb_prompt, command_handler): Replace target_executing by + is_running. + * inf-loop.c: Include "gdbthread.h". Don't mark as not executing + here. Replace target_executing by is_running. + * infrun.c (handle_inferior_event): Mark all threads as + not-executing. + * linux-nat.c (linux_nat_resume): Don't mark thread as executing + here. + * stack.c (get_selected_block): Return null if inferior is + executing. + * target.c (target_resume): Mark resumed ptid as executing. + * breakpoint.c (until_break_command): Replace target_executing + check by is_executing. + * remote.c (remote_async_resume): Don't mark inferior as executing + here. + * mi/mi-interp.c (mi_cmd_interpreter_exec): Replace target_executing + by any_running. + + * mi/mi-main.c (mi_cmd_exec_interrupt, mi_cmd_execute) + (mi_execute_async_cli_command): Replace target_executing by + is_running. + + * frame.c (get_current_frame): Error out if the current thread is + executing. + (has_stack_frames): New. + (get_selected_frame, deprecated_safe_get_selected_frame): Check + has_stack_frames. + + * Makefile.in (event-top.o, frame.o, inf-loop.o, top.o): Depend on + $(gdbthread_h). + 2008-07-09 Pedro Alves * symfile.c (load_command): Reopen the exec file and reread diff --git a/gdb/Makefile.in b/gdb/Makefile.in index d4b1297f37a..f12d3858967 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2106,7 +2106,7 @@ event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \ event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \ $(terminal_h) $(event_loop_h) $(event_top_h) $(interps_h) \ $(exceptions_h) $(cli_script_h) $(gdbcmd_h) $(readline_h) \ - $(readline_history_h) $(main_h) + $(readline_history_h) $(main_h) $(gdbthread_h) exceptions.o: exceptions.c $(defs_h) $(exceptions_h) $(breakpoint_h) \ $(target_h) $(inferior_h) $(annotate_h) $(ui_out_h) $(gdb_assert_h) \ $(gdb_string_h) $(serial_h) @@ -2141,7 +2141,8 @@ frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \ $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(user_regs_h) \ $(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) $(gdbcore_h) \ $(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \ - $(command_h) $(gdbcmd_h) $(observer_h) $(objfiles_h) $(exceptions_h) + $(command_h) $(gdbcmd_h) $(observer_h) $(objfiles_h) $(exceptions_h) \ + $(gdbthread_h) frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(gdb_assert_h) $(dummy_frame_h) $(gdb_obstack_h) $(value_h) \ $(regcache_h) @@ -2322,7 +2323,7 @@ infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ $(user_regs_h) $(exceptions_h) $(cli_decode_h) $(gdbthread_h) inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \ $(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h) \ - $(language_h) + $(language_h) $(gdbthread_h) inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \ $(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) \ $(inflow_h) $(gdb_select_h) @@ -2928,7 +2929,7 @@ top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \ $(annotate_h) $(completer_h) $(top_h) $(version_h) $(serial_h) \ $(doublest_h) $(gdb_assert_h) $(readline_h) $(readline_history_h) \ $(event_top_h) $(gdb_string_h) $(gdb_stat_h) $(ui_out_h) \ - $(cli_out_h) $(main_h) $(event_loop_h) + $(cli_out_h) $(main_h) $(event_loop_h) $(gdbthread_h) tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \ $(expression_h) $(gdbcmd_h) $(value_h) $(target_h) $(language_h) \ $(gdb_string_h) $(inferior_h) $(tracepoint_h) $(remote_h) \ diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 5024750ea48..ec7d6a87223 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -6229,7 +6229,7 @@ until_break_command (char *arg, int from_tty, int anywhere) deleted when the target stops. Otherwise, we're already stopped and delete breakpoints via cleanup chain. */ - if (target_can_async_p () && target_executing) + if (target_can_async_p () && is_running (inferior_ptid)) { arg1 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); diff --git a/gdb/event-top.c b/gdb/event-top.c index e8e9f68bb9a..681dca8a64d 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -32,6 +32,7 @@ #include "exceptions.h" #include "cli/cli-script.h" /* for reset_command_nest_depth */ #include "main.h" +#include "gdbthread.h" /* For dont_repeat() */ #include "gdbcmd.h" @@ -268,7 +269,7 @@ display_gdb_prompt (char *new_prompt) if (!current_interp_display_prompt_p ()) return; - if (target_executing && sync_execution) + if (sync_execution && is_running (inferior_ptid)) { /* This is to trick readline into not trying to display the prompt. Even though we display the prompt using this @@ -516,7 +517,7 @@ command_handler (char *command) /* Do any commands attached to breakpoint we stopped at. Only if we are always running synchronously. Or if we have just executed a command that doesn't start the target. */ - if (!target_can_async_p () || !target_executing) + if (!target_can_async_p () || !is_running (inferior_ptid)) { bpstat_do_actions (&stop_bpstat); do_cleanups (old_chain); diff --git a/gdb/frame.c b/gdb/frame.c index a14367cf8ae..9f0d07d6b4f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -40,6 +40,7 @@ #include "observer.h" #include "objfiles.h" #include "exceptions.h" +#include "gdbthread.h" static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); @@ -930,6 +931,9 @@ get_current_frame (void) error (_("No stack.")); if (!target_has_memory) error (_("No memory.")); + if (is_executing (inferior_ptid)) + error (_("Target is executing.")); + if (current_frame == NULL) { struct frame_info *sentinel_frame = @@ -950,6 +954,20 @@ get_current_frame (void) static struct frame_info *selected_frame; +static int +has_stack_frames (void) +{ + if (!target_has_registers || !target_has_stack || !target_has_memory) + return 0; + + /* If the current thread is executing, don't try to read from + it. */ + if (is_executing (inferior_ptid)) + return 0; + + return 1; +} + /* Return the selected frame. Always non-NULL (unless there isn't an inferior sufficient for creating a frame) in which case an error is thrown. */ @@ -959,9 +977,7 @@ get_selected_frame (const char *message) { if (selected_frame == NULL) { - if (message != NULL && (!target_has_registers - || !target_has_stack - || !target_has_memory)) + if (message != NULL && !has_stack_frames ()) error (("%s"), message); /* Hey! Don't trust this. It should really be re-finding the last selected frame of the currently selected thread. This, @@ -980,7 +996,7 @@ get_selected_frame (const char *message) struct frame_info * deprecated_safe_get_selected_frame (void) { - if (!target_has_registers || !target_has_stack || !target_has_memory) + if (!has_stack_frames ()) return NULL; return get_selected_frame (NULL); } diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index 2ed3cb6444f..389b2fc24fc 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -41,6 +41,25 @@ struct thread_info In fact, this may be overloaded with kernel thread id, etc. */ int num; /* Convenient handle (GDB thread id) */ + + /* 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 + thread is off and running. */ + /* This field is internal to thread.c. Never access it directly, + use is_executing instead. */ + int executing_; + + /* Frontend view of the running state. Note that this is different + from EXECUTING. When the thread is stopped internally while + handling an internal event, like a software single-step + breakpoint, executing will be false, but running will still be + true. As a possible future extension, this could turn into + enum { stopped, stepping, finishing, until(ling), ... } */ + /* This field is internal to thread.c. Never access it directly, + use is_running instead. */ + int running_; + /* State from wait_for_inferior */ CORE_ADDR prev_pc; struct breakpoint *step_resume_breakpoint; @@ -63,10 +82,6 @@ struct thread_info when we finally do stop stepping. */ bpstat stepping_through_solib_catchpoints; - /* This field is internal for thread.c. Never access it directly, - use is_running instead. */ - int running_; - /* Private data used by the target vector implementation. */ struct private_thread_info *private; }; @@ -161,9 +176,19 @@ extern void switch_to_thread (ptid_t ptid); If PIDGET (PTID) is -1, marks all threads. */ extern void set_running (ptid_t ptid, int running); -/* Reports if thread PTID is know to be running right now. */ +/* Reports if thread PTID is known to be running right now. */ extern int is_running (ptid_t ptid); +/* Reports if any thread is known to be running right now. */ +extern int any_running (void); + +/* Marks thread PTID as executing, or as stopped. + If PIDGET (PTID) is -1, marks all threads. */ +extern void set_executing (ptid_t ptid, int executing); + +/* Reports if thread PTID is executing. */ +extern int is_executing (ptid_t ptid); + /* Commands with a prefix of `thread'. */ extern struct cmd_list_element *thread_cmd_list; diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c index f77bc65ac6d..3f98bfcaa15 100644 --- a/gdb/inf-loop.c +++ b/gdb/inf-loop.c @@ -26,6 +26,7 @@ #include "remote.h" #include "exceptions.h" #include "language.h" +#include "gdbthread.h" static int fetch_inferior_event_wrapper (gdb_client_data client_data); @@ -72,14 +73,6 @@ inferior_event_handler (enum inferior_event_type event_type, break; case INF_EXEC_COMPLETE: - - /* This is the first thing to do -- so that continuations know that - the target is stopped. For example, command_line_handler_continuation - will run breakpoint commands, and if we think that the target is - running, we'll refuse to execute most commands. MI continuation - presently uses target_executing to either print or not print *stopped. */ - target_executing = 0; - /* Unregister the inferior from the event loop. This is done so that when the inferior is not running we don't get distracted by spurious inferior output. */ @@ -121,8 +114,8 @@ inferior_event_handler (enum inferior_event_type event_type, /* If no breakpoint command resumed the inferior, prepare for interaction with the user. */ - if (!target_executing) - { + if (!is_running (inferior_ptid)) + { if (was_sync) { display_gdb_prompt (0); diff --git a/gdb/inferior.h b/gdb/inferior.h index dd07efafe6c..3c69d4ed71f 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -111,12 +111,6 @@ extern const char *get_inferior_io_terminal (void); extern ptid_t inferior_ptid; -/* Is the inferior running right now, as a result of a 'run&', - 'continue&' etc command? This is used in asycn gdb to determine - whether a command that the user enters while the target is running - is allowed or not. */ -extern int target_executing; - /* Are we simulating synchronous execution? This is used in async gdb to implement the 'run', 'continue' etc commands, which will not redisplay the prompt until the execution is actually over. */ diff --git a/gdb/infrun.c b/gdb/infrun.c index dbb61100578..fd0ea248c0a 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1771,6 +1771,11 @@ handle_inferior_event (struct execution_control_state *ecs) && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event) add_thread (ecs->ptid); + /* Mark all threads as not-executing. In non-stop, this should be + adjusted to only mark ecs->ptid. */ + if (ecs->ws.kind != TARGET_WAITKIND_IGNORE) + set_executing (pid_to_ptid (-1), 0); + switch (ecs->ws.kind) { case TARGET_WAITKIND_LOADED: diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index ce3df53f5db..0821e97fb5a 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1624,10 +1624,7 @@ linux_nat_resume (ptid_t ptid, int step, enum target_signal signo) signo ? strsignal (signo) : "0"); if (target_can_async_p ()) - { - target_executing = 1; - target_async (inferior_event_handler, 0); - } + target_async (inferior_event_handler, 0); } /* Issue kill to specified lwp. */ diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 14144348d43..5318a4a19b8 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -175,8 +175,8 @@ mi_cmd_exec_continue (char *command, char **argv, int argc) void mi_cmd_exec_interrupt (char *command, char **argv, int argc) { - if (!target_executing) - error ("mi_cmd_exec_interrupt: Inferior not executing."); + if (!is_running (inferior_ptid)) + error ("mi_cmd_exec_interrupt: Inferior not running."); interrupt_target_command (NULL, 0); } @@ -1059,7 +1059,7 @@ mi_cmd_execute (struct mi_parse *parse) if (parse->cmd->argv_func != NULL) { - if (target_executing) + if (is_running (inferior_ptid)) { if (strcmp (parse->command, "exec-interrupt")) { @@ -1144,7 +1144,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc) if (target_can_async_p ()) { /* If we're not executing, an exception should have been throw. */ - gdb_assert (target_executing); + gdb_assert (is_running (inferior_ptid)); do_cleanups (old_cleanups); } else diff --git a/gdb/remote.c b/gdb/remote.c index e71c467b51a..4792cada24a 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -3232,13 +3232,6 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal) NOT asynchronously. */ if (target_can_async_p ()) target_async (inferior_event_handler, 0); - /* Tell the world that the target is now executing. */ - /* FIXME: cagney/1999-09-23: Is it the targets responsibility to set - this? Instead, should the client of target just assume (for - async targets) that the target is going to start executing? Is - this information already found in the continuation block? */ - if (target_is_async_p ()) - target_executing = 1; } diff --git a/gdb/stack.c b/gdb/stack.c index 3d78f740893..18c4298ed7f 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -43,6 +43,7 @@ #include "regcache.h" #include "solib.h" #include "valprint.h" +#include "gdbthread.h" #include "gdb_assert.h" #include @@ -1643,6 +1644,9 @@ get_selected_block (CORE_ADDR *addr_in_block) if (!target_has_stack) return 0; + if (is_executing (inferior_ptid)) + return 0; + return get_frame_block (get_selected_frame (NULL), addr_in_block); } diff --git a/gdb/target.c b/gdb/target.c index af430bdc215..6e7108035b9 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1787,8 +1787,8 @@ target_resume (ptid_t ptid, int step, enum target_signal signal) { dcache_invalidate (target_dcache); (*current_target.to_resume) (ptid, step, signal); + set_executing (ptid, 1); set_running (ptid, 1); - } /* Look through the list of possible targets for a target that can follow forks. */ diff --git a/gdb/thread.c b/gdb/thread.c index aa18228a59f..9bd5f04d23b 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -63,6 +63,9 @@ static void thread_apply_command (char *, int); static void restore_current_thread (ptid_t); static void prune_threads (void); +static int main_thread_running = 0; +static int main_thread_executing = 0; + void delete_step_resume_breakpoint (void *arg) { @@ -104,6 +107,9 @@ init_thread_list (void) struct thread_info *tp, *tpnext; highest_thread_num = 0; + main_thread_running = 0; + main_thread_executing = 0; + if (!thread_list) return; @@ -441,8 +447,6 @@ prune_threads (void) } } -static int main_thread_running = 0; - void set_running (ptid_t ptid, int running) { @@ -494,6 +498,9 @@ is_running (ptid_t ptid) { struct thread_info *tp; + if (!target_has_execution) + return 0; + if (!thread_list) return main_thread_running; @@ -502,6 +509,67 @@ is_running (ptid_t ptid) return tp->running_; } +int +any_running (void) +{ + struct thread_info *tp; + + if (!target_has_execution) + return 0; + + if (!thread_list) + return main_thread_running; + + for (tp = thread_list; tp; tp = tp->next) + if (tp->running_) + return 1; + + return 0; +} + +int +is_executing (ptid_t ptid) +{ + struct thread_info *tp; + + if (!target_has_execution) + return 0; + + if (!thread_list) + return main_thread_executing; + + tp = find_thread_pid (ptid); + gdb_assert (tp); + return tp->executing_; +} + +void +set_executing (ptid_t ptid, int executing) +{ + struct thread_info *tp; + + if (!thread_list) + { + /* This target does not add the main thread to the thread list. + Use a global flag to indicate that the thread is + executing. */ + main_thread_executing = executing; + return; + } + + if (PIDGET (ptid) == -1) + { + for (tp = thread_list; tp; tp = tp->next) + tp->executing_ = executing; + } + else + { + tp = find_thread_pid (ptid); + gdb_assert (tp); + tp->executing_ = executing; + } +} + /* Prints the list of threads and their details on UIOUT. This is a version of 'info_thread_command' suitable for use from MI. diff --git a/gdb/top.c b/gdb/top.c index 4f0c58d0f1d..84894346697 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -46,6 +46,7 @@ #include "gdb_assert.h" #include "main.h" #include "event-loop.h" +#include "gdbthread.h" /* readline include files */ #include "readline/readline.h" @@ -181,12 +182,6 @@ int remote_timeout = 2; int remote_debug = 0; -/* Non-zero means the target is running. 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 - target is off and running, which gdb is doing something else. */ -int target_executing = 0; - /* Sbrk location on entry to main. Used for statistics only. */ #ifdef HAVE_SBRK char *lim_at_start; @@ -422,7 +417,9 @@ execute_command (char *p, int from_tty) /* If the target is running, we allow only a limited set of commands. */ - if (target_can_async_p () && target_executing && !get_cmd_async_ok (c)) + if (target_can_async_p () + && any_running () + && !get_cmd_async_ok (c)) error (_("Cannot execute this command while the target is running.")); /* Pass null arg rather than an empty one. */ @@ -486,7 +483,7 @@ execute_command (char *p, int from_tty) /* FIXME: This should be cacheing the frame and only running when the frame changes. */ - if (!target_executing && target_has_stack) + if (target_has_stack && !is_running (inferior_ptid)) { flang = get_frame_language (); if (!warned -- 2.30.2