[MAJOR] convert all expiration timers from timeval to ticks

This is the first attempt at moving all internal parts from
using struct timeval to integer ticks. Those provides simpler
and faster code due to simplified operations, and this change
also saved about 64 bytes per session.

A new header file has been added : include/common/ticks.h.

It is possible that some functions should finally not be inlined
because they're used quite a lot (eg: tick_first, tick_add_ifset
and tick_is_expired). More measurements are required in order to
decide whether this is interesting or not.

Some function and variable names are still subject to change for
a better overall logics.
diff --git a/src/appsession.c b/src/appsession.c
index fcd4e02..10b4df0 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -18,6 +18,7 @@
 #include <common/config.h>
 #include <common/memory.h>
 #include <common/sessionhash.h>
+#include <common/ticks.h>
 #include <common/time.h>
 
 #include <types/buffers.h>
@@ -93,7 +94,7 @@
 
 		task_init(appsess_refresh);
 		appsess_refresh->context = NULL;
-		tv_ms_add(&appsess_refresh->expire, &now, TBLCHKINT);
+		appsess_refresh->expire = tick_add(now_ms, MS_TO_TICKS(TBLCHKINT));
 		appsess_refresh->process = appsession_refresh;
 		task_queue(appsess_refresh);
 		initialized ++;
@@ -101,7 +102,7 @@
 	return 0;
 }
 
-void appsession_refresh(struct task *t, struct timeval *next)
+void appsession_refresh(struct task *t, int *next)
 {
 	struct proxy           *p = proxy;
 	struct appsession_hash *htbl;
@@ -112,7 +113,7 @@
 		if (p->appsession_name != NULL) {
 			htbl = &p->htbl_proxy;
 			as_hash_for_each_entry_safe(i, element, back, &p->htbl_proxy, hash_list) {
-				if (tv_isle(&element->expire, &now)) {
+				if (tick_is_expired(element->expire, now_ms)) {
 					if ((global.mode & MODE_DEBUG) &&
 					    (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 						int len;
@@ -131,7 +132,7 @@
 		}
 		p = p->next;
 	}
-	tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
+	t->expire = tick_add(now_ms, MS_TO_TICKS(TBLCHKINT)); /* check expiration every 5 seconds */
 	task_queue(t);
 	*next = t->expire;
 } /* end appsession_refresh */
diff --git a/src/backend.c b/src/backend.c
index 033b650..7116965 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -22,6 +22,7 @@
 #include <common/config.h>
 #include <common/debug.h>
 #include <common/eb32tree.h>
+#include <common/ticks.h>
 #include <common/time.h>
 
 #include <types/acl.h>
@@ -1831,8 +1832,7 @@
 			s->be->lbprm.server_take_conn(s->srv);
 	}
 
-	if (!tv_add_ifset(&s->req->cex, &now, &s->be->timeout.connect))
-		tv_eternity(&s->req->cex);
+	s->req->cex = tick_add_ifset(now_ms, s->be->timeout.connect);
 	return SN_ERR_NONE;  /* connection is OK */
 }
 
@@ -1850,7 +1850,7 @@
 
 	if (t->conn_retries < 0) {
 		/* if not retryable anymore, let's abort */
-		tv_eternity(&t->req->cex);
+		t->req->cex = TICK_ETERNITY;
 		srv_close_with_err(t, conn_err, SN_FINST_C,
 				   503, error_message(t, HTTP_ERR_503));
 		if (t->srv)
@@ -1894,7 +1894,7 @@
 			return 1;
 	    
 		case SN_ERR_INTERNAL:
-			tv_eternity(&t->req->cex);
+			t->req->cex = TICK_ETERNITY;
 			srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
 					   500, error_message(t, HTTP_ERR_500));
 			if (t->srv)
@@ -1965,7 +1965,7 @@
 			goto redispatch;
 		}
 
-		tv_eternity(&t->req->cex);
+		t->req->cex = TICK_ETERNITY;
 		srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q,
 				   503, error_message(t, HTTP_ERR_503));
 
@@ -1975,7 +1975,7 @@
 
 	case SRV_STATUS_NOSRV:
 		/* note: it is guaranteed that t->srv == NULL here */
-		tv_eternity(&t->req->cex);
+		t->req->cex = TICK_ETERNITY;
 		srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
 				   503, error_message(t, HTTP_ERR_503));
 
@@ -1983,15 +1983,14 @@
 		return 1;
 
 	case SRV_STATUS_QUEUED:
-		if (!tv_add_ifset(&t->req->cex, &now, &t->be->timeout.queue))
-			tv_eternity(&t->req->cex);
+		t->req->cex = tick_add_ifset(now_ms, t->be->timeout.queue);
 		t->srv_state = SV_STIDLE;
 		/* do nothing else and do not wake any other session up */
 		return 1;
 
 	case SRV_STATUS_INTERNAL:
 	default:
-		tv_eternity(&t->req->cex);
+		t->req->cex = TICK_ETERNITY;
 		srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
 				   500, error_message(t, HTTP_ERR_500));
 		if (t->srv)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 90611cd..8afc69c 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -971,10 +971,7 @@
 			      file, linenum, *err, args[0]);
 			return -1;
 		}
-		if (val > 0)
-			__tv_from_ms(&curproxy->timeout.appsession, val);
-		else
-			tv_eternity(&curproxy->timeout.appsession);
+		curproxy->timeout.appsession = val;
 
 		if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
 			Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
@@ -2994,9 +2991,9 @@
 		}
 
 		if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
