diff options
Diffstat (limited to 'libglusterfs/src/timespec.c')
| -rw-r--r-- | libglusterfs/src/timespec.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/libglusterfs/src/timespec.c b/libglusterfs/src/timespec.c new file mode 100644 index 00000000000..96cef5c6f07 --- /dev/null +++ b/libglusterfs/src/timespec.c @@ -0,0 +1,129 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <stdio.h> +#include <inttypes.h> +#include <time.h> +#include <sys/time.h> +#include <string.h> + +#if defined GF_DARWIN_HOST_OS +#include <mach/mach_time.h> +static mach_timebase_info_data_t gf_timebase; +#endif + +#include "glusterfs/timespec.h" +#include "glusterfs/libglusterfs-messages.h" +#include "glusterfs/common-utils.h" + +void +timespec_now(struct timespec *ts) +{ +#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || \ + defined GF_BSD_HOST_OS + if (0 == clock_gettime(CLOCK_MONOTONIC, ts)) { + /* All good */ + return; + } + + /* Fall back, but there is hope in gettimeofday() syscall */ + struct timeval tv; + if (0 == gettimeofday(&tv, NULL)) { + /* Again, all good */ + TIMEVAL_TO_TIMESPEC(&tv, ts); + return; + } + + /* If control hits here, there is surely a problem, + mainly because, as per man page too, these syscalls + shouldn't fail. Best way is to ABORT, because it is + not right */ + GF_ABORT("gettimeofday() failed!!"); + +#elif defined GF_DARWIN_HOST_OS + uint64_t time = mach_absolute_time(); + static double scaling = 0.0; + + if (mach_timebase_info(&gf_timebase) != KERN_SUCCESS) { + gf_timebase.numer = 1; + gf_timebase.denom = 1; + } + if (gf_timebase.denom == 0) { + gf_timebase.numer = 1; + gf_timebase.denom = 1; + } + + scaling = (double)gf_timebase.numer / (double)gf_timebase.denom; + time *= scaling; + + ts->tv_sec = (time * NANO); + ts->tv_nsec = (time - (ts->tv_sec * GIGA)); + +#endif /* Platform verification */ +} + +void +timespec_now_realtime(struct timespec *ts) +{ +#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || \ + defined GF_BSD_HOST_OS + if (0 == clock_gettime(CLOCK_REALTIME, ts)) { + return; + } +#endif + + /* Fall back to gettimeofday()*/ + struct timeval tv = { + 0, + }; + if (0 == gettimeofday(&tv, NULL)) { + TIMEVAL_TO_TIMESPEC(&tv, ts); + return; + } + + return; +} + +void +timespec_adjust_delta(struct timespec *ts, struct timespec delta) +{ + ts->tv_nsec = ((ts->tv_nsec + delta.tv_nsec) % 1000000000); + ts->tv_sec += ((ts->tv_nsec + delta.tv_nsec) / 1000000000); + ts->tv_sec += delta.tv_sec; +} + +void +timespec_sub(const struct timespec *begin, const struct timespec *end, + struct timespec *res) +{ + if (end->tv_nsec < begin->tv_nsec) { + res->tv_sec = end->tv_sec - begin->tv_sec - 1; + res->tv_nsec = end->tv_nsec + 1000000000 - begin->tv_nsec; + } else { + res->tv_sec = end->tv_sec - begin->tv_sec; + res->tv_nsec = end->tv_nsec - begin->tv_nsec; + } +} + +int +timespec_cmp(const struct timespec *lhs_ts, const struct timespec *rhs_ts) +{ + if (lhs_ts->tv_sec < rhs_ts->tv_sec) { + return -1; + } else if (lhs_ts->tv_sec > rhs_ts->tv_sec) { + return 1; + } else if (lhs_ts->tv_nsec < rhs_ts->tv_nsec) { + return -1; + } else if (lhs_ts->tv_nsec > rhs_ts->tv_nsec) { + return 1; + } + + return 0; +} |
