* mi/mi-main.c: Include <sys/resource.h> if present.
(rusage): Declare if HAVE_GETRUSAGE. (current_command_ts, do_timings): New static variables. (timestamp, print_diff_now, print_diff, timeval_diff): New static timing functions. (mi_cmd_enable_timings): New function for new MI command. (captured_mi_execute_command, mi_execute_async_cli_command): Call timing functions. * mi/mi-cmds.c (mi_cmds): Add entry for new MI command -enable-timings. * mi/mi-cmds.h (mi_cmd_enable_timings): New extern. * mi/mi-parse.h: (mi_timestamp): New structure. (mi_parse): Add mi_timestamp* member.
This commit is contained in:
parent
24325aea77
commit
d8c83789e9
|
@ -53,6 +53,7 @@ struct mi_cmd mi_cmds[] =
|
|||
{ "data-read-memory", { NULL, 0 }, 0, mi_cmd_data_read_memory},
|
||||
{ "data-write-memory", { NULL, 0 }, 0, mi_cmd_data_write_memory},
|
||||
{ "data-write-register-values", { NULL, 0 }, 0, mi_cmd_data_write_register_values},
|
||||
{ "enable-timings", { NULL, 0 }, 0, mi_cmd_enable_timings},
|
||||
{ "environment-cd", { NULL, 0 }, 0, mi_cmd_env_cd},
|
||||
{ "environment-directory", { NULL, 0 }, 0, mi_cmd_env_dir},
|
||||
{ "environment-path", { NULL, 0 }, 0, mi_cmd_env_path},
|
||||
|
|
|
@ -72,6 +72,7 @@ extern mi_cmd_argv_ftype mi_cmd_data_list_changed_registers;
|
|||
extern mi_cmd_argv_ftype mi_cmd_data_read_memory;
|
||||
extern mi_cmd_argv_ftype mi_cmd_data_write_memory;
|
||||
extern mi_cmd_argv_ftype mi_cmd_data_write_register_values;
|
||||
extern mi_cmd_argv_ftype mi_cmd_enable_timings;
|
||||
extern mi_cmd_argv_ftype mi_cmd_env_cd;
|
||||
extern mi_cmd_argv_ftype mi_cmd_env_dir;
|
||||
extern mi_cmd_argv_ftype mi_cmd_env_path;
|
||||
|
|
114
gdb/mi/mi-main.c
114
gdb/mi/mi-main.c
|
@ -50,6 +50,14 @@
|
|||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if defined HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
struct rusage rusage;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
FROM_TTY = 0
|
||||
|
@ -81,6 +89,12 @@ struct captured_mi_execute_command_args
|
|||
int mi_debug_p;
|
||||
struct ui_file *raw_stdout;
|
||||
|
||||
/* This is used to pass the current command timestamp
|
||||
down to continuation routines. */
|
||||
static struct mi_timestamp *current_command_ts;
|
||||
|
||||
static int do_timings = 0;
|
||||
|
||||
/* The token of the last asynchronous command */
|
||||
static char *last_async_command;
|
||||
static char *previous_async_command;
|
||||
|
@ -103,6 +117,11 @@ static int get_register (int regnum, int format);
|
|||
layer that calls libgdb. Any operation used in the below should be
|
||||
formalized. */
|
||||
|
||||
static void timestamp (struct mi_timestamp *tv);
|
||||
|
||||
static void print_diff_now (struct mi_timestamp *start);
|
||||
static void print_diff (struct mi_timestamp *start, struct mi_timestamp *end);
|
||||
|
||||
enum mi_cmd_result
|
||||
mi_cmd_gdb_exit (char *command, char **argv, int argc)
|
||||
{
|
||||
|
@ -194,7 +213,7 @@ mi_cmd_exec_continue (char *args, int from_tty)
|
|||
}
|
||||
|
||||
/* Interrupt the execution of the target. Note how we must play around
|
||||
with the token varialbes, in order to display the current token in
|
||||
with the token variables, in order to display the current token in
|
||||
the result of the interrupt command, and the previous execution
|
||||
token when the target finally stops. See comments in
|
||||
mi_cmd_execute. */
|
||||
|
@ -1013,6 +1032,30 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
|
|||
return MI_CMD_DONE;
|
||||
}
|
||||
|
||||
enum mi_cmd_result
|
||||
mi_cmd_enable_timings (char *command, char **argv, int argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
do_timings = 1;
|
||||
else if (argc == 1)
|
||||
{
|
||||
if (strcmp (argv[0], "yes") == 0)
|
||||
do_timings = 1;
|
||||
else if (strcmp (argv[0], "no") == 0)
|
||||
do_timings = 0;
|
||||
else
|
||||
goto usage_error;
|
||||
}
|
||||
else
|
||||
goto usage_error;
|
||||
|
||||
return MI_CMD_DONE;
|
||||
|
||||
usage_error:
|
||||
error ("mi_cmd_enable_timings: Usage: %s {yes|no}", command);
|
||||
return MI_CMD_ERROR;
|
||||
}
|
||||
|
||||
/* Execute a command within a safe environment.
|
||||
Return <0 for error; >=0 for ok.
|
||||
|
||||
|
@ -1027,6 +1070,8 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
|
|||
(struct captured_mi_execute_command_args *) data;
|
||||
struct mi_parse *context = args->command;
|
||||
|
||||
struct mi_timestamp cmd_finished;
|
||||
|
||||
switch (context->op)
|
||||
{
|
||||
|
||||
|
@ -1041,8 +1086,15 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
|
|||
indication of what action is required and then switch on
|
||||
that. */
|
||||
args->action = EXECUTE_COMMAND_DISPLAY_PROMPT;
|
||||
|
||||
if (do_timings)
|
||||
current_command_ts = context->cmd_start;
|
||||
|
||||
args->rc = mi_cmd_execute (context);
|
||||
|
||||
if (do_timings)
|
||||
timestamp (&cmd_finished);
|
||||
|
||||
if (!target_can_async_p () || !target_executing)
|
||||
{
|
||||
/* print the result if there were no errors
|
||||
|
@ -1057,6 +1109,10 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
|
|||
fputs_unfiltered ("^done", raw_stdout);
|
||||
mi_out_put (uiout, raw_stdout);
|
||||
mi_out_rewind (uiout);
|
||||
/* Have to check cmd_start, since the command could be
|
||||
-enable-timings. */
|
||||
if (do_timings && context->cmd_start)
|
||||
print_diff (context->cmd_start, &cmd_finished);
|
||||
fputs_unfiltered ("\n", raw_stdout);
|
||||
}
|
||||
else if (args->rc == MI_CMD_ERROR)
|
||||
|
@ -1152,6 +1208,14 @@ mi_execute_command (char *cmd, int from_tty)
|
|||
if (command != NULL)
|
||||
{
|
||||
struct gdb_exception result;
|
||||
|
||||
if (do_timings)
|
||||
{
|
||||
command->cmd_start = (struct mi_timestamp *)
|
||||
xmalloc (sizeof (struct mi_timestamp));
|
||||
timestamp (command->cmd_start);
|
||||
}
|
||||
|
||||
/* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either
|
||||
be pushed even further down or even eliminated? */
|
||||
args.command = command;
|
||||
|
@ -1341,6 +1405,8 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
|
|||
fputs_unfiltered ("*stopped", raw_stdout);
|
||||
mi_out_put (uiout, raw_stdout);
|
||||
mi_out_rewind (uiout);
|
||||
if (do_timings)
|
||||
print_diff_now (current_command_ts);
|
||||
fputs_unfiltered ("\n", raw_stdout);
|
||||
return MI_CMD_QUIET;
|
||||
}
|
||||
|
@ -1457,3 +1523,49 @@ _initialize_mi_main (void)
|
|||
DEPRECATED_REGISTER_GDBARCH_SWAP (old_regs);
|
||||
deprecated_register_gdbarch_swap (NULL, 0, mi_setup_architecture_data);
|
||||
}
|
||||
|
||||
static void
|
||||
timestamp (struct mi_timestamp *tv)
|
||||
{
|
||||
long usec;
|
||||
gettimeofday (&tv->wallclock, NULL);
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
getrusage (RUSAGE_SELF, &rusage);
|
||||
tv->utime.tv_sec = rusage.ru_utime.tv_sec;
|
||||
tv->utime.tv_usec = rusage.ru_utime.tv_usec;
|
||||
tv->stime.tv_sec = rusage.ru_stime.tv_sec;
|
||||
tv->stime.tv_usec = rusage.ru_stime.tv_usec;
|
||||
#else
|
||||
usec = get_run_time ();
|
||||
tv->utime.tv_sec = usec/1000000;
|
||||
tv->utime.tv_usec = usec - 1000000*tv->utime.tv_sec;
|
||||
tv->stime.tv_sec = 0;
|
||||
tv->stime.tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
print_diff_now (struct mi_timestamp *start)
|
||||
{
|
||||
struct mi_timestamp now;
|
||||
timestamp (&now);
|
||||
print_diff (start, &now);
|
||||
}
|
||||
|
||||
static long
|
||||
timeval_diff (struct timeval start, struct timeval end)
|
||||
{
|
||||
return ((end.tv_sec - start.tv_sec) * 1000000)
|
||||
+ (end.tv_usec - start.tv_usec);
|
||||
}
|
||||
|
||||
static void
|
||||
print_diff (struct mi_timestamp *start, struct mi_timestamp *end)
|
||||
{
|
||||
fprintf_unfiltered
|
||||
(raw_stdout,
|
||||
",time={wallclock=\"%0.5f\",user=\"%0.5f\",system=\"%0.5f\"}",
|
||||
timeval_diff (start->wallclock, end->wallclock) / 1000000.0,
|
||||
timeval_diff (start->utime, end->utime) / 1000000.0,
|
||||
timeval_diff (start->stime, end->stime) / 1000000.0);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
|
||||
/* MI parser */
|
||||
|
||||
/* Timestamps for current command and last asynchronous command. */
|
||||
struct mi_timestamp {
|
||||
struct timeval wallclock;
|
||||
struct timeval utime;
|
||||
struct timeval stime;
|
||||
};
|
||||
|
||||
enum mi_command_type
|
||||
{
|
||||
MI_COMMAND, CLI_COMMAND
|
||||
|
@ -35,6 +42,7 @@ struct mi_parse
|
|||
char *command;
|
||||
char *token;
|
||||
const struct mi_cmd *cmd;
|
||||
struct mi_timestamp *cmd_start;
|
||||
char *args;
|
||||
char **argv;
|
||||
int argc;
|
||||
|
|
Loading…
Reference in New Issue