[beast: 51/57] SFI: platform: add timestamp handling
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 51/57] SFI: platform: add timestamp handling
- Date: Sun, 23 Jul 2017 10:02:04 +0000 (UTC)
commit 28859da9a2331455c932233c529d53d88d6e5128
Author: Tim Janik <timj gnu org>
Date: Wed Jul 19 02:53:28 2017 +0200
SFI: platform: add timestamp handling
Signed-off-by: Tim Janik <timj gnu org>
sfi/platform.cc | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
sfi/platform.hh | 8 +++
2 files changed, 141 insertions(+), 4 deletions(-)
---
diff --git a/sfi/platform.cc b/sfi/platform.cc
index 260a976..d2255bc 100644
--- a/sfi/platform.cc
+++ b/sfi/platform.cc
@@ -9,9 +9,118 @@
#include <windows.h>
#endif // _WIN32
#include <cstring>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <execinfo.h> // _EXECINFO_H
namespace Bse {
+// == Timestamps ==
+static clockid_t monotonic_clockid = CLOCK_REALTIME;
+static uint64 monotonic_start = 0;
+static uint64 monotonic_resolution = 1000; // assume 1µs resolution for gettimeofday fallback
+static uint64 realtime_start = 0;
+
+static void
+timestamp_init_ ()
+{
+ static const bool initialize = [] () {
+ realtime_start = timestamp_realtime();
+ struct timespec tp = { 0, 0 };
+ if (clock_getres (CLOCK_REALTIME, &tp) >= 0)
+ monotonic_resolution = tp.tv_sec * 1000000000ULL + tp.tv_nsec;
+ uint64 mstart = realtime_start;
+#ifdef CLOCK_MONOTONIC
+ // CLOCK_MONOTONIC_RAW cannot slew, but doesn't measure SI seconds accurately
+ // CLOCK_MONOTONIC may slew, but attempts to accurately measure SI seconds
+ if (monotonic_clockid == CLOCK_REALTIME && clock_getres (CLOCK_MONOTONIC, &tp) >= 0)
+ {
+ monotonic_clockid = CLOCK_MONOTONIC;
+ monotonic_resolution = tp.tv_sec * 1000000000ULL + tp.tv_nsec;
+ mstart = timestamp_benchmark(); // here, monotonic_start=0 still
+ }
+#endif
+ monotonic_start = mstart;
+ return true;
+ } ();
+ (void) initialize;
+}
+namespace { static struct Timestamper { Timestamper() { timestamp_init_(); } } realtime_startup; } // Anon
+
+/// Provides the timestamp_realtime() value from program startup.
+uint64
+timestamp_startup ()
+{
+ timestamp_init_();
+ return realtime_start;
+}
+
+/// Return the current time as uint64 in µseconds.
+uint64
+timestamp_realtime ()
+{
+ struct timespec tp = { 0, 0 };
+ if (ISLIKELY (clock_gettime (CLOCK_REALTIME, &tp) >= 0))
+ return tp.tv_sec * 1000000ULL + tp.tv_nsec / 1000;
+ else
+ {
+ struct timeval now = { 0, 0 };
+ gettimeofday (&now, NULL);
+ return now.tv_sec * 1000000ULL + now.tv_usec;
+ }
+}
+
+/// Provide resolution of timestamp_benchmark() in nano-seconds.
+uint64
+timestamp_resolution ()
+{
+ timestamp_init_();
+ return monotonic_resolution;
+}
+
+/// Returns benchmark timestamp in nano-seconds, clock starts around program startup.
+uint64
+timestamp_benchmark ()
+{
+ struct timespec tp = { 0, 0 };
+ uint64 stamp;
+ if (ISLIKELY (clock_gettime (monotonic_clockid, &tp) >= 0))
+ {
+ stamp = tp.tv_sec * 1000000000ULL + tp.tv_nsec;
+ stamp -= monotonic_start; // reduce number of significant bits
+ }
+ else
+ {
+ stamp = timestamp_realtime() * 1000;
+ stamp -= MIN (stamp, monotonic_start); // reduce number of significant bits
+ }
+ return stamp;
+}
+
+/// Convert @a stamp into a string, adding µsecond fractions if space permits.
+String
+timestamp_format (uint64 stamp, uint maxlength)
+{
+ const size_t fieldwidth = std::max (maxlength, 1U);
+ const String fsecs = string_format ("%u", size_t (stamp) / 1000000);
+ const String usecs = string_format ("%06u", size_t (stamp) % 1000000);
+ String r = fsecs;
+ if (r.size() < fieldwidth)
+ r += '.';
+ if (r.size() < fieldwidth)
+ r += usecs.substr (0, fieldwidth - r.size());
+ return r;
+}
+
+/// A monotonically increasing counter, increments are atomic and visible in all threads.
+uint64
+monotonic_counter ()
+{
+ static std::atomic<uint64> global_monotonic_counter { 4294967297 };
+ return global_monotonic_counter++;
+}
+
+// == program and executable names ==
static std::string
get_executable_path()
{
@@ -104,13 +213,33 @@ program_cwd ()
return cached_program_cwd;
}
-struct EarlyStartup102 {
- EarlyStartup102()
+// == Early Startup ctors ==
+namespace {
+struct EarlyStartup {
+ EarlyStartup()
{
+ timestamp_init_();
program_cwd(); // initialize early, i.e. before main() changes cwd
}
};
-
-static EarlyStartup102 _early_startup_102 __attribute__ ((init_priority (102)));
+static EarlyStartup _early_startup __attribute__ ((init_priority (101)));
+} // Anon
+
+// == backtraces ==
+#ifdef _EXECINFO_H
+int (*backtrace_pointers) (void **buffer, int size) = &::backtrace; // GLibc only
+#else // !_EXECINFO_H
+static int
+dummy_backtrace (void **buffer, int size)
+{
+ if (size)
+ {
+ buffer[0] = __builtin_return_address (0);
+ return 1;
+ }
+ return 0;
+}
+int (*backtrace_pointers) (void **buffer, int size) = &dummy_backtrace;
+#endif // !_EXECINFO_H
} // Bse
diff --git a/sfi/platform.hh b/sfi/platform.hh
index 50e7fe0..a0e7998 100644
--- a/sfi/platform.hh
+++ b/sfi/platform.hh
@@ -6,6 +6,14 @@
namespace Bse {
+// == Timestamp Handling ==
+uint64 timestamp_startup (); // µseconds
+uint64 timestamp_realtime (); // µseconds
+uint64 timestamp_benchmark (); // nseconds
+uint64 timestamp_resolution (); // nseconds
+String timestamp_format (uint64 stamp, uint maxlength = 8);
+uint64 monotonic_counter ();
+
// == process info ==
String program_alias (); ///< Retrieve the program name as used for logging
or debug messages.
void program_alias_init (String customname); ///< Set program_alias to a non-localized alias
other than program_argv0 if desired.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]