diff --git a/include/common/appsession.h b/include/common/appsession.h index eb9ba2d0f..8fa681cae 100644 --- a/include/common/appsession.h +++ b/include/common/appsession.h @@ -44,7 +44,7 @@ void destroy(void *data); 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 6ac32a1c9..839af55a5 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 #include -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 298d30d07..da4ea0e94 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -58,7 +58,7 @@ extern const char http_is_ver_token[256]; #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 3fa541a2d..38d7325cc 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 +#include #include 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 c113f0352..4370cb39d 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 2c724ad61..c594d525e 100644 --- a/include/proto/task.h +++ b/include/proto/task.h @@ -111,12 +111,10 @@ struct task *task_queue(struct task *task); * - 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 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 4afc293e3..9b781b842 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -63,9 +63,9 @@ struct buffer { 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 392c94ee7..a1b6e9d4d 100644 --- a/include/types/fd.h +++ b/include/types/fd.h @@ -81,7 +81,7 @@ struct fdtab { * 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 */ struct poller { void *private; /* any private data for the poller */ @@ -92,7 +92,7 @@ struct poller { int REGPRM2 (*cond_c)(const int fd, int dir); /* clear polling on for if set */ void REGPRM1 (*rem)(const int fd); /* remove any polling on */ void REGPRM1 (*clo)(const int fd); /* mark 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 c403e59f4..532348ec9 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -96,7 +96,6 @@ struct proxy { 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 proxy { 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 1fd78be56..42699dbff 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 task { 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 d11fb1950..0307ff7c4 100644 --- a/src/appsession.c +++ b/src/appsession.c @@ -125,7 +125,7 @@ int appsession_task_init(void) 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 @@ int appsession_refresh(struct task *t) 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 @@ int appsession_refresh(struct task *t) } 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 @@ int appsession_refresh(struct task *t) 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 69e79d408..002394ea4 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1,7 +1,7 @@ /* * Backend variables and functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2007 Willy Tarreau * * 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 @@ int connect_server(struct session *s) 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 @@ int srv_redispatch_connect(struct session *t) 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 b2e76b310..1edaa8fc0 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -766,7 +766,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args) 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args) } } 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args) 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args) 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args) 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 @@ int readcfgfile(const char *file) } } 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 83a539eea..96f5895f6 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1,7 +1,7 @@ /* * Health-checks functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2007 Willy Tarreau * * 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 @@ static int event_srv_chk_r(int fd) * 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 @@ int process_chk(struct task *t) 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 @@ int process_chk(struct task *t) * 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 @@ int process_chk(struct task *t) /* FIXME: we allow up to 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 @@ int process_chk(struct task *t) 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 @@ int process_chk(struct task *t) //fprintf(stderr, "process_chk: 7\n"); /* FIXME: we allow up to 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 @@ int process_chk(struct task *t) } 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 @@ int process_chk(struct task *t) 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 @@ int process_chk(struct task *t) //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 4a891b06d..52b281bde 100644 --- a/src/client.c +++ b/src/client.c @@ -1,7 +1,7 @@ /* * Client-side variables and functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2007 Willy Tarreau * * 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 @@ int event_accept(int fd) { 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 @@ int event_accept(int fd) { 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 b4844998a..a867e8dc3 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -220,16 +220,22 @@ REGPRM1 static void __fd_clo(int fd) /* * 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 c48f50215..3c97707cc 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -81,10 +81,11 @@ REGPRM1 static void __fd_rem(const int fd) /* * 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 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time) } /* 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 ed79abf01..fb5cc41ea 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -78,7 +78,7 @@ REGPRM1 static void __fd_rem(int fd) /* * 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 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time) /* 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 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time) 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 c3b777647..d2fcc7c7c 100644 --- a/src/ev_sepoll.c +++ b/src/ev_sepoll.c @@ -259,13 +259,14 @@ static struct ev_to_epoll { /* * 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 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time) } 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 a2e335e1e..0acf75fb5 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -684,17 +684,17 @@ static void tell_old_pids(int sig) */ 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 9506b167e..0f78d07a7 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -442,8 +442,8 @@ void client_retnclose(struct session *s, const struct chunk *msg) 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 @@ static http_meth_t find_http_meth(const char *str, const int len) * 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 @@ int process_session(struct task *t) /* 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 @@ int process_session(struct task *t) task_delete(t); session_free(s); task_free(t); - return TIME_ETERNITY; /* rest in peace for eternity */ + tv_eternity(next); } @@ -1529,7 +1529,7 @@ int process_cli(struct session *t) } /* 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 @@ int process_cli(struct session *t) * 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 @@ int process_cli(struct session *t) 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 @@ int process_cli(struct session *t) /* 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 @@ int process_cli(struct session *t) /* 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 @@ int process_cli(struct session *t) 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 @@ int process_cli(struct session *t) } 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 @@ int process_cli(struct session *t) */ 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 @@ int process_cli(struct session *t) /* 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 @@ int process_cli(struct session *t) 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 @@ int process_cli(struct session *t) /* 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 @@ int process_cli(struct session *t) 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 @@ int process_cli(struct session *t) } 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 @@ int process_srv(struct session *t) * 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 @@ int process_srv(struct session *t) * 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) * 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 @@ int process_srv(struct session *t) /* 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 @@ int process_srv(struct session *t) /* 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 @@ int process_srv(struct session *t) * 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) /* 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 @@ int process_srv(struct session *t) /* 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) } 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) 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 @@ int process_srv(struct session *t) } 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 @@ void manage_client_side_cookies(struct session *t, struct buffer *req) }/* 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 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr) 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 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len) 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 3cc355a84..dd7f993e3 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1,7 +1,7 @@ /* * Proxy variables and functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2007 Willy Tarreau * * 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 @@ int start_proxies(int verbose) /* * 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 @@ int maintain_proxies(void) 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 9b53687de..37d3ed850 100644 --- a/src/queue.c +++ b/src/queue.c @@ -45,9 +45,9 @@ unsigned int srv_dynamic_maxconn(const struct server *s) /* * 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 @@ int process_srv_queue(struct task *t) 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 e420ace34..4691a9c5a 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -165,8 +165,8 @@ int stream_sock_read(int fd) { */ 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 @@ int stream_sock_write(int fd) { */ 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 890558128..953da6c7c 100644 --- a/src/task.c +++ b/src/task.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -23,9 +24,6 @@ #include -/* 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 @@ struct task *_task_wakeup(struct task *t) { return __task_wakeup(t); } + /* * task_queue() * @@ -80,19 +79,15 @@ struct task *task_queue(struct task *task) /* * 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 @@ int wake_expired_tasks() 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 @@ int wake_expired_tasks() } } 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 @@ int wake_expired_tasks() * - 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 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 @@ int process_runnable_tasks() 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 262bc4491..cf3d5cff6 100644 --- a/src/time.c +++ b/src/time.c @@ -94,6 +94,33 @@ REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct tim return __tv_ms_elapsed(tv1, tv2); } +/* + * adds to , set the result to and returns a pointer + */ +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