Flesh out time_*() API.

This commit is contained in:
Jason Evans 2016-02-19 12:35:37 -08:00
parent e5d5a4a517
commit 94451d184b
8 changed files with 397 additions and 56 deletions

View file

@ -1,11 +1,160 @@
#include "jemalloc/internal/jemalloc_internal.h"
#define BILLION 1000000000
UNUSED static bool
time_valid(const struct timespec *time)
{
if (time->tv_sec > TIME_SEC_MAX)
return (false);
if (time->tv_nsec >= BILLION)
return (false);
return (true);
}
void
time_init(struct timespec *time, time_t sec, long nsec)
{
time->tv_sec = sec;
time->tv_nsec = nsec;
assert(time_valid(time));
}
time_t
time_sec(const struct timespec *time)
{
assert(time_valid(time));
return (time->tv_sec);
}
long
time_nsec(const struct timespec *time)
{
assert(time_valid(time));
return (time->tv_nsec);
}
void
time_copy(struct timespec *time, const struct timespec *source)
{
assert(time_valid(source));
*time = *source;
}
int
time_compare(const struct timespec *a, const struct timespec *b)
{
int ret;
assert(time_valid(a));
assert(time_valid(b));
ret = (a->tv_sec > b->tv_sec) - (a->tv_sec < b->tv_sec);
if (ret == 0)
ret = (a->tv_nsec > b->tv_nsec) - (a->tv_nsec < b->tv_nsec);
return (ret);
}
void
time_add(struct timespec *time, const struct timespec *addend)
{
assert(time_valid(time));
assert(time_valid(addend));
time->tv_sec += addend->tv_sec;
time->tv_nsec += addend->tv_nsec;
if (time->tv_nsec >= BILLION) {
time->tv_sec++;
time->tv_nsec -= BILLION;
}
assert(time_valid(time));
}
void
time_subtract(struct timespec *time, const struct timespec *subtrahend)
{
assert(time_valid(time));
assert(time_valid(subtrahend));
assert(time_compare(time, subtrahend) >= 0);
time->tv_sec -= subtrahend->tv_sec;
if (time->tv_nsec < subtrahend->tv_nsec) {
time->tv_sec--;
time->tv_nsec += BILLION;
}
time->tv_nsec -= subtrahend->tv_nsec;
}
void
time_imultiply(struct timespec *time, uint64_t multiplier)
{
time_t sec;
uint64_t nsec;
assert(time_valid(time));
sec = time->tv_sec * multiplier;
nsec = time->tv_nsec * multiplier;
sec += nsec / BILLION;
nsec %= BILLION;
time_init(time, sec, (long)nsec);
assert(time_valid(time));
}
void
time_idivide(struct timespec *time, uint64_t divisor)
{
time_t sec;
uint64_t nsec;
assert(time_valid(time));
sec = time->tv_sec / divisor;
nsec = ((time->tv_sec % divisor) * BILLION + time->tv_nsec) / divisor;
sec += nsec / BILLION;
nsec %= BILLION;
time_init(time, sec, (long)nsec);
assert(time_valid(time));
}
uint64_t
time_divide(const struct timespec *time, const struct timespec *divisor)
{
uint64_t t, d;
assert(time_valid(time));
assert(time_valid(divisor));
t = time_sec(time) * BILLION + time_nsec(time);
d = time_sec(divisor) * BILLION + time_nsec(divisor);
assert(d != 0);
return (t / d);
}
bool
time_update(struct timespec *time)
{
struct timespec old_time;
memcpy(&old_time, time, sizeof(struct timespec));
assert(time_valid(time));
time_copy(&old_time, time);
#ifdef _WIN32
FILETIME ft;
@ -27,10 +176,11 @@ time_update(struct timespec *time)
#endif
/* Handle non-monotonic clocks. */
if (unlikely(old_time.tv_sec > time->tv_sec))
if (unlikely(time_compare(&old_time, time) > 0)) {
time_copy(time, &old_time);
return (true);
if (unlikely(old_time.tv_sec == time->tv_sec))
return old_time.tv_nsec > time->tv_nsec;
}
assert(time_valid(time));
return (false);
}