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:
Vladimir Prus
2008-03-14 17:21:08 +00:00
parent 0f2830ff5e
commit 683f2885af
11 changed files with 92 additions and 17 deletions

View File

@ -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> 2008-03-14 Pedro Alves <pedro@codesourcery.com>
* top.c (execute_command): Disable break and stop * top.c (execute_command): Disable break and stop

View File

@ -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) \ thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
$(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(exceptions_h) \ $(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(exceptions_h) \
$(command_h) $(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_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) \ 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) \ $(cli_script_h) $(cli_setshow_h) $(cli_decode_h) $(symtab_h) \
$(inferior_h) $(exceptions_h) $(target_h) $(breakpoint_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) \ 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) \ $(event_top_h) $(event_loop_h) $(inferior_h) $(ui_out_h) $(top_h) \
$(exceptions_h) $(mi_main_h) $(mi_cmds_h) $(mi_out_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 $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-interp.c
mi-main.o: $(srcdir)/mi/mi-main.c $(defs_h) $(target_h) $(inferior_h) \ 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) \ $(gdb_string_h) $(exceptions_h) $(top_h) $(gdbthread_h) $(mi_cmds_h) \

View File

@ -43,7 +43,7 @@ struct captured_execute_command_args
/* These implement the cli out interpreter: */ /* These implement the cli out interpreter: */
static void * static void *
cli_interpreter_init (void) cli_interpreter_init (int top_level)
{ {
return NULL; return NULL;
} }

View File

@ -129,3 +129,7 @@ Called with @var{objfile} equal to @code{NULL} to indicate
previously loaded symbol table data has now been invalidated. previously loaded symbol table data has now been invalidated.
@end deftypefun @end deftypefun
@deftypefun void new_thread (struct thread_info *@var{t})
The thread specified by @var{t} has been created.
@end deftypefun

View File

@ -81,6 +81,7 @@ void _initialize_interpreter (void);
static struct interp *interp_list = NULL; static struct interp *interp_list = NULL;
static struct interp *current_interpreter = NULL; static struct interp *current_interpreter = NULL;
static struct interp *top_level_interpreter = NULL;
static int interpreter_initialized = 0; 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 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 interpreter back in place and return 0. If we can't restore the
old interpreter, then raise an internal error, since we are in 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 int
interp_set (struct interp *interp) interp_set (struct interp *interp, int top_level)
{ {
struct interp *old_interp = current_interpreter; struct interp *old_interp = current_interpreter;
int first_time = 0; int first_time = 0;
char buffer[64]; 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) if (current_interpreter != NULL)
{ {
do_all_continuations (); do_all_continuations ();
@ -152,6 +164,8 @@ interp_set (struct interp *interp)
} }
current_interpreter = interp; current_interpreter = interp;
if (top_level)
top_level_interpreter = interp;
/* We use interpreter_p for the "set interpreter" variable, so we need /* 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. */ 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) if (interp->procs->init_proc != NULL)
{ {
interp->data = interp->procs->init_proc (); interp->data = interp->procs->init_proc (top_level);
} }
interp->inited = 1; interp->inited = 1;
} }
@ -182,7 +196,7 @@ interp_set (struct interp *interp)
if (interp->procs->resume_proc != NULL if (interp->procs->resume_proc != NULL
&& (!interp->procs->resume_proc (interp->data))) && (!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__, internal_error (__FILE__, __LINE__,
_("Failed to initialize new interp \"%s\" %s"), _("Failed to initialize new interp \"%s\" %s"),
interp->name, "and could not restore old interp!\n"); 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); old_quiet = interp_set_quiet (old_interp, 1);
use_quiet = interp_set_quiet (interp_to_use, 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]); error (_("Could not switch to interpreter \"%s\"."), prules[0]);
for (i = 1; i < nrules; i++) 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]); struct gdb_exception e = interp_exec (interp_to_use, prules[i]);
if (e.reason < 0) if (e.reason < 0)
{ {
interp_set (old_interp); interp_set (old_interp, 0);
interp_set_quiet (interp_to_use, use_quiet); interp_set_quiet (interp_to_use, use_quiet);
interp_set_quiet (old_interp, old_quiet); interp_set_quiet (old_interp, old_quiet);
error (_("error in command: \"%s\"."), prules[i]); 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 (interp_to_use, use_quiet);
interp_set_quiet (old_interp, old_quiet); interp_set_quiet (old_interp, old_quiet);
} }
@ -462,6 +476,13 @@ interpreter_completer (char *text, char *word)
return matches; 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. */ /* This just adds the "interpreter-exec" command. */
void void
_initialize_interpreter (void) _initialize_interpreter (void)

