[MAJOR] replaced all timeouts with struct timeval
The timeout functions were difficult to manipulate because they were
rounding results to the millisecond. Thus, it was difficult to compare
and to check what expired and what did not. Also, the comparison
functions were heavy with multiplies and divides by 1000. Now, all
timeouts are stored in timevals, reducing the number of operations
for updates and leading to cleaner and more efficient code.
diff --git a/include/common/appsession.h b/include/common/appsession.h
index eb9ba2d..8fa681c 100644
--- a/include/common/appsession.h
+++ b/include/common/appsession.h
@@ -44,7 +44,7 @@
static void print_table(const CHTbl *htbl);
#endif
-int appsession_refresh(struct task *t);
+void appsession_refresh(struct task *t, struct timeval *next);
int appsession_task_init(void);
int appsession_init(void);
void appsession_cleanup(void);
diff --git a/include/proto/checks.h b/include/proto/checks.h
index 6ac32a1..839af55 100644
--- a/include/proto/checks.h
+++ b/include/proto/checks.h
@@ -2,7 +2,7 @@
include/proto/checks.h
Functions prototypes for the checks.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -25,7 +25,7 @@
#include <types/task.h>
#include <common/config.h>
-int process_chk(struct task *t);
+void process_chk(struct task *t, struct timeval *next);
#endif /* _PROTO_CHECKS_H */
diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
index 298d30d..da4ea0e 100644
--- a/include/proto/proto_http.h
+++ b/include/proto/proto_http.h
@@ -58,7 +58,7 @@
#define HTTP_IS_VER_TOKEN(x) (http_is_ver_token[(unsigned char)(x)])
int event_accept(int fd);
-int process_session(struct task *t);
+void process_session(struct task *t, struct timeval *next);
int process_cli(struct session *t);
int process_srv(struct session *t);
diff --git a/include/proto/proxy.h b/include/proto/proxy.h
index 3fa541a..38d7325 100644
--- a/include/proto/proxy.h
+++ b/include/proto/proxy.h
@@ -2,7 +2,7 @@
include/proto/proxy.h
This file defines function prototypes for proxy management.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -23,10 +23,11 @@
#define _PROTO_PROXY_H
#include <common/config.h>
+#include <common/time.h>
#include <types/proxy.h>
int start_proxies(int verbose);
-int maintain_proxies(void);
+void maintain_proxies(struct timeval *next);
void soft_stop(void);
void pause_proxy(struct proxy *p);
void pause_proxies(void);
diff --git a/include/proto/queue.h b/include/proto/queue.h
index c113f03..4370cb3 100644
--- a/include/proto/queue.h
+++ b/include/proto/queue.h
@@ -2,7 +2,7 @@
include/proto/queue.h
This file defines everything related to queues.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px);
struct pendconn *pendconn_add(struct session *sess);
void pendconn_free(struct pendconn *p);
-int process_srv_queue(struct task *t);
+void process_srv_queue(struct task *t, struct timeval *next);
unsigned int srv_dynamic_maxconn(const struct server *s);
diff --git a/include/proto/task.h b/include/proto/task.h
index 2c724ad..c594d52 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -111,12 +111,10 @@
* - wake up all expired tasks
* - call all runnable tasks
* - call maintain_proxies() to enable/disable the listeners
- * - return the delay till next event in ms, -1 = wait indefinitely
- * Note: this part should be rewritten with the O(ln(n)) scheduler.
- *
+ * - return the date of next event in <next> or eternity.
*/
-int process_runnable_tasks();
+void process_runnable_tasks(struct timeval *next);
#endif /* _PROTO_TASK_H */
diff --git a/include/types/buffers.h b/include/types/buffers.h
index 4afc293..9b781b8 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -63,9 +63,9 @@
struct timeval rex; /* expiration date for a read */
struct timeval wex; /* expiration date for a write */
struct timeval cex; /* expiration date for a connect */
- int rto; /* read timeout */
- int wto; /* write timeout */
- int cto; /* connect timeout */
+ struct timeval rto; /* read timeout */
+ struct timeval wto; /* write timeout */
+ struct timeval cto; /* connect timeout */
unsigned int l; /* data length */
char *r, *w, *lr; /* read ptr, write ptr, last read */
char *rlim; /* read limit, used for header rewriting */
diff --git a/include/types/fd.h b/include/types/fd.h
index 392c94e..a1b6e9d 100644
--- a/include/types/fd.h
+++ b/include/types/fd.h
@@ -81,7 +81,7 @@
* it returns 0. It may be the same as clr().
* - clo() should be used to do indicate the poller that fd will be closed. It
* may be the same as rem() on some pollers.
- * - poll() calls the poller, waiting at most wait_time ms.
+ * - poll() calls the poller, expiring at <exp>
*/
struct poller {
void *private; /* any private data for the poller */
@@ -92,7 +92,7 @@
int REGPRM2 (*cond_c)(const int fd, int dir); /* clear polling on <fd> for <dir> if set */
void REGPRM1 (*rem)(const int fd); /* remove any polling on <fd> */
void REGPRM1 (*clo)(const int fd); /* mark <fd> as closed */
- void REGPRM2 (*poll)(struct poller *p, int wait_time); /* the poller itself */
+ void REGPRM2 (*poll)(struct poller *p, struct timeval *exp); /* the poller itself */
int REGPRM1 (*init)(struct poller *p); /* poller initialization */
void REGPRM1 (*term)(struct poller *p); /* termination of this poller */
int REGPRM1 (*test)(struct poller *p); /* pre-init check of the poller */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index c403e59..532348e 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -96,7 +96,6 @@
char *appsession_name; /* name of the cookie to look for */
int appsession_name_len; /* strlen(appsession_name), computed only once */
int appsession_len; /* length of the appsession cookie value to be used */
- int appsession_timeout;
CHTbl htbl_proxy; /* Per Proxy hashtable */
char *capture_name; /* beginning of the name of the cookie to capture */
int capture_namelen; /* length of the cookie name to match */
@@ -104,9 +103,10 @@
struct uri_auth *uri_auth; /* if non-NULL, the (list of) per-URI authentications */
char *monitor_uri; /* a special URI to which we respond with HTTP/200 OK */
int monitor_uri_len; /* length of the string above. 0 if unused */
- int clitimeout; /* client I/O timeout (in milliseconds) */
- int srvtimeout; /* server I/O timeout (in milliseconds) */
- int contimeout; /* connect timeout (in milliseconds) */
+ struct timeval clitimeout; /* client I/O timeout (in milliseconds) */
+ struct timeval srvtimeout; /* server I/O timeout (in milliseconds) */
+ struct timeval contimeout; /* connect timeout (in milliseconds) */
+ struct timeval appsession_timeout;
char *id; /* proxy id */
struct list pendconns; /* pending connections with no server assigned yet */
int nbpend, nbpend_max; /* number of pending connections with no server assigned yet */
diff --git a/include/types/task.h b/include/types/task.h
index 1fd78be..42699db 100644
--- a/include/types/task.h
+++ b/include/types/task.h
@@ -2,7 +2,7 @@
include/types/task.h
Macros, variables and structures for task management.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -38,7 +38,7 @@
struct ultree *wq; /* NULL if unqueued, or back ref to the carrier node in the WQ */
int state; /* task state : IDLE or RUNNING */
struct timeval expire; /* next expiration time for this task, use only for fast sorting */
- int (*process)(struct task *t); /* the function which processes the task */
+ void (*process)(struct task *t, struct timeval *next); /* the function which processes the task */
void *context; /* the task's context */
};
diff --git a/src/appsession.c b/src/appsession.c
index d11fb19..0307ff7 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -125,7 +125,7 @@
return 0;
}
-int appsession_refresh(struct task *t)
+void appsession_refresh(struct task *t, struct timeval *next)
{
struct proxy *p = proxy;
CHTbl *htbl;
@@ -143,7 +143,7 @@
for (element = list_head(&htbl->table[i]);
element != NULL; element = list_next(element)) {
asession = (appsess *)list_data(element);
- if (tv_ms_le2(&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_ms_le2(&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)) */
@@ -174,7 +174,7 @@
p = p->next;
}
tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
- return TBLCHKINT;
+ *next = t->expire;
} /* end appsession_refresh */
int match_str(const void *key1, const void *key2)
diff --git a/src/backend.c b/src/backend.c
index 69e79d4..002394e 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1,7 +1,7 @@
/*
* Backend variables and functions.
*
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 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
@@ -550,8 +550,8 @@
s->srv->cur_sess_max = s->srv->cur_sess;
}
- if (s->be->contimeout)
- tv_ms_add(&s->req->cex, &now, s->be->contimeout);
+ if (tv_isset(&s->be->contimeout))
+ tv_add(&s->req->cex, &now, &s->be->contimeout);
else
tv_eternity(&s->req->cex);
return SN_ERR_NONE; /* connection is OK */
@@ -680,8 +680,8 @@
case SRV_STATUS_QUEUED:
/* FIXME-20060503 : we should use the queue timeout instead */
- if (t->be->contimeout)
- tv_ms_add(&t->req->cex, &now, t->be->contimeout);
+ if (tv_isset(&t->be->contimeout))
+ tv_add(&t->req->cex, &now, &t->be->contimeout);
else
tv_eternity(&t->req->cex);
t->srv_state = SV_STIDLE;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index b2e76b3..1edaa8f 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -766,7 +766,7 @@
curproxy->appsession_name = strdup(args[1]);
curproxy->appsession_name_len = strlen(curproxy->appsession_name);
curproxy->appsession_len = atoi(args[3]);
- curproxy->appsession_timeout = atoi(args[5]);
+ __tv_from_ms(&curproxy->appsession_timeout, atoi(args[5]));
rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
if (rc) {
Alert("Error Init Appsession Hashtable.\n");
@@ -857,7 +857,7 @@
}
}
else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
- if (curproxy->contimeout != defproxy.contimeout) {
+ if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
return 0;
}
@@ -869,10 +869,10 @@
file, linenum, args[0]);
return -1;
}
- curproxy->contimeout = atol(args[1]);
+ __tv_from_ms(&curproxy->contimeout, atol(args[1]));
}
else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
- if (curproxy->clitimeout != defproxy.clitimeout) {
+ if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
file, linenum, args[0]);
return 0;
@@ -885,10 +885,10 @@
file, linenum, args[0]);
return -1;
}
- curproxy->clitimeout = atol(args[1]);
+ __tv_from_ms(&curproxy->clitimeout, atol(args[1]));
}
else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
- if (curproxy->srvtimeout != defproxy.srvtimeout) {
+ if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
return 0;
}
@@ -900,7 +900,7 @@
file, linenum, args[0]);
return -1;
}
- curproxy->srvtimeout = atol(args[1]);
+ __tv_from_ms(&curproxy->srvtimeout, atol(args[1]));
}
else if (!strcmp(args[0], "retries")) { /* connection retries */
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
@@ -2385,8 +2385,9 @@
}
}
if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
- (((curproxy->cap & PR_CAP_FE) && !curproxy->clitimeout) ||
- ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && (!curproxy->contimeout || !curproxy->srvtimeout)))) {
+ (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
+ ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
+ (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
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"
diff --git a/src/checks.c b/src/checks.c
index 83a539e..96f5895 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1,7 +1,7 @@
/*
* Health-checks functions.
*
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 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
@@ -275,13 +275,12 @@
* manages a server health-check. Returns
* the time the task accepts to wait, or TIME_ETERNITY for infinity.
*/
-int process_chk(struct task *t)
+void process_chk(struct task *t, struct timeval *next)
{
__label__ new_chk, out;
struct server *s = t->context;
struct sockaddr_in sa;
int fd;
- int next_time;
//fprintf(stderr, "process_chk: task=%p\n", t);
@@ -289,9 +288,9 @@
fd = s->curfd;
if (fd < 0) { /* no check currently running */
//fprintf(stderr, "process_chk: 2\n");
- if (!tv_ms_le2(&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_time = tv_ms_remain2(&now, &t->expire);
+ *next = t->expire;
goto out;
}
@@ -299,10 +298,10 @@
* the server should not be checked.
*/
if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED) {
- while (tv_ms_le2(&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_time = tv_ms_remain2(&now, &t->expire);
+ *next = t->expire;
goto out;
}
@@ -410,7 +409,7 @@
/* FIXME: we allow up to <inter> for a connection to establish, but we should use another parameter */
tv_ms_add(&t->expire, &now, s->inter);
task_queue(t); /* restore t to its place in the task list */
- return tv_ms_remain(&now, &t->expire);
+ *next = t->expire;
}
else if (errno != EALREADY && errno != EISCONN && errno != EAGAIN) {
s->result = -1; /* a real error */
@@ -422,7 +421,7 @@
if (!s->result) { /* nothing done */
//fprintf(stderr, "process_chk: 6\n");
- while (tv_ms_le2(&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 */
}
@@ -437,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_ms_le2(&t->expire, &now))
+ while (__tv_isle(&t->expire, &now))
tv_ms_add(&t->expire, &t->expire, s->inter);
goto new_chk;
}
@@ -488,11 +487,11 @@
}
s->curfd = -1; /* no check running anymore */
fd_delete(fd);
- while (tv_ms_le2(&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_ms_le2(&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) {
@@ -503,7 +502,7 @@
set_server_down(s);
s->curfd = -1;
fd_delete(fd);
- while (tv_ms_le2(&t->expire, &now))
+ while (__tv_isle(&t->expire, &now))
tv_ms_add(&t->expire, &t->expire, s->inter);
goto new_chk;
}
@@ -512,12 +511,9 @@
//fprintf(stderr, "process_chk: 11\n");
s->result = 0;
task_queue(t); /* restore t to its place in the task list */
- next_time = tv_ms_remain2(&now, &t->expire);
+ *next = t->expire;
out:
- /* Ensure that we don't report sub-millisecond timeouts */
- if (next_time != TIME_ETERNITY)
- next_time++;
- return next_time;
+ return;
}
diff --git a/src/client.c b/src/client.c
index 4a891b0..52b281b 100644
--- a/src/client.c
+++ b/src/client.c
@@ -1,7 +1,7 @@
/*
* Client-side variables and functions.
*
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 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
@@ -386,7 +386,7 @@
s->rep->rto = s->be->srvtimeout;
s->rep->wto = s->fe->clitimeout;
- s->rep->cto = 0;
+ tv_zero(&s->rep->cto);
fd_insert(cfd);
fdtab[cfd].owner = t;
@@ -421,13 +421,13 @@
tv_eternity(&s->rep->wex);
tv_eternity(&t->expire);
- if (s->fe->clitimeout) {
+ if (tv_isset(&s->fe->clitimeout)) {
if (EV_FD_ISSET(cfd, DIR_RD)) {
- tv_ms_add(&s->req->rex, &now, s->fe->clitimeout);
+ tv_add(&s->req->rex, &now, &s->fe->clitimeout);
t->expire = s->req->rex;
}
if (EV_FD_ISSET(cfd, DIR_WR)) {
- tv_ms_add(&s->rep->wex, &now, s->fe->clitimeout);
+ tv_add(&s->rep->wex, &now, &s->fe->clitimeout);
t->expire = s->req->rex;
}
}
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
index b484499..a867e8d 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -220,16 +220,22 @@
/*
* epoll() poller
*/
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
{
int status;
int fd;
int count;
+ int wait_time;
if (likely(nbchanges))
fd_flush_changes();
/* now let's wait for events */
+ if (tv_isset(exp))
+ wait_time = tv_ms_remain(&now, exp);
+ else
+ wait_time = -1;
+
status = epoll_wait(epoll_fd, epoll_events, maxfd, wait_time);
tv_now(&now);
diff --git a/src/ev_poll.c b/src/ev_poll.c
index c48f502..3c97707 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -81,10 +81,11 @@
/*
* Poll() poller
*/
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
{
int status;
int fd, nbfd;
+ int wait_time;
int fds, count;
int sr, sw;
@@ -123,6 +124,11 @@
}
/* now let's wait for events */
+ if (tv_isset(exp))
+ wait_time = tv_ms_remain(&now, exp);
+ else
+ wait_time = -1;
+
status = poll(poll_events, nbfd, wait_time);
tv_now(&now);
diff --git a/src/ev_select.c b/src/ev_select.c
index ed79abf..fb5cc41 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -78,7 +78,7 @@
/*
* Select() poller
*/
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
{
int status;
int fd, i;
@@ -89,12 +89,14 @@
/* allow select to return immediately when needed */
delta.tv_sec = delta.tv_usec = 0;
- if (wait_time > 0) { /* FIXME */
- /* Convert to timeval */
- /* to avoid eventual select loops due to timer precision */
- wait_time += SCHEDULER_RESOLUTION;
- delta.tv_sec = wait_time / 1000;
- delta.tv_usec = (wait_time % 1000) * 1000;
+ if (tv_isset(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 ++;
+ }
}
/* let's restore fdset state */
@@ -118,7 +120,7 @@
readnotnull ? tmp_evts[DIR_RD] : NULL,
writenotnull ? tmp_evts[DIR_WR] : NULL,
NULL,
- (wait_time >= 0) ? &delta : NULL);
+ tv_isset(exp) ? &delta : NULL);
tv_now(&now);
diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c
index c3b7776..d2fcc7c 100644
--- a/src/ev_sepoll.c
+++ b/src/ev_sepoll.c
@@ -259,13 +259,14 @@
/*
* speculative epoll() poller
*/
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
{
static unsigned int last_skipped;
int status;
int fd, opcode;
int count;
int spec_idx;
+ int wait_time;
/* Here we have two options :
@@ -370,6 +371,12 @@
}
wait_time = 0;
}
+ else {
+ if (tv_isset(exp))
+ wait_time = tv_ms_remain(&now, exp);
+ else
+ wait_time = -1;
+ }
last_skipped = 0;
/* now let's wait for events */
diff --git a/src/haproxy.c b/src/haproxy.c
index a2e335e..0acf75f 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -684,17 +684,17 @@
*/
void run_poll_loop()
{
- int next_time;
- tv_now(&now);
+ struct timeval next;
+ tv_now(&now);
while (1) {
- next_time = process_runnable_tasks();
+ process_runnable_tasks(&next);
/* stop when there's no connection left and we don't allow them anymore */
if (!actconn && listeners == 0)
break;
- cur_poller.poll(&cur_poller, next_time);
+ cur_poller.poll(&cur_poller, &next);
}
}
diff --git a/src/proto_http.c b/src/proto_http.c
index 9506b16..0f78d07 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -442,8 +442,8 @@
EV_FD_CLR(s->cli_fd, DIR_RD);
EV_FD_SET(s->cli_fd, DIR_WR);
tv_eternity(&s->req->rex);
- if (s->fe->clitimeout)
- tv_ms_add(&s->rep->wex, &now, s->fe->clitimeout);
+ if (tv_isset(&s->fe->clitimeout))
+ tv_add(&s->rep->wex, &now, &s->fe->clitimeout);
else
tv_eternity(&s->rep->wex);
s->cli_state = CL_STSHUTR;
@@ -532,7 +532,7 @@
* the time the task accepts to wait, or TIME_ETERNITY for
* infinity.
*/
-int process_session(struct task *t)
+void process_session(struct task *t, struct timeval *next)
{
struct session *s = t->context;
int fsm_resync = 0;
@@ -563,11 +563,11 @@
/* 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)
+ if (tv_remain2(&now, &t->expire) <= 0)
exit(100);
#endif
-
- return tv_ms_remain2(&now, &t->expire); /* nothing more to do */
+ *next = t->expire;
+ return; /* nothing more to do */
}
s->fe->feconn--;
@@ -615,7 +615,7 @@
task_delete(t);
session_free(s);
task_free(t);
- return TIME_ETERNITY; /* rest in peace for eternity */
+ tv_eternity(next);
}
@@ -1529,7 +1529,7 @@
}
/* 3: has the read timeout expired ? */
- else if (unlikely(tv_ms_le2(&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,8 +1547,8 @@
* full. We cannot loop here since stream_sock_read will disable it only if
* req->l == rlim-data
*/
- if (t->fe->clitimeout)
- tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout))
+ tv_add(&req->rex, &now, &t->fe->clitimeout);
else
tv_eternity(&req->rex);
}
@@ -1912,8 +1912,8 @@
t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
- if (!t->fe->clitimeout ||
- (t->srv_state < SV_STDATA && t->be->srvtimeout)) {
+ if (!tv_isset(&t->fe->clitimeout) ||
+ (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout))) {
/* 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
@@ -1936,8 +1936,10 @@
/* flush the request so that we can drop the connection early
* if the client closes first.
*/
- tv_ms_add(&req->cex, &now,
- t->be->contimeout ? t->be->contimeout : 0);
+ if (tv_isset(&t->be->contimeout))
+ tv_add(&req->cex, &now, &t->be->contimeout);
+ else
+ req->cex = now;
}
/* OK let's go on with the BODY now */
@@ -1996,14 +1998,14 @@
/* We must ensure that the read part is still alive when switching
* to shutw */
EV_FD_SET(t->cli_fd, DIR_RD);
- if (t->fe->clitimeout)
- tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout))
+ tv_add(&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_ms_le2(&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;
@@ -2020,15 +2022,15 @@
return 1;
}
/* write timeout */
- else if (tv_ms_le2(&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 (t->fe->clitimeout)
- tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout))
+ tv_add(&req->rex, &now, &t->fe->clitimeout);
t->cli_state = CL_STSHUTW;
if (!(t->flags & SN_ERR_MASK))
@@ -2053,8 +2055,8 @@
} else {
/* there's still some space in the buffer */
if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
- if (!t->fe->clitimeout ||
- (t->srv_state < SV_STDATA && t->be->srvtimeout))
+ if (!tv_isset(&t->fe->clitimeout) ||
+ (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout)))
/* 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
@@ -2062,7 +2064,7 @@
*/
tv_eternity(&req->rex);
else
- tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+ tv_add(&req->rex, &now, &t->fe->clitimeout);
}
}
@@ -2076,8 +2078,8 @@
/* buffer not empty */
if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
/* restart writing */
- if (t->fe->clitimeout) {
- tv_ms_add(&rep->wex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout)) {
+ tv_add(&rep->wex, &now, &t->fe->clitimeout);
/* FIXME: to prevent the client from expiring read timeouts during writes,
* we refresh it. */
req->rex = rep->wex;
@@ -2112,7 +2114,7 @@
t->cli_state = CL_STCLOSE;
return 1;
}
- else if (tv_ms_le2(&rep->wex, &now)) {
+ else if (__tv_isle(&rep->wex, &now)) {
tv_eternity(&rep->wex);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
@@ -2149,8 +2151,8 @@
/* buffer not empty */
if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
/* restart writing */
- if (t->fe->clitimeout) {
- tv_ms_add(&rep->wex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout)) {
+ tv_add(&rep->wex, &now, &t->fe->clitimeout);
/* FIXME: to prevent the client from expiring read timeouts during writes,
* we refresh it. */
req->rex = rep->wex;
@@ -2184,7 +2186,7 @@
t->cli_state = CL_STCLOSE;
return 1;
}
- else if (tv_ms_le2(&req->rex, &now)) {
+ else if (__tv_isle(&req->rex, &now)) {
tv_eternity(&req->rex);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
@@ -2215,8 +2217,8 @@
} else {
/* there's still some space in the buffer */
if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
- if (t->fe->clitimeout)
- tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+ if (tv_isset(&t->fe->clitimeout))
+ tv_add(&req->rex, &now, &t->fe->clitimeout);
else
tv_eternity(&req->rex);
//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
@@ -2281,7 +2283,7 @@
* already set the connect expiration date to the right
* timeout. We just have to check that it has not expired.
*/
- if (!tv_ms_le2(&req->cex, &now))
+ if (!__tv_isle(&req->cex, &now))
return 0;
/* We will set the queue timer to the time spent, just for
@@ -2303,7 +2305,7 @@
* to any other session to release it and wake us up again.
*/
if (t->pend_pos) {
- if (!tv_ms_le2(&req->cex, &now))
+ if (!__tv_isle(&req->cex, &now))
return 0;
else {
/* we've been waiting too long here */
@@ -2349,7 +2351,7 @@
srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C, 0, NULL);
return 1;
}
- if (!(req->flags & BF_WRITE_STATUS) && !tv_ms_le2(&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 */
}
@@ -2416,8 +2418,8 @@
tv_eternity(&req->wex);
} else /* need the right to write */ {
EV_FD_SET(t->srv_fd, DIR_WR);
- if (t->be->srvtimeout) {
- tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout)) {
+ tv_add(&req->wex, &now, &t->be->srvtimeout);
/* FIXME: to prevent the server from expiring read timeouts during writes,
* we refresh it. */
rep->rex = req->wex;
@@ -2428,8 +2430,8 @@
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 (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
else
tv_eternity(&rep->rex);
@@ -2517,8 +2519,8 @@
* full. We cannot loop here since stream_sock_read will disable it only if
* rep->l == rlim-data
*/
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
else
tv_eternity(&rep->rex);
}
@@ -2584,7 +2586,7 @@
/* read timeout : return a 504 to the client.
*/
else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_RD) &&
- tv_ms_le2(&rep->rex, &now))) {
+ __tv_isle(&rep->rex, &now))) {
tv_eternity(&rep->rex);
tv_eternity(&req->wex);
fd_delete(t->srv_fd);
@@ -2624,8 +2626,8 @@
/* We must ensure that the read part is still
* alive when switching to shutw */
EV_FD_SET(t->srv_fd, DIR_RD);
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
shutdown(t->srv_fd, SHUT_WR);
t->srv_state = SV_STSHUTW;
@@ -2638,15 +2640,15 @@
* some work to do on the headers.
*/
else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_WR) &&
- tv_ms_le2(&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 (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
t->srv_state = SV_STSHUTW;
if (!(t->flags & SN_ERR_MASK))
@@ -2667,8 +2669,8 @@
else if (likely(req->l)) {
if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
/* restart writing */
- if (t->be->srvtimeout) {
- tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout)) {
+ tv_add(&req->wex, &now, &t->be->srvtimeout);
/* FIXME: to prevent the server from expiring read timeouts during writes,
* we refresh it. */
rep->rex = req->wex;
@@ -2964,8 +2966,8 @@
/* We must ensure that the read part is still alive when switching
* to shutw */
EV_FD_SET(t->srv_fd, DIR_RD);
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
shutdown(t->srv_fd, SHUT_WR);
t->srv_state = SV_STSHUTW;
@@ -3034,14 +3036,14 @@
/* We must ensure that the read part is still alive when switching
* to shutw */
EV_FD_SET(t->srv_fd, DIR_RD);
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
t->srv_state = SV_STSHUTW;
return 1;
}
/* read timeout */
- else if (tv_ms_le2(&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;
@@ -3052,15 +3054,15 @@
return 1;
}
/* write timeout */
- else if (tv_ms_le2(&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 (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
t->srv_state = SV_STSHUTW;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_SRVTO;
@@ -3079,8 +3081,8 @@
else { /* buffer not empty, there are still data to be transferred */
if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
/* restart writing */
- if (t->be->srvtimeout) {
- tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout)) {
+ tv_add(&req->wex, &now, &t->be->srvtimeout);
/* FIXME: to prevent the server from expiring read timeouts during writes,
* we refresh it. */
rep->rex = req->wex;
@@ -3098,8 +3100,8 @@
}
else {
if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
else
tv_eternity(&rep->rex);
}
@@ -3147,7 +3149,7 @@
return 1;
}
- else if (tv_ms_le2(&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);
@@ -3176,8 +3178,8 @@
else { /* buffer not empty */
if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
/* restart writing */
- if (t->be->srvtimeout) {
- tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout)) {
+ tv_add(&req->wex, &now, &t->be->srvtimeout);
/* FIXME: to prevent the server from expiring read timeouts during writes,
* we refresh it. */
rep->rex = req->wex;
@@ -3228,7 +3230,7 @@
return 1;
}
- else if (tv_ms_le2(&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);
@@ -3255,8 +3257,8 @@
}
else {
if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
- if (t->be->srvtimeout)
- tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+ if (tv_isset(&t->be->srvtimeout))
+ tv_add(&rep->rex, &now, &t->be->srvtimeout);
else
tv_eternity(&rep->rex);
}
@@ -4375,7 +4377,7 @@
}/* end while(srv) */
}/* end else if server == NULL */
- tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+ tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
}/* end if ((t->proxy->appsession_name != NULL) ... */
}
@@ -4835,7 +4837,7 @@
if (asession_temp->serverid[0] == '\0')
memcpy(asession_temp->serverid, t->srv->id, server_id_len);
- tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+ tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
#if defined(DEBUG_HASH)
print_table(&(t->be->htbl_proxy));
@@ -4997,7 +4999,7 @@
pool_free_to(apools.sessid, local_asession.sessid);
}
- tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+ tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
asession_temp->request_count++;
#if defined(DEBUG_HASH)
diff --git a/src/proxy.c b/src/proxy.c
index 3cc355a..dd7f993 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1,7 +1,7 @@
/*
* Proxy variables and functions.
*
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 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
@@ -170,17 +170,16 @@
/*
* this function enables proxies when there are enough free sessions,
* or stops them when the table is full. It is designed to be called from the
- * select_loop(). It returns the time left before next expiration event
- * during stop time, TIME_ETERNITY otherwise.
+ * select_loop(). It returns the date of next expiration event during stop
+ * time, ETERNITY otherwise.
*/
-int maintain_proxies(void)
+void maintain_proxies(struct timeval *next)
{
struct proxy *p;
struct listener *l;
- int tleft; /* time left */
p = proxy;
- tleft = TIME_ETERNITY; /* infinite time */
+ tv_eternity(next);
/* if there are enough free sessions, we'll activate proxies */
if (actconn < global.maxconn) {
@@ -233,13 +232,13 @@
p->state = PR_STSTOPPED;
}
else {
- tleft = MINTIME(t, tleft);
+ tv_bound(next, &p->stop_time);
}
}
p = p->next;
}
}
- return tleft;
+ return;
}
diff --git a/src/queue.c b/src/queue.c
index 9b53687..37d3ed8 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -45,9 +45,9 @@
/*
* Manages a server's connection queue. If woken up, will try to dequeue as
* many pending sessions as possible, and wake them up. The task has nothing
- * else to do, so it always returns TIME_ETERNITY.
+ * else to do, so it always returns ETERNITY.
*/
-int process_srv_queue(struct task *t)
+void process_srv_queue(struct task *t, struct timeval *next)
{
struct server *s = (struct server*)t->context;
struct proxy *p = s->proxy;
@@ -65,7 +65,7 @@
task_wakeup(sess->task);
}
- return TIME_ETERNITY;
+ tv_eternity(next);
}
/* Detaches the next pending connection from either a server or a proxy, and
diff --git a/src/stream_sock.c b/src/stream_sock.c
index e420ace..4691a9c 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -165,8 +165,8 @@
*/
if (b->flags & BF_PARTIAL_READ) {
- if (b->rto) {
- tv_ms_add(&b->rex, &now, b->rto);
+ if (tv_isset(&b->rto)) {
+ tv_add(&b->rex, &now, &b->rto);
goto out_wakeup;
}
out_eternity:
@@ -315,8 +315,8 @@
*/
if (b->flags & BF_PARTIAL_WRITE) {
- if (b->wto) {
- tv_ms_add(&b->wex, &now, b->wto);
+ if (tv_isset(&b->wto)) {
+ tv_add(&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 8905581..953da6c 100644
--- a/src/task.c
+++ b/src/task.c
@@ -15,6 +15,7 @@
#include <common/standard.h>
#include <common/time.h>
+#include <proto/proxy.h>
#include <proto/task.h>
#include <types/task.h>
@@ -23,9 +24,6 @@
#include <import/tree.h>
-/* FIXME : this should be removed very quickly ! */
-extern int maintain_proxies(void);
-
void **pool_task= NULL;
void **pool_tree64 = NULL;
static struct ultree *stack[LLONGBITS];
@@ -47,6 +45,7 @@
{
return __task_wakeup(t);
}
+
/*
* task_queue()
*
@@ -80,19 +79,15 @@
/*
* Extract all expired timers from the wait queue, and wakes up all
- * associated tasks.
- * Returns the time to wait for next task (next_time).
- *
- * FIXME: Use an alternative queue for ETERNITY tasks.
+ * associated tasks. Returns the date of next event (or eternity).
*
*/
-int wake_expired_tasks()
+void wake_expired_tasks(struct timeval *next)
{
__label__ out;
int slen;
struct task *task;
void *data;
- int next_time;
/*
* Hint: tasks are *rarely* expired. So we can try to optimize
@@ -102,19 +97,19 @@
if (likely(timer_wq.data != NULL)) {
task = LIST_ELEM(timer_wq.data, struct task *, qlist);
if (likely(__tv_isge(&task->expire, &now) > 0)) {
- next_time = tv_ms_remain(&now, &task->expire);
+ __tv_remain(&now, &task->expire, next);
goto out;
}
}
/* OK we lose. Let's scan the tree then. */
- next_time = TIME_ETERNITY;
+ tv_eternity(next);
tree64_foreach(&timer_wq, data, stack, slen) {
task = LIST_ELEM(data, struct task *, qlist);
if (__tv_isgt(&task->expire, &now)) {
- next_time = tv_ms_remain(&now, &task->expire);
+ __tv_remain2(&now, &task->expire, next);
break;
}
@@ -131,10 +126,7 @@
}
}
out:
- /* Ensure that we don't report sub-millisecond timeouts */
- if (next_time != TIME_ETERNITY)
- next_time++;
- return next_time;
+ return;
}
/*
@@ -142,17 +134,16 @@
* - wake up all expired tasks
* - call all runnable tasks
* - call maintain_proxies() to enable/disable the listeners
- * - return the delay till next event in ms, -1 = wait indefinitely
+ * - return the date of next event in <next> or eternity.
*
*/
-int process_runnable_tasks()
+void process_runnable_tasks(struct timeval *next)
{
- int next_time;
- int time2;
+ struct timeval temp;
struct task *t;
void *queue;
- next_time = wake_expired_tasks();
+ wake_expired_tasks(next);
/* process each task in the run queue now. Each task may be deleted
* since we only use the run queue's head. Note that any task can be
* woken up by any other task and it will be processed immediately
@@ -161,21 +152,20 @@
queue = run_queue;
foreach_dlist_item(t, queue, struct task *, qlist) {
- int temp_time;
-
DLIST_DEL(&t->qlist);
t->qlist.p = NULL;
t->state = TASK_IDLE;
- temp_time = t->process(t);
- next_time = MINTIME(temp_time, next_time);
+ t->process(t, &temp);
+ tv_bound(next, &temp);
}
/* maintain all proxies in a consistent state. This should quickly
* become a task because it becomes expensive when there are huge
* numbers of proxies. */
- time2 = maintain_proxies();
- return MINTIME(time2, next_time);
+ maintain_proxies(&temp);
+ tv_bound(next, &temp);
+ return;
}
/*
diff --git a/src/time.c b/src/time.c
index 262bc44..cf3d5cf 100644
--- a/src/time.c
+++ b/src/time.c
@@ -95,6 +95,33 @@
}
/*
+ * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
+ */
+REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
+{
+ return __tv_add(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.
+ */
+REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
+{
+ return __tv_remain(tv1, tv2, tv);
+}
+
+/*
+ * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
+ * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
+ * eternity.
+ */
+REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
+{
+ return __tv_remain2(tv1, tv2, tv);
+}
+
+/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8