Commit 28a115e5 authored by Niklas Hambüchen's avatar Niklas Hambüchen Committed by Ben Gamari

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
parent 7c7914d0
......@@ -21,8 +21,10 @@ typedef int64_t Time;
#if TIME_RESOLUTION == 1000000000
// I'm being lazy, but it's awkward to define fully general versions of these
#define TimeToMS(t) ((t) / 1000000)
#define TimeToUS(t) ((t) / 1000)
#define TimeToNS(t) (t)
#define MSToTime(t) ((Time)(t) * 1000000)
#define USToTime(t) ((Time)(t) * 1000)
#define NSToTime(t) ((Time)(t))
#else
......@@ -38,3 +40,5 @@ INLINE_HEADER Time fsecondsToTime (double t)
{
return (Time)(t * TIME_RESOLUTION);
}
Time getProcessElapsedTime (void);
......@@ -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);
......
......@@ -13,7 +13,6 @@
void initializeTimer (void);
Time getProcessCPUTime (void);
Time getProcessElapsedTime (void);
void getProcessTimes (Time *user, Time *elapsed);
/* Get the current date and time.
......
......@@ -605,6 +605,7 @@
SymI_HasProto(getFullProgArgv) \
SymI_HasProto(setFullProgArgv) \
SymI_HasProto(freeFullProgArgv) \
SymI_HasProto(getProcessElapsedTime) \
SymI_HasProto(getStablePtr) \
SymI_HasProto(foreignExportStablePtr) \
SymI_HasProto(hs_init) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment