gdb: Use C++11 std::chrono
This patch fixes a few problems with GDB's time handling. #1 - It avoids problems with gnulib's C++ namespace support On MinGW, the struct timeval that should be passed to gnulib's gettimeofday replacement is incompatible with libiberty's timeval_sub/timeval_add. That's because gnulib also replaces "struct timeval" with its own definition, while libiberty expects the system's. E.g., in code like this: gettimeofday (&prompt_ended, NULL); timeval_sub (&prompt_delta, &prompt_ended, &prompt_started); timeval_add (&prompt_for_continue_wait_time, &prompt_for_continue_wait_time, &prompt_delta); That's currently handled in gdb by not using gnulib's gettimeofday at all (see common/gdb_sys_time.h), but that #undef hack won't work with if/when we enable gnulib's C++ namespace support, because that mode adds compile time warnings for uses of ::gettimeofday, which are hard errors with -Werror. #2 - But there's an elephant in the room: gettimeofday is not monotonic... We're using it to: a) check how long functions take, for performance analysis b) compute when in the future to fire events in the event-loop c) print debug timestamps But that's exactly what gettimeofday is NOT meant for. Straight from the man page: ~~~ The time returned by gettimeofday() is affected by discontinuous jumps in the system time (e.g., if the system administrator manually changes the system time). If you need a monotonically increasing clock, see clock_gettime(2). ~~~ std::chrono (part of the C++11 standard library) has a monotonic clock exactly for such purposes (std::chrono::steady_clock). This commit switches to use that instead of gettimeofday, fixing all the issues mentioned above. gdb/ChangeLog: 2016-11-23 Pedro Alves <palves@redhat.com> * Makefile.in (SFILES): Add common/run-time-clock.c. (HFILES_NO_SRCDIR): Add common/run-time-clock.h. (COMMON_OBS): Add run-time-clock.o. * common/run-time-clock.c, common/run-time-clock.h: New files. * defs.h (struct timeval, print_transfer_performance): Delete declarations. * event-loop.c (struct gdb_timer) <when>: Now a std::chrono::steady_clock::time_point. (create_timer): use std::chrono::steady_clock instead of gettimeofday. Use new instead of malloc. (delete_timer): Use delete instead of xfree. (duration_cast_timeval): New. (update_wait_timeout): Use std::chrono::steady_clock instead of gettimeofday. * maint.c: Include <chrono> instead of "gdb_sys_time.h", <time.h> and "timeval-utils.h". (scoped_command_stats::~scoped_command_stats) (scoped_command_stats::scoped_command_stats): Use std::chrono::steady_clock instead of gettimeofday. Use user_cpu_time_clock instead of get_run_time. * maint.h: Include "run-time-clock.h" and <chrono>. (scoped_command_stats): <m_start_cpu_time>: Now a user_cpu_time_clock::time_point. <m_start_wall_time>: Now a std::chrono::steady_clock::time_point. * mi/mi-main.c: Include "run-time-clock.h" and <chrono> instead of "gdb_sys_time.h" and <sys/resource.h>. (rusage): Delete. (mi_execute_command): Use new instead of XNEW. (mi_load_progress): Use std::chrono::steady_clock instead of gettimeofday. (timestamp): Rewrite in terms of std::chrono::steady_clock, user_cpu_time_clock and system_cpu_time_clock. (timeval_diff): Delete. (print_diff): Adjust to use std::chrono::steady_clock, user_cpu_time_clock and system_cpu_time_clock. * mi/mi-parse.h: Include "run-time-clock.h" and <chrono> instead of "gdb_sys_time.h". (struct mi_timestamp): Change fields types to std::chrono::steady_clock::time_point, user_cpu_time_clock::time and system_cpu_time_clock::time_point, instead of struct timeval. * symfile.c: Include <chrono> instead of <time.h> and "gdb_sys_time.h". (struct time_range): New. (generic_load): Use std::chrono::steady_clock instead of gettimeofday. (print_transfer_performance): Replace timeval parameters with a std::chrono::steady_clock::duration parameter. Adjust. * utils.c: Include <chrono> instead of "timeval-utils.h", "gdb_sys_time.h", and <time.h>. (prompt_for_continue_wait_time): Now a std::chrono::steady_clock::duration. (defaulted_query, prompt_for_continue): Use std::chrono::steady_clock instead of gettimeofday/timeval_sub/timeval_add. (reset_prompt_for_continue_wait_time): Use std::chrono::steady_clock::duration instead of struct timeval. (get_prompt_for_continue_wait_time): Return a std::chrono::steady_clock::duration instead of struct timeval. (vfprintf_unfiltered): Use std::chrono::steady_clock instead of gettimeofday. Use std::string. Use '.' instead of ':'. * utils.h: Include <chrono>. (get_prompt_for_continue_wait_time): Return a std::chrono::steady_clock::duration instead of struct timeval. gdb/gdbserver/ChangeLog: 2016-11-23 Pedro Alves <palves@redhat.com> * debug.c: Include <chrono> instead of "gdb_sys_time.h". (debug_vprintf): Use std::chrono::steady_clock instead of gettimeofday. Use '.' instead of ':'. * tracepoint.c: Include <chrono> instead of "gdb_sys_time.h". (get_timestamp): Use std::chrono::steady_clock instead of gettimeofday.
This commit is contained in:
parent
7836e407c6
commit
dcb07cfa15
16 changed files with 358 additions and 210 deletions
58
gdb/utils.c
58
gdb/utils.c
|
@ -37,7 +37,6 @@
|
|||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include "timeval-utils.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "serial.h"
|
||||
#include "bfd.h"
|
||||
|
@ -61,8 +60,7 @@
|
|||
|
||||
#include "readline/readline.h"
|
||||
|
||||
#include "gdb_sys_time.h"
|
||||
#include <time.h>
|
||||
#include <chrono>
|
||||
|
||||
#include "gdb_usleep.h"
|
||||
#include "interps.h"
|
||||
|
@ -98,7 +96,7 @@ static void set_width (void);
|
|||
Modified in prompt_for_continue and defaulted_query.
|
||||
Used in report_command_stats. */
|
||||
|
||||
static struct timeval prompt_for_continue_wait_time;
|
||||
static std::chrono::steady_clock::duration prompt_for_continue_wait_time;
|
||||
|
||||
/* A flag indicating whether to timestamp debugging messages. */
|
||||
|
||||
|
@ -1184,9 +1182,6 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
|
|||
int def_value;
|
||||
char def_answer, not_def_answer;
|
||||
char *y_string, *n_string, *question, *prompt;
|
||||
/* Used to add duration we waited for user to respond to
|
||||
prompt_for_continue_wait_time. */
|
||||
struct timeval prompt_started, prompt_ended, prompt_delta;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
/* Set up according to which answer is the default. */
|
||||
|
@ -1261,8 +1256,10 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
|
|||
annotation_level > 1 ? "\n\032\032query\n" : "");
|
||||
make_cleanup (xfree, prompt);
|
||||
|
||||
/* Used for calculating time spend waiting for user. */
|
||||
gettimeofday (&prompt_started, NULL);
|
||||
/* Used to add duration we waited for user to respond to
|
||||
prompt_for_continue_wait_time. */
|
||||
using namespace std::chrono;
|
||||
steady_clock::time_point prompt_started = steady_clock::now ();
|
||||
|
||||
prepare_to_handle_input ();
|
||||
|
||||
|
@ -1307,10 +1304,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
|
|||
}
|
||||
|
||||
/* Add time spend in this routine to prompt_for_continue_wait_time. */
|
||||
gettimeofday (&prompt_ended, NULL);
|
||||
timeval_sub (&prompt_delta, &prompt_ended, &prompt_started);
|
||||
timeval_add (&prompt_for_continue_wait_time,
|
||||
&prompt_for_continue_wait_time, &prompt_delta);
|
||||
prompt_for_continue_wait_time += steady_clock::now () - prompt_started;
|
||||
|
||||
if (annotation_level > 1)
|
||||
printf_filtered (("\n\032\032post-query\n"));
|
||||
|
@ -1816,12 +1810,11 @@ prompt_for_continue (void)
|
|||
{
|
||||
char *ignore;
|
||||
char cont_prompt[120];
|
||||
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
||||
/* Used to add duration we waited for user to respond to
|
||||
prompt_for_continue_wait_time. */
|
||||
struct timeval prompt_started, prompt_ended, prompt_delta;
|
||||
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
||||
|
||||
gettimeofday (&prompt_started, NULL);
|
||||
using namespace std::chrono;
|
||||
steady_clock::time_point prompt_started = steady_clock::now ();
|
||||
|
||||
if (annotation_level > 1)
|
||||
printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
|
||||
|
@ -1844,10 +1837,7 @@ prompt_for_continue (void)
|
|||
make_cleanup (xfree, ignore);
|
||||
|
||||
/* Add time spend in this routine to prompt_for_continue_wait_time. */
|
||||
gettimeofday (&prompt_ended, NULL);
|
||||
timeval_sub (&prompt_delta, &prompt_ended, &prompt_started);
|
||||
timeval_add (&prompt_for_continue_wait_time,
|
||||
&prompt_for_continue_wait_time, &prompt_delta);
|
||||
prompt_for_continue_wait_time += steady_clock::now () - prompt_started;
|
||||
|
||||
if (annotation_level > 1)
|
||||
printf_unfiltered (("\n\032\032post-prompt-for-continue\n"));
|
||||
|
@ -1877,15 +1867,15 @@ prompt_for_continue (void)
|
|||
void
|
||||
reset_prompt_for_continue_wait_time (void)
|
||||
{
|
||||
static const struct timeval zero_timeval = { 0 };
|
||||
using namespace std::chrono;
|
||||
|
||||
prompt_for_continue_wait_time = zero_timeval;
|
||||
prompt_for_continue_wait_time = steady_clock::duration::zero ();
|
||||
}
|
||||
|
||||
/* Fetch the cumulative time spent in prompt_for_continue. */
|
||||
|
||||
struct timeval
|
||||
get_prompt_for_continue_wait_time (void)
|
||||
std::chrono::steady_clock::duration
|
||||
get_prompt_for_continue_wait_time ()
|
||||
{
|
||||
return prompt_for_continue_wait_time;
|
||||
}
|
||||
|
@ -2308,21 +2298,21 @@ vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
|
|||
old_cleanups = make_cleanup (xfree, linebuffer);
|
||||
if (debug_timestamp && stream == gdb_stdlog)
|
||||
{
|
||||
struct timeval tm;
|
||||
char *timestamp;
|
||||
using namespace std::chrono;
|
||||
int len, need_nl;
|
||||
|
||||
gettimeofday (&tm, NULL);
|
||||
steady_clock::time_point now = steady_clock::now ();
|
||||
seconds s = duration_cast<seconds> (now.time_since_epoch ());
|
||||
microseconds us = duration_cast<microseconds> (now.time_since_epoch () - s);
|
||||
|
||||
len = strlen (linebuffer);
|
||||
need_nl = (len > 0 && linebuffer[len - 1] != '\n');
|
||||
|
||||
timestamp = xstrprintf ("%ld:%ld %s%s",
|
||||
(long) tm.tv_sec, (long) tm.tv_usec,
|
||||
linebuffer,
|
||||
need_nl ? "\n": "");
|
||||
make_cleanup (xfree, timestamp);
|
||||
fputs_unfiltered (timestamp, stream);
|
||||
std::string timestamp = string_printf ("%ld.%06ld %s%s",
|
||||
(long) s.count (),
|
||||
(long) us.count (),
|
||||
linebuffer, need_nl ? "\n": "");
|
||||
fputs_unfiltered (timestamp.c_str (), stream);
|
||||
}
|
||||
else
|
||||
fputs_unfiltered (linebuffer, stream);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue