]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MAJOR] changed TV_ETERNITY to ~0 instead of 0
authorWilly Tarreau <w@1wt.eu>
Sat, 28 Apr 2007 20:40:08 +0000 (22:40 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 29 Apr 2007 11:44:24 +0000 (13:44 +0200)
The fact that TV_ETERNITY was 0 was very awkward because it
required that comparison functions handled the special case.
Now it is ~0 and all comparisons are performed on unsigned
values, so that it is naturally greater than any other value.

A performance gain of about 2-5% has been noticed.

include/common/time.h
src/proto_http.c
src/task.c
src/time.c

index 36c5ca5a2b16d04681cdda9e7eb8f5078f531b8d..cb1e40b5aebf7a7857db2c06c38d31e707242e97 100644 (file)
 #include <sys/time.h>
 #include <common/config.h>
 
-#define TIME_ETERNITY          -1
+/* eternity when exprimed in timeval */
+#ifndef TV_ETERNITY
+#define TV_ETERNITY     (~0UL)
+#endif
+
+/* eternity when exprimed in ms */
+#ifndef TV_ETERNITY_MS
+#define TV_ETERNITY_MS  (-1)
+#endif
+
+#define TIME_ETERNITY   (TV_ETERNITY_MS)
+
 
 /* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
 #define MINTIME(old, new)      (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
@@ -72,7 +83,6 @@ REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2);
  */
 REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2);
 
