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:
Pedro Alves 2016-11-23 15:36:26 +00:00
parent 7836e407c6
commit dcb07cfa15
16 changed files with 358 additions and 210 deletions

View File

@ -1,3 +1,69 @@
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.
2016-11-22 Simon Marchi <simon.marchi@polymtl.ca>
* Makefile.in: Fix whitespace formatting.

View File

@ -1201,6 +1201,7 @@ SFILES = \
common/print-utils.c \
common/ptid.c \
common/rsp-low.c \
common/run-time-clock.c \
common/signals.c \
common/signals-state-save-restore.c \
common/vec.c \
@ -1485,6 +1486,7 @@ HFILES_NO_SRCDIR = \
common/ptid.h \
common/queue.h \
common/rsp-low.h \
common/run-time-clock.h \
common/signals-state-save-restore.h \
common/symbol.h \
common/vec.h \
@ -1739,6 +1741,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
registry.o \
reverse.o \
rsp-low.o \
run-time-clock.o \
rust-lang.o \
selftest.o \
sentinel-frame.o \

View File

@ -0,0 +1,58 @@
/* User/system CPU time clocks that follow the std::chrono interface.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "common-defs.h"
#include "run-time-clock.h"
#if defined HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
using namespace std::chrono;
run_time_clock::time_point
run_time_clock::now () noexcept
{
return time_point (microseconds (get_run_time ()));
}
#ifdef HAVE_GETRUSAGE
static std::chrono::microseconds
timeval_to_microseconds (struct timeval *tv)
{
return (seconds (tv->tv_sec) + microseconds (tv->tv_usec));
}
#endif
void
run_time_clock::now (user_cpu_time_clock::time_point &user,
system_cpu_time_clock::time_point &system) noexcept
{
#ifdef HAVE_GETRUSAGE
struct rusage rusage;
getrusage (RUSAGE_SELF, &rusage);
microseconds utime = timeval_to_microseconds (&rusage.ru_utime);
microseconds stime = timeval_to_microseconds (&rusage.ru_stime);
user = user_cpu_time_clock::time_point (utime);
system = system_cpu_time_clock::time_point (stime);
#else
user = user_cpu_time_clock::time_point (microseconds (get_run_time ()));
system = system_cpu_time_clock::time_point (microseconds::zero ());
#endif
}

View File

@ -0,0 +1,75 @@
/* User/system CPU time clocks that follow the std::chrono interface.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef RUN_TIME_CLOCK_H
#define RUN_TIME_CLOCK_H
#include <chrono>
/* Count the total amount of time spent executing in user mode. */
struct user_cpu_time_clock
{
using duration = std::chrono::microseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<user_cpu_time_clock>;
static constexpr bool is_steady = true;
/* Use run_time_clock::now instead. */
static time_point now () noexcept = delete;
};
/* Count the total amount of time spent executing in kernel mode. */
struct system_cpu_time_clock
{
using duration = std::chrono::microseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<system_cpu_time_clock>;
static constexpr bool is_steady = true;
/* Use run_time_clock::now instead. */
static time_point now () noexcept = delete;
};
/* Count the total amount of time spent executing in userspace+kernel
mode. */
struct run_time_clock
{
using duration = std::chrono::microseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<run_time_clock>;
static constexpr bool is_steady = true;
static time_point now () noexcept;
/* Return the user/system time as separate time points, if
supported. If not supported, then the combined user+kernel time
is returned in USER and SYSTEM is set to zero. */
static void now (user_cpu_time_clock::time_point &user,
system_cpu_time_clock::time_point &system) noexcept;
};
#endif

View File

@ -303,20 +303,6 @@ extern void symbol_file_command (char *, int);
/* * Remote targets may wish to use this as their load function. */
extern void generic_load (const char *name, int from_tty);
/* * Report on STREAM the performance of memory transfer operation,
such as 'load'.
@param DATA_COUNT is the number of bytes transferred.
@param WRITE_COUNT is the number of separate write operations, or 0,
if that information is not available.
@param START_TIME is the time at which an operation was started.
@param END_TIME is the time at which an operation ended. */
struct timeval;
extern void print_transfer_performance (struct ui_file *stream,
unsigned long data_count,
unsigned long write_count,
const struct timeval *start_time,
const struct timeval *end_time);
/* From top.c */
typedef void initialize_file_ftype (void);