-		    (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
+		    (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
 		     ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
-		      (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
+		      (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
 			Warning("parsing %s : missing timeouts for %s '%s'.\n"
 				"   | While not properly invalid, you will certainly encounter various problems\n"
 				"   | with such a configuration. To fix this, please ensure that all following\n"
@@ -3009,29 +3006,29 @@
 		 * parameters have been set or must be copied from contimeouts.
 		 */
 		if (curproxy != &defproxy) {
-			if (!tv_isset(&curproxy->timeout.tarpit) ||
-			    __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
+			if (!curproxy->timeout.tarpit ||
+			    curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
 				/* tarpit timeout not set. We search in the following order:
 				 * default.tarpit, curr.connect, default.connect.
 				 */
-				if (tv_isset(&defproxy.timeout.tarpit))
+				if (defproxy.timeout.tarpit)
 					curproxy->timeout.tarpit = defproxy.timeout.tarpit;
-				else if (tv_isset(&curproxy->timeout.connect))
+				else if (curproxy->timeout.connect)
 					curproxy->timeout.tarpit = curproxy->timeout.connect;
-				else if (tv_isset(&defproxy.timeout.connect))
+				else if (defproxy.timeout.connect)
 					curproxy->timeout.tarpit = defproxy.timeout.connect;
 			}
 			if ((curproxy->cap & PR_CAP_BE) &&
-			    (!tv_isset(&curproxy->timeout.queue) ||
-			     __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
+			    (!curproxy->timeout.queue ||
+			     curproxy->timeout.queue == defproxy.timeout.queue)) {
 				/* queue timeout not set. We search in the following order:
 				 * default.queue, curr.connect, default.connect.
 				 */
-				if (tv_isset(&defproxy.timeout.queue))
+				if (defproxy.timeout.queue)
 					curproxy->timeout.queue = defproxy.timeout.queue;
-				else if (tv_isset(&curproxy->timeout.connect))
+				else if (curproxy->timeout.connect)
 					curproxy->timeout.queue = curproxy->timeout.connect;
-				else if (tv_isset(&defproxy.timeout.connect))
+				else if (defproxy.timeout.connect)
 					curproxy->timeout.queue = defproxy.timeout.connect;
 			}
 		}
diff --git a/src/checks.c b/src/checks.c
index 91db026..2dc1d60 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -367,9 +367,7 @@
 #endif
 			if (ret == s->proxy->check_len) {
 				/* we allow up to <timeout.check> if nonzero for a responce */
-				//fprintf(stderr, "event_srv_chk_w, ms=%lu\n", __tv_to_ms(&s->proxy->timeout.check));
-				tv_add_ifset(&t->expire, &now, &s->proxy->timeout.check);
-
+				t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
 				EV_FD_SET(fd, DIR_RD);   /* prepare for reading reply */
 				goto out_nowake;
 			}
@@ -526,7 +524,7 @@
  * manages a server health-check. Returns
  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
  */
-void process_chk(struct task *t, struct timeval *next)
+void process_chk(struct task *t, int *next)
 {
 	__label__ new_chk, out;
 	struct server *s = t->context;
@@ -540,7 +538,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 (!tick_is_expired(t->expire, now_ms)) { /* not good time yet */
 			task_queue(t);	/* restore t to its place in the task list */
 			*next = t->expire;
 			goto out;
@@ -550,8 +548,8 @@
 		 * the server should not be checked.
 		 */
 		if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED) {
-			while (tv_isle(&t->expire, &now))
-				tv_ms_add(&t->expire, &t->expire, s->inter);
+			while (tick_is_expired(t->expire, now_ms))
+				t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 			task_queue(t);	/* restore t to its place in the task list */
 			*next = t->expire;
 			goto out;
@@ -637,8 +635,6 @@
 
 				if (s->result == SRV_CHK_UNKNOWN) {
 					if ((connect(fd, (struct sockaddr *)&sa, sizeof(sa)) != -1) || (errno == EINPROGRESS)) {
-						struct timeval tv_con;
-
 						/* OK, connection in progress or established */
 			
 						//fprintf(stderr, "process_chk: 4\n");
@@ -662,11 +658,11 @@
 						 * to establish but only when timeout.check is set
 						 * as it may be to short for a full check otherwise
 						 */
-						tv_ms_add(&t->expire, &now, s->inter);
+						t->expire = tick_add(now_ms, MS_TO_TICKS(s->inter));
 
-						if (tv_isset(&s->proxy->timeout.check) && tv_isset(&s->proxy->timeout.connect)) {
-							tv_add(&tv_con, &now, &s->proxy->timeout.connect);
-							tv_bound(&t->expire, &tv_con);
+						if (s->proxy->timeout.check && s->proxy->timeout.connect) {
+							int t_con = tick_add(now_ms, s->proxy->timeout.connect);
+							t->expire = tick_first(t->expire, t_con);
 						}
 
 						task_queue(t);	/* restore t to its place in the task list */
@@ -683,8 +679,8 @@
 
 		if (s->result == SRV_CHK_UNKNOWN) { /* nothing done */
 			//fprintf(stderr, "process_chk: 6\n");
-			while (tv_isle(&t->expire, &now))
-				tv_ms_add(&t->expire, &t->expire, s->inter);
+			while (tick_is_expired(t->expire, now_ms))
+				t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 			goto new_chk; /* may be we should initialize a new check */
 		}
 
@@ -701,14 +697,14 @@
 		 * to establish but only when timeout.check is set
 		 * as it may be to short for a full check otherwise
 		 */
-		while (tv_isle(&t->expire, &now)) {
-			struct timeval tv_con;
+		while (tick_is_expired(t->expire, now_ms)) {
+			int t_con;
 
-			tv_add(&tv_con, &t->expire, &s->proxy->timeout.connect);
-			tv_ms_add(&t->expire, &t->expire, s->inter);
+			t_con = tick_add(t->expire, s->proxy->timeout.connect);
+			t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 
-			if (tv_isset(&s->proxy->timeout.check))
-				tv_bound(&t->expire, &tv_con);
+			if (s->proxy->timeout.check)
+				t->expire = tick_first(t->expire, t_con);
 		}
 		goto new_chk;
 	}
@@ -763,10 +759,10 @@
 				rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
 				//fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, srv_getinter(s), global.spread_checks, rv);
 			}
-			tv_ms_add(&t->expire, &now, srv_getinter(s) + rv);
+			t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
 			goto new_chk;
 		}
-		else if ((s->result & SRV_CHK_ERROR) || tv_isle(&t->expire, &now)) {
+		else if ((s->result & SRV_CHK_ERROR) || tick_is_expired(t->expire, now_ms)) {
 			//fprintf(stderr, "process_chk: 10\n");
 			/* failure or timeout detected */
 			if (s->health > s->rise) {
@@ -784,7 +780,7 @@
 				rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
 				//fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, srv_getinter(s), global.spread_checks, rv);
 			}
-			tv_ms_add(&t->expire, &now, srv_getinter(s) + rv);
+			t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
 			goto new_chk;
 		}
 		/* if result is unknown and there's no timeout, we have to wait again */
@@ -855,8 +851,9 @@
 			t->context = s;
 
 			/* check this every ms */
-			tv_ms_add(&t->expire, &now,
-				  ((mininter && mininter >= srv_getinter(s)) ? mininter : srv_getinter(s)) * srvpos / nbchk);
+			t->expire = tick_add(now_ms,
+					     MS_TO_TICKS(((mininter && mininter >= srv_getinter(s)) ?
+							  mininter : srv_getinter(s)) * srvpos / nbchk));
 			task_queue(t);
 
 			srvpos++;
diff --git a/src/client.c b/src/client.c
index 96c3a0a..a40c2a4 100644
--- a/src/client.c
+++ b/src/client.c
@@ -354,7 +354,7 @@
 
 		s->rep->rto = s->be->timeout.server;
 		s->rep->wto = s->fe->timeout.client;
-		tv_eternity(&s->rep->cto);
+		s->rep->cto = TICK_ETERNITY;
 
 		fd_insert(cfd);
 		fdtab[cfd].owner = t;
@@ -384,28 +384,28 @@
 			EV_FD_SET(cfd, DIR_RD);
 		}
 
-		tv_eternity(&s->req->rex);
-		tv_eternity(&s->req->wex);
-		tv_eternity(&s->req->cex);
-		tv_eternity(&s->rep->rex);
-		tv_eternity(&s->rep->wex);
-		tv_eternity(&s->txn.exp);
-		tv_eternity(&t->expire);
+		s->req->rex = TICK_ETERNITY;
+		s->req->wex = TICK_ETERNITY;
+		s->req->cex = TICK_ETERNITY;
+		s->rep->rex = TICK_ETERNITY;
+		s->rep->wex = TICK_ETERNITY;
+		s->txn.exp = TICK_ETERNITY;
+		t->expire = TICK_ETERNITY;
 
-		if (tv_isset(&s->fe->timeout.client)) {
+		if (s->fe->timeout.client) {
 			if (EV_FD_ISSET(cfd, DIR_RD)) {
-				tv_add(&s->req->rex, &now, &s->fe->timeout.client);
+				s->req->rex = tick_add(now_ms, s->fe->timeout.client);
 				t->expire = s->req->rex;
 			}
 			if (EV_FD_ISSET(cfd, DIR_WR)) {
-				tv_add(&s->rep->wex, &now, &s->fe->timeout.client);
+				s->rep->wex = tick_add(now_ms, s->fe->timeout.client);
 				t->expire = s->rep->wex;
 			}
 		}
 
-		if (s->cli_state == CL_STHEADERS && tv_isset(&s->fe->timeout.httpreq)) {
-			tv_add(&s->txn.exp, &now, &s->fe->timeout.httpreq);
-			tv_bound(&t->expire, &s->txn.exp);
+		if (s->cli_state == CL_STHEADERS && s->fe->timeout.httpreq) {
+			s->txn.exp = tick_add(now_ms, s->fe->timeout.httpreq);
+			t->expire = tick_first(t->expire, s->txn.exp);
 		}
 
 		if (p->mode != PR_MODE_HEALTH)
diff --git a/src/dumpstats.c b/src/dumpstats.c
index ddadddd..354d274 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1,7 +1,7 @@
 /*
  * Functions dedicated to statistics output
  *
- * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@
 #include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/uri_auth.h>
 #include <common/version.h>
@@ -139,7 +140,7 @@
 			snprintf(err, errlen, "a positive value is expected for 'stats timeout' in 'global section'");
 			return -1;
 		}
-		__tv_from_ms(&global.stats_timeout, timeout);
+		global.stats_timeout = MS_TO_TICKS(timeout);
 	}
 	else if (!strcmp(args[0], "maxconn")) {
 		int maxconn = atol(args[1]);
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
index adb0fd6..1c4e437 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -17,6 +17,7 @@
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/tools.h>
 
@@ -221,7 +222,7 @@
 /*
  * epoll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
+REGPRM2 static void _do_poll(struct poller *p, int exp)
 {
 	int status;
 	int fd;
@@ -234,12 +235,12 @@
 	/* now let's wait for events */
 	if (run_queue)
 		wait_time = 0;
-	else if (tv_iseternity(exp))
+	else if (!exp)
 		wait_time = MAX_DELAY_MS;
-	else if (tv_isge(&now, exp))
+	else if (tick_is_expired(exp, now_ms))
 		wait_time = 0;
 	else {
-		wait_time = __tv_ms_elapsed(&now, exp) + 1;
+		wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1;
 		if (wait_time > MAX_DELAY_MS)
 			wait_time = MAX_DELAY_MS;
 	}
diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c
index 71e9ecf..604340b 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -23,6 +23,7 @@
 
 #include <common/compat.h>
 #include <common/config.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/tools.h>
 
@@ -99,44 +100,29 @@
 /*
  * kqueue() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
+REGPRM2 static void _do_poll(struct poller *p, int exp)
 {
 	int status;
 	int count, fd, delta_ms;
 	struct timespec timeout;
 
-	if (run_queue) {
-		timeout.tv_sec = timeout.tv_nsec = 0;
-		delta_ms = 0;
-	}
-	else if (tv_isset(exp)) {
-		const struct timeval max_delay = {
-			.tv_sec  = MAX_DELAY_MS / 1000,
-			.tv_usec = (MAX_DELAY_MS % 1000) * 1000
-		};
-		struct timeval delta;
+	delta_ms        = 0;
+	timeout.tv_sec  = 0;
+	timeout.tv_nsec = 0;
 
-		if (tv_isge(&now, exp)) {
-			delta.tv_sec = delta.tv_usec = 0;
-			delta_ms = 0;
+	if (!run_queue) {
+		if (!exp) {
+			delta_ms        = MAX_DELAY_MS;
+			timeout.tv_sec  = (MAX_DELAY_MS / 1000);
+			timeout.tv_nsec = (MAX_DELAY_MS % 1000) * 1000000;
 		}
-		else {
-			tv_remain(&now, exp, &delta);
-			if (__tv_isgt(&delta, &max_delay)) {
-				delta    = max_delay;
+		else if (!tick_is_expired(exp, now_ms)) {
+			delta_ms = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1;
+			if (delta_ms > MAX_DELAY_MS)
 				delta_ms = MAX_DELAY_MS;
-			} else {
-				delta_ms = delta.tv_sec * 1000 + delta.tv_usec / 1000;
-			}
+			timeout.tv_sec  = (delta_ms / 1000);
+			timeout.tv_nsec = (delta_ms % 1000) * 1000000;
 		}
-
-		timeout.tv_sec  = delta.tv_sec;
-		timeout.tv_nsec = delta.tv_usec * 1000;
-	}
-	else {
-		delta_ms = MAX_DELAY_MS;
-		timeout.tv_sec  = MAX_DELAY_MS / 1000;
-		timeout.tv_nsec = (MAX_DELAY_MS % 1000) * 1000000;
 	}
 
 	fd = MIN(maxfd, global.tune.maxpollevents);
diff --git a/src/ev_poll.c b/src/ev_poll.c
index a0355aa..0a0f23d 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -17,6 +17,7 @@
 
 #include <common/compat.h>
 #include <common/config.h>
+#include <common/ticks.h>
 #include <common/time.h>
 
 #include <types/fd.h>
@@ -81,7 +82,7 @@
 /*
  * Poll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
+REGPRM2 static void _do_poll(struct poller *p, int exp)
 {
 	int status;
 	int fd, nbfd;
@@ -126,12 +127,12 @@
 	/* now let's wait for events */
 	if (run_queue)
 		wait_time = 0;
-	else if (tv_iseternity(exp))
+	else if (!exp)
 		wait_time = MAX_DELAY_MS;
-	else if (tv_isge(&now, exp))
+	else if (tick_is_expired(exp, now_ms))
 		wait_time = 0;
 	else {
-		wait_time = __tv_ms_elapsed(&now, exp) + 1;
+		wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1;
 		if (wait_time > MAX_DELAY_MS)
 			wait_time = MAX_DELAY_MS;
 	}
diff --git a/src/ev_select.c b/src/ev_select.c
index 30df928..ecdd870 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -16,6 +16,7 @@
 
 #include <common/compat.h>
 #include <common/config.h>
+#include <common/ticks.h>
 #include <common/time.h>
 
 #include <types/fd.h>
@@ -78,12 +79,8 @@
 /*
  * Select() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
+REGPRM2 static void _do_poll(struct poller *p, int exp)
 {
-	const struct timeval max_delay = {
-		.tv_sec  = MAX_DELAY_MS / 1000,
-		.tv_usec = (MAX_DELAY_MS % 1000) * 1000
-	};
 	int status;
 	int fd, i;
 	struct timeval delta;
@@ -92,28 +89,22 @@
 	int fds;
 	char count;
 		
-	/* allow select to return immediately when needed */
-	delta.tv_sec = delta.tv_usec = 0;
-	delta_ms = 0;
+	delta_ms      = 0;
+	delta.tv_sec  = 0;
+	delta.tv_usec = 0;
+
 	if (!run_queue) {
-		if (!tv_isset(exp)) {
-			delta = max_delay;
-			delta_ms = MAX_DELAY_MS;
+		if (!exp) {
+			delta_ms      = MAX_DELAY_MS;
+			delta.tv_sec  = (MAX_DELAY_MS / 1000);
+			delta.tv_usec = (MAX_DELAY_MS % 1000) * 1000;
 		}
-		else if (tv_islt(&now, exp)) {
-			tv_remain(&now, exp, &delta);
-			/* To avoid eventual select loops due to timer precision */
-			delta.tv_usec += SCHEDULER_RESOLUTION * 1000;
-			if (delta.tv_usec >= 1000000) {
-				delta.tv_usec -= 1000000;
-				delta.tv_sec ++;
-			}
-			if (__tv_isge(&delta, &max_delay)) {
-				delta = max_delay;
+		else if (!tick_is_expired(exp, now_ms)) {
+			delta_ms = TICKS_TO_MS(tick_remain(now_ms, exp)) + SCHEDULER_RESOLUTION;
+			if (delta_ms > MAX_DELAY_MS)
 				delta_ms = MAX_DELAY_MS;
-			} else {
-				delta_ms = delta.tv_sec * 1000 + delta.tv_usec / 1000;
-			}
+			delta.tv_sec  = (delta_ms / 1000);
+			delta.tv_usec = (delta_ms % 1000) * 1000;
 		}
 	}
 
diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c
index f42a97f..2419b68 100644
--- a/src/ev_sepoll.c
+++ b/src/ev_sepoll.c
@@ -52,6 +52,7 @@
 #include <common/config.h>
 #include <common/debug.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/tools.h>
 
@@ -287,7 +288,7 @@
 /*
  * speculative epoll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
+REGPRM2 static void _do_poll(struct poller *p, int exp)
 {
 	static unsigned int last_skipped;
 	static unsigned int spec_processed;
@@ -434,12 +435,12 @@
 		wait_time = 0;
 	}
 	else {
-		if (tv_iseternity(exp))
+		if (!exp)
 			wait_time = MAX_DELAY_MS;
-		else if (tv_isge(&now, exp))
+		else if (tick_is_expired(exp, now_ms))
 			wait_time = 0;
 		else {
-			wait_time = __tv_ms_elapsed(&now, exp) + 1;
+			wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1;
 			if (wait_time > MAX_DELAY_MS)
 				wait_time = MAX_DELAY_MS;
 		}
diff --git a/src/haproxy.c b/src/haproxy.c
index d0a6bbf..0c8bbb0 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -118,7 +118,7 @@
 	logfac2 : -1,
 	loglev1 : 7, /* max syslog level : debug */
 	loglev2 : 7,
-	.stats_timeout = { .tv_sec = 10, .tv_usec = 0 }, /* stats timeout = 10 seconds */
+	.stats_timeout = MS_TO_TICKS(10000), /* stats timeout = 10 seconds */
 	.stats_sock = {
 		.timeout = &global.stats_timeout,
 		.maxconn = 10, /* 10 concurrent stats connections */
@@ -894,7 +894,7 @@
  */
 void run_poll_loop()
 {
-	struct timeval next;
+	int next;
 
 	tv_update_date(0,1);
 	while (1) {
@@ -914,7 +914,7 @@
 			break;
 
 		/* The poller will ensure it returns around <next> */
-		cur_poller.poll(&cur_poller, &next);
+		cur_poller.poll(&cur_poller, next);
 	}
 }
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 308ecb0..beb14d4 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -30,6 +30,7 @@
 #include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/uri_auth.h>
 #include <common/version.h>
@@ -652,7 +653,7 @@
  * the time the task accepts to wait, or TIME_ETERNITY for
  * infinity.
  */
-void process_session(struct task *t, struct timeval *next)
+void process_session(struct task *t, int *next)
 {
 	struct session *s = t->context;
 	int fsm_resync = 0;
@@ -674,23 +675,15 @@
 		s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 		s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 
-		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);
+		t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
+				       tick_first(s->rep->rex, s->rep->wex));
+		t->expire = tick_first(t->expire, s->req->cex);
 		if (s->cli_state == CL_STHEADERS)
-			tv_bound(&t->expire, &s->txn.exp);
+			t->expire = tick_first(t->expire, s->txn.exp);
 
 		/* restore t to its place in the task list */
 		task_queue(t);
 
-#ifdef DEBUG_FULL
-		/* DEBUG code : this should never ever happen, otherwise it indicates
-		 * that a task still has something to do and will provoke a quick loop.
-		 */
-		if (tv_ms_remain2(&now, &t->expire) <= 0)
-			exit(100);
-#endif
 		*next = t->expire;
 		return; /* nothing more to do */
 	}
@@ -726,7 +719,7 @@
 	task_delete(t);
 	session_free(s);
 	task_free(t);
-	tv_eternity(next);
+	*next = TICK_ETERNITY;
 }
 
 
@@ -1647,8 +1640,8 @@
 			}
 
 			/* 3: has the read timeout expired ? */
-			else if (unlikely(tv_isle(&req->rex, &now) ||
-					  tv_isle(&txn->exp, &now))) {
+			else if (unlikely(tick_is_expired(req->rex, now_ms) ||
+					  tick_is_expired(txn->exp, now_ms))) {
 				/* read timeout : give up with an error message. */
 				txn->status = 408;
 				client_retnclose(t, error_message(t, HTTP_ERR_408));
@@ -1666,8 +1659,7 @@
 				 * full. We cannot loop here since stream_sock_read will disable it only if
 				 * req->l == rlim-data
 				 */
-				if (!tv_add_ifset(&req->rex, &now, &t->fe->timeout.client))
-					tv_eternity(&req->rex);
+				req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
 			}
 			return t->cli_state != CL_STHEADERS;
 		}
@@ -2245,8 +2237,8 @@
 
 		t->logs.tv_request = now;
 
-		if (!tv_isset(&t->fe->timeout.client) ||
-		    (t->srv_state < SV_STDATA && tv_isset(&t->be->timeout.server))) {
+		if (!t->fe->timeout.client ||
+		    (t->srv_state < SV_STDATA && t->be->timeout.server)) {
 			/* If the client has no timeout, or if the server is not ready yet,
 			 * and we know for sure that it can expire, then it's cleaner to
 			 * disable the timeout on the client side so that too low values
@@ -2256,7 +2248,7 @@
 			 * when it switches its state, otherwise a client can stay connected
 			 * indefinitely. This now seems to be OK.
 			 */
-			tv_eternity(&req->rex);
+			req->rex = TICK_ETERNITY;
 		}
 
 		/* When a connection is tarpitted, we use the tarpit timeout,
@@ -2269,8 +2261,9 @@
 			/* flush the request so that we can drop the connection early
 			 * if the client closes first.
 			 */
-			if (!tv_add_ifset(&req->cex, &now, &t->be->timeout.tarpit))
-				req->cex = now;
+			req->cex = tick_add_ifset(now_ms, t->be->timeout.tarpit);
+			if (!req->cex)
+				req->cex = now_ms;
 		}
 
 		/* OK let's go on with the BODY now */
@@ -2329,13 +2322,13 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->cli_fd, DIR_RD);
-			tv_add_ifset(&req->rex, &now, &t->fe->timeout.client);
+			req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
 			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 (tick_is_expired(req->rex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_RD);
 			buffer_shutr(req);
 			t->cli_state = CL_STSHUTR;
@@ -2352,14 +2345,14 @@
 			return 1;
 		}	
 		/* write timeout */
-		else if (tv_isle(&rep->wex, &now)) {
+		else if (tick_is_expired(rep->wex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
 			buffer_shutw(rep);
 			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);
-			tv_add_ifset(&req->rex, &now, &t->fe->timeout.client);
+			req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
 
 			t->cli_state = CL_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2379,21 +2372,21 @@
 			/* no room to read more data */
 			if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
 				/* stop reading until we get some space */
-				tv_eternity(&req->rex);
+				req->rex = TICK_ETERNITY;
 			}
 		} else {
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-				if (!tv_isset(&t->fe->timeout.client) ||
-				    (t->srv_state < SV_STDATA && tv_isset(&t->be->timeout.server)))
+				if (!t->fe->timeout.client ||
+				    (t->srv_state < SV_STDATA && t->be->timeout.server))
 					/* If the client has no timeout, or if the server not ready yet, and we
 					 * know for sure that it can expire, then it's cleaner to disable the
 					 * timeout on the client side so that too low values cannot make the
 					 * sessions abort too early.
 					 */
-					tv_eternity(&req->rex);
+					req->rex = TICK_ETERNITY;
 				else
-					tv_add(&req->rex, &now, &t->fe->timeout.client);
+					req->rex = tick_add(now_ms, t->fe->timeout.client);
 			}
 		}
 
@@ -2401,19 +2394,18 @@
 		    ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&rep->wex);
+				rep->wex = TICK_ETERNITY;
 			}
 		} else {
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_add_ifset(&rep->wex, &now, &t->fe->timeout.client)) {
+				rep->wex = tick_add_ifset(now_ms, t->fe->timeout.client);
+				if (rep->wex) {
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
 				}
-				else
-					tv_eternity(&rep->wex);
 			}
 		}
 		return 0; /* other cases change nothing */
@@ -2442,7 +2434,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (tv_isle(&rep->wex, &now)) {
+		else if (tick_is_expired(rep->wex, now_ms)) {
 			buffer_shutw(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -2473,14 +2465,13 @@
 		    || ((s == SV_STHEADERS) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&rep->wex);
+				rep->wex = TICK_ETERNITY;
 			}
 		} else {
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (!tv_add_ifset(&rep->wex, &now, &t->fe->timeout.client))
-					tv_eternity(&rep->wex);
+				rep->wex = tick_add_ifset(now_ms, t->fe->timeout.client);
 			}
 		}
 		return 0;
@@ -2508,7 +2499,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (tv_isle(&req->rex, &now)) {
+		else if (tick_is_expired(req->rex, now_ms)) {
 			buffer_shutr(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -2533,15 +2524,12 @@
 
 			if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
 				/* stop reading until we get some space */
-				tv_eternity(&req->rex);
-				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
+				req->rex = TICK_ETERNITY;
 			}
 		} else {
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-				if (!tv_add_ifset(&req->rex, &now, &t->fe->timeout.client))
-					tv_eternity(&req->rex);
-				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
+				req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
 			}
 		}
 		return 0;
@@ -2615,7 +2603,7 @@
 		else if (c == CL_STCLOSE || c == CL_STSHUTW ||
 			 (c == CL_STSHUTR &&
 			  (t->req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
-			tv_eternity(&req->cex);
+			req->cex = TICK_ETERNITY;
 			if (t->pend_pos)
 				t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
 			/* note that this must not return any error because it would be able to
@@ -2634,7 +2622,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 (!tick_is_expired(req->cex, now_ms))
 					return 0;
 
 				/* We will set the queue timer to the time spent, just for
@@ -2643,7 +2631,7 @@
 				 * It will not cause trouble to the logs because we can exclude
 				 * the tarpitted connections by filtering on the 'PT' status flags.
 				 */
-				tv_eternity(&req->cex);
+				req->cex = TICK_ETERNITY;
 				t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
 				srv_close_with_err(t, SN_ERR_PRXCOND, SN_FINST_T,
 						   500, error_message(t, HTTP_ERR_500));
@@ -2656,11 +2644,11 @@
 			 * to any other session to release it and wake us up again.
 			 */
 			if (t->pend_pos) {
-				if (!tv_isle(&req->cex, &now)) {
+				if (!tick_is_expired(req->cex, now_ms)) {
 					return 0;
 				} else {
 					/* we've been waiting too long here */
-					tv_eternity(&req->cex);
+					req->cex = TICK_ETERNITY;
 					t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
 					srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q,
 							   503, error_message(t, HTTP_ERR_503));
@@ -2741,7 +2729,7 @@
 		    (c == CL_STSHUTR &&
 		     ((t->req->l == 0 && !(req->flags & BF_WRITE_STATUS)) ||
 		      t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
-			tv_eternity(&req->cex);
+			req->cex = TICK_ETERNITY;
 			if (!(t->flags & SN_CONN_TAR)) {
 				/* if we are in turn-around, we have already closed the FD */
 				fd_delete(t->srv_fd);
@@ -2757,8 +2745,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)) {
-			//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);
+		if (!(req->flags & BF_WRITE_STATUS) && !tick_is_expired(req->cex, now_ms)) {
 			return 0; /* nothing changed */
 		}
 		else if (!(req->flags & BF_WRITE_STATUS) || (req->flags & BF_WRITE_ERROR)) {
@@ -2767,7 +2754,7 @@
 
 			if (t->flags & SN_CONN_TAR) {
 				/* We are doing a turn-around waiting for a new connection attempt. */
-				if (!tv_isle(&req->cex, &now))
+				if (!tick_is_expired(req->cex, now_ms))
 					return 0;
 				t->flags &= ~SN_CONN_TAR;
 			}
@@ -2795,7 +2782,7 @@
 					 * time of 1 second. We will wait in the previous if block.
 					 */
 					t->flags |= SN_CONN_TAR;
-					tv_ms_add(&req->cex, &now, 1000);
+					req->cex = tick_add(now_ms, MS_TO_TICKS(1000));
 					return 0;
 				}
 			}
@@ -2843,23 +2830,20 @@
 			//fprintf(stderr,"3: c=%d, s=%d\n", c, s);
 			if (req->l == 0) /* nothing to write */ {
 				EV_FD_CLR(t->srv_fd, DIR_WR);
-				tv_eternity(&req->wex);
+				req->wex = TICK_ETERNITY;
 			} else  /* need the right to write */ {
 				EV_FD_SET(t->srv_fd, DIR_WR);
-				if (tv_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
+				req->wex = tick_add_ifset(now_ms, t->be->timeout.server);
+				if (req->wex) {
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
 				}
-				else
-					tv_eternity(&req->wex);
 			}
 
 			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_add_ifset(&rep->rex, &now, &t->be->timeout.server))
-					tv_eternity(&rep->rex);
-		
+				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 				t->srv_state = SV_STDATA;
 				rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */
 
@@ -2885,7 +2869,7 @@
 				 * hdr_idx_init(&t->txn.hdr_idx);
 				 */
 			}
-			tv_eternity(&req->cex);
+			req->cex = TICK_ETERNITY;
 			return 1;
 		}
 	}
@@ -2940,8 +2924,7 @@
 			 * full. We cannot loop here since stream_sock_read will disable it only if
 			 * rep->l == rlim-data
 			 */
-			if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
-				tv_eternity(&rep->rex);
+			req->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 		}
 
 
@@ -3003,10 +2986,9 @@
 				return 1;
 			}
 
-			/* read timeout : return a 504 to the client.
-			 */
+			/* read timeout : return a 504 to the client. */
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_RD) &&
-			                  tv_isle(&rep->rex, &now))) {
+			                  tick_is_expired(rep->rex, now_ms))) {
 				buffer_shutr(rep);
 				buffer_shutw(req);
 				fd_delete(t->srv_fd);
@@ -3047,7 +3029,7 @@
 				/* We must ensure that the read part is still
 				 * alive when switching to shutw */
 				EV_FD_SET(t->srv_fd, DIR_RD);
-				tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
+				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 
 				shutdown(t->srv_fd, SHUT_WR);
 				t->srv_state = SV_STSHUTW;
@@ -3060,14 +3042,14 @@
 			 * some work to do on the headers.
 			 */
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_WR) &&
-					  tv_isle(&req->wex, &now))) {
+					  tick_is_expired(req->wex, now_ms))) {
 				EV_FD_CLR(t->srv_fd, DIR_WR);
 				buffer_shutw(req);
 				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);
