aboutsummaryrefslogtreecommitdiff
path: root/gdb/common
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-11-23 15:36:26 +0000
committerPedro Alves <palves@redhat.com>2016-11-23 15:36:26 +0000
commitdcb07cfa156a8e9f768c7f2b5d32f27b6dfe939f (patch)
tree74eba37984da3795a212a592ff091dc93a97282a /gdb/common
parent7836e407c65761b003bfbcb7ce89947736330a15 (diff)
downloadgdb-dcb07cfa156a8e9f768c7f2b5d32f27b6dfe939f.zip
gdb-dcb07cfa156a8e9f768c7f2b5d32f27b6dfe939f.tar.gz
gdb-dcb07cfa156a8e9f768c7f2b5d32f27b6dfe939f.tar.bz2
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.
Diffstat (limited to 'gdb/common')
-rw-r--r--gdb/common/run-time-clock.c58
-rw-r--r--gdb/common/run-time-clock.h75
2 files changed, 133 insertions, 0 deletions
diff --git a/gdb/common/run-time-clock.c b/gdb/common/run-time-clock.c
new file mode 100644
index 0000000..f9dc7a0
--- /dev/null
+++ b/gdb/common/run-time-clock.c
@@ -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
+}
diff --git a/gdb/common/run-time-clock.h b/gdb/common/run-time-clock.h
new file mode 100644
index 0000000..ee531bb
--- /dev/null
+++ b/gdb/common/run-time-clock.h
@@ -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