aboutsummaryrefslogtreecommitdiff
path: root/support/timespec.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/timespec.c')
-rw-r--r--support/timespec.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/support/timespec.c b/support/timespec.c
index ea6b947..9f5449e 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);
+}