-				tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
+				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 
 				t->srv_state = SV_STSHUTW;
 				if (!(t->flags & SN_ERR_MASK))
@@ -3088,13 +3070,12 @@
 			else if (likely(req->l)) {
 				if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
 					/* restart writing */
-					if (tv_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
+					req->wex = tick_add_ifset(now_ms, t->be->timeout.server);
+					if (req->wex) {
 						/* FIXME: to prevent the server from expiring read timeouts during writes,
 						 * we refresh it. */
 						rep->rex = req->wex;
 					}
-					else
-						tv_eternity(&req->wex);
 				}
 			}
 
@@ -3102,7 +3083,7 @@
 			else {
 				if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
 					/* stop writing */
-					tv_eternity(&req->wex);
+					req->wex = TICK_ETERNITY;
 				}
 			}
 
@@ -3396,7 +3377,7 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->srv_fd, DIR_RD);
-			tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
+			rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 
 			shutdown(t->srv_fd, SHUT_WR);
 			t->srv_state = SV_STSHUTW;
@@ -3469,13 +3450,13 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->srv_fd, DIR_RD);
-			tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
+			rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 
 			t->srv_state = SV_STSHUTW;
 			return 1;
 		}
 		/* read timeout */
-		else if (tv_isle(&rep->rex, &now)) {
+		else if (tick_is_expired(rep->rex, now_ms)) {
 			EV_FD_CLR(t->srv_fd, DIR_RD);
 			buffer_shutr(rep);
 			t->srv_state = SV_STSHUTR;
@@ -3486,14 +3467,14 @@
 			return 1;
 		}	
 		/* write timeout */
-		else if (tv_isle(&req->wex, &now)) {
+		else if (tick_is_expired(req->wex, now_ms)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
 			buffer_shutw(req);
 			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);
-			tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
+			rep->cex = tick_add_ifset(now_ms, t->be->timeout.server);
 			t->srv_state = SV_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVTO;
@@ -3506,32 +3487,30 @@
 		if (req->l == 0) {
 			if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&req->wex);
+				req->wex = TICK_ETERNITY;
 			}
 		}
 		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_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
