Commit ebced74b authored by Patrick McLean's avatar Patrick McLean Committed by Evan Hunt
Browse files

Add isc_time_now_hires function to get current time with high resolution

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.
parent bee4ee93
......@@ -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
......
......@@ -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 */
......
......@@ -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);
/*%<
......
......@@ -33,6 +33,10 @@
#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)
......@@ -41,6 +45,10 @@
#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;
......
......@@ -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);
/*
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment