summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-11-27 20:55:51 -0500
committerTavian Barnes <tavianator@tavianator.com>2024-12-02 16:34:26 -0500
commitbac8214e90488fd562d29f6fea18ae75ecd9029e (patch)
tree0ce8c582da2d00e36c93dea8744e0048820f33c9 /src
parent7855b9ad9164ae7ea99a00641f3eadb56015ffc6 (diff)
downloadbfs-bac8214e90488fd562d29f6fea18ae75ecd9029e.tar.xz
xtime: New timespec utility functions
Diffstat (limited to 'src')
-rw-r--r--src/eval.c29
-rw-r--r--src/xtime.c53
-rw-r--r--src/xtime.h36
3 files changed, 95 insertions, 23 deletions
diff --git a/src/eval.c b/src/eval.c
index 6e9fffd..d632e7c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -137,11 +137,9 @@ static const struct bfs_stat *eval_stat(struct bfs_eval *state) {
* Get the difference (in seconds) between two struct timespecs.
*/
static time_t timespec_diff(const struct timespec *lhs, const struct timespec *rhs) {
- time_t ret = lhs->tv_sec - rhs->tv_sec;
- if (lhs->tv_nsec < rhs->tv_nsec) {
- --ret;
- }
- return ret;
+ struct timespec diff = *lhs;
+ timespec_sub(&diff, rhs);
+ return diff.tv_sec;
}
bool bfs_expr_cmp(const struct bfs_expr *expr, long long n) {
@@ -260,8 +258,7 @@ bool eval_newer(const struct bfs_expr *expr, struct bfs_eval *state) {
return false;
}
- return time->tv_sec > expr->reftime.tv_sec
- || (time->tv_sec == expr->reftime.tv_sec && time->tv_nsec > expr->reftime.tv_nsec);
+ return timespec_cmp(time, &expr->reftime) > 0;
}
/**
@@ -1047,21 +1044,6 @@ static int eval_gettime(struct bfs_eval *state, struct timespec *ts) {
}
/**
- * Record an elapsed time.
- */
-static void timespec_elapsed(struct timespec *elapsed, const struct timespec *start, const struct timespec *end) {
- elapsed->tv_sec += end->tv_sec - start->tv_sec;
- elapsed->tv_nsec += end->tv_nsec - start->tv_nsec;
- if (elapsed->tv_nsec < 0) {
- elapsed->tv_nsec += 1000000000L;
- --elapsed->tv_sec;
- } else if (elapsed->tv_nsec >= 1000000000L) {
- elapsed->tv_nsec -= 1000000000L;
- ++elapsed->tv_sec;
- }
-}
-
-/**
* Evaluate an expression.
*/
static bool eval_expr(struct bfs_expr *expr, struct bfs_eval *state) {
@@ -1079,7 +1061,8 @@ static bool eval_expr(struct bfs_expr *expr, struct bfs_eval *state) {
if (time) {
if (eval_gettime(state, &end) == 0) {
- timespec_elapsed(&expr->elapsed, &start, &end);
+ timespec_sub(&end, &start);
+ timespec_add(&expr->elapsed, &end);
}
}
diff --git a/src/xtime.c b/src/xtime.c
index 49d7c36..6b8a141 100644
--- a/src/xtime.c
+++ b/src/xtime.c
@@ -354,6 +354,59 @@ error:
return -1;
}
+/** One nanosecond. */
+static const long NS = 1000L * 1000 * 1000;
+
+void timespec_add(struct timespec *lhs, const struct timespec *rhs) {
+ lhs->tv_sec += rhs->tv_sec;
+ lhs->tv_nsec += rhs->tv_nsec;
+ if (lhs->tv_nsec >= NS) {
+ lhs->tv_nsec -= NS;
+ lhs->tv_sec += 1;
+ }
+}
+
+void timespec_sub(struct timespec *lhs, const struct timespec *rhs) {
+ lhs->tv_sec -= rhs->tv_sec;
+ lhs->tv_nsec -= rhs->tv_nsec;
+ if (lhs->tv_nsec < 0) {
+ lhs->tv_nsec += NS;
+ lhs->tv_sec -= 1;
+ }
+}
+
+int timespec_cmp(const struct timespec *lhs, const struct timespec *rhs) {
+ if (lhs->tv_sec < rhs->tv_sec) {
+ return -1;
+ } else if (lhs->tv_sec > rhs->tv_sec) {
+ return 1;
+ }
+
+ if (lhs->tv_nsec < rhs->tv_nsec) {
+ return -1;
+ } else if (lhs->tv_nsec > rhs->tv_nsec) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void timespec_min(struct timespec *dest, const struct timespec *src) {
+ if (timespec_cmp(src, dest) < 0) {
+ *dest = *src;
+ }
+}
+
+void timespec_max(struct timespec *dest, const struct timespec *src) {
+ if (timespec_cmp(src, dest) > 0) {
+ *dest = *src;
+ }
+}
+
+double timespec_ns(const struct timespec *ts) {
+ return 1.0e9 * ts->tv_sec + ts->tv_nsec;
+}
+
#if defined(_POSIX_TIMERS) && BFS_HAS_TIMER_CREATE
# define BFS_POSIX_TIMERS _POSIX_TIMERS
#else
diff --git a/src/xtime.h b/src/xtime.h
index 2927a2e..b76fef2 100644
--- a/src/xtime.h
+++ b/src/xtime.h
@@ -47,6 +47,42 @@ int xtimegm(struct tm *tm, time_t *timep);
int xgetdate(const char *str, struct timespec *result);
/**
+ * Add to a timespec.
+ */
+void timespec_add(struct timespec *lhs, const struct timespec *rhs);
+
+/**
+ * Subtract from a timespec.
+ */
+void timespec_sub(struct timespec *lhs, const struct timespec *rhs);
+
+/**
+ * Compare two timespecs.
+ *
+ * @return
+ * An integer with the sign of (*lhs - *rhs).
+ */
+int timespec_cmp(const struct timespec *lhs, const struct timespec *rhs);
+
+/**
+ * Update a minimum timespec.
+ */
+void timespec_min(struct timespec *dest, const struct timespec *src);
+
+/**
+ * Update a maximum timespec.
+ */
+void timespec_max(struct timespec *dest, const struct timespec *src);
+
+/**
+ * Convert a timespec to floating point.
+ *
+ * @return
+ * The value in nanoseconds.
+ */
+double timespec_ns(const struct timespec *ts);
+
+/**
* A timer.
*/
struct timer;