+				req->wex = tick_add_ifset(now_ms, t->be->timeout.server);
+				if (req->wex) {
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
 				}
-				else
-					tv_eternity(&req->wex);
 			}
 		}
 
 		/* recompute response time-outs */
 		if (rep->l == BUFSIZE) { /* no room to read more data */
 			if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
-				tv_eternity(&rep->rex);
+				rep->rex = TICK_ETERNITY;
 			}
 		}
 		else {
 			if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-				if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
-					tv_eternity(&rep->rex);
+				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 			}
 		}
 
@@ -3580,7 +3559,7 @@
 
 			return 1;
 		}
-		else if (tv_isle(&req->wex, &now)) {
+		else if (tick_is_expired(req->wex, now_ms)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
 			buffer_shutw(req);
 			fd_delete(t->srv_fd);
@@ -3605,14 +3584,13 @@
 		else if (req->l == 0) {
 			if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&req->wex);
+				req->wex = TICK_ETERNITY;
 			}
 		}
 		else { /* buffer not empty */
 			if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
 				/* restart writing */
-				if (!tv_add_ifset(&req->wex, &now, &t->be->timeout.server))
-					tv_eternity(&req->wex);
+				req->wex = tick_add_ifset(now_ms, t->be->timeout.server);
 			}
 		}
 		return 0;