View File

@ -212,7 +212,7 @@ gdb_notifier;
first occasion after WHEN. */
struct gdb_timer
{
struct timeval when;
std::chrono::steady_clock::time_point when;
int timer_id;
struct gdb_timer *next;
timer_handler_func *proc; /* Function to call to do the work. */
@ -1097,33 +1097,22 @@ delete_async_event_handler (async_event_handler **async_handler_ptr)
*async_handler_ptr = NULL;
}
/* Create a timer that will expire in MILLISECONDS from now. When the
timer is ready, PROC will be executed. At creation, the timer is
aded to the timers queue. This queue is kept sorted in order of
increasing timers. Return a handle to the timer struct. */
/* Create a timer that will expire in MS milliseconds from now. When
the timer is ready, PROC will be executed. At creation, the timer
is added to the timers queue. This queue is kept sorted in order
of increasing timers. Return a handle to the timer struct. */
int
create_timer (int milliseconds, timer_handler_func * proc,
create_timer (int ms, timer_handler_func *proc,
gdb_client_data client_data)
{
using namespace std::chrono;
struct gdb_timer *timer_ptr, *timer_index, *prev_timer;
struct timeval time_now, delta;
/* Compute seconds. */
delta.tv_sec = milliseconds / 1000;
/* Compute microseconds. */
delta.tv_usec = (milliseconds % 1000) * 1000;
steady_clock::time_point time_now = steady_clock::now ();
gettimeofday (&time_now, NULL);
timer_ptr = XNEW (struct gdb_timer);
timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec;
timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec;
/* Carry? */
if (timer_ptr->when.tv_usec >= 1000000)
{
timer_ptr->when.tv_sec += 1;
timer_ptr->when.tv_usec -= 1000000;
}
timer_ptr = new gdb_timer ();
timer_ptr->when = time_now + milliseconds (ms);
timer_ptr->proc = proc;
timer_ptr->client_data = client_data;
timer_list.num_timers++;
@ -1136,11 +1125,7 @@ create_timer (int milliseconds, timer_handler_func * proc,
timer_index != NULL;
timer_index = timer_index->next)
{
/* If the seconds field is greater or if it is the same, but the
microsecond field is greater. */
if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec)
|| ((timer_index->when.tv_sec == timer_ptr->when.tv_sec)
&& (timer_index->when.tv_usec > timer_ptr->when.tv_usec)))
if (timer_index->when > timer_ptr->when)
break;
}
@ -1194,47 +1179,56 @@ delete_timer (int id)
;
prev_timer->next = timer_ptr->next;
}
xfree (timer_ptr);
delete timer_ptr;
gdb_notifier.timeout_valid = 0;
}
/* Convert a std::chrono duration to a struct timeval. */
template<typename Duration>
static struct timeval
duration_cast_timeval (const Duration &d)
{
using namespace std::chrono;
seconds sec = duration_cast<seconds> (d);
microseconds msec = duration_cast<microseconds> (d - sec);
struct timeval tv;
tv.tv_sec = sec.count ();
tv.tv_usec = msec.count ();
return tv;
}
/* Update the timeout for the select() or poll(). Returns true if the
timer has already expired, false otherwise. */
static int
update_wait_timeout (void)
{
struct timeval time_now, delta;
if (timer_list.first_timer != NULL)
{
gettimeofday (&time_now, NULL);
delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec;
delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec;
/* Borrow? */
if (delta.tv_usec < 0)
{
delta.tv_sec -= 1;
delta.tv_usec += 1000000;
}
using namespace std::chrono;
steady_clock::time_point time_now = steady_clock::now ();
struct timeval timeout;
/* Cannot simply test if delta.tv_sec is negative because time_t
might be unsigned. */
if (timer_list.first_timer->when.tv_sec < time_now.tv_sec
|| (timer_list.first_timer->when.tv_sec == time_now.tv_sec
&& timer_list.first_timer->when.tv_usec < time_now.tv_usec))
if (timer_list.first_timer->when < time_now)
{
/* It expired already. */
delta.tv_sec = 0;
delta.tv_usec = 0;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
}
else
{
steady_clock::duration d = timer_list.first_timer->when - time_now;
timeout = duration_cast_timeval (d);
}
/* Update the timeout for select/ poll. */
if (use_poll)
{
#ifdef HAVE_POLL
gdb_notifier.poll_timeout = delta.tv_sec * 1000;
gdb_notifier.poll_timeout = timeout.tv_sec * 1000;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
@ -1242,12 +1236,12 @@ update_wait_timeout (void)
}
else
{
gdb_notifier.select_timeout.tv_sec = delta.tv_sec;
gdb_notifier.select_timeout.tv_usec = delta.tv_usec;
gdb_notifier.select_timeout.tv_sec = timeout.tv_sec;
gdb_notifier.select_timeout.tv_usec = timeout.tv_usec;
}
gdb_notifier.timeout_valid = 1;
if (delta.tv_sec == 0 && delta.tv_usec == 0)
if (timer_list.first_timer->when < time_now)
return 1;
}
else

View File

@ -1,3 +1,12 @@
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.
2016-11-22 Simon Marchi <simon.marchi@polymtl.ca>
* Makefile.in: Fix whitespace formatting.

View File

@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
#include "gdb_sys_time.h"
#include <chrono>
/* Enable miscellaneous debugging output. The name is historical - it
was originally used to debug LinuxThreads support. */
@ -27,8 +27,7 @@ int debug_threads;
int debug_timestamp;
/* Print a debugging message.
If the text begins a new line it is preceded by a timestamp, if the
system has gettimeofday.
If the text begins a new line it is preceded by a timestamp.
We don't get fancy with newline checking, we just check whether the
previous call ended with "\n". */
@ -41,14 +40,13 @@ debug_vprintf (const char *format, va_list ap)
if (debug_timestamp && new_line)
{
struct timeval tm;
using namespace std::chrono;
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;
/* If gettimeofday doesn't exist, and as a portability solution it has
been replaced with, e.g., time, then it doesn't make sense to print
the microseconds field. Is there a way to check for that? */
fprintf (stderr, "%ld:%06ld ", (long) tm.tv_sec, (long) tm.tv_usec);
fprintf (stderr, "%ld.%06ld ", (long) s.count (), (long) us.count ());
}
#endif

View File

@ -25,7 +25,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include "gdb_sys_time.h"
#include <chrono>
#include <inttypes.h>
#include "ax.h"
#include "tdesc.h"
@ -7410,12 +7410,10 @@ getauxval (unsigned long type)
static LONGEST
get_timestamp (void)
{
struct timeval tv;
using namespace std::chrono;
if (gettimeofday (&tv, 0) != 0)
return -1;
else
return (LONGEST) tv.tv_sec * 1000000 + tv.tv_usec;
steady_clock::time_point now = steady_clock::now ();
return duration_cast<microseconds> (now.time_since_epoch ()).count ();
}
void

View File

@ -24,8 +24,6 @@
#include "arch-utils.h"
#include <ctype.h>
#include <signal.h>
#include "gdb_sys_time.h"
#include <time.h>
#include "command.h"
#include "gdbcmd.h"
#include "symtab.h"
@ -39,7 +37,6 @@
#include "objfiles.h"
#include "value.h"
#include "top.h"
#include "timeval-utils.h"
#include "maint.h"
#include "selftest.h"
@ -822,23 +819,21 @@ scoped_command_stats::~scoped_command_stats ()
if (m_time_enabled && per_command_time)
{
long cmd_time = get_run_time () - m_start_cpu_time;
struct timeval now_wall_time, delta_wall_time, wait_time;
using namespace std::chrono;
gettimeofday (&now_wall_time, NULL);
timeval_sub (&delta_wall_time,
&now_wall_time, &m_start_wall_time);
run_time_clock::duration cmd_time
= run_time_clock::now () - m_start_cpu_time;
steady_clock::duration wall_time
= steady_clock::now () - m_start_wall_time;
/* Subtract time spend in prompt_for_continue from walltime. */
wait_time = get_prompt_for_continue_wait_time ();
timeval_sub (&delta_wall_time, &delta_wall_time, &wait_time);
wall_time -= get_prompt_for_continue_wait_time ();
printf_unfiltered (!m_msg_type
? _("Startup time: %ld.%06ld (cpu), %ld.%06ld (wall)\n")
: _("Command execution time: %ld.%06ld (cpu), %ld.%06ld (wall)\n"),
cmd_time / 1000000, cmd_time % 1000000,
(long) delta_wall_time.tv_sec,
(long) delta_wall_time.tv_usec);
? _("Startup time: %.6f (cpu), %.6f (wall)\n")
: _("Command execution time: %.6f (cpu), %.6f (wall)\n"),
duration<double> (cmd_time).count (),
duration<double> (wall_time).count ());
}
if (m_space_enabled && per_command_space)
@ -892,8 +887,10 @@ scoped_command_stats::scoped_command_stats (bool msg_type)
if (msg_type == 0 || per_command_time)
{
m_start_cpu_time = get_run_time ();
gettimeofday (&m_start_wall_time, NULL);
using namespace std::chrono;
m_start_cpu_time = run_time_clock::now ();
m_start_wall_time = steady_clock::now ();
m_time_enabled = 1;
}
else

