Introduce a new function for querying the monotonic clock, something that
is necessary in every context where relative time is measured and where
wall clock time jumps should have no effect. Remove fill_clock_gettime()
since the only contexts where CLOCK_MONOTONIC_RAW are used are
get_cycles_per_msec() and --clocksource=clock_gettime. I think both contexts
should use CLOCK_MONOTONIC instead of its raw variant such that the values
read from the clock are frequency adjusted (a computer clock crystal can
deviate up to 500 ppm from its nominal frequency).
This patch improves accuracy of the helper_thread code on Darwin. Darwin
supports CLOCK_MONOTONIC but not pthread_condattr_setclock(). In other
words, this patch causes the helper thread code to switch from the
real-time clock to the monotonic clock on Darwin.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
fi
print_config "CLOCK_MONOTONIC" "$clock_monotonic"
fi
print_config "CLOCK_MONOTONIC" "$clock_monotonic"
-##########################################
-# CLOCK_MONOTONIC_RAW probe
-if test "$clock_monotonic_raw" != "yes" ; then
- clock_monotonic_raw="no"
-fi
-if test "$clock_gettime" = "yes" ; then
- cat > $TMPC << EOF
-#include <stdio.h>
-#include <time.h>
-int main(int argc, char **argv)
-{
- return clock_gettime(CLOCK_MONOTONIC_RAW, NULL);
-}
-EOF
- if compile_prog "" "$LIBS" "clock monotonic"; then
- clock_monotonic_raw="yes"
- fi
-fi
-print_config "CLOCK_MONOTONIC_RAW" "$clock_monotonic_raw"
-
##########################################
# clockid_t probe
if test "$clockid_t" != "yes" ; then
##########################################
# clockid_t probe
if test "$clockid_t" != "yes" ; then
-static int fill_timespec(struct timespec *ts)
+static unsigned long long ts_utime_since_now(const struct timespec *start)
-#ifdef CONFIG_CLOCK_GETTIME
-#ifdef CONFIG_CLOCK_MONOTONIC
- clockid_t clk = CLOCK_MONOTONIC;
-#else
- clockid_t clk = CLOCK_REALTIME;
-#endif
- if (!clock_gettime(clk, ts))
- return 0;
-
- perror("clock_gettime");
- return 1;
-#else
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
- return 0;
-#endif
-}
-
-static unsigned long long ts_utime_since_now(struct timespec *t)
-{
- long long sec, nsec;
- if (fill_timespec(&now))
+ if (fio_get_mono_time(&now) < 0)
-
- sec = now.tv_sec - t->tv_sec;
- nsec = now.tv_nsec - t->tv_nsec;
- if (sec > 0 && nsec < 0) {
- sec--;
- nsec += 1000000000;
- }
- sec *= 1000000;
- nsec /= 1000;
- return sec + nsec;
+ return utime_since(start, &now);
}
static int fio_posixaio_cancel(struct thread_data fio_unused *td,
}
static int fio_posixaio_cancel(struct thread_data fio_unused *td,
- if (t && !fill_timespec(&start))
+ if (t && fio_get_mono_time(&start) == 0)
have_timeout = 1;
else
memset(&start, 0, sizeof(start));
have_timeout = 1;
else
memset(&start, 0, sizeof(start));
#endif /* FIO_DEBUG_TIME */
#endif /* FIO_DEBUG_TIME */
-#ifdef CONFIG_CLOCK_GETTIME
-static int fill_clock_gettime(struct timespec *ts)
+/*
+ * Queries the value of the monotonic clock if a monotonic clock is available
+ * or the wall clock time if no monotonic clock is available. Returns 0 if
+ * querying the clock succeeded or -1 if querying the clock failed.
+ */
+int fio_get_mono_time(struct timespec *ts)
-#if defined(CONFIG_CLOCK_MONOTONIC_RAW)
- return clock_gettime(CLOCK_MONOTONIC_RAW, ts);
-#elif defined(CONFIG_CLOCK_MONOTONIC)
- return clock_gettime(CLOCK_MONOTONIC, ts);
+ int ret;
+
+#ifdef CONFIG_CLOCK_GETTIME
+#if defined(CONFIG_CLOCK_MONOTONIC)
+ ret = clock_gettime(CLOCK_MONOTONIC, ts);
- return clock_gettime(CLOCK_REALTIME, ts);
+ ret = clock_gettime(CLOCK_REALTIME, ts);
+#else
+ struct timeval tv;
+
+ ret = gettimeofday(&tv, NULL);
+ if (ret == 0) {
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+ }
+ assert(ret <= 0);
+ return ret;
+}
static void __fio_gettime(struct timespec *tp)
{
static void __fio_gettime(struct timespec *tp)
{
#endif
#ifdef CONFIG_CLOCK_GETTIME
case CS_CGETTIME: {
#endif
#ifdef CONFIG_CLOCK_GETTIME
case CS_CGETTIME: {
- if (fill_clock_gettime(tp) < 0) {
- log_err("fio: clock_gettime fails\n");
+ if (fio_get_mono_time(tp) < 0) {
+ log_err("fio: fio_get_mono_time() fails\n");
+extern int fio_get_mono_time(struct timespec *);
extern void fio_gettime(struct timespec *, void *);
extern void fio_gtod_init(void);
extern void fio_clock_init(void);
extern void fio_gettime(struct timespec *, void *);
extern void fio_gtod_init(void);
extern void fio_clock_init(void);
-#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
- clock_gettime(CLOCK_MONOTONIC, &ts);
-#else
- clock_gettime(CLOCK_REALTIME, &ts);
-#endif
+ fio_get_mono_time(&ts);
memcpy(&last_du, &ts, sizeof(ts));
memcpy(&last_ss, &ts, sizeof(ts));
memcpy(&last_si, &ts, sizeof(ts));
memcpy(&last_du, &ts, sizeof(ts));
memcpy(&last_ss, &ts, sizeof(ts));
memcpy(&last_si, &ts, sizeof(ts));
-#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK
- clock_gettime(CLOCK_MONOTONIC, &ts);
-#else
- clock_gettime(CLOCK_REALTIME, &ts);
-#endif
+ fio_get_mono_time(&ts);
if (action == A_RESET) {
last_du = ts;
if (action == A_RESET) {
last_du = ts;