diff options
Diffstat (limited to 'support/timespec.c')
-rw-r--r-- | support/timespec.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/support/timespec.c b/support/timespec.c index ea6b947546..9f5449e49e 100644 --- a/support/timespec.c +++ b/support/timespec.c @@ -19,6 +19,8 @@ #include <support/timespec.h> #include <stdio.h> #include <stdint.h> +#include <assert.h> +#include <intprops.h> void test_timespec_before_impl (const char *file, int line, @@ -57,3 +59,65 @@ test_timespec_equal_or_after_impl (const char *file, int line, (intmax_t) diff.tv_sec, (intmax_t) diff.tv_nsec); } } + +/* Convert TIME to nanoseconds stored in a long. + Returns long maximum or minimum if the conversion overflows + or underflows, respectively. */ +long +support_timespec_ns (struct timespec time) +{ + long time_ns; + if (INT_MULTIPLY_WRAPV(time.tv_sec, TIMESPEC_HZ, &time_ns)) + { + return (time.tv_sec < 0) ? TYPE_MINIMUM(long): TYPE_MAXIMUM(long); + } + if (INT_ADD_WRAPV(time_ns, time.tv_nsec, &time_ns)) + { + return (time.tv_nsec < 0) ? TYPE_MINIMUM(long): TYPE_MAXIMUM(long); + } + return time_ns; +} + +/* Returns time normalized timespec with .tv_nsec < TIMESPEC_HZ + and the whole seconds added to .tv_sec. If an overflow or + underflow occurs the values are clamped to its maximum or + minimum respectively. */ +struct timespec +support_timespec_normalize (struct timespec time) +{ + struct timespec norm; + if (INT_ADD_WRAPV (time.tv_sec, (time.tv_nsec / TIMESPEC_HZ), &norm.tv_sec)) + { + norm.tv_sec = (time.tv_nsec < 0) ? TYPE_MINIMUM (time_t): TYPE_MAXIMUM (time_t); + norm.tv_nsec = (time.tv_nsec < 0) ? -1 * (TIMESPEC_HZ - 1) : TIMESPEC_HZ - 1; + return norm; + } + norm.tv_nsec = time.tv_nsec % TIMESPEC_HZ; + return norm; +} + +/* Returns TRUE if the observed time is within the given percentage + bounds of the expected time, and FALSE otherwise. + For example the call + + support_timespec_check_in_range(expected, observed, 0.5, 1.2); + + will check if + + 0.5 of expected <= observed <= 1.2 of expected + + In other words it will check if observed time is within 50% to + 120% of the expected time. */ +int +support_timespec_check_in_range (struct timespec expected, struct timespec observed, + double lower_bound, double upper_bound) +{ + assert (upper_bound >= lower_bound); + long expected_norm, observed_norm; + expected_norm = support_timespec_ns (expected); + /* Don't divide by zero */ + assert(expected_norm != 0); + observed_norm = support_timespec_ns (observed); + double ratio = (double)observed_norm / expected_norm; + return (lower_bound <= ratio && ratio <= upper_bound); +} |