diff options
author | Niklas Hambüchen <mail@nh2.me> | 2017-09-19 15:09:29 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-09-19 15:58:45 -0400 |
commit | 28a115e5e2c3c19b860545f1fcde4317bac3ee2a (patch) | |
tree | 35b97efde537ab5d79bb9abe4cf71c7a9c2d8961 /libraries/base/cbits/inputReady.c | |
parent | 7c7914d02a7ff189aba2f4feca31366fb4ab2664 (diff) | |
download | haskell-28a115e5e2c3c19b860545f1fcde4317bac3ee2a.tar.gz |
base: fdReady(): Improve accuracy and simplify code.
This is done by reusing the existing cross-platform
`getProcessElapsedTime()` function, which already provides nanosecond
monotonic clocks, and fallback for platforms that don't have those.
To do this, `getProcessElapsedTime()` had to be moved from a private RTS
symbol into the public interface.
Accuracy is improved in 2 ways:
* Use of the monotonic clock where available
* Measuring the total time spent waiting instead of a sum
of intervals (between which there are small gaps)
Reviewers: bgamari, austin, hvr, erikd, simonmar
Reviewed By: bgamari
Subscribers: rwbarton, thomie
Differential Revision: https://phabricator.haskell.org/D3953
Diffstat (limited to 'libraries/base/cbits/inputReady.c')
-rw-r--r-- | libraries/base/cbits/inputReady.c | 31 |
1 files changed, 10 insertions, 21 deletions
diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c index e27851a2c7..dbfdb28b70 100644 --- a/libraries/base/cbits/inputReady.c +++ b/libraries/base/cbits/inputReady.c @@ -7,9 +7,9 @@ /* select and supporting types is not Posix */ /* #include "PosixSource.h" */ #include "HsBase.h" +#include "Rts.h" #if !defined(_WIN32) #include <poll.h> -#include <sys/time.h> #endif /* @@ -25,37 +25,26 @@ fdReady(int fd, int write, int msecs, int isSock) #if !defined(_WIN32) struct pollfd fds[1]; - // if we need to track the then record the current time in case we are + // if we need to track the time then record the end time in case we are // interrupted. - struct timeval tv0; + Time endTime = 0; if (msecs > 0) { - if (gettimeofday(&tv0, NULL) != 0) { - fprintf(stderr, "fdReady: gettimeofday failed: %s\n", - strerror(errno)); - abort(); - } + endTime = getProcessElapsedTime() + MSToTime(msecs); } fds[0].fd = fd; fds[0].events = write ? POLLOUT : POLLIN; fds[0].revents = 0; + Time remaining = MSToTime(msecs); + int res; - while ((res = poll(fds, 1, msecs)) < 0) { + while ((res = poll(fds, 1, TimeToMS(remaining))) < 0) { if (errno == EINTR) { if (msecs > 0) { - struct timeval tv; - if (gettimeofday(&tv, NULL) != 0) { - fprintf(stderr, "fdReady: gettimeofday failed: %s\n", - strerror(errno)); - abort(); - } - - int elapsed = 1000 * (tv.tv_sec - tv0.tv_sec) - + (tv.tv_usec - tv0.tv_usec) / 1000; - msecs -= elapsed; - if (msecs <= 0) return 0; - tv0 = tv; + Time now = getProcessElapsedTime(); + if (now >= endTime) return 0; + remaining = endTime - now; } } else { return (-1); |