@@ -3660,7 +3638,7 @@
 
 			return 1;
 		}
-		else if (tv_isle(&rep->rex, &now)) {
+		else if (tick_is_expired(rep->rex, now_ms)) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
 			buffer_shutr(rep);
 			fd_delete(t->srv_fd);
@@ -3684,13 +3662,12 @@
 		}
 		else if (rep->l == BUFSIZE) { /* no room to read more data */
 			if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
-				tv_eternity(&rep->rex);
+				rep->rex = TICK_ETERNITY;
 			}
 		}
 		else {
 			if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-				if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
-					tv_eternity(&rep->rex);
+				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 			}
 		}
 		return 0;
@@ -3699,7 +3676,7 @@
 		/* this server state is set by the client to study the body for server assignment */
 
 		/* Have we been through this long enough to timeout? */
-		if (!tv_isle(&req->rex, &now)) {
+		if (!tick_is_expired(req->rex, now_ms)) {
 			/* balance url_param check_post should have been the only to get into this.
 			 * just wait for data, check to compare how much
 			 */
@@ -3746,7 +3723,7 @@
 			if ( len < limit )
 				return 0;
 		}
-		t->srv_state=SV_STIDLE;
+		t->srv_state = SV_STIDLE;
 		return 1;
 	}
 	else { /* SV_STCLOSE : nothing to do */
@@ -4382,7 +4359,7 @@
 						}/* end while(srv) */
 					}/* end else if server == NULL */
 
