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:
parent
414c69f7a7
commit
95e54da724
@ -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
|
||||
|
@ -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
|
||||
|
16
gdb/defs.h
16
gdb/defs.h
@ -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). */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
29
gdb/thread.c
29
gdb/thread.c
@ -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. */
|
||||
|
194
gdb/utils.c
194
gdb/utils.c
@ -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, ¤t_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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user