summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/qtime.c14
-rw-r--r--lib/qtime.h64
2 files changed, 66 insertions, 12 deletions
diff --git a/lib/qtime.c b/lib/qtime.c
index cdcf09f9..3e1e8269 100644
--- a/lib/qtime.c
+++ b/lib/qtime.c
@@ -47,7 +47,7 @@
*
* The qtime_t value is in nano-seconds.
*
- * The result from times() is in units of sysconf(_SC_CLK_TCK).
+ * The result from times() is in units of sysconf(_SC_CLK_TCK) ticks per second.
*
* NB: it is assumed that qt_craft_monotonic will be called often enough to
* ensure that it is not fooled by the clock wrapping round.
@@ -61,7 +61,7 @@
* So this should be a safe assumption -- particularly as 60, 100, 250 and
* 1000 ticks per second appear to be the popular options.
*
- * For safety, this asserts that the value is <= 1,000,000.
+ * For safety, this asserts that sysconf(_SC_CLK_TCK) <= 1,000,000.
*/
#ifdef GNU_LINUX
@@ -89,12 +89,12 @@ qt_craft_monotonic(void) {
/* clock either to jump or to get stuck ! */
#ifdef TIMES_TAKES_NULL
- this_times_sample = times(NULL) ; /* assume this saves effort ! */
+ this_times_sample = times(NULL) ; /* assume this saves effort ! */
#else
this_times_sample = times(&dummy) ;
#endif
- if (this_times_sample == (clock_t)-1)
+ if (this_times_sample == (uint64_t)-1) /* deal with theoretical error */
{
errno = 0 ;
this_times_sample = times(&dummy) ;
@@ -102,7 +102,10 @@ qt_craft_monotonic(void) {
zabort_errno("times() failed") ;
} ;
+ /* Advance the monotonic clock in sysconf(_SC_CLK_TCK) units. */
+ monotonic += (this_times_sample - last_times_sample) ;
+ /* Set up times_scale_q & times_scale_q if not yet done */
if (times_clk_tcks == 0) /* Is zero until it's initialized */
{
lldiv_t qr ;
@@ -118,8 +121,7 @@ qt_craft_monotonic(void) {
last_times_sample = this_times_sample ;
} ;
- monotonic += (this_times_sample - last_times_sample) ;
-
+ /* Scale to qtime_t units. */
if (times_scale_r == 0)
return monotonic * times_scale_q ;
else
diff --git a/lib/qtime.h b/lib/qtime.h
index 24c3eb8e..4cfdd1fb 100644
--- a/lib/qtime.h
+++ b/lib/qtime.h
@@ -88,22 +88,33 @@ qtime2timeval(struct timeval* p_tv, qtime_t qt) ;
* * Monotonic Clock
*
* Using clock_gettime(CLOCK_MONOTONIC, &ts) if it is available, otherwise
- * a manufactured equivalent using times().
+ * a manufactured equivalent using times() -- see qt_craft_monotonic().
*/
Inline qtime_t
-qt_get_timeofday(void) ; /* gettimeofday(&tv, NULL) */
-
-Inline qtime_t
qt_get_realtime(void) ; /* clock_gettime(CLOCK_REALTIME, &ts) */
Inline qtime_t
qt_get_monotonic(void) ; /* clock_gettime(CLOCK_MONOTONIC, &ts */
/* OR equivalent using times() */
+Inline qtime_t /* monotonic time from CLOCK_REALTIME */
+qt_realtime2monotonic(qtime_t realtime) ;
+Inline qtime_t /* CLOCK_REALTIME from monotonic time */
+qt_monotonic2realtime(qtime_t monotonic) ;
+
/* Function to manufacture a monotonic clock. */
extern qtime_t qt_craft_monotonic(void) ;
+/* These are provided just in case gettimeofday() != CLOCK_REALTIME */
+Inline qtime_t
+qt_get_timeofday(void) ; /* gettimeofday(&tv, NULL) */
+
+Inline qtime_t /* monotonic time from timeofday */
+qt_timeofday2monotonic(qtime_t timeofday) ;
+Inline qtime_t /* timeofday from monotonic time */
+qt_monotonic2timeofday(qtime_t monotonic) ;
+
/*==============================================================================
* Inline conversion functions
*/
@@ -115,7 +126,8 @@ extern qtime_t qt_craft_monotonic(void) ;
Inline qtime_t
timespec2qtime(struct timespec* p_ts)
{
- return ((qtime_t)(p_ts->tv_sec) * QTIME_SECOND) + p_ts->tv_nsec ;
+ return QTIME(p_ts->tv_sec) + p_ts->tv_nsec ;
+ confirm(QTIME_SECOND == TIMESPEC_SECOND) ;
} ;
/* Convert timeval to qtime_t
@@ -125,7 +137,8 @@ timespec2qtime(struct timespec* p_ts)
Inline qtime_t
timeval2qtime(struct timeval* p_tv)
{
- return ((qtime_t)(p_tv->tv_sec) * QTIME_SECOND) + (p_tv->tv_usec * 1000) ;
+ return QTIME(p_tv->tv_sec) + (p_tv->tv_usec * 1000) ;
+ confirm(QTIME_SECOND == TIMEVAL_SECOND * 1000) ;
} ;
/* Convert qtime_t to timespec
@@ -136,8 +149,11 @@ Inline struct timespec*
qtime2timespec(struct timespec* p_ts, qtime_t qt)
{
lldiv_t imd = lldiv(qt, QTIME_SECOND) ;
+ confirm(sizeof(long long) >= sizeof(qtime_t)) ;
+
p_ts->tv_sec = imd.quot ;
p_ts->tv_nsec = imd.rem ;
+ confirm(TIMESPEC_SECOND == QTIME_SECOND) ;
return p_ts ;
} ;
@@ -150,8 +166,11 @@ Inline struct timeval*
qtime2timeval(struct timeval* p_tv, qtime_t qt)
{
lldiv_t imd = lldiv(qt, QTIME_SECOND) ;
+ confirm(sizeof(long long) >= sizeof(qtime_t)) ;
+
p_tv->tv_sec = imd.quot ;
p_tv->tv_usec = imd.rem / 1000 ;
+ confirm(TIMEVAL_SECOND * 1000 == QTIME_SECOND) ;
return p_tv ;
} ;
@@ -211,4 +230,37 @@ qt_get_monotonic(void)
#endif
} ;
+/*==============================================================================
+ * Conversion between realtime/timeofday and monotonic
+ *
+ */
+
+/* Convert a CLOCK_REALTIME time to our local monotonic time. */
+Inline qtime_t
+qt_realtime2monotonic(qtime_t realtime)
+{
+ return qt_get_monotonic() + (realtime - qt_get_realtime()) ;
+} ;
+
+/* Convert a local monotonic time to CLOCK_REALTIME time. */
+Inline qtime_t
+qt_monotonic2realtime(qtime_t monotonic)
+{
+ return qt_get_realtime() + (monotonic - qt_get_monotonic()) ;
+} ;
+
+/* Convert a gettimeofday() time to our local monotonic time. */
+Inline qtime_t
+qt_timeofday2monotonic(qtime_t timeofday)
+{
+ return qt_get_monotonic() + (timeofday - qt_get_timeofday()) ;
+} ;
+
+/* Convert a local monotonic time to gettimeofday() time. */
+Inline qtime_t
+qt_monotonic2timeofday(qtime_t monotonic)
+{
+ return qt_get_timeofday() + (monotonic - qt_get_monotonic()) ;
+} ;
+
#endif /* _ZEBRA_QTIME_H */