-					tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
+					asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession);
 				}/* end if ((t->proxy->appsession_name != NULL) ... */
 			}
 
@@ -4837,7 +4814,7 @@
 				if (asession_temp->serverid[0] == '\0')
 					memcpy(asession_temp->serverid, t->srv->id, server_id_len);
 		      
-				tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
+				asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession);
 
 #if defined(DEBUG_HASH)
 				appsession_hash_dump(&(t->be->htbl_proxy));
@@ -5000,7 +4977,7 @@
 		pool_free2(apools.sessid, local_asession.sessid);
 	}
 
-	tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
+	asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession);
 	asession_temp->request_count++;
 
 #if defined(DEBUG_HASH)
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 6968562..ba3da5f 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -32,6 +32,7 @@
 #include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/version.h>
 
@@ -500,18 +501,18 @@
 		fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
 		fdtab[cfd].peerlen = sizeof(s->cli_addr);
 
-		tv_eternity(&s->req->rex);
-		tv_eternity(&s->req->wex);
-		tv_eternity(&s->req->cex);
-		tv_eternity(&s->rep->rex);
-		tv_eternity(&s->rep->wex);
+		s->req->rex = TICK_ETERNITY;
+		s->req->wex = TICK_ETERNITY;
+		s->req->cex = TICK_ETERNITY;
+		s->rep->rex = TICK_ETERNITY;
+		s->rep->wex = TICK_ETERNITY;
 
-		tv_eternity(&s->req->wto);
-		tv_eternity(&s->req->cto);
-		tv_eternity(&s->req->rto);
-		tv_eternity(&s->rep->rto);
-		tv_eternity(&s->rep->cto);
-		tv_eternity(&s->rep->wto);
+		s->req->wto = TICK_ETERNITY;
+		s->req->cto = TICK_ETERNITY;
+		s->req->rto = TICK_ETERNITY;
+		s->rep->rto = TICK_ETERNITY;
+		s->rep->cto = TICK_ETERNITY;
+		s->rep->wto = TICK_ETERNITY;
 
 		if (l->timeout)
 			s->req->rto = *l->timeout;
@@ -519,10 +520,10 @@
 		if (l->timeout)
 			s->rep->wto = *l->timeout;
 