View File

@ -35,7 +35,7 @@ extern struct gdb_exception interp_exec (struct interp *interp,
const char *command); const char *command);
extern int interp_quiet_p (struct interp *interp); 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_resume_ftype) (void *data);
typedef int (interp_suspend_ftype) (void *data); typedef int (interp_suspend_ftype) (void *data);
typedef int (interp_prompt_p_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, struct ui_out *uiout,
const struct interp_procs *procs); const struct interp_procs *procs);
extern void interp_add (struct interp *interp); 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 interp *interp_lookup (const char *name);
extern struct ui_out *interp_ui_out (struct interp *interp); extern struct ui_out *interp_ui_out (struct interp *interp);
extern int current_interp_named_p (const char *name); extern int current_interp_named_p (const char *name);
extern int current_interp_display_prompt_p (void); extern int current_interp_display_prompt_p (void);
extern void current_interp_command_loop (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); extern void clear_interpreter_hooks (void);

View File

@ -649,7 +649,7 @@ Excess command line arguments ignored. (%s%s)\n"),
if (interp == NULL) if (interp == NULL)
error (_("Interpreter `%s' unrecognized"), interpreter_p); error (_("Interpreter `%s' unrecognized"), interpreter_p);
/* Install it. */ /* Install it. */
if (!interp_set (interp)) if (!interp_set (interp, 1))
{ {
fprintf_unfiltered (gdb_stderr, fprintf_unfiltered (gdb_stderr,
"Interpreter `%s' failed to initialize.\n", "Interpreter `%s' failed to initialize.\n",

View File

@ -31,6 +31,8 @@
#include "mi-cmds.h" #include "mi-cmds.h"
#include "mi-out.h" #include "mi-out.h"
#include "mi-console.h" #include "mi-console.h"
#include "observer.h"
#include "gdbthread.h"
struct mi_interp struct mi_interp
{ {
@ -64,8 +66,10 @@ static void mi1_command_loop (void);
static void mi_insert_notify_hooks (void); static void mi_insert_notify_hooks (void);
static void mi_remove_notify_hooks (void); static void mi_remove_notify_hooks (void);
static void mi_new_thread (struct thread_info *t);
static void * static void *
mi_interpreter_init (void) mi_interpreter_init (int top_level)
{ {
struct mi_interp *mi = XMALLOC (struct mi_interp); 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->targ = mi_console_file_new (raw_stdout, "@", '"');
mi->event_channel = mi_console_file_new (raw_stdout, "=", 0); mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
if (top_level)
observer_attach_new_thread (mi_new_thread);
return mi; return mi;
} }
@ -314,6 +321,15 @@ mi_command_loop (int mi_version)
start_event_loop (); 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 */ extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
void void

View File

@ -62,6 +62,7 @@ struct observer;
struct bpstats; struct bpstats;
struct so_list; struct so_list;
struct objfile; struct objfile;
struct thread_info;
EOF EOF
;; ;;
esac esac

View File

@ -39,6 +39,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#include "ui-out.h" #include "ui-out.h"
#include "observer.h"
/* Definition of struct thread_info exported to gdbthread.h */ /* Definition of struct thread_info exported to gdbthread.h */
@ -137,6 +138,8 @@ add_thread (ptid_t ptid)
if (print_thread_events) if (print_thread_events)
printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid)); printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
observer_notify_new_thread (result);
return result; return result;
} }

View File

@ -48,7 +48,7 @@ tui_exit (void)
/* These implement the TUI interpreter. */ /* These implement the TUI interpreter. */
static void * static void *
tui_init (void) tui_init (int top_level)
{ {
/* Install exit handler to leave the screen in a good shape. */ /* Install exit handler to leave the screen in a good shape. */
atexit (tui_exit); atexit (tui_exit);