[commit: ghc] master: base: fdReady(): Improve accuracy and simplify code. (28a115e)

git at git.haskell.org git at git.haskell.org
Tue Sep 19 21:55:28 UTC 2017


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/28a115e5e2c3c19b860545f1fcde4317bac3ee2a/ghc

>---------------------------------------------------------------

commit 28a115e5e2c3c19b860545f1fcde4317bac3ee2a
Author: Niklas Hambüchen <mail at nh2.me>
Date:   Tue Sep 19 15:09:29 2017 -0400

    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


>---------------------------------------------------------------

28a115e5e2c3c19b860545f1fcde4317bac3ee2a
 includes/rts/Time.h               |  4 ++++
 libraries/base/cbits/inputReady.c | 31 ++++++++++---------------------
 rts/GetTime.h                     |  1 -
 rts/RtsSymbols.c                  |  1 +
 4 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/includes/rts/Time.h b/includes/rts/Time.h
index 5fa166e..12c6d27 100644
--- a/includes/rts/Time.h
+++ b/includes/rts/Time.h
@@ -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);
diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c
index e27851a..dbfdb28 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);
diff --git a/rts/GetTime.h b/rts/GetTime.h
index 719b45f..97f499c 100644
--- a/rts/GetTime.h
+++ b/rts/GetTime.h
@@ -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.
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index fb9be7f..a696f44 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -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)                                            \



More information about the ghc-commits mailing list