diff options
author | Cedric Ware <cedric.ware__bml@normalesup.org> | 2020-04-20 12:10:01 -0500 |
---|---|---|
committer | dana <dana@dana.is> | 2020-04-20 12:10:01 -0500 |
commit | 25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae (patch) | |
tree | 120e8f1e11ab3791b6fbe1d6302dda275d09c2ac /Src/utils.c | |
parent | f179dbf72a4f482c1ad513b7c58cd7f96c7cf7f3 (diff) | |
download | zsh-25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae.tar.gz zsh-25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae.tar.xz zsh-25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae.zip |
45708: zsh/system: Enable sub-second timeout in zsystem flock
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 36 |
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. |