Implement MI notification for new threads.
* doc/observer.texi (new_thread): Document. * observer.sh: Forward declare struct thread_info. * thread.c (add_thread): Notify observer. * interps.h (interp_init_ftype): New parameter top_level. (interp_set): Likewise. (top_level_interpreter_data): Declare. * interps.c (interp_set): New parameter top_level. Pass it to interpreter's init function. Remember top level interpreter. (interpreter_exec_cmd): Adjust. (top_level_interpreter_data): New. * main.c (captured_main): Pass 1 for top_level parameter of interp_set. * cli/cli-interp.c (cli_interpreter_init): New parameter top_level. * tui/tui-interp.c (tui_init): New parameter top_level. * mi/mi-interp.c (mi_new_thread): New. (mi_interpreter_init): If top level, register observer for new threads. * Makefile.in (mi-interp.o, thread.o): Update dependencies.
This commit is contained in:
parent
0f2830ff5e
commit
683f2885af
|
@ -1,3 +1,31 @@
|
|||
2008-03-14 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
Implement MI notification for new threads.
|
||||
* doc/observer.texi (new_thread): Document.
|
||||
* observer.sh: Forward declare struct thread_info.
|
||||
* thread.c (add_thread): Notify observer.
|
||||
|
||||
* interps.h (interp_init_ftype): New parameter
|
||||
top_level.
|
||||
(interp_set): Likewise.
|
||||
(top_level_interpreter_data): Declare.
|
||||
* interps.c (interp_set): New parameter top_level.
|
||||
Pass it to interpreter's init function. Remember
|
||||
top level interpreter.
|
||||
(interpreter_exec_cmd): Adjust.
|
||||
(top_level_interpreter_data): New.
|
||||
* main.c (captured_main): Pass 1 for top_level
|
||||
parameter of interp_set.
|
||||
* cli/cli-interp.c (cli_interpreter_init): New
|
||||
parameter top_level.
|
||||
* tui/tui-interp.c (tui_init): New parameter top_level.
|
||||
|
||||
* mi/mi-interp.c (mi_new_thread): New.
|
||||
(mi_interpreter_init): If top level, register
|
||||
observer for new threads.
|
||||
|
||||
* Makefile.in (mi-interp.o, thread.o): Update dependencies.
|
||||
|
||||
2008-03-14 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* top.c (execute_command): Disable break and stop
|
||||
|
|
|
@ -2883,7 +2883,7 @@ target-memory.o: target-memory.c $(defs_h) $(vec_h) $(target_h) \
|
|||
thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
|
||||
$(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(exceptions_h) \
|
||||
$(command_h) $(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) \
|
||||
$(ui_out_h)
|
||||
$(ui_out_h) $(observer_h)
|
||||
top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \
|
||||
$(cli_script_h) $(cli_setshow_h) $(cli_decode_h) $(symtab_h) \
|
||||
$(inferior_h) $(exceptions_h) $(target_h) $(breakpoint_h) \
|
||||
|
@ -3228,7 +3228,7 @@ mi-getopt.o: $(srcdir)/mi/mi-getopt.c $(defs_h) $(mi_getopt_h) \
|
|||
mi-interp.o: $(srcdir)/mi/mi-interp.c $(defs_h) $(gdb_string_h) $(interps_h) \
|
||||
$(event_top_h) $(event_loop_h) $(inferior_h) $(ui_out_h) $(top_h) \
|
||||
$(exceptions_h) $(mi_main_h) $(mi_cmds_h) $(mi_out_h) \
|
||||
$(mi_console_h)
|
||||
$(mi_console_h) $(observer_h) $(gdbthread_h)
|
||||
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-interp.c
|
||||
mi-main.o: $(srcdir)/mi/mi-main.c $(defs_h) $(target_h) $(inferior_h) \
|
||||
$(gdb_string_h) $(exceptions_h) $(top_h) $(gdbthread_h) $(mi_cmds_h) \
|
||||
|
|
|
@ -43,7 +43,7 @@ struct captured_execute_command_args
|
|||
/* These implement the cli out interpreter: */
|
||||
|
||||
static void *
|
||||
cli_interpreter_init (void)
|
||||
cli_interpreter_init (int top_level)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -129,3 +129,7 @@ Called with @var{objfile} equal to @code{NULL} to indicate
|
|||
previously loaded symbol table data has now been invalidated.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void new_thread (struct thread_info *@var{t})
|
||||
The thread specified by @var{t} has been created.
|
||||
@end deftypefun
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ void _initialize_interpreter (void);
|
|||
|
||||
static struct interp *interp_list = NULL;
|
||||
static struct interp *current_interpreter = NULL;
|
||||
static struct interp *top_level_interpreter = NULL;
|
||||
|
||||
static int interpreter_initialized = 0;
|
||||
|
||||
|
@ -124,16 +125,27 @@ interp_add (struct interp *interp)
|
|||
init proc is successful, return 1, if it fails, set the old
|
||||
interpreter back in place and return 0. If we can't restore the
|
||||
old interpreter, then raise an internal error, since we are in
|
||||
pretty bad shape at this point. */
|
||||
pretty bad shape at this point.
|
||||
|
||||
The TOP_LEVEL parameter tells if this new interpreter is
|
||||
the top-level one. The top-level is what is requested
|
||||
on the command line, and is responsible for reporting general
|
||||
notification about target state changes. For example, if
|
||||
MI is the top-level interpreter, then it will always report
|
||||
events such as target stops and new thread creation, even if they
|
||||
are caused by CLI commands. */
|
||||
int
|
||||
interp_set (struct interp *interp)
|
||||
interp_set (struct interp *interp, int top_level)
|
||||
{
|
||||
struct interp *old_interp = current_interpreter;
|
||||
int first_time = 0;
|
||||
|
||||
|
||||
char buffer[64];
|
||||
|
||||
/* If we already have an interpreter, then trying to
|
||||
set top level interpreter is kinda pointless. */
|
||||
gdb_assert (!top_level || !current_interpreter);
|
||||
gdb_assert (!top_level || !top_level_interpreter);
|
||||
|
||||
if (current_interpreter != NULL)
|
||||
{
|
||||
do_all_continuations ();
|
||||
|
@ -152,6 +164,8 @@ interp_set (struct interp *interp)
|
|||
}
|
||||
|
||||
current_interpreter = interp;
|
||||
if (top_level)
|
||||
top_level_interpreter = interp;
|
||||
|
||||
/* We use interpreter_p for the "set interpreter" variable, so we need
|
||||
to make sure we have a malloc'ed copy for the set command to free. */
|
||||
|
@ -171,7 +185,7 @@ interp_set (struct interp *interp)
|
|||
{
|
||||
if (interp->procs->init_proc != NULL)
|
||||
{
|
||||
interp->data = interp->procs->init_proc ();
|
||||
interp->data = interp->procs->init_proc (top_level);
|
||||
}
|
||||
interp->inited = 1;
|
||||
}
|
||||
|
@ -182,7 +196,7 @@ interp_set (struct interp *interp)
|
|||
if (interp->procs->resume_proc != NULL
|
||||
&& (!interp->procs->resume_proc (interp->data)))
|
||||
{
|
||||
if (old_interp == NULL || !interp_set (old_interp))
|
||||
if (old_interp == NULL || !interp_set (old_interp, 0))
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Failed to initialize new interp \"%s\" %s"),
|
||||
interp->name, "and could not restore old interp!\n");
|
||||
|
@ -390,7 +404,7 @@ interpreter_exec_cmd (char *args, int from_tty)
|
|||
old_quiet = interp_set_quiet (old_interp, 1);
|
||||
use_quiet = interp_set_quiet (interp_to_use, 1);
|
||||
|
||||
if (!interp_set (interp_to_use))
|
||||
if (!interp_set (interp_to_use, 0))
|
||||
error (_("Could not switch to interpreter \"%s\"."), prules[0]);
|
||||
|
||||
for (i = 1; i < nrules; i++)
|
||||
|
@ -398,14 +412,14 @@ interpreter_exec_cmd (char *args, int from_tty)
|
|||
struct gdb_exception e = interp_exec (interp_to_use, prules[i]);
|
||||
if (e.reason < 0)
|
||||
{
|
||||
interp_set (old_interp);
|
||||
interp_set (old_interp, 0);
|
||||
interp_set_quiet (interp_to_use, use_quiet);
|
||||
interp_set_quiet (old_interp, old_quiet);
|
||||
error (_("error in command: \"%s\"."), prules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
interp_set (old_interp);
|
||||
interp_set (old_interp, 0);
|
||||
interp_set_quiet (interp_to_use, use_quiet);
|
||||
interp_set_quiet (old_interp, old_quiet);
|
||||
}
|
||||
|
@ -462,6 +476,13 @@ interpreter_completer (char *text, char *word)
|
|||
return matches;
|
||||
}
|
||||
|
||||
extern void *
|
||||
top_level_interpreter_data (void)
|
||||
{
|
||||
gdb_assert (top_level_interpreter);
|
||||
return top_level_interpreter->data;
|
||||
}
|
||||
|
||||
/* This just adds the "interpreter-exec" command. */
|
||||
void
|
||||
_initialize_interpreter (void)
|
||||
|
|
|
@ -35,7 +35,7 @@ extern struct gdb_exception interp_exec (struct interp *interp,
|
|||
const char *command);
|
||||
extern int interp_quiet_p (struct interp *interp);
|
||||
|
||||
typedef void *(interp_init_ftype) (void);
|
||||
typedef void *(interp_init_ftype) (int top_level);
|
||||
typedef int (interp_resume_ftype) (void *data);
|
||||
typedef int (interp_suspend_ftype) (void *data);
|
||||
typedef int (interp_prompt_p_ftype) (void *data);
|
||||
|
@ -57,13 +57,15 @@ extern struct interp *interp_new (const char *name, void *data,
|
|||
struct ui_out *uiout,
|
||||
const struct interp_procs *procs);
|
||||
extern void interp_add (struct interp *interp);
|
||||
extern int interp_set (struct interp *interp);
|
||||
extern int interp_set (struct interp *interp, int top_level);
|
||||
extern struct interp *interp_lookup (const char *name);
|
||||
extern struct ui_out *interp_ui_out (struct interp *interp);
|
||||
|
||||
extern int current_interp_named_p (const char *name);
|
||||
extern int current_interp_display_prompt_p (void);
|
||||
extern void current_interp_command_loop (void);
|
||||
/* Returns opaque data associated with the top-level interpreter. */
|
||||
extern void *top_level_interpreter_data (void);
|
||||
|
||||
extern void clear_interpreter_hooks (void);
|
||||
|
||||
|
|
|
@ -649,7 +649,7 @@ Excess command line arguments ignored. (%s%s)\n"),
|
|||
if (interp == NULL)
|
||||
error (_("Interpreter `%s' unrecognized"), interpreter_p);
|
||||
/* Install it. */
|
||||
if (!interp_set (interp))
|
||||
if (!interp_set (interp, 1))
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"Interpreter `%s' failed to initialize.\n",
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "mi-cmds.h"
|
||||
#include "mi-out.h"
|
||||
#include "mi-console.h"
|
||||
#include "observer.h"
|
||||
#include "gdbthread.h"
|
||||
|
||||
struct mi_interp
|
||||
{
|
||||
|
@ -64,8 +66,10 @@ static void mi1_command_loop (void);
|
|||
static void mi_insert_notify_hooks (void);
|
||||
static void mi_remove_notify_hooks (void);
|
||||
|
||||
static void mi_new_thread (struct thread_info *t);
|
||||
|
||||
static void *
|
||||
mi_interpreter_init (void)
|
||||
mi_interpreter_init (int top_level)
|
||||
{
|
||||
struct mi_interp *mi = XMALLOC (struct mi_interp);
|
||||
|
||||
|
@ -83,6 +87,9 @@ mi_interpreter_init (void)
|
|||
mi->targ = mi_console_file_new (raw_stdout, "@", '"');
|
||||
mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
|
||||
|
||||
if (top_level)
|
||||
observer_attach_new_thread (mi_new_thread);
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
|
@ -314,6 +321,15 @@ mi_command_loop (int mi_version)
|
|||
start_event_loop ();
|
||||
}
|
||||
|
||||
static void
|
||||
mi_new_thread (struct thread_info *t)
|
||||
{
|
||||
struct mi_interp *mi = top_level_interpreter_data ();
|
||||
|
||||
fprintf_unfiltered (mi->event_channel, "thread-created,id=%d", t->num);
|
||||
gdb_flush (mi->event_channel);
|
||||
}
|
||||
|
||||
extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
|
|
|
@ -62,6 +62,7 @@ struct observer;
|
|||
struct bpstats;
|
||||
struct so_list;
|
||||
struct objfile;
|
||||
struct thread_info;
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include "ui-out.h"
|
||||
#include "observer.h"
|
||||
|
||||
/* Definition of struct thread_info exported to gdbthread.h */
|
||||
|
||||
|
@ -137,6 +138,8 @@ add_thread (ptid_t ptid)
|
|||
|
||||
if (print_thread_events)
|
||||
printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
|
||||
|
||||
observer_notify_new_thread (result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ tui_exit (void)
|
|||
/* These implement the TUI interpreter. */
|
||||
|
||||
static void *
|
||||
tui_init (void)
|
||||
tui_init (int top_level)
|
||||
{
|
||||
/* Install exit handler to leave the screen in a good shape. */
|
||||
atexit (tui_exit);
|
||||
|
|
Loading…
Reference in New Issue