Remove global continuations in favour of a per-thread

continuations.

	* gdbthread.h (struct thread_info): Add comments around
	continuations and intermediate_continuations.
	(save_infrun_state, load_infrun_state): Delete continuations and
	intermediate_continuations arguments.
	* infrun.c (fetch_inferior_event): Only call normal_stop if
	stop_soon is NO_STOP_QUIETLY.
	(context_switch): Don't context-switch the continuations.
	* thread.c (clear_thread_inferior_resources): Discard all
	continuations of the thread we're clearing.
	(save_infrun_state, load_infrun_state): Delete continuations and
	intermediate_continuations arguments, and the code referencing
	them.
	* utils.c: Include "gdbthread.h".
	(cmd_continuation, intermediate_continuation): Delete.
	(add_continuation): Add thread_info* argument.  Install the
	continuation on it.
	(restore_thread_cleanup): New.
	(do_all_continuations_ptid, do_all_continuations_thread_callback):
	New.
	(do_all_continuations): Reimplement.
	(discard_all_continuations_thread_callback,
	discard_all_continuations_thread): New.
	(discard_all_continuations): Reimplement.
	(add_intermediate_continuation): Add thread_info* argument.
	Install the continuation on it.
	(do_all_intermediate_continuations_thread_callback)
	(do_all_intermediate_continuations_thread): New.
	(do_all_intermediate_continuations): Reimplement.
	(discard_all_intermediate_continuations_thread_callback): New.
	(discard_all_intermediate_continuations_thread): New.
	(discard_all_intermediate_continuations): Reimplement.

	* breakpoint.c (until_break_command): Install the continuation on
	the current thread.

	* defs.h (cmd_continuation, intermediate_continuation): Delete.
	(struct thread_info): Forward declare.
	(add_continuation, add_intermediate_continuation): Add
	thread_info* argument.
	(do_all_continuations_thread, discard_all_continuations_thread)
	(do_all_intermediate_continuations_thread)
	(discard_all_intermediate_continuations_thread): Declare.
	* inf-loop.c (inferior_event_handler): In non-stop only run
	continuations on the thread that stopped.  In all-stop, run
	continuations on all threads.
	* infcmd.c (step_once, finish_command): Adjust.
This commit is contained in:
Pedro Alves 2008-09-08 21:57:42 +00:00
parent 414c69f7a7
commit 95e54da724
8 changed files with 239 additions and 101 deletions

View File

@ -1,3 +1,55 @@
2008-09-08 Pedro Alves <pedro@codesourcery.com>
Remove global continuations in favour of a per-thread
continuations.
* gdbthread.h (struct thread_info): Add comments around
continuations and intermediate_continuations.
(save_infrun_state, load_infrun_state): Delete continuations and
intermediate_continuations arguments.
* infrun.c (fetch_inferior_event): Only call normal_stop if
stop_soon is NO_STOP_QUIETLY.
(context_switch): Don't context-switch the continuations.
* thread.c (clear_thread_inferior_resources): Discard all
continuations of the thread we're clearing.
(save_infrun_state, load_infrun_state): Delete continuations and
intermediate_continuations arguments, and the code referencing
them.
* utils.c: Include "gdbthread.h".
(cmd_continuation, intermediate_continuation): Delete.
(add_continuation): Add thread_info* argument. Install the
continuation on it.
(restore_thread_cleanup): New.
(do_all_continuations_ptid, do_all_continuations_thread_callback):
New.
(do_all_continuations): Reimplement.
(discard_all_continuations_thread_callback,
discard_all_continuations_thread): New.
(discard_all_continuations): Reimplement.
(add_intermediate_continuation): Add thread_info* argument.
Install the continuation on it.
(do_all_intermediate_continuations_thread_callback)
(do_all_intermediate_continuations_thread): New.
(do_all_intermediate_continuations): Reimplement.
(discard_all_intermediate_continuations_thread_callback): New.
(discard_all_intermediate_continuations_thread): New.
(discard_all_intermediate_continuations): Reimplement.
* breakpoint.c (until_break_command): Install the continuation on
the current thread.
* defs.h (cmd_continuation, intermediate_continuation): Delete.
(struct thread_info): Forward declare.
(add_continuation, add_intermediate_continuation): Add
thread_info* argument.
(do_all_continuations_thread, discard_all_continuations_thread)
(do_all_intermediate_continuations_thread)
(discard_all_intermediate_continuations_thread): Declare.
* inf-loop.c (inferior_event_handler): In non-stop only run
continuations on the thread that stopped. In all-stop, run
continuations on all threads.
* infcmd.c (step_once, finish_command): Adjust.
2008-09-08 Pedro Alves <pedro@codesourcery.com>
Remove the global stop_step in favour of a per-thread

