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).
This commit is contained in:
Pedro Alves 2008-07-09 22:16:15 +00:00
parent 4487aabf2e
commit 8ea051c51f
16 changed files with 199 additions and 58 deletions

View File

@ -1,3 +1,50 @@
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

View File

@ -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) \

View File

@ -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));

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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,7 +114,7 @@ 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)
{

View File

@ -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. */

View File

@ -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:

View File

@ -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);
}
}
/* Issue kill to specified lwp. */

View File

@ -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

View File

@ -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;
}

View File

@ -43,6 +43,7 @@
#include "regcache.h"
#include "solib.h"
#include "valprint.h"
#include "gdbthread.h"
#include "gdb_assert.h"
#include <ctype.h>
@ -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);
}

View File

@ -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. */

View File

@ -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.

View File

@ -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