-
 /* sets <tv> to the current time */
 REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
 {
@@ -87,13 +97,13 @@ REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
  */
 REGPRM2 static inline int tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
 {
-       if (tv1->tv_sec < tv2->tv_sec)
+       if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
                return -1;
-       else if (tv1->tv_sec > tv2->tv_sec)
+       else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
                return 1;
-       else if (tv1->tv_usec < tv2->tv_usec)
+       else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
                return -1;
-       else if (tv1->tv_usec > tv2->tv_usec)
+       else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
                return 1;
        else
                return 0;
@@ -104,11 +114,11 @@ REGPRM2 static inline int tv_cmp(const struct timeval *tv1, const struct timeval
  */
 REGPRM2 static inline int tv_cmp_ge(const struct timeval *tv1, const struct timeval *tv2)
 {
-       if (tv1->tv_sec > tv2->tv_sec)
+       if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
                return 1;
-       if (tv1->tv_sec < tv2->tv_sec)
+       if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
                return 0;
-       if (tv1->tv_usec >= tv2->tv_usec)
+       if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec)
                return 1;
        return 0;
 }
@@ -122,7 +132,7 @@ REGPRM2 static inline unsigned long tv_diff(const struct timeval *tv1, const str
        unsigned long ret;
   
        ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
-       if (tv2->tv_usec > tv1->tv_usec)
+       if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
                ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
        else
                ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
@@ -142,7 +152,7 @@ REGPRM2 static inline unsigned long tv_remain(const struct timeval *tv1, const s
                return 0; /* event elapsed */
 
        ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
-       if (tv2->tv_usec > tv1->tv_usec)
+       if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
                ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
        else
                ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
@@ -151,42 +161,75 @@ REGPRM2 static inline unsigned long tv_remain(const struct timeval *tv1, const s
 
 
 /*
- * zeroes a struct timeval
+ * sets a struct timeval to its highest value so that it can never happen
+ * note that only tv_usec is necessary to detect it since a tv_usec > 999999
+ * is normally not possible.
+ *
  */
 
 REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
 {
-       tv->tv_sec = tv->tv_usec = 0;
+       tv->tv_sec = tv->tv_usec = TV_ETERNITY;
        return tv;
 }
 
 /*
- * returns 1 if tv is null, else 0
+ * sets a struct timeval to 0
+ *
  */
-REGPRM1 static inline int tv_iseternity(const struct timeval *tv)
-{
-       if ((tv->tv_sec | tv->tv_usec) == 0)
-               return 1;
-       else
-               return 0;
+REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
+       tv->tv_sec = tv->tv_usec = 0;
+       return tv;
 }
 
 /*
- * returns the first event between tv1 and tv2 into tvmin.
- * a zero tv is ignored. tvmin is returned.
+ * returns non null if tv is [eternity], otherwise 0.
  */
-REGPRM3 static inline const struct timeval *tv_min(struct timeval *tvmin,
-                                    const struct timeval *tv1,
-                                    const struct timeval *tv2)
-{
+#define tv_iseternity(tv)       ((tv)->tv_usec == TV_ETERNITY)
 
-       if (tv_cmp2(tv1, tv2) <= 0)
-               *tvmin = *tv1;
-       else
-               *tvmin = *tv2;
+/*
+ * returns non null if tv is [0], otherwise 0.
+ */
+#define tv_iszero(tv)           (((tv)->tv_sec | (tv)->tv_usec) == 0)
 
-       return tvmin;
-}
+/*
+ * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
+ * This should be very fast because it's used in schedulers.
+ * It has been optimized to return 1  (so call it in a loop which continues
+ * as long as tv1<=tv2)
+ */
+
+#define tv_isbefore(tv1, tv2)                                               \
+       (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 :  \
+        (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
+         unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
+
+/*
+ * returns the first event between <tv1> and <tv2> into <tvmin>.
+ * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
+ * to be the same as <tv1> or <tv2>, it is recommended to use
+ * tv_bound instead.
+ */
+#define tv_min(tvmin, tv1, tv2) ({      \
+        if (tv_isbefore(tv1, tv2)) {    \
+                *tvmin = *tv1;          \
+        }                               \
+        else {                          \
+                *tvmin = *tv2;          \
+        }                               \
+        tvmin;                          \
+})
+
+/*
+ * returns the first event between <tv1> and <tv2> into <tvmin>.
+ * a zero tv is ignored. <tvmin> is returned. This function has been
+ * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
+ */
+#define tv_bound(tv1, tv2) ({      \
+        if (tv_isbefore(tv2, tv1)) \
+                  *tv1 = *tv2;     \
+        tv1;                       \
+})
 
 
 #endif /* _COMMON_TIME_H */
index 00277f5ca7ae05af6fb005bb41dec309be9f9797..86dbc999f0a18b19abd8e08863075cc8ab95bc5e 100644 (file)
@@ -524,7 +524,6 @@ static http_meth_t find_http_meth(const char *str, const int len)
 
 }
 
-
 /* Processes the client and server jobs of a session task, then
  * puts it back to the wait queue in a clean state, or
  * cleans up its resources if it must be deleted. Returns
@@ -546,14 +545,14 @@ int process_session(struct task *t)
        } while (fsm_resync);
 
        if (s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE) {
-               struct timeval min1, min2;
                s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 
-               tv_min(&min1, &s->req->rex, &s->req->wex);
-               tv_min(&min2, &s->rep->rex, &s->rep->wex);
-               tv_min(&min1, &min1, &s->req->cex);
-               tv_min(&t->expire, &min1, &min2);
+               t->expire = s->req->rex;
+               tv_min(&t->expire, &s->req->rex, &s->req->wex);
+               tv_bound(&t->expire, &s->req->cex);
+               tv_bound(&t->expire, &s->rep->rex);
+               tv_bound(&t->expire, &s->rep->wex);
 
                /* restore t to its place in the task list */
                task_queue(t);
index a0bf7af60bf193fd3f604d74c49b3c84fa5de69a..a2ca0404bd6892a72fc1b4b6706cc8f0b332bd27 100644 (file)
@@ -12,8 +12,8 @@
 
 #include <common/config.h>
 #include <common/mini-clist.h>
-#include <common/time.h>
 #include <common/standard.h>
+#include <common/time.h>
 
 #include <proto/task.h>
 #include <types/task.h>
@@ -106,7 +106,7 @@ int wake_expired_tasks()
        tree64_foreach(&timer_wq, data, stack, slen) {
                task = LIST_ELEM(data, struct task *, qlist);
 
-               if (unlikely(tv_cmp_ge(&task->expire, &now) > 0)) {
+               if (!tv_isbefore(&task->expire, &now)) {
                        next_time = tv_remain(&now, &task->expire);
                        break;
                }
index 1c5732f3eb46307477ca2ccc97f0045e9fcfb3c6..d94e364730f7b731f5d9f7abd37e0f9410627c87 100644 (file)
@@ -41,19 +41,21 @@ REGPRM3 struct timeval *tv_delayfrom(struct timeval *tv, const struct timeval *f
  */
 REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
 {
-       if (tv1->tv_sec == tv2->tv_sec) {
-               if (tv2->tv_usec >= tv1->tv_usec + 1000)
+       if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
+               if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
                        return -1;
-               else if (tv1->tv_usec >= tv2->tv_usec + 1000)
+               else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
                        return 1;
                else
                        return 0;
        }
-       else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
-                ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
+       else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
+                (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
+                 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
                return -1;
-       else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
-                ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
+       else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
+                (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
+                 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
                return 1;
        else
                return 0;
@@ -61,45 +63,32 @@ REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
 
 /*
  * compares <tv1> and <tv2> : returns 0 if tv1 < tv2, 1 if tv1 >= tv2,
- * considering that 0 is the eternity.
+ * assuming that TV_ETERNITY is greater than everything.
  */
 REGPRM2 int tv_cmp_ge2(const struct timeval *tv1, const struct timeval *tv2)
 {
-       if (unlikely(tv_iseternity(tv1)))
+       if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
                return 1;
-       if (unlikely(tv_iseternity(tv2)))
-               return 0; /* same */
-
-       if (tv1->tv_sec > tv2->tv_sec)
-               return 1;
-       if (tv1->tv_sec < tv2->tv_sec)
+       if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
                return 0;
-       if (tv1->tv_usec >= tv2->tv_usec)
+       if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec)
                return 1;
        return 0;
 }
 
 /*
  * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
- * considering that 0 is the eternity.
+ * assuming that TV_ETERNITY is greater than everything.
  */
 REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
 {
-       if (unlikely(tv_iseternity(tv1)))
-               if (unlikely(tv_iseternity(tv2)))
-                       return 0; /* same */
-               else
-                       return 1; /* tv1 later than tv2 */
-       else if (likely(tv_iseternity(tv2)))
-               return -1; /* tv2 later than tv1 */
-    
-       if (tv1->tv_sec > tv2->tv_sec)
+       if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
                return 1;
-       else if (tv1->tv_sec < tv2->tv_sec)
+       else if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
                return -1;
-       else if (tv1->tv_usec > tv2->tv_usec)
+       else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
                return 1;
-       else if (tv1->tv_usec < tv2->tv_usec)
+       else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
                return -1;
        else
                return 0;
@@ -107,7 +96,7 @@ REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
 
 /*
  * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
- * considering that 0 is the eternity.
+ * assuming that TV_ETERNITY is greater than everything.
  */
 REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
 {
@@ -119,19 +108,21 @@ REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
        else if (tv_iseternity(tv2))
                return -1; /* tv2 later than tv1 */
     
-       if (tv1->tv_sec == tv2->tv_sec) {
-               if (tv1->tv_usec >= tv2->tv_usec + 1000)
+       if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
+               if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
                        return 1;
-               else if (tv2->tv_usec >= tv1->tv_usec + 1000)
+               else if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
                        return -1;
                else
                        return 0;
        }
-       else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
-                ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
+       else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
+                (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
+                 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
                return 1;
-       else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
-                ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
+       else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
+                (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
+                 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
                return -1;
        else
                return 0;
@@ -153,7 +144,7 @@ REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval
                return 0; /* event elapsed */
 
        ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
-       if (tv2->tv_usec > tv1->tv_usec)
+       if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
                ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
        else
                ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
@@ -180,7 +171,7 @@ REGPRM2 unsigned long tv_delta(const struct timeval *tv1, const struct timeval *
                tv2 = tmp;
        }
        ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
-       if (tv1->tv_usec > tv2->tv_usec)
+       if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
                ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
        else
                ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;