]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add isc_time_now_hires function to get current time with high resolution
authorPatrick McLean <chutzpah@gentoo.org>
Sat, 20 Mar 2021 05:48:22 +0000 (22:48 -0700)
committerEvan Hunt <each@isc.org>
Sat, 20 Mar 2021 18:25:55 +0000 (11:25 -0700)
The current isc_time_now uses CLOCK_REALTIME_COARSE which only updates
on a timer tick. This clock is generally fine for millisecond accuracy,
but on servers with 100hz clocks, this clock is nowhere near accurate
enough for microsecond accuracy.

This commit adds a new isc_time_now_hires function that uses
CLOCK_REALTIME, which gives the current time, though it is somewhat
expensive to call. When microsecond accuracy is required, it may be
required to use extra resources for higher accuracy.

lib/isc/include/isc/util.h
lib/isc/tests/time_test.c
lib/isc/unix/include/isc/time.h
lib/isc/unix/time.c
lib/isc/win32/include/isc/time.h
lib/isc/win32/libisc.def.in
lib/isc/win32/time.c

index 3c8c40b67914b204f9b3f893c39be52def53cf21..2d99015034709659e5075f9c23a2a916412145dd 100644 (file)
@@ -340,6 +340,8 @@ mock_assert(const int result, const char *const expression,
  * Time
  */
 #define TIME_NOW(tp) RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
+#define TIME_NOW_HIRES(tp) \
+       RUNTIME_CHECK(isc_time_now_hires((tp)) == ISC_R_SUCCESS)
 
 /*%
  * Alignment
index e16fd3e4ed57f59dfe0ed747d06cd221f0d676d6..52e065342277fca377d0c39620e264a8b4e0a1d5 100644 (file)
@@ -128,7 +128,7 @@ isc_time_formatISO8601us_test(void **state) {
        UNUSED(state);
 
        setenv("TZ", "America/Los_Angeles", 1);
-       result = isc_time_now(&t);
+       result = isc_time_now_hires(&t);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */
@@ -236,7 +236,7 @@ isc_time_formatISO8601Lus_test(void **state) {
        UNUSED(state);
 
        setenv("TZ", "America/Los_Angeles", 1);
-       result = isc_time_now(&t);
+       result = isc_time_now_hires(&t);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */
index cb94320109029322a292a9cc58f5186986e8f500..adf56fc19d6eefa5d2f0a7aab1a583224e95c520 100644 (file)
@@ -150,6 +150,26 @@ isc_time_now(isc_time_t *t);
  *             in the current definition of isc_time_t.
  */
 
+isc_result_t
+isc_time_now_hires(isc_time_t *t);
+/*%<
+ * Set 't' to the current absolute time. Uses higher resolution clocks
+ * recommended when microsecond accuracy is required.
+ *
+ * Requires:
+ *
+ *\li  't' is a valid pointer.
+ *
+ * Returns:
+ *
+ *\li  Success
+ *\li  Unexpected error
+ *             Getting the time from the system failed.
+ *\li  Out of range
+ *             The time from the system is too large to be represented
+ *             in the current definition of isc_time_t.
+ */
+
 isc_result_t
 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
 /*%<
index b7e900aa48b9c4e12277b2b34073d3d474dbd001..9ef93879d67b1bd42860e0ece96a6728862aedf7 100644 (file)
 #define NS_PER_US 1000      /*%< Nanoseconds per microsecond. */
 #define NS_PER_MS 1000000    /*%< Nanoseconds per millisecond. */
 
+#if defined(CLOCK_REALTIME)
+#define CLOCKSOURCE_HIRES CLOCK_REALTIME
+#endif /* #if defined(CLOCK_REALTIME) */
+
 #if defined(CLOCK_REALTIME_COARSE)
 #define CLOCKSOURCE CLOCK_REALTIME_COARSE
 #elif defined(CLOCK_REALTIME_FAST)
 #define CLOCKSOURCE CLOCK_REALTIME
 #endif /* if defined(CLOCK_REALTIME_COARSE) */
 
+#if !defined(CLOCKSOURCE_HIRES)
+#define CLOCKSOURCE_HIRES CLOCKSOURCE
+#endif /* #ifndef CLOCKSOURCE_HIRES */
+
 /*%
  *** Intervals
  ***/
@@ -106,14 +114,14 @@ isc_time_isepoch(const isc_time_t *t) {
        return (false);
 }
 
-isc_result_t
-isc_time_now(isc_time_t *t) {
+static inline isc_result_t
+time_now(isc_time_t *t, clockid_t clock) {
        struct timespec ts;
        char strbuf[ISC_STRERRORSIZE];
 
        REQUIRE(t != NULL);
 
-       if (clock_gettime(CLOCKSOURCE, &ts) == -1) {
+       if (clock_gettime(clock, &ts) == -1) {
                strerror_r(errno, strbuf, sizeof(strbuf));
                UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
                return (ISC_R_UNEXPECTED);
@@ -138,6 +146,16 @@ isc_time_now(isc_time_t *t) {
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+isc_time_now_hires(isc_time_t *t) {
+       return time_now(t, CLOCKSOURCE_HIRES);
+}
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+       return time_now(t, CLOCKSOURCE);
+}
+
 isc_result_t
 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
        struct timespec ts;
index 71fda16433a1b3f1ed25db85e5fbd792e0524ab6..c52a04061c8de62d85c0069caeee996b252954c2 100644 (file)
@@ -164,6 +164,26 @@ isc_time_now(isc_time_t *t);
  *             in the current definition of isc_time_t.
  */
 
+isc_result_t
+isc_time_now_hires(isc_time_t *t);
+/*%<
+ * Set 't' to the current absolute time. Uses higher resolution clocks
+ * recommended when microsecond accuracy is required.
+ *
+ * Requires:
+ *
+ *\li  't' is a valid pointer.
+ *
+ * Returns:
+ *
+ *\li  Success
+ *\li  Unexpected error
+ *             Getting the time from the system failed.
+ *\li  Out of range
+ *             The time from the system is too large to be represented
+ *             in the current definition of isc_time_t.
+ */
+
 isc_result_t
 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
 /*
index 27f7272b04084a84afdfa62b39c2faff41bb2f92..6bfc93d7f95c52963879e07f38406d393bafae9a 100644 (file)
@@ -691,6 +691,7 @@ isc_time_isepoch
 isc_time_microdiff
 isc_time_nanoseconds
 isc_time_now
+isc_time_now_hires
 isc_time_nowplusinterval
 isc_time_parsehttptimestamp
 isc_time_secondsastimet
index d35cf5e370d68381887ecc5017fa62b39317b658..3cce3536ff3f082616ed200f8d8ab38b7067b20b 100644 (file)
@@ -124,6 +124,15 @@ isc_time_now(isc_time_t *t) {
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+isc_time_now_hires(isc_time_t *t) {
+       REQUIRE(t != NULL);
+
+       GetSystemTimePreciseAsFileTime(&t->absolute);
+
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
        ULARGE_INTEGER i1;