-		tv_eternity(&t->expire);
-		if (l->timeout && tv_isset(l->timeout)) {
+		t->expire = TICK_ETERNITY;
+		if (l->timeout && *l->timeout) {
 			EV_FD_SET(cfd, DIR_RD);
-			tv_add(&s->req->rex, &now, &s->req->rto);
+			s->req->rex = tick_add(now_ms, s->req->rto);
 			t->expire = s->req->rex;
 		}
 
@@ -592,13 +593,13 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			EV_FD_SET(t->cli_fd, DIR_RD);
-			tv_add_ifset(&req->rex, &now, &req->rto);
+			req->rex = tick_add_ifset(now_ms, req->rto);
 			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 (tick_is_expired(req->rex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_RD);
 			buffer_shutr(req);
 			t->cli_state = CL_STSHUTR;
@@ -615,14 +616,14 @@
 			return 1;
 		}	
 		/* write timeout */
-		else if (tv_isle(&rep->wex, &now)) {
+		else if (tick_is_expired(rep->wex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
 			buffer_shutw(rep);
 			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);
-			tv_add_ifset(&req->rex, &now, &req->rto);
+			req->rex = tick_add_ifset(now_ms, req->rto);
 
 			t->cli_state = CL_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
@@ -642,21 +643,21 @@
 			/* no room to read more data */
 			if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
 				/* stop reading until we get some space */
-				tv_eternity(&req->rex);
+				req->rex = TICK_ETERNITY;
 			}
 		} else {
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-				if (!tv_isset(&req->rto) ||
-				    (t->srv_state < SV_STDATA && tv_isset(&req->wto)))
+				if (!req->rto ||
+				    (t->srv_state < SV_STDATA && req->wto))
 					/* If the client has no timeout, or if the server not ready yet, and we
 					 * know for sure that it can expire, then it's cleaner to disable the
 					 * timeout on the client side so that too low values cannot make the
 					 * sessions abort too early.
 					 */
-					tv_eternity(&req->rex);
+					req->rex = TICK_ETERNITY;
 				else
-					tv_add(&req->rex, &now, &req->rto);
+					req->rex = tick_add(now_ms, req->rto);
 			}
 		}
 
@@ -664,19 +665,18 @@
 		    ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&rep->wex);
+				rep->wex = TICK_ETERNITY;
 			}
 		} else {
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (tv_add_ifset(&rep->wex, &now, &rep->wto)) {
+				rep->wex = tick_add_ifset(now_ms, rep->wto);
+				if (rep->wex) {
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
 				}
-				else
-					tv_eternity(&rep->wex);
 			}
 		}
 		return 0; /* other cases change nothing */
@@ -704,7 +704,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (tv_isle(&rep->wex, &now)) {
+		else if (tick_is_expired(rep->wex, now_ms)) {
 			buffer_shutw(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -724,14 +724,13 @@
 		if (rep->l == 0) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
-				tv_eternity(&rep->wex);
+				rep->wex = TICK_ETERNITY;
 			}
 		} else {
 			/* buffer not empty */
 			if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
 				/* restart writing */
-				if (!tv_add_ifset(&rep->wex, &now, &rep->wto))
-					tv_eternity(&rep->wex);
+				rep->wex = tick_add_ifset(now_ms, rep->wto);
 			}
 		}
 		return 0;
@@ -759,7 +758,7 @@
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
-		else if (tv_isle(&req->rex, &now)) {
+		else if (tick_is_expired(req->rex, now_ms)) {
 			buffer_shutr(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -784,15 +783,12 @@
 
 			if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
 				/* stop reading until we get some space */
-				tv_eternity(&req->rex);
-				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
+				req->rex = TICK_ETERNITY;
 			}
 		} else {
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-				if (!tv_add_ifset(&req->rex, &now, &req->rto))
-					tv_eternity(&req->rex);
-				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
+				req->rex = tick_add_ifset(now_ms, req->rto);
 			}
 		}
 		return 0;
@@ -1256,7 +1252,7 @@
  * the time the task accepts to wait, or TIME_ETERNITY for
  * infinity.
  */
-void process_uxst_session(struct task *t, struct timeval *next)
+void process_uxst_session(struct task *t, int *next)
 {
 	struct session *s = t->context;
 	int fsm_resync = 0;
@@ -1357,7 +1353,7 @@
  * for now. It only knows states SV_STIDLE, SV_STCONN, SV_STDATA, and
  * SV_STCLOSE. Returns in <next> the task's expiration date.
  */
-void process_uxst_stats(struct task *t, struct timeval *next)
+void process_uxst_stats(struct task *t, int *next)
 {
 	struct session *s = t->context;
 	struct listener *listener;
@@ -1468,11 +1464,9 @@
 		s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 		s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 
-		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);
+		t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
+				       tick_first(s->rep->rex, s->rep->wex));
+		t->expire = tick_first(t->expire, s->req->cex);
 
 		/* restore t to its place in the task list */
 		task_queue(t);
@@ -1497,7 +1491,7 @@
 	task_delete(t);
 	session_free(s);
 	task_free(t);
-	tv_eternity(next);
+	*next = TICK_ETERNITY;
 }
 
 __attribute__((constructor))
diff --git a/src/proxy.c b/src/proxy.c
index 21b039d..e597fc5 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -90,8 +90,8 @@
 	unsigned timeout;
 	int retval, cap;
 	const char *res, *name;
-	struct timeval *tv = NULL;
-	struct timeval *td = NULL;
+	int *tv = NULL;
+	int *td = NULL;
 
 	retval = 0;
 	name = args[0];
@@ -155,16 +155,12 @@
 			 (cap & PR_CAP_BE) ? "backend" : "frontend");
 		retval = 1;
 	}
-	else if (defpx && !__tv_iseq(tv, td)) {
+	else if (defpx && *tv != *td) {
 		snprintf(err, errlen, "overwriting %s timeout which was already specified", name);
 		retval = 1;
 	}
 
-	if (timeout)
-		__tv_from_ms(tv, timeout);
-	else
-		tv_eternity(tv);
-
+	*tv = MS_TO_TICKS(timeout);
 	return retval;
 }
 
@@ -303,7 +299,7 @@
  * select_loop(). It adjusts the date of next expiration event during stop
  * time if appropriate.
  */