View File

@ -19,6 +19,9 @@
#ifndef MAINT_H
#define MAINT_H
#include "run-time-clock.h"
#include <chrono>
extern void set_per_command_time (int);
extern void set_per_command_space (int);
@ -48,8 +51,8 @@ class scoped_command_stats
int m_time_enabled : 1;
int m_space_enabled : 1;
int m_symtab_enabled : 1;
long m_start_cpu_time;
struct timeval m_start_wall_time;
run_time_clock::time_point m_start_cpu_time;
std::chrono::steady_clock::time_point m_start_wall_time;
long m_start_space;
/* Total number of symtabs (over all objfiles). */
int m_start_nr_symtabs;

View File

@ -56,15 +56,8 @@
#include "observer.h"
#include <ctype.h>
#include "gdb_sys_time.h"
#if defined HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_GETRUSAGE
struct rusage rusage;
#endif
#include "run-time-clock.h"
#include <chrono>
enum
{
@ -2169,7 +2162,7 @@ mi_execute_command (const char *cmd, int from_tty)
if (do_timings)
{
command->cmd_start = XNEW (struct mi_timestamp);
command->cmd_start = new mi_timestamp ();
timestamp (command->cmd_start);
}
@ -2390,8 +2383,8 @@ mi_load_progress (const char *section_name,
unsigned long total_sent,
unsigned long grand_total)
{
struct timeval time_now, delta, update_threshold;
static struct timeval last_update;
using namespace std::chrono;
static steady_clock::time_point last_update;
static char *previous_sect_name = NULL;
int new_section;
struct ui_out *saved_uiout;
@ -2416,19 +2409,6 @@ mi_load_progress (const char *section_name,
uiout = current_uiout;
update_threshold.tv_sec = 0;
update_threshold.tv_usec = 500000;
gettimeofday (&time_now, NULL);
delta.tv_usec = time_now.tv_usec - last_update.tv_usec;
delta.tv_sec = time_now.tv_sec - last_update.tv_sec;
if (delta.tv_usec < 0)
{
delta.tv_sec -= 1;
delta.tv_usec += 1000000L;
}
new_section = (previous_sect_name ?
strcmp (previous_sect_name, section_name) : 1);
if (new_section)
@ -2451,13 +2431,12 @@ mi_load_progress (const char *section_name,
gdb_flush (mi->raw_stdout);
}
if (delta.tv_sec >= update_threshold.tv_sec &&
delta.tv_usec >= update_threshold.tv_usec)
steady_clock::time_point time_now = steady_clock::now ();
if (time_now - last_update > milliseconds (500))
{
struct cleanup *cleanup_tuple;
last_update.tv_sec = time_now.tv_sec;
last_update.tv_usec = time_now.tv_usec;
last_update = time_now;
if (current_token)
fputs_unfiltered (current_token, mi->raw_stdout);
fputs_unfiltered ("+download", mi->raw_stdout);
@ -2480,23 +2459,10 @@ mi_load_progress (const char *section_name,
static void
timestamp (struct mi_timestamp *tv)
{
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
{
long usec = get_run_time ();
using namespace std::chrono;
tv->utime.tv_sec = usec/1000000L;
tv->utime.tv_usec = usec - 1000000L*tv->utime.tv_sec;
tv->stime.tv_sec = 0;
tv->stime.tv_usec = 0;
}
#endif
tv->wallclock = steady_clock::now ();
run_time_clock::now (tv->utime, tv->stime);
}
static void
@ -2517,23 +2483,20 @@ mi_print_timing_maybe (struct ui_file *file)
print_diff_now (file, current_command_ts);
}
static long
timeval_diff (struct timeval start, struct timeval end)
{
return ((end.tv_sec - start.tv_sec) * 1000000L)
+ (end.tv_usec - start.tv_usec);
}
static void
print_diff (struct ui_file *file, struct mi_timestamp *start,
struct mi_timestamp *end)
{
using namespace std::chrono;
duration<double> wallclock = end->wallclock - start->wallclock;
duration<double> utime = end->utime - start->utime;
duration<double> stime = end->stime - start->stime;
fprintf_unfiltered
(file,
",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);
wallclock.count (), utime.count (), stime.count ());
}
void

View File

@ -20,15 +20,17 @@
#ifndef MI_PARSE_H
#define MI_PARSE_H
#include "gdb_sys_time.h"
#include "run-time-clock.h"
#include <chrono>
/* MI parser */
/* Timestamps for current command and last asynchronous command. */
struct mi_timestamp {
struct timeval wallclock;
struct timeval utime;
struct timeval stime;
struct mi_timestamp
{
std::chrono::steady_clock::time_point wallclock;
user_cpu_time_clock::time_point utime;
system_cpu_time_clock::time_point stime;
};
enum mi_command_type

View File

@ -61,8 +61,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <ctype.h>
#include <time.h>
#include "gdb_sys_time.h"
#include <chrono>
#include "psymtab.h"
@ -2066,11 +2065,15 @@ clear_memory_write_data (void *arg)
VEC_free (memory_write_request_s, vec);
}
static void print_transfer_performance (struct ui_file *stream,
unsigned long data_count,
unsigned long write_count,
std::chrono::steady_clock::duration d);
void
generic_load (const char *args, int from_tty)
{
bfd *loadfile_bfd;
struct timeval start_time, end_time;
char *filename;
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
struct load_section_data cbdata;
@ -2131,13 +2134,15 @@ generic_load (const char *args, int from_tty)
bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
gettimeofday (&start_time, NULL);
using namespace std::chrono;
steady_clock::time_point start_time = steady_clock::now ();
if (target_write_memory_blocks (cbdata.requests, flash_discard,
load_progress) != 0)
error (_("Load failed"));
gettimeofday (&end_time, NULL);
steady_clock::time_point end_time = steady_clock::now ();
entry = bfd_get_start_address (loadfile_bfd);
entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
@ -2160,32 +2165,32 @@ generic_load (const char *args, int from_tty)
print_transfer_performance (gdb_stdout, total_progress.data_count,
total_progress.write_count,
&start_time, &end_time);
end_time - start_time);
do_cleanups (old_cleanups);
}
/* Report how fast the transfer went. */
/* Report on STREAM the performance of a memory transfer operation,
such as 'load'. DATA_COUNT is the number of bytes transferred.
WRITE_COUNT is the number of separate write operations, or 0, if
that information is not available. TIME is how long the operation
lasted. */
void
static void
print_transfer_performance (struct ui_file *stream,
unsigned long data_count,
unsigned long write_count,
const struct timeval *start_time,
const struct timeval *end_time)
std::chrono::steady_clock::duration time)
{
ULONGEST time_count;
using namespace std::chrono;
struct ui_out *uiout = current_uiout;
/* Compute the elapsed time in milliseconds, as a tradeoff between
accuracy and overflow. */
time_count = (end_time->tv_sec - start_time->tv_sec) * 1000;
time_count += (end_time->tv_usec - start_time->tv_usec) / 1000;
milliseconds ms = duration_cast<milliseconds> (time);
ui_out_text (uiout, "Transfer rate: ");
if (time_count > 0)
if (ms.count () > 0)
{
unsigned long rate = ((ULONGEST) data_count * 1000) / time_count;
unsigned long rate = ((ULONGEST) data_count * 1000) / ms.count ();
if (ui_out_is_mi_like_p (uiout))
{

View File

@ -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);

View File

@ -23,6 +23,7 @@
#include "exceptions.h"
#include "common/scoped_restore.h"
#include <chrono>
extern void initialize_utils (void);
@ -51,7 +52,7 @@ extern const char *gdb_bfd_errmsg (bfd_error_type error_tag, char **matching);
/* Reset the prompt_for_continue clock. */
void reset_prompt_for_continue_wait_time (void);
/* Return the 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 ();
/* Parsing utilites. */