Merge branch 'timers' into merge-timers
diff --git a/include/common/time.h b/include/common/time.h
index 33a62f8..001d63e 100644
--- a/include/common/time.h
+++ b/include/common/time.h
@@ -157,46 +157,53 @@
 }
 
 /* tv_iseq: compares <tv1> and <tv2> : returns 1 if tv1 == tv2, otherwise 0 */
+#define tv_iseq __tv_iseq
 REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
 {
-    return ((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) &&
-	    ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
+	return ((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) &&
+		((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
 }
 
 /* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
+#define tv_isgt _tv_isgt
+REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2);
 REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
 {
-    return
-	((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
-	((unsigned)tv1->tv_usec >  (unsigned)tv2->tv_usec) :
-	((unsigned)tv1->tv_sec  >  (unsigned)tv2->tv_sec);
+	return
+		((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
+		((unsigned)tv1->tv_usec >  (unsigned)tv2->tv_usec) :
+		((unsigned)tv1->tv_sec  >  (unsigned)tv2->tv_sec);
 }
 
 /* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
+#define tv_isge __tv_isge
 REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
 {
-    return
-	((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
-	((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
-	((unsigned)tv1->tv_sec  >  (unsigned)tv2->tv_sec);
+	return
+		((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
+		((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
+		((unsigned)tv1->tv_sec  >  (unsigned)tv2->tv_sec);
 }
 
 /* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
+#define tv_islt __tv_islt
 REGPRM2 static inline int __tv_islt(const struct timeval *tv1, const struct timeval *tv2)
 {
-    return
-	((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
-	((unsigned)tv1->tv_usec <  (unsigned)tv2->tv_usec) :
-	((unsigned)tv1->tv_sec  <  (unsigned)tv2->tv_sec);
+	return
+		((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
+		((unsigned)tv1->tv_usec <  (unsigned)tv2->tv_usec) :
+		((unsigned)tv1->tv_sec  <  (unsigned)tv2->tv_sec);
 }
 
 /* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
+#define tv_isle _tv_isle
+REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2);
 REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
 {
-    return
-	((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
-	((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
-	((unsigned)tv1->tv_sec  <  (unsigned)tv2->tv_sec);
+	return
+		((unsigned)tv1->tv_sec  == (unsigned)tv2->tv_sec) ?
+		((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
+		((unsigned)tv1->tv_sec  <  (unsigned)tv2->tv_sec);
 }
 
 /*
@@ -328,7 +335,7 @@
 /*
  * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
  */
-#define tv_add __tv_add
+#define tv_add _tv_add
 REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
 REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
 {
@@ -343,6 +350,25 @@
 
 
 /*
+ * If <inc> is set, then add it to <from> and set the result to <tv>, then
+ * return 1, otherwise return 0. It is meant to be used in if conditions.
+ */
+#define tv_add_ifset _tv_add_ifset
+REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
+REGPRM3 static inline int __tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
+{
+	if (tv_iseternity(inc))
+		return 0;
+	tv->tv_usec = from->tv_usec + inc->tv_usec;
+	tv->tv_sec  = from->tv_sec  + inc->tv_sec;
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+	return 1;
+}
+
+/*
  * adds <inc> to <tv> and returns a pointer <tv>
  */
 REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
diff --git a/src/appsession.c b/src/appsession.c
index 0307ff7..72b7e40 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -143,7 +143,7 @@
 				for (element = list_head(&htbl->table[i]);
 				     element != NULL; element = list_next(element)) {
 					asession = (appsess *)list_data(element);
-					if (__tv_isle(&asession->expire, &now)) {
+					if (tv_isle(&asession->expire, &now)) {
 						if ((global.mode & MODE_DEBUG) &&
 						    (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 							int len;
@@ -165,7 +165,7 @@
 						}
 						else
 							element = last;
-					}/* end if (__tv_isle(&asession->expire, &now)) */
+					}/* end if (tv_isle(&asession->expire, &now)) */
 					else
 						last = element;
 				}/* end  for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
diff --git a/src/backend.c b/src/backend.c
index 002394e..8abaf1c 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -550,9 +550,7 @@
 			s->srv->cur_sess_max = s->srv->cur_sess;
 	}
 
-	if (tv_isset(&s->be->contimeout))
-		tv_add(&s->req->cex, &now, &s->be->contimeout);
-	else
+	if (!tv_add_ifset(&s->req->cex, &now, &s->be->contimeout))
 		tv_eternity(&s->req->cex);
 	return SN_ERR_NONE;  /* connection is OK */
 }
@@ -680,9 +678,7 @@
 
 	case SRV_STATUS_QUEUED:
 		/* FIXME-20060503 : we should use the queue timeout instead */
-		if (tv_isset(&t->be->contimeout))
-			tv_add(&t->req->cex, &now, &t->be->contimeout);
-		else
+		if (!tv_add_ifset(&t->req->cex, &now, &t->be->contimeout))
 			tv_eternity(&t->req->cex);
 		t->srv_state = SV_STIDLE;
 		/* do nothing else and do not wake any other session up */
diff --git a/src/checks.c b/src/checks.c
index 96f5895..91dd531 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -288,7 +288,7 @@
 	fd = s->curfd;
 	if (fd < 0) {   /* no check currently running */
 		//fprintf(stderr, "process_chk: 2\n");
-		if (!__tv_isle(&t->expire, &now)) { /* not good time yet */
+		if (!tv_isle(&t->expire, &now)) { /* not good time yet */
 			task_queue(t);	/* restore t to its place in the task list */
 			*next = t->expire;
 			goto out;
@@ -298,7 +298,7 @@
 		 * the server should not be checked.
 		 */
 		if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED) {
-			while (__tv_isle(&t->expire, &now))
+			while (tv_isle(&t->expire, &now))
 				tv_ms_add(&t->expire, &t->expire, s->inter);
 			task_queue(t);	/* restore t to its place in the task list */
 			*next = t->expire;
@@ -421,7 +421,7 @@
 
 		if (!s->result) { /* nothing done */
 			//fprintf(stderr, "process_chk: 6\n");
-			while (__tv_isle(&t->expire, &now))
+			while (tv_isle(&t->expire, &now))
 				tv_ms_add(&t->expire, &t->expire, s->inter);
 			goto new_chk; /* may be we should initialize a new check */
 		}
@@ -436,7 +436,7 @@
 
 		//fprintf(stderr, "process_chk: 7\n");
 		/* FIXME: we allow up to <inter> for a connection to establish, but we should use another parameter */
-		while (__tv_isle(&t->expire, &now))
+		while (tv_isle(&t->expire, &now))
 			tv_ms_add(&t->expire, &t->expire, s->inter);
 		goto new_chk;
 	}
@@ -487,11 +487,11 @@
 			}
 			s->curfd = -1; /* no check running anymore */
 			fd_delete(fd);
-			while (__tv_isle(&t->expire, &now))
+			while (tv_isle(&t->expire, &now))
 				tv_ms_add(&t->expire, &t->expire, s->inter);
 			goto new_chk;
 		}
-		else if (s->result < 0 || __tv_isle(&t->expire, &now)) {
+		else if (s->result < 0 || tv_isle(&t->expire, &now)) {
 			//fprintf(stderr, "process_chk: 10\n");
 			/* failure or timeout detected */
 			if (s->health > s->rise) {
@@ -502,7 +502,7 @@
 				set_server_down(s);
 			s->curfd = -1;
 			fd_delete(fd);
-			while (__tv_isle(&t->expire, &now))
+			while (tv_isle(&t->expire, &now))
 				tv_ms_add(&t->expire, &t->expire, s->inter);
 			goto new_chk;
 		}
diff --git a/src/proto_http.c b/src/proto_http.c
index 0f78d07..d1bfdcf 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -442,9 +442,7 @@
 	EV_FD_CLR(s->cli_fd, DIR_RD);
 	EV_FD_SET(s->cli_fd, DIR_WR);
 	tv_eternity(&s->req->rex);
-	if (tv_isset(&s->fe->clitimeout))
-		tv_add(&s->rep->wex, &now, &s->fe->clitimeout);
-	else
+	if (!tv_add_ifset(&s->rep->wex, &now, &s->fe->clitimeout))
 		tv_eternity(&s->rep->wex);
 	s->cli_state = CL_STSHUTR;
 	buffer_flush(s->rep);
@@ -1529,7 +1527,7 @@
 			}
 
 			/* 3: has the read timeout expired ? */
-			else if (unlikely(__tv_isle(&req->rex, &now))) {
+			else if (unlikely(tv_isle(&req->rex, &now))) {
 				/* read timeout : give up with an error message. */
 				txn->status = 408;
 				client_retnclose(t, error_message(t, HTTP_ERR_408));
@@ -1547,9 +1545,7 @@
 				 * full. We cannot loop here since stream_sock_read will disable it only if
 				 * req->l == rlim-data
 				 */
-				if (tv_isset(&t->fe->clitimeout))
-					tv_add(&req->rex, &now, &t->fe->clitimeout);
-				else
+				if (!tv_add_ifset(&req->rex, &now, &t->fe->clitimeout))
 					tv_eternity(&req->rex);
 			}
 			return t->cli_state != CL_STHEADERS;
@@ -1936,9 +1932,7 @@
 			/* flush the request so that we can drop the connection early
 			 * if the client closes first.
 			 */
-			if (tv_isset(&t->be->contimeout))
-				tv_add(&req->cex, &now, &t->be->contimeout);
-			else
+			if (!tv_add_ifset(&req->cex, &now, &t->be->contimeout))
 				req->cex = now;
 		}
 
@@ -1998,14 +1992,13 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->cli_fd, DIR_RD);
-			if (tv_isset(&t->fe->clitimeout))
-				tv_add(&req->rex, &now, &t->fe->clitimeout);
+			tv_add_ifset(&req->rex, &now, &t->fe->clitimeout);
 			t->cli_state = CL_STSHUTW;
 			//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
 			return 1;
 		}
 		/* read timeout */
-		else if (__tv_isle(&req->rex, &now)) {
+		else if (tv_isle(&req->rex, &now)) {
 			EV_FD_CLR(t->cli_fd, DIR_RD);
 			tv_eternity(&req->rex);
 			t->cli_state = CL_STSHUTR;
@@ -2022,15 +2015,14 @@
 			return 1;
 		}	
 		/* write timeout */
-		else if (__tv_isle(&rep->wex, &now)) {
+		else if (tv_isle(&rep->wex, &now)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
 			tv_eternity(&rep->wex);
 			shutdown(t->cli_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->cli_fd, DIR_RD);
-			if (tv_isset(&t->fe->clitimeout))
-				tv_add(&req->rex, &now, &t->fe->clitimeout);
+			tv_add_ifset(&req->rex, &now, &t->fe->clitimeout);
 
 			t->cli_state = CL_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2078,8 +2070,7 @@
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_isset(&t->fe->clitimeout)) {
-					tv_add(&rep->wex, &now, &t->fe->clitimeout);
+				if (tv_add_ifset(&rep->wex, &now, &t->fe->clitimeout)) {
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
@@ -2114,7 +2105,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (__tv_isle(&rep->wex, &now)) {
+		else if (tv_isle(&rep->wex, &now)) {
 			tv_eternity(&rep->wex);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -2151,8 +2142,7 @@
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_isset(&t->fe->clitimeout)) {
-					tv_add(&rep->wex, &now, &t->fe->clitimeout);
+				if (tv_add_ifset(&rep->wex, &now, &t->fe->clitimeout)) {
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
@@ -2186,7 +2176,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (__tv_isle(&req->rex, &now)) {
+		else if (tv_isle(&req->rex, &now)) {
 			tv_eternity(&req->rex);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -2217,9 +2207,7 @@
 		} else {
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-				if (tv_isset(&t->fe->clitimeout))
-					tv_add(&req->rex, &now, &t->fe->clitimeout);
-				else
+				if (!tv_add_ifset(&req->rex, &now, &t->fe->clitimeout))
 					tv_eternity(&req->rex);
 				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
 			}
@@ -2283,7 +2271,7 @@
 				 * already set the connect expiration date to the right
 				 * timeout. We just have to check that it has not expired.
 				 */
-				if (!__tv_isle(&req->cex, &now))
+				if (!tv_isle(&req->cex, &now))
 					return 0;
 
 				/* We will set the queue timer to the time spent, just for
@@ -2305,7 +2293,7 @@
 			 * to any other session to release it and wake us up again.
 			 */
 			if (t->pend_pos) {
-				if (!__tv_isle(&req->cex, &now))
+				if (!tv_isle(&req->cex, &now))
 					return 0;
 				else {
 					/* we've been waiting too long here */
@@ -2351,7 +2339,7 @@
 			srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C, 0, NULL);
 			return 1;
 		}
-		if (!(req->flags & BF_WRITE_STATUS) && !__tv_isle(&req->cex, &now)) {
+		if (!(req->flags & BF_WRITE_STATUS) && !tv_isle(&req->cex, &now)) {
 			//fprintf(stderr,"1: c=%d, s=%d, now=%d.%06d, exp=%d.%06d\n", c, s, now.tv_sec, now.tv_usec, req->cex.tv_sec, req->cex.tv_usec);
 			return 0; /* nothing changed */
 		}
@@ -2418,8 +2406,7 @@
 				tv_eternity(&req->wex);
 			} else  /* need the right to write */ {
 				EV_FD_SET(t->srv_fd, DIR_WR);
-				if (tv_isset(&t->be->srvtimeout)) {
-					tv_add(&req->wex, &now, &t->be->srvtimeout);
+				if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -2430,9 +2417,7 @@
 
 			if (t->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
 				EV_FD_SET(t->srv_fd, DIR_RD);
-				if (tv_isset(&t->be->srvtimeout))
-					tv_add(&rep->rex, &now, &t->be->srvtimeout);
-				else
+				if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 					tv_eternity(&rep->rex);
 		
 				t->srv_state = SV_STDATA;
@@ -2519,9 +2504,7 @@
 			 * full. We cannot loop here since stream_sock_read will disable it only if
 			 * rep->l == rlim-data
 			 */
-			if (tv_isset(&t->be->srvtimeout))
-				tv_add(&rep->rex, &now, &t->be->srvtimeout);
-			else
+			if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 				tv_eternity(&rep->rex);
 		}
 
@@ -2586,7 +2569,7 @@
 			/* read timeout : return a 504 to the client.
 			 */
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_RD) &&
-			                  __tv_isle(&rep->rex, &now))) {
+			                  tv_isle(&rep->rex, &now))) {
 				tv_eternity(&rep->rex);
 				tv_eternity(&req->wex);
 				fd_delete(t->srv_fd);
@@ -2626,8 +2609,7 @@
 				/* We must ensure that the read part is still
 				 * alive when switching to shutw */
 				EV_FD_SET(t->srv_fd, DIR_RD);
-				if (tv_isset(&t->be->srvtimeout))
-					tv_add(&rep->rex, &now, &t->be->srvtimeout);
+				tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
 				shutdown(t->srv_fd, SHUT_WR);
 				t->srv_state = SV_STSHUTW;
@@ -2640,15 +2622,14 @@
 			 * some work to do on the headers.
 			 */
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_WR) &&
-					  __tv_isle(&req->wex, &now))) {
+					  tv_isle(&req->wex, &now))) {
 				EV_FD_CLR(t->srv_fd, DIR_WR);
 				tv_eternity(&req->wex);
 				shutdown(t->srv_fd, SHUT_WR);
 				/* We must ensure that the read part is still alive
 				 * when switching to shutw */
 				EV_FD_SET(t->srv_fd, DIR_RD);
-				if (tv_isset(&t->be->srvtimeout))
-					tv_add(&rep->rex, &now, &t->be->srvtimeout);
+				tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
 				t->srv_state = SV_STSHUTW;
 				if (!(t->flags & SN_ERR_MASK))
@@ -2669,8 +2650,7 @@
 			else if (likely(req->l)) {
 				if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
 					/* restart writing */
-					if (tv_isset(&t->be->srvtimeout)) {
-						tv_add(&req->wex, &now, &t->be->srvtimeout);
+					if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 						/* FIXME: to prevent the server from expiring read timeouts during writes,
 						 * we refresh it. */
 						rep->rex = req->wex;
@@ -2966,8 +2946,7 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->srv_fd, DIR_RD);
-			if (tv_isset(&t->be->srvtimeout))
-				tv_add(&rep->rex, &now, &t->be->srvtimeout);
+			tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
 			shutdown(t->srv_fd, SHUT_WR);
 			t->srv_state = SV_STSHUTW;
@@ -3036,14 +3015,13 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->srv_fd, DIR_RD);
-			if (tv_isset(&t->be->srvtimeout))
-				tv_add(&rep->rex, &now, &t->be->srvtimeout);
+			tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
 			t->srv_state = SV_STSHUTW;
 			return 1;
 		}
 		/* read timeout */
-		else if (__tv_isle(&rep->rex, &now)) {
+		else if (tv_isle(&rep->rex, &now)) {
 			EV_FD_CLR(t->srv_fd, DIR_RD);
 			tv_eternity(&rep->rex);
 			t->srv_state = SV_STSHUTR;
@@ -3054,15 +3032,14 @@
 			return 1;
 		}	
 		/* write timeout */
-		else if (__tv_isle(&req->wex, &now)) {
+		else if (tv_isle(&req->wex, &now)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
 			tv_eternity(&req->wex);
 			shutdown(t->srv_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->srv_fd, DIR_RD);
-			if (tv_isset(&t->be->srvtimeout))
-				tv_add(&rep->rex, &now, &t->be->srvtimeout);
+			tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 			t->srv_state = SV_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVTO;
@@ -3081,8 +3058,7 @@
 		else { /* buffer not empty, there are still data to be transferred */
 			if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_isset(&t->be->srvtimeout)) {
-					tv_add(&req->wex, &now, &t->be->srvtimeout);
+				if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -3100,9 +3076,7 @@
 		}
 		else {
 			if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-				if (tv_isset(&t->be->srvtimeout))
-					tv_add(&rep->rex, &now, &t->be->srvtimeout);
-				else
+				if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 					tv_eternity(&rep->rex);
 			}
 		}
@@ -3149,7 +3123,7 @@
 
 			return 1;
 		}
-		else if (__tv_isle(&req->wex, &now)) {
+		else if (tv_isle(&req->wex, &now)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
 			tv_eternity(&req->wex);
 			fd_delete(t->srv_fd);
@@ -3178,8 +3152,7 @@
 		else { /* buffer not empty */
 			if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_isset(&t->be->srvtimeout)) {
-					tv_add(&req->wex, &now, &t->be->srvtimeout);
+				if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -3230,7 +3203,7 @@
 
 			return 1;
 		}
-		else if (__tv_isle(&rep->rex, &now)) {
+		else if (tv_isle(&rep->rex, &now)) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
 			tv_eternity(&rep->rex);
 			fd_delete(t->srv_fd);
@@ -3257,9 +3230,7 @@
 		}
 		else {
 			if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-				if (tv_isset(&t->be->srvtimeout))
-					tv_add(&rep->rex, &now, &t->be->srvtimeout);
-				else
+				if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 					tv_eternity(&rep->rex);
 			}
 		}
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 4691a9c..ae5993b 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -165,10 +165,8 @@
 	 */
 
 	if (b->flags & BF_PARTIAL_READ) {
-		if (tv_isset(&b->rto)) {
-			tv_add(&b->rex, &now, &b->rto);
+		if (tv_add_ifset(&b->rex, &now, &b->rto))
 			goto out_wakeup;
-		}
 	out_eternity:
 		tv_eternity(&b->rex);
 	}
@@ -315,8 +313,7 @@
 	 */
 
 	if (b->flags & BF_PARTIAL_WRITE) {
-		if (tv_isset(&b->wto)) {
-			tv_add(&b->wex, &now, &b->wto);
+		if (tv_add_ifset(&b->wex, &now, &b->wto)) {
 			/* FIXME: to prevent the client from expiring read timeouts during writes,
 			 * we refresh it. A solution would be to merge read+write timeouts into a
 			 * unique one, although that needs some study particularly on full-duplex
diff --git a/src/task.c b/src/task.c
index 953da6c..41c0b2a 100644
--- a/src/task.c
+++ b/src/task.c
@@ -84,7 +84,6 @@
  */
 void wake_expired_tasks(struct timeval *next)
 {
-	__label__ out;
 	int slen;
 	struct task *task;
 	void *data;
@@ -96,9 +95,9 @@
 
 	if (likely(timer_wq.data != NULL)) {
 		task = LIST_ELEM(timer_wq.data, struct task *, qlist);
-		if (likely(__tv_isge(&task->expire, &now) > 0)) {
-			__tv_remain(&now, &task->expire, next);
-			goto out;
+		if (likely(tv_isgt(&task->expire, &now))) {
+			tv_remain(&now, &task->expire, next);
+			return;
 		}
 	}
 
@@ -108,8 +107,8 @@
 	tree64_foreach(&timer_wq, data, stack, slen) {
 		task = LIST_ELEM(data, struct task *, qlist);
 
-		if (__tv_isgt(&task->expire, &now)) {
-			__tv_remain2(&now, &task->expire, next);
+		if (tv_isgt(&task->expire, &now)) {
+			tv_remain(&now, &task->expire, next);
 			break;
 		}
 
@@ -125,7 +124,6 @@
 			task->state = TASK_RUNNING;
 		}
 	}
- out:
 	return;
 }
 
diff --git a/src/time.c b/src/time.c
index cf3d5cf..b80dca9 100644
--- a/src/time.c
+++ b/src/time.c
@@ -103,6 +103,15 @@
 }
 
 /*
+ * If <inc> is set, then add it to <from> and set the result to <tv>, then
+ * return 1, otherwise return 0. It is meant to be used in if conditions.
+ */
+REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
+{
+	return __tv_add_ifset(tv, from, inc);
+}
+
+/*
  * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
  * 0 is returned. The result is stored into tv.
  */
@@ -121,6 +130,18 @@
 	return __tv_remain2(tv1, tv2, tv);
 }
 
+/* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
+REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2)
+{
+	return __tv_isle(tv1, tv2);
+}
+
+/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
+REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
+{
+	return __tv_isgt(tv1, tv2);
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8