summaryrefslogtreecommitdiff
path: root/Src/utils.c
diff options
context:
space:
mode:
authorCedric Ware <cedric.ware__bml@normalesup.org>2020-04-20 12:10:01 -0500
committerdana <dana@dana.is>2020-04-20 12:10:01 -0500
commit25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae (patch)
tree120e8f1e11ab3791b6fbe1d6302dda275d09c2ac /Src/utils.c
parentf179dbf72a4f482c1ad513b7c58cd7f96c7cf7f3 (diff)
downloadzsh-25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae.tar.gz
zsh-25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae.zip
45708: zsh/system: Enable sub-second timeout in zsystem flock
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c
index 69885fed3..e258ef836 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2749,6 +2749,42 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds)
}
/*
+ * Return the difference between 2 times, given as struct timespec*,
+ * expressed in microseconds, as a long. If the difference doesn't fit
+ * into a long, return LONG_MIN or LONG_MAX so that the times can still
+ * be compared.
+ *
+ * Note: returns a long rather than a zlong because zsleep() below
+ * takes a long.
+ */
+
+/**/
+long
+timespec_diff_us(const struct timespec *t1, const struct timespec *t2)
+{
+ int reverse = (t1->tv_sec > t2->tv_sec);
+ time_t diff_sec;
+ long diff_usec, max_margin, res;
+
+ /* Don't just subtract t2-t1 because time_t might be unsigned. */
+ diff_sec = (reverse ? t1->tv_sec - t2->tv_sec : t2->tv_sec - t1->tv_sec);
+ if (diff_sec > LONG_MAX / 1000000L) {
+ goto overflow;
+ }
+ res = diff_sec * 1000000L;
+ max_margin = LONG_MAX - res;
+ diff_usec = (reverse ?
+ t1->tv_nsec - t2->tv_nsec : t2->tv_nsec - t1->tv_nsec
+ ) / 1000;
+ if (diff_usec <= max_margin) {
+ res += diff_usec;
+ return (reverse ? -res : res);
+ }
+ overflow:
+ return (reverse ? LONG_MIN : LONG_MAX);
+}
+
+/*
* Sleep for the given number of microseconds --- must be within
* range of a long at the moment, but this is only used for
* limited internal purposes.