View File

@ -6320,7 +6320,8 @@ until_break_command (char *arg, int from_tty, int anywhere)
args->breakpoint2 = breakpoint2;
discard_cleanups (old_chain);
add_continuation (until_break_command_continuation, args,
add_continuation (inferior_thread (),
until_break_command_continuation, args,
xfree);
}
else

View File

@ -681,22 +681,24 @@ extern void free_command_lines (struct command_line **);
when opening an extended-remote connection. */
struct continuation;
/* In infrun.c. */
extern struct continuation *cmd_continuation;
/* Used only by the step_1 function. */
extern struct continuation *intermediate_continuation;
struct thread_info;
/* From utils.c */
extern void add_continuation (void (*)(void *), void *,
extern void add_continuation (struct thread_info *,
void (*)(void *), void *,
void (*)(void *));
extern void do_all_continuations (void);
extern void do_all_continuations_thread (struct thread_info *);
extern void discard_all_continuations (void);
extern void discard_all_continuations_thread (struct thread_info *);
extern void add_intermediate_continuation (void (*)(void *), void *,
extern void add_intermediate_continuation (struct thread_info *,
void (*)(void *), void *,
void (*)(void *));
extern void do_all_intermediate_continuations (void);
extern void do_all_intermediate_continuations_thread (struct thread_info *);
extern void discard_all_intermediate_continuations (void);
extern void discard_all_intermediate_continuations_thread (struct thread_info *);
/* String containing the current directory (what getwd would return). */

View File

@ -136,9 +136,16 @@ struct thread_info
when we finally do stop stepping. */
bpstat stepping_through_solib_catchpoints;
/* The below are only per-thread in non-stop mode. */
/* Per-thread command support. */
/* Pointer to what is left to do for an execution command after the
target stops. Used only in asynchronous mode, by targets that
support async execution. Several execution commands use it. */
struct continuation *continuations;
/* Similar to the above, but used when a single execution command
requires several resume/stop iterations. Used by the step
command. */
struct continuation *intermediate_continuations;
/* Nonzero if the thread is being proceeded for a "finish" command
@ -226,15 +233,11 @@ extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
extern int thread_count (void);
/* infrun context switch: save the debugger state for the given thread. */
extern void save_infrun_state (ptid_t ptid,
struct continuation *continuations,
struct continuation *intermediate_continuations);
extern void save_infrun_state (ptid_t ptid);
/* infrun context switch: load the debugger state previously saved
for the given thread. */
extern void load_infrun_state (ptid_t ptid,
struct continuation **continuations,
struct continuation **intermediate_continuations);
extern void load_infrun_state (ptid_t ptid);
/* Switch from one thread to another. */
extern void switch_to_thread (ptid_t ptid);

View File

@ -98,13 +98,23 @@ inferior_event_handler (enum inferior_event_type event_type,
touch the inferior memory, e.g. to remove breakpoints, so run
them before running breakpoint commands, which may resume the
target. */
do_all_intermediate_continuations ();
if (non_stop
&& target_has_execution
&& !ptid_equal (inferior_ptid, null_ptid))
do_all_intermediate_continuations_thread (inferior_thread ());
else
do_all_intermediate_continuations ();
/* Always finish the previous command before running any
breakpoint commands. Any stop cancels the previous command.
E.g. a "finish" or "step-n" command interrupted by an
unrelated breakpoint is canceled. */
do_all_continuations ();
if (non_stop
&& target_has_execution
&& !ptid_equal (inferior_ptid, null_ptid))
do_all_continuations_thread (inferior_thread ());
else
do_all_continuations ();
if (current_language != expected_language
&& language_mode == language_mode_auto)
@ -125,7 +135,11 @@ inferior_event_handler (enum inferior_event_type event_type,
case INF_EXEC_CONTINUE:
/* Is there anything left to do for the command issued to
complete? */
do_all_intermediate_continuations ();
if (non_stop)
do_all_intermediate_continuations_thread (inferior_thread ());
else
do_all_intermediate_continuations ();
break;
case INF_QUIT_REQ:

View File

@ -947,7 +947,7 @@ which has no line number information.\n"), name);
if (skip_subroutines)
tp->step_over_calls = STEP_OVER_ALL;
inferior_thread ()->step_multi = (count > 1);
tp->step_multi = (count > 1);
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
args = xmalloc (sizeof (*args));
@ -955,7 +955,7 @@ which has no line number information.\n"), name);
args->single_inst = single_inst;
args->count = count;
args->thread = thread;
add_intermediate_continuation (step_1_continuation, args, xfree);
add_intermediate_continuation (tp, step_1_continuation, args, xfree);
}
}
@ -1440,7 +1440,7 @@ finish_command (char *arg, int from_tty)
cargs->breakpoint = breakpoint;
cargs->function = function;
add_continuation (finish_command_continuation, cargs,
add_continuation (tp, finish_command_continuation, cargs,
finish_command_continuation_free_arg);
discard_cleanups (old_chain);
@ -2103,7 +2103,8 @@ attach_command (char *args, int from_tty)
a->args = xstrdup (args);
a->from_tty = from_tty;
a->async_exec = async_exec;
add_continuation (attach_command_continuation, a,
add_continuation (inferior_thread (),
attach_command_continuation, a,
attach_command_continuation_free_args);
return;
}

View File

@ -106,6 +106,9 @@ clear_thread_inferior_resources (struct thread_info *tp)
}
bpstat_clear (&tp->stop_bpstat);
discard_all_intermediate_continuations_thread (tp);
discard_all_continuations_thread (tp);
}
static void
@ -442,9 +445,7 @@ gdb_list_thread_ids (struct ui_out *uiout, char **error_message)
/* Load infrun state for the thread PID. */
void
load_infrun_state (ptid_t ptid,
struct continuation **continuations,
struct continuation **intermediate_continuations)
load_infrun_state (ptid_t ptid)
{
struct thread_info *tp;
@ -453,24 +454,12 @@ load_infrun_state (ptid_t ptid,
tp = find_thread_id (pid_to_thread_id (ptid));
if (tp == NULL)
return;
/* In all-stop mode, these are global state, while in non-stop mode,
they are per thread. */
if (non_stop)
{
*continuations = tp->continuations;
tp->continuations = NULL;
*intermediate_continuations = tp->intermediate_continuations;
tp->intermediate_continuations = NULL;
}
}
/* Save infrun state for the thread PID. */
void
save_infrun_state (ptid_t ptid,
struct continuation *continuations,
struct continuation *intermediate_continuations)
save_infrun_state (ptid_t ptid)
{
struct thread_info *tp;
@ -479,14 +468,6 @@ save_infrun_state (ptid_t ptid,
tp = find_thread_id (pid_to_thread_id (ptid));
if (tp == NULL)
return;
/* In all-stop mode, these are global state, while in non-stop mode,
they are per thread. */
if (non_stop)
{
tp->continuations = continuations;
tp->intermediate_continuations = intermediate_continuations;
}
}
/* Return true if TP is an active thread. */

View File

@ -25,6 +25,7 @@
#include "gdb_string.h"
#include "event-top.h"
#include "exceptions.h"
#include "gdbthread.h"
#ifdef TUI
#include "tui/tui.h" /* For tui_get_command_dimension. */
@ -105,13 +106,6 @@ static int debug_timestamp = 0;
static struct cleanup *cleanup_chain; /* cleaned up after a failed command */
static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */
/* Pointer to what is left to do for an execution command after the
target stops. Used only in asynchronous mode, by targets that
support async execution. The finish and until commands use it. So
does the target extended-remote command. */
struct continuation *cmd_continuation;
struct continuation *intermediate_continuation;
/* Nonzero if we have job control. */
int job_control;
@ -477,14 +471,14 @@ struct continuation
struct cleanup base;
};
/* Add a continuation to the continuation list, the global list
cmd_continuation. The new continuation will be added at the
front. */
/* Add a continuation to the continuation list of THREAD. The new
continuation will be added at the front. */
void
add_continuation (void (*continuation_hook) (void *), void *args,
add_continuation (struct thread_info *thread,
void (*continuation_hook) (void *), void *args,
void (*continuation_free_args) (void *))
{
struct cleanup *as_cleanup = &cmd_continuation->base;
struct cleanup *as_cleanup = &thread->continuations->base;
make_cleanup_ftype *continuation_hook_fn = continuation_hook;
make_my_cleanup2 (&as_cleanup,
@ -492,53 +486,122 @@ add_continuation (void (*continuation_hook) (void *), void *args,
args,
continuation_free_args);
cmd_continuation = (struct continuation *) as_cleanup;
thread->continuations = (struct continuation *) as_cleanup;
}
/* Walk down the cmd_continuation list, and execute all the
continuations. There is a problem though. In some cases new
continuations may be added while we are in the middle of this
loop. If this happens they will be added in the front, and done
before we have a chance of exhausting those that were already
there. We need to then save the beginning of the list in a pointer
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer. */
void
do_all_continuations (void)
static void
restore_thread_cleanup (void *arg)
{
struct cleanup *continuation_ptr;
ptid_t *ptid_p = arg;
switch_to_thread (*ptid_p);
}
/* Walk down the continuation list of PTID, and execute all the
continuations. There is a problem though. In some cases new
continuations may be added while we are in the middle of this loop.
If this happens they will be added in the front, and done before we
have a chance of exhausting those that were already there. We need
to then save the beginning of the list in a pointer and do the
continuations from there on, instead of using the global beginning
of list as our iteration pointer. */
static void
do_all_continuations_ptid (ptid_t ptid,
struct continuation **continuations_p)
{
struct cleanup *old_chain;
ptid_t current_thread;
struct cleanup *as_cleanup;
if (*continuations_p == NULL)
return;
current_thread = inferior_ptid;
/* Restore selected thread on exit. Don't try to restore the frame
as well, because:
- When running continuations, the selected frame is always #0.
- The continuations may trigger symbol file loads, which may
change the frame layout (frame ids change), which would trigger
a warning if we used make_cleanup_restore_current_thread. */
old_chain = make_cleanup (restore_thread_cleanup, &current_thread);
/* Let the continuation see this thread as selected. */
switch_to_thread (ptid);
/* Copy the list header into another pointer, and set the global
list header to null, so that the global list can change as a side
effect of invoking the continuations and the processing of the
preexisting continuations will not be affected. */
continuation_ptr = &cmd_continuation->base;
cmd_continuation = NULL;
as_cleanup = &(*continuations_p)->base;
*continuations_p = NULL;
/* Work now on the list we have set aside. */
do_my_cleanups (&continuation_ptr, NULL);
do_my_cleanups (&as_cleanup, NULL);
do_cleanups (old_chain);
}
/* Walk down the cmd_continuation list, and get rid of all the
continuations. */
/* Callback for iterate over threads. */
static int
do_all_continuations_thread_callback (struct thread_info *thread, void *data)
{
do_all_continuations_ptid (thread->ptid, &thread->continuations);
return 0;
}
/* Do all continuations of thread THREAD. */
void
do_all_continuations_thread (struct thread_info *thread)
{
do_all_continuations_thread_callback (thread, NULL);
}
/* Do all continuations of all threads. */
void
do_all_continuations (void)
{
iterate_over_threads (do_all_continuations_thread_callback, NULL);
}
/* Callback for iterate over threads. */
static int
discard_all_continuations_thread_callback (struct thread_info *thread,
void *data)
{
struct cleanup *continuation_ptr = &thread->continuations->base;
discard_my_cleanups (&continuation_ptr, NULL);
thread->continuations = NULL;
return 0;
}
/* Get rid of all the continuations of THREAD. */
void
discard_all_continuations_thread (struct thread_info *thread)
{
discard_all_continuations_thread_callback (thread, NULL);
}
/* Get rid of all the continuations of all threads. */
void
discard_all_continuations (void)
{
struct cleanup *continuation_ptr = &cmd_continuation->base;
discard_my_cleanups (&continuation_ptr, NULL);
cmd_continuation = NULL;
iterate_over_threads (discard_all_continuations_thread_callback, NULL);
}
/* Add a continuation to the continuation list, the global list
intermediate_continuation. The new continuation will be added at
the front. */
/* Add a continuation to the intermediate continuation list of THREAD.
The new continuation will be added at the front. */
void
add_intermediate_continuation (void (*continuation_hook)
add_intermediate_continuation (struct thread_info *thread,
void (*continuation_hook)
(void *), void *args,
void (*continuation_free_args) (void *))
{
struct cleanup *as_cleanup = &intermediate_continuation->base;
struct cleanup *as_cleanup = &thread->intermediate_continuations->base;
make_cleanup_ftype *continuation_hook_fn = continuation_hook;
make_my_cleanup2 (&as_cleanup,
@ -546,7 +609,7 @@ add_intermediate_continuation (void (*continuation_hook)
args,
continuation_free_args);
intermediate_continuation = (struct continuation *) as_cleanup;
thread->intermediate_continuations = (struct continuation *) as_cleanup;
}
/* Walk down the cmd_continuation list, and execute all the
@ -557,31 +620,52 @@ add_intermediate_continuation (void (*continuation_hook)
there. We need to then save the beginning of the list in a pointer
and do the continuations from there on, instead of using the
global beginning of list as our iteration pointer.*/
static int
do_all_intermediate_continuations_thread_callback (struct thread_info *thread,
void *data)
{
do_all_continuations_ptid (thread->ptid,
&thread->intermediate_continuations);
return 0;
}
/* Do all intermediate continuations of thread THREAD. */
void
do_all_intermediate_continuations_thread (struct thread_info *thread)
{
do_all_intermediate_continuations_thread_callback (thread, NULL);
}
/* Do all intermediate continuations of all threads. */
void
do_all_intermediate_continuations (void)
{
struct cleanup *continuation_ptr;
/* Copy the list header into another pointer, and set the global
list header to null, so that the global list can change as a side
effect of invoking the continuations and the processing of the
preexisting continuations will not be affected. */
continuation_ptr = &intermediate_continuation->base;
intermediate_continuation = NULL;
/* Work now on the list we have set aside. */
do_my_cleanups (&continuation_ptr, NULL);
iterate_over_threads (do_all_intermediate_continuations_thread_callback, NULL);
}
/* Walk down the cmd_continuation list, and get rid of all the
continuations. */
/* Callback for iterate over threads. */
static int
discard_all_intermediate_continuations_thread_callback (struct thread_info *thread,
void *data)
{
struct cleanup *continuation_ptr = &thread->intermediate_continuations->base;
discard_my_cleanups (&continuation_ptr, NULL);
thread->intermediate_continuations = NULL;
return 0;
}
/* Get rid of all the intermediate continuations of THREAD. */
void
discard_all_intermediate_continuations_thread (struct thread_info *thread)
{
discard_all_intermediate_continuations_thread_callback (thread, NULL);
}
/* Get rid of all the intermediate continuations of all threads. */
void
discard_all_intermediate_continuations (void)
{
struct cleanup *continuation_ptr = &intermediate_continuation->base;
discard_my_cleanups (&continuation_ptr, NULL);
continuation_ptr = NULL;
iterate_over_threads (discard_all_intermediate_continuations_thread_callback, NULL);
}