-void maintain_proxies(struct timeval *next)
+void maintain_proxies(int *next)
 {
 	struct proxy *p;
 	struct listener *l;
@@ -346,7 +342,7 @@
 		while (p) {
 			if (p->state != PR_STSTOPPED) {
 				int t;
-				t = tv_ms_remain2(&now, &p->stop_time);
+				t = tick_remain(now_ms, p->stop_time);
 				if (t == 0) {
 					Warning("Proxy %s stopped.\n", p->id);
 					send_log(p, LOG_WARNING, "Proxy %s stopped.\n", p->id);
@@ -363,7 +359,7 @@
 					pool_gc2();
 				}
 				else {
-					tv_bound(next, &p->stop_time);
+					*next = tick_first(*next, p->stop_time);
 				}
 			}
 			p = p->next;
@@ -389,7 +385,7 @@
 		if (p->state != PR_STSTOPPED) {
 			Warning("Stopping proxy %s in %d ms.\n", p->id, p->grace);
 			send_log(p, LOG_WARNING, "Stopping proxy %s in %d ms.\n", p->id, p->grace);
-			tv_ms_add(&p->stop_time, &now, p->grace);
+			p->stop_time = tick_add(now_ms, p->grace);
 		}
 		p = p->next;
 	}
diff --git a/src/senddata.c b/src/senddata.c
index e81a2de..7fb1f96 100644
--- a/src/senddata.c
+++ b/src/senddata.c
@@ -2,7 +2,7 @@
  * Helper functions to send data over a socket and buffer.
  * Should probably move somewhere else, but where ?
  *
- * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,6 +28,7 @@
 #include <common/debug.h>
 #include <common/memory.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 #include <common/version.h>
 
@@ -56,8 +57,7 @@
 	EV_FD_CLR(s->cli_fd, DIR_RD);
 	EV_FD_SET(s->cli_fd, DIR_WR);
 	buffer_shutr(s->req);
-	if (!tv_add_ifset(&s->rep->wex, &now, &s->rep->wto))
-		tv_eternity(&s->rep->wex);
+	s->rep->wex = tick_add_ifset(now_ms, s->rep->wto);
 	s->cli_state = CL_STSHUTR;
 	buffer_flush(s->rep);
 	if (msg && msg->len)
diff --git a/src/stream_sock.c b/src/stream_sock.c
index fab32ca..aa45bdd 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1,7 +1,7 @@
 /*
  * Functions operating on SOCK_STREAM and buffers.
  *
- * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
 #include <common/config.h>
 #include <common/debug.h>
 #include <common/standard.h>
+#include <common/ticks.h>
 #include <common/time.h>
 
 #include <types/buffers.h>
@@ -42,7 +43,7 @@
  * otherwise.
  */
 int stream_sock_read(int fd) {
-	__label__ out_eternity, out_wakeup, out_shutdown_r, out_error;
+	__label__ out_wakeup, out_shutdown_r, out_error;
 	struct buffer *b = fdtab[fd].cb[DIR_RD].b;
 	int ret, max, retval, cur_read;
 	int read_poll = MAX_READ_POLL_LOOPS;
@@ -88,7 +89,8 @@
 			 * never happen, but better safe than sorry !
 			 */
 			EV_FD_CLR(fd, DIR_RD);
-			goto out_eternity;
+			b->rex = TICK_ETERNITY;
+			goto out_wakeup;
 		}
 
 		/*
@@ -154,7 +156,8 @@
 				}
 
 				EV_FD_CLR(fd, DIR_RD);
-				goto out_eternity;
+				b->rex = TICK_ETERNITY;
+				goto out_wakeup;
 			}
 
 			/* if too many bytes were missing from last read, it means that
@@ -218,12 +221,8 @@
 	 * have at least read something.
 	 */
 
-	if (b->flags & BF_PARTIAL_READ) {
-		if (tv_add_ifset(&b->rex, &now, &b->rto))
-			goto out_wakeup;
-	out_eternity:
-		tv_eternity(&b->rex);
-	}
+	if (b->flags & BF_PARTIAL_READ)
+		b->rex = tick_add_ifset(now_ms, b->rto);
 
  out_wakeup:
 	if (b->flags & BF_READ_STATUS)
@@ -234,7 +233,8 @@
  out_shutdown_r:
 	fdtab[fd].ev &= ~FD_POLL_HUP;
 	b->flags |= BF_READ_NULL;
-	goto out_eternity;
+	b->rex = TICK_ETERNITY;
+	goto out_wakeup;
 
  out_error:
 	/* There was an error. we must wakeup the task. No need to clear
@@ -243,7 +243,8 @@
 	fdtab[fd].state = FD_STERROR;
 	fdtab[fd].ev &= ~FD_POLL_STICKY;
 	b->flags |= BF_READ_ERROR;
-	goto out_eternity;
+	b->rex = TICK_ETERNITY;
+	goto out_wakeup;
 }
 
 
@@ -254,7 +255,7 @@
  * otherwise.
  */
 int stream_sock_write(int fd) {
-	__label__ out_eternity, out_wakeup, out_error;
+	__label__ out_wakeup, out_error;
 	struct buffer *b = fdtab[fd].cb[DIR_WR].b;
 	int ret, max, retval;
 	int write_poll = MAX_WRITE_POLL_LOOPS;
@@ -314,7 +315,8 @@
 			 * let's disable the write event and pretend we never came there.
 			 */
 			EV_FD_CLR(fd, DIR_WR);
-			goto out_eternity;
+			b->wex = TICK_ETERNITY;
+			goto out_wakeup;
 		}
 
 #ifndef MSG_NOSIGNAL
@@ -344,7 +346,8 @@
 
 			if (!b->l) {
 				EV_FD_CLR(fd, DIR_WR);
-				goto out_eternity;
+				b->wex = TICK_ETERNITY;
+				goto out_wakeup;
 			}
 
 			/* if the system buffer is full, don't insist */
@@ -375,17 +378,15 @@
 	 */
 
 	if (b->flags & BF_PARTIAL_WRITE) {
-		if (tv_add_ifset(&b->wex, &now, &b->wto)) {
+		b->wex = tick_add_ifset(now_ms, b->wto);
+		if (b->wex) {
 			/* 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
 			 * TCP connections. */
 			if (!(b->flags & BF_SHUTR_STATUS))
 				b->rex = b->wex;
-			goto out_wakeup;
 		}
-	out_eternity:
-		tv_eternity(&b->wex);
 	}
 
  out_wakeup:
@@ -401,9 +402,8 @@
 	fdtab[fd].state = FD_STERROR;
 	fdtab[fd].ev &= ~FD_POLL_STICKY;
 	b->flags |= BF_WRITE_ERROR;
-	goto out_eternity;
-
-
+	b->wex = TICK_ETERNITY;
+	goto out_wakeup;
 }
 
 
diff --git a/src/task.c b/src/task.c
index 13d6817..5a9a2c2 100644
--- a/src/task.c
+++ b/src/task.c
@@ -171,10 +171,10 @@
  */
 struct task *task_queue(struct task *task)
 {
-	if (unlikely(tv_iseternity(&task->expire)))
+	if (unlikely(!task->expire))
 		return task;
 
-	task->eb.key = timeval_to_ticks(&task->expire);
+	task->eb.key = task->expire;
 #ifdef DEBUG_CHECK_INVALID_EXPIRATION_DATES
 	if ((task->eb.key - now_ms) & TIMER_SIGN_BIT)
 		/* we're queuing too far away or in the past (most likely) */
@@ -200,7 +200,7 @@
  * Extract all expired timers from the timer queue, and wakes up all
  * associated tasks. Returns the date of next event (or eternity).
  */
-void wake_expired_tasks(struct timeval *next)
+void wake_expired_tasks(int *next)
 {
 	struct task *task;
 	struct eb32_node *eb;
@@ -238,7 +238,7 @@
 	} while (((tree - now_tree) & TIMER_TREE_MASK) < TIMER_TREES/2);
 
 	/* We have found no task to expire in any tree */
-	tv_eternity(next);
+	*next = TICK_ETERNITY;
 	return;
 }
 
@@ -257,9 +257,9 @@
  *
  * The function adjusts <next> if a new event is closer.
  */
-void process_runnable_tasks(struct timeval *next)
+void process_runnable_tasks(int *next)
 {
-	struct timeval temp;
+	int temp;
 	struct task *t;
 	struct eb32_node *eb;
 	unsigned int tree, stop;
@@ -294,7 +294,7 @@
 			task_dequeue(t);
 
 			t->process(t, &temp);
-			tv_bound(next, &temp);
+			*next = tick_first(*next, temp);
 
 			if (!--max_processed)
 				return;