]> sjero.net Git - iperf/commitdiff
Timer Utilities
authorGerrit Renker <gerrit@erg.abdn.ac.uk>
Tue, 24 Feb 2009 19:30:50 +0000 (20:30 +0100)
committerGerrit Renker <gerrit@erg.abdn.ac.uk>
Tue, 24 Feb 2009 19:30:50 +0000 (20:30 +0100)
Apart from extending the Timestamp class (support for measuring elapsed
time and an `after' test), the main point of this patch is to update
the delay_loop() function.

The present implementation used a tight loop of continually calling
gettimeofday(2) until the specified amount of time has passed. This
is resource-intensive. In addition, while the loop worked reasonably
in many cases, it sometimes caused unwanted delays of 50 milliseconds
or more (process preempted?).

This has been replaced with nanosleep(2) as default now. The advantage
of nanosleep over the old solution is that signals are blocked and it
seems a much more robust solution.

Also, nanosleep uses the hrtimers interface internally
(/usr/src/davem-2.6/Documentation/hrtimers/hrtimers.txt).

For people who would like to keep the old behaviour, #ifdefs with
alternatives have been added.

compat/delay.cpp
include/Timestamp.hpp

index 9fc69c68b2d2235560b250bbfdb06061c3d1b990..5d42469193077630607e30271fd691f21b353e1a 100644 (file)
  * ------------------------------------------------------------------- */
 
 #include "Timestamp.hpp"
-
+#include "util.h"
 #include "delay.hpp"
 
 /* -------------------------------------------------------------------
- * A micro-second delay function. This uses gettimeofday (underneith
- * the Timestamp) which has a resolution of upto microseconds. I've
- * found it's good to within about 10 usecs.
- * I used to do calibration, but iperf automatically adjusts itself
- * so that isn't necesary, and it causes some problems if the
- * calibration adjustment is larger than your sleep time.
+ * A micro-second delay function.
  * ------------------------------------------------------------------- */
+void delay_loop(unsigned long usec)
+{
+#ifdef SLEEP_VIA_SELECT
+     // This is a hack but works apparently quite well
+     // I found that it sometimes under-estimates the timeout
+     struct timeval tv;
+
+     tv.tv_sec = 0;
+     tv.tv_usec = usec;
 
-void delay_loop( unsigned long usec ) {
+     select(1, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
+#elif defined(SLEEP_OLD_METHOD)
+    /* Tis uses gettimeofday (underneath the Timestamp), which has a
+     * resolution of upto microseconds. I've found it's good to within
+     * about 10 usecs. I used to do calibration, but iperf automatically
+     * adjusts itself so that isn't necesary, and it causes some problems
+     * if the calibration adjustment is larger than your sleep time.
+     * Note: I found this has problems - if the loop gets interrupted,
+     * long sleeps can result. I found up to 50..60msec. -- Gerrit */
     Timestamp end;
     end.add( usec * 1e-6 );
 
@@ -71,4 +83,14 @@ void delay_loop( unsigned long usec ) {
     while ( now.before( end ) ) {
         now.setnow();
     }
+#else
+    // This is preferred; it is even better than usleep (see manpage).
+    struct timespec ts;
+
+    ts.tv_sec = 0;
+    ts.tv_nsec = usec * 1000L;
+
+    if (nanosleep(&ts, NULL) < 0)
+        WARN_errno(1, "nanosleep");
+#endif
 }
index ae05f859a1cadaf4c51a82898873625831a9f314..d98bcfcd13254b3ba13273183e41efbe5ae9a98e 100644 (file)
@@ -151,6 +151,16 @@ public:
         (mTime.tv_usec - right.tv_usec);
     }
 
+    /* -------------------------------------------------------------------
+     * Return the number of microseconds from now to last time of setting.
+     * ------------------------------------------------------------------- */
+    long delta_usec(void) {
+        struct timeval previous = mTime;
+
+        setnow();
+        return subUsec(previous);
+    }
+
     /* -------------------------------------------------------------------
      * subtract the right timestamp from my timestamp.
      * return the difference in seconds as a floating point.
@@ -199,15 +209,6 @@ public:
                 mTime.tv_usec <  kMillion );
     }
 
-    /* -------------------------------------------------------------------
-     * return true if my timestamp is before the right timestamp.
-     * ------------------------------------------------------------------- */
-    bool before( Timestamp right ) {
-        return mTime.tv_sec < right.mTime.tv_sec  ||
-        (mTime.tv_sec == right.mTime.tv_sec &&
-         mTime.tv_usec < right.mTime.tv_usec);
-    }
-    
     /* -------------------------------------------------------------------
      * return true if my timestamp is before the right timestamp.
      * ------------------------------------------------------------------- */
@@ -216,15 +217,17 @@ public:
         (mTime.tv_sec == right.tv_sec &&
          mTime.tv_usec < right.tv_usec);
     }
+    bool before( Timestamp right ) { return before(right.mTime); }
 
     /* -------------------------------------------------------------------
      * return true if my timestamp is after the right timestamp.
      * ------------------------------------------------------------------- */
-    bool after( Timestamp right ) {
-        return mTime.tv_sec > right.mTime.tv_sec  ||
-        (mTime.tv_sec == right.mTime.tv_sec &&
-         mTime.tv_usec > right.mTime.tv_usec);
+    bool after( timeval right ) {
+        return mTime.tv_sec > right.tv_sec  ||
+        (mTime.tv_sec == right.tv_sec &&
+         mTime.tv_usec > right.tv_usec);
     }
+    bool after( Timestamp right ) { return after(right.mTime); }
 
     /**
      * This function returns the fraction of time elapsed after the beginning