* 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 <pedro@codesourcery.com>
+
+ 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 <pedro@codesourcery.com>
* symfile.c (load_command): Reopen the exec file and reread
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)
$(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)
$(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)
$(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) \
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));
#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"
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
/* 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);
#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);
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 =
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. */
{
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,
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);
}
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;
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;
};
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;
#include "remote.h"
#include "exceptions.h"
#include "language.h"
+#include "gdbthread.h"
static int fetch_inferior_event_wrapper (gdb_client_data client_data);
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. */
/* 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);
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. */
&& 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:
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. */
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);
}
if (parse->cmd->argv_func != NULL)
{
- if (target_executing)
+ if (is_running (inferior_ptid))
{
if (strcmp (parse->command, "exec-interrupt"))
{
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
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;
}
\f
#include "regcache.h"
#include "solib.h"
#include "valprint.h"
+#include "gdbthread.h"
#include "gdb_assert.h"
#include <ctype.h>
if (!target_has_stack)
return 0;
+ if (is_executing (inferior_ptid))
+ return 0;
+
return get_frame_block (get_selected_frame (NULL), addr_in_block);
}
{
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. */
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)
{
struct thread_info *tp, *tpnext;
highest_thread_num = 0;
+ main_thread_running = 0;
+ main_thread_executing = 0;
+
if (!thread_list)
return;
}
}
-static int main_thread_running = 0;
-
void
set_running (ptid_t ptid, int running)
{
{
struct thread_info *tp;
+ if (!target_has_execution)
+ return 0;
+
if (!thread_list)
return main_thread_running;
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.
#include "gdb_assert.h"
#include "main.h"
#include "event-loop.h"
+#include "gdbthread.h"
/* readline include files */
#include "readline/readline.h"
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;
/* 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. */
/* 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