From a64ada2c833ec88d770ff993226700427154a724 Mon Sep 17 00:00:00 2001 From: michalbiesek <39981869+michalbiesek@users.noreply.github.com> Date: Thu, 27 Jun 2019 09:26:49 +0200 Subject: [PATCH] cc: extend duration module (#192) - add fast (low overhead) duration timers for linux - add duration compare method --- include/time/cc_timer.h | 23 ++++++++++++++++++++- src/time/cc_timer_darwin.c | 6 ++++++ src/time/cc_timer_linux.c | 42 +++++++++++++++++++++++++++----------- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/include/time/cc_timer.h b/include/time/cc_timer.h index 6a8c382ee..86b871a7a 100644 --- a/include/time/cc_timer.h +++ b/include/time/cc_timer.h @@ -49,6 +49,14 @@ struct duration; /* data structure to measure duration */ * relationship between this unit and nanosecond can be obtained via another * syscall */ + +enum duration_type { + DURATION_PRECISE, /* default */ + DURATION_FAST, + + MAX_DURATION_TYPE +}; + #ifdef OS_DARWIN struct duration { bool started; @@ -58,6 +66,7 @@ struct duration { }; #elif defined OS_LINUX struct duration { + enum duration_type type; bool started; bool stopped; struct timespec start; @@ -86,12 +95,12 @@ struct timeout { bool is_intvl; }; - /* update duration */ void duration_reset(struct duration *d); /* get a reading of duration and copy it without stopping the original timer */ void duration_snapshot(struct duration *s, const struct duration *d); void duration_start(struct duration *d); +void duration_start_type(struct duration *d, enum duration_type type); void duration_stop(struct duration *d); /* read duration */ double duration_ns(struct duration *d); @@ -99,6 +108,18 @@ double duration_us(struct duration *d); double duration_ms(struct duration *d); double duration_sec(struct duration *d); +static inline int +duration_compare(const void *lhs, const void *rhs) +{ + double lns = duration_ns((struct duration *)lhs); + double rns = duration_ns((struct duration *)rhs); + if (lns < rns) + return -1; + if (lns > rns) + return 1; + + return 0; +} /* * Not all possible granularity can be meaningfully used for sleep or event. diff --git a/src/time/cc_timer_darwin.c b/src/time/cc_timer_darwin.c index 3127643be..a6c4110b1 100644 --- a/src/time/cc_timer_darwin.c +++ b/src/time/cc_timer_darwin.c @@ -72,6 +72,12 @@ duration_start(struct duration *d) d->start = mach_absolute_time(); } +void +duration_start_type(struct duration *d, enum duration_type type) +{ + duration_start(d); +} + void duration_stop(struct duration *d) { diff --git a/src/time/cc_timer_linux.c b/src/time/cc_timer_linux.c index 778fedf98..29de5306b 100644 --- a/src/time/cc_timer_linux.c +++ b/src/time/cc_timer_linux.c @@ -25,24 +25,35 @@ * CLOCK_REALTIME can be reset when clock has drifted, so it may not always be * monotonic, and should be avoided if possible. */ +static const clockid_t cid[MAX_DURATION_TYPE] = { + [DURATION_PRECISE] = #if defined(CLOCK_MONOTONIC_RAW) -static const clockid_t cid = CLOCK_MONOTONIC_RAW; + CLOCK_MONOTONIC_RAW #elif defined(CLOCK_MONOTONIC) -static const clockid_t cid = CLOCK_MONOTONIC; + CLOCK_MONOTONIC #elif defined(CLOCK_REALTIME) -static const clockid_t cid = CLOCK_REALTIME; + CLOCK_REALTIME #else -static const clockid_t cid = (clockid_t)-1; + (clockid_t)-1 #endif +, +#if defined(CLOCK_MONOTONIC) + CLOCK_MONOTONIC +#elif defined(CLOCK_REALTIME) + CLOCK_REALTIME +#else + (clockid_t)-1 +#endif +}; static inline void -_gettime(struct timespec *ts) +_gettime(struct timespec *ts, enum duration_type type) { int ret; - ASSERT(cid != (clockid_t)-1); + ASSERT(cid[type] != (clockid_t)-1); - ret = clock_gettime(cid, ts); + ret = clock_gettime(cid[type], ts); if (ret == -1) { /* * Note(yao): for the purpose of this module, it doesn't make much sense @@ -73,10 +84,17 @@ duration_reset(struct duration *d) void duration_start(struct duration *d) +{ + duration_start_type(d, DURATION_PRECISE); +} + +void +duration_start_type(struct duration *d, enum duration_type type) { ASSERT(d != NULL); - _gettime(&d->start); + _gettime(&d->start, type); + d->type = type; d->started = true; } @@ -87,8 +105,9 @@ duration_snapshot(struct duration *s, const struct duration *d) s->started = true; s->start = d->start; + s->type = d->type; s->stopped = true; - _gettime(&s->stop); + _gettime(&s->stop, s->type); } void @@ -96,7 +115,7 @@ duration_stop(struct duration *d) { ASSERT(d != NULL); - _gettime(&d->stop); + _gettime(&d->stop, d->type); d->stopped = true; } @@ -153,9 +172,8 @@ _now_ns(void) { struct timespec now; - _gettime(&now); + _gettime(&now, cid[DURATION_PRECISE]); return now.tv_sec * NSEC_PER_SEC + now.tv_nsec; - } void