typedef struct appsessions {
char *sessid;
char *serverid;
- struct timeval expire; /* next expiration time for this application session */
+ int expire; /* next expiration time for this application session (in tick) */
unsigned long int request_count;
struct list hash_list;
} appsess;
/* Callback for destroy */
void destroy(appsess *data);
-void appsession_refresh(struct task *t, struct timeval *next);
+void appsession_refresh(struct task *t, int *next);
int appsession_task_init(void);
int appsession_init(void);
void appsession_cleanup(void);
--- /dev/null
+/*
+ include/common/ticks.h
+ Functions and macros for manipulation of expiration timers
+
+ Copyright (C) 2000-2008 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
+ License as published by the Free Software Foundation, version 2.1
+ exclusively.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * Using a mix of milliseconds and timeval for internal timers is expensive and
+ * overkill, because we don't need such a precision to compute timeouts.
+ * So we're converting them to "ticks". Right now, one tick equals one
+ * millisecond, but that might change in the future. Ticks are stored as 32bit
+ * values, and sorted in four 30bit-wide rotating arrays, which means that any
+ * timer may be 2^30 ms in the future, or 12.4 days. The ticks are designed to
+ * wrap after they pass 2^32. That means that we cannot directly compare them,
+ * but we can check the sign of their difference.
+ *
+ * We must both support absolute dates (well in fact, dates relative to now+/-
+ * 12 days), and intervals (for timeouts). Both types need an "eternity" magic
+ * value. For optimal code generation, we'll use zero as the magic value
+ * indicating that an expiration timer or a timeout is not set. We have to
+ * check that we don't return this value when adding timeouts to <now>. If a
+ * computation returns 0, we must increase it to 1 (which will push the timeout
+ * 1 ms further).
+ */
+
+#ifndef _COMMON_TICKS_H
+#define _COMMON_TICKS_H
+
+#include <common/config.h>
+#include <common/standard.h>
+
+#define TICK_ETERNITY 0
+
+/* right now, ticks are milliseconds. Both negative ms and negative ticks
+ * indicate eternity.
+ */
+#define MS_TO_TICKS(ms) (ms)
+#define TICKS_TO_MS(tk) (tk)
+
+/* return 1 if tick is set, otherwise 0 */
+static inline int tick_isset(int expire)
+{
+ return expire != 0;
+}
+
+/* Add <timeout> to <now>, and return the resulting expiration date.
+ * <timeout> will not be checked for null values.
+ */
+static inline int tick_add(int now, int timeout)
+{
+ now += timeout;
+ if (unlikely(!now))
+ now++; /* unfortunate value */
+ return now;
+}
+
+/* add <timeout> to <now> if it is set, otherwise set it to eternity.
+ * Return the resulting expiration date.
+ */
+static inline int tick_add_ifset(int now, int timeout)
+{
+ if (!timeout)
+ return TICK_ETERNITY;
+ return tick_add(now, timeout);
+}
+
+/* return 1 if timer <timer> is expired at date <now>, otherwise zero */
+static inline int tick_is_expired(int timer, int now)
+{
+ if (!tick_isset(timer))
+ return 0;
+ return (timer - now) <= 0;
+}
+
+/* return the first one of the two timers, both of which may be infinite */
+static inline int tick_first(int t1, int t2)
+{
+ if (!tick_isset(t1))
+ return t2;
+ if (!tick_isset(t2))
+ return t1;
+ if ((t1 - t2) <= 0)
+ return t1;
+ else
+ return t2;
+}
+
+/* return the number of ticks remaining from <now> to <exp>, or zero if expired */
+static inline int tick_remain(int now, int exp)
+{
+ if (tick_is_expired(exp, now))
+ return 0;
+ return exp - now;
+}
+
+#endif /* _COMMON_TICKS_H */
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ */
#include <common/config.h>
#include <common/memory.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/buffers.h>
/* marks the buffer as "shutdown pending" for reads and cancels the timeout */
static inline void buffer_shutr(struct buffer *buf)
{
- tv_eternity(&buf->rex);
+ buf->rex = TICK_ETERNITY;
buf->flags |= BF_SHUTR_PENDING;
}
/* marks the buffer as "shutdown pending" for writes and cancels the timeout */
static inline void buffer_shutw(struct buffer *buf)
{
- tv_eternity(&buf->wex);
+ buf->wex = TICK_ETERNITY;
buf->flags |= BF_SHUTW_PENDING;
}
#define HTTP_IS_VER_TOKEN(x) (http_is_ver_token[(unsigned char)(x)])
int event_accept(int fd);
-void process_session(struct task *t, struct timeval *next);
+void process_session(struct task *t, int *next);
int process_cli(struct session *t);
int process_srv(struct session *t);
include/proto/proto_uxst.h
This file contains UNIX-stream socket protocol definitions.
- Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2008 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
int uxst_event_accept(int fd);
void uxst_add_listener(struct listener *listener);
-void process_uxst_stats(struct task *t, struct timeval *next);
+void process_uxst_stats(struct task *t, int *next);
#endif /* _PROTO_PROTO_UXST_H */
#define _PROTO_PROXY_H
#include <common/config.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/proxy.h>
int start_proxies(int verbose);
-void maintain_proxies(struct timeval *next);
+void maintain_proxies(int *next);
void soft_stop(void);
void pause_proxy(struct proxy *p);
void pause_proxies(void);
/* this function initializes all timeouts for proxy p */
static inline void proxy_reset_timeouts(struct proxy *proxy)
{
- tv_eternity(&proxy->timeout.client);
- tv_eternity(&proxy->timeout.tarpit);
- tv_eternity(&proxy->timeout.queue);
- tv_eternity(&proxy->timeout.connect);
- tv_eternity(&proxy->timeout.server);
- tv_eternity(&proxy->timeout.appsession);
- tv_eternity(&proxy->timeout.httpreq);
- tv_eternity(&proxy->timeout.check);
+ proxy->timeout.client = TICK_ETERNITY;
+ proxy->timeout.tarpit = TICK_ETERNITY;
+ proxy->timeout.queue = TICK_ETERNITY;
+ proxy->timeout.connect = TICK_ETERNITY;
+ proxy->timeout.server = TICK_ETERNITY;
+ proxy->timeout.appsession = TICK_ETERNITY;
+ proxy->timeout.httpreq = TICK_ETERNITY;
+ proxy->timeout.check = TICK_ETERNITY;
}
#endif /* _PROTO_PROXY_H */
* - return the date of next event in <next> or eternity.
*/
-void process_runnable_tasks(struct timeval *next);
+void process_runnable_tasks(int *next);
/*
* 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);
#endif /* _PROTO_TASK_H */
include/types/buffers.h
Buffer management definitions, macros and inline functions.
- Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2008 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
#include <common/config.h>
#include <common/memory.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
/* The BF_* macros designate Buffer Flags, which may be ORed in the bit field
* member 'flags' in struct buffer.
*/
struct buffer {
unsigned int flags; /* BF_* */
- struct timeval rex; /* expiration date for a read */
- struct timeval wex; /* expiration date for a write */
- struct timeval cex; /* expiration date for a connect */
- struct timeval rto; /* read timeout */
- struct timeval wto; /* write timeout */
- struct timeval cto; /* connect timeout */
+ int rex; /* expiration date for a read, in ticks */
+ int wex; /* expiration date for a write, in ticks */
+ int cex; /* expiration date for a connect, in ticks */
+ int rto; /* read timeout, in ticks */
+ int wto; /* write timeout, in ticks */
+ int cto; /* connect timeout, in ticks */
unsigned int l; /* data length */
char *r, *w, *lr; /* read ptr, write ptr, last read */
char *rlim; /* read limit, used for header rewriting */
include/types/fd.h
File descriptors states.
- Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2008 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
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, struct timeval *exp); /* the poller itself */
+ void REGPRM2 (*poll)(struct poller *p, int 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 */
int maxaccept; /* max number of consecutive accept() */
} tune;
struct listener stats_sock; /* unix socket listener for statistics */
- struct timeval stats_timeout;
+ int stats_timeout; /* in ticks */
};
extern struct global global;
include/types/proto_http.h
This file contains HTTP protocol definitions.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2008 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
char *srv_cookie; /* cookie presented by the server, in capture mode */
int status; /* HTTP status from the server, negative if from proxy */
unsigned int flags; /* transaction flags */
- struct timeval exp; /* expiration date for the transaction (generally a request) */
+ int exp; /* expiration date for the transaction (generally a request), int ticks */
};
/* This structure is used by http_find_header() to return values of headers.
struct listener *next; /* next address for the same proxy, or NULL */
struct list proto_list; /* list in the protocol header */
int (*accept)(int fd); /* accept() function passed to fdtab[] */
- void (*handler)(struct task *t, struct timeval *next); /* protocol handler */
- struct timeval *timeout; /* pointer to client-side timeout */
+ void (*handler)(struct task *t, int *next); /* protocol handler */
+ int *timeout; /* pointer to client-side timeout */
void *private; /* any private data which may be used by accept() */
union { /* protocol-dependant access restrictions */
struct { /* UNIX socket permissions */
int monitor_uri_len; /* length of the string above. 0 if unused */
struct list mon_fail_cond; /* list of conditions to fail monitoring requests (chained) */
struct { /* WARNING! check proxy_reset_timeouts() in proxy.h !!! */
- struct timeval client; /* client I/O timeout (in milliseconds) */
- struct timeval tarpit; /* tarpit timeout, defaults to connect if unspecified */
- struct timeval queue; /* queue timeout, defaults to connect if unspecified */
- struct timeval connect; /* connect timeout (in milliseconds) */
- struct timeval server; /* server I/O timeout (in milliseconds) */
- struct timeval appsession; /* appsession cookie expiration */
- struct timeval httpreq; /* maximum time for complete HTTP request */
- struct timeval check; /* maximum time for complete check */
+ int client; /* client I/O timeout (in ticks) */
+ int tarpit; /* tarpit timeout, defaults to connect if unspecified */
+ int queue; /* queue timeout, defaults to connect if unspecified */
+ int connect; /* connect timeout (in ticks) */
+ int server; /* server I/O timeout (in ticks) */
+ int appsession; /* appsession cookie expiration */
+ int httpreq; /* maximum time for complete HTTP request */
+ int check; /* maximum time for complete check */
} timeout;
char *id; /* proxy id */
struct list pendconns; /* pending connections with no server assigned yet */
signed char logfac1, logfac2; /* log facility for both servers. -1 = disabled */
int loglev1, loglev2; /* log level for each server, 7 by default */
int to_log; /* things to be logged (LW_*) */
- struct timeval stop_time; /* date to stop listening, when stopping != 0 */
+ int stop_time; /* date to stop listening, when stopping != 0 (int ticks) */
int nb_reqadd, nb_rspadd;
struct hdr_exp *req_exp; /* regular expressions for request headers */
struct hdr_exp *rsp_exp; /* regular expressions for response headers */
struct task {
struct eb32_node eb; /* ebtree node used to hold the task in the wait queue */
int state; /* task state : IDLE or RUNNING */
- struct timeval expire; /* next expiration time for this task, use only for fast sorting */
- void (*process)(struct task *t, struct timeval *next); /* the function which processes the task */
+ unsigned int expire; /* next expiration time for this task */
+ void (*process)(struct task *t, int *next); /* the function which processes the task */
void *context; /* the task's context */
int nice; /* the task's current nice value from -1024 to +1024 */
};
#include <common/config.h>
#include <common/memory.h>
#include <common/sessionhash.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/buffers.h>
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 ++;
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;
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;
}
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 */
#include <common/config.h>
#include <common/debug.h>
#include <common/eb32tree.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/acl.h>
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 */
}
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)
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)
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));
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));
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)
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);
}
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"
* 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;
}
}
#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;
}
* 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;
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;
* 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;
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");
* 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 */
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 */
}
* 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;
}
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) {
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 */
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++;
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;
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)
/*
* 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
#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>
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]);
#include <common/compat.h>
#include <common/config.h>
#include <common/standard.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <common/tools.h>
/*
* 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;
/* 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;
}
#include <common/compat.h>
#include <common/config.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <common/tools.h>
/*
* 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;
-
- if (tv_isge(&now, exp)) {
- delta.tv_sec = delta.tv_usec = 0;
- delta_ms = 0;
+ delta_ms = 0;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 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);
#include <common/compat.h>
#include <common/config.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/fd.h>
/*
* 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;
/* 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;
}
#include <common/compat.h>
#include <common/config.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/fd.h>
/*
* 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;
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;
}
}
#include <common/config.h>
#include <common/debug.h>
#include <common/standard.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <common/tools.h>
/*
* 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;
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;
}
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 */
*/
void run_poll_loop()
{
- struct timeval next;
+ int next;
tv_update_date(0,1);
while (1) {
break;
/* The poller will ensure it returns around <next> */
- cur_poller.poll(&cur_poller, &next);
+ cur_poller.poll(&cur_poller, next);
}
}
#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>
* 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;
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 */
}
task_delete(t);
session_free(s);
task_free(t);
- tv_eternity(next);
+ *next = TICK_ETERNITY;
}
}
/* 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));
* 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;
}
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
* 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,
/* 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 */
/* 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;
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))
/* 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);
}
}
((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 */
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;
|| ((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;
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;
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;
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
* 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
* 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));
* 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));
(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);
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)) {
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;
}
* 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;
}
}
//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 */
* hdr_idx_init(&t->txn.hdr_idx);
*/
}
- tv_eternity(&req->cex);
+ req->cex = TICK_ETERNITY;
return 1;
}
}
* 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);
}
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);
/* 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;
* 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))
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);
}
}
else {
if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
/* stop writing */
- tv_eternity(&req->wex);
+ req->wex = TICK_ETERNITY;
}
}
/* 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;
/* 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;
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;
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);
}
}
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);
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;
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);
}
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;
/* 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
*/
if ( len < limit )
return 0;
}
- t->srv_state=SV_STIDLE;
+ t->srv_state = SV_STIDLE;
return 1;
}
else { /* SV_STCLOSE : nothing to do */
}/* 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) ... */
}
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));
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)
#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>
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;
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;
}
/* 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;
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))
/* 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);
}
}
((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 */
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;
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;
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;
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;
* 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;
* 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;
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);
task_delete(t);
session_free(s);
task_free(t);
- tv_eternity(next);
+ *next = TICK_ETERNITY;
}
__attribute__((constructor))
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];
(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;
}
* 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;
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);
pool_gc2();
}
else {
- tv_bound(next, &p->stop_time);
+ *next = tick_first(*next, p->stop_time);
}
}
p = p->next;
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;
}
* 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
#include <common/debug.h>
#include <common/memory.h>
#include <common/standard.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <common/version.h>
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)
/*
* 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
#include <common/config.h>
#include <common/debug.h>
#include <common/standard.h>
+#include <common/ticks.h>
#include <common/time.h>
#include <types/buffers.h>
* 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;
* never happen, but better safe than sorry !
*/
EV_FD_CLR(fd, DIR_RD);
- goto out_eternity;
+ b->rex = TICK_ETERNITY;
+ goto out_wakeup;
}
/*
}
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
* 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)
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
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;
}
* 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;
* 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
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 */
*/
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:
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;
}
*/
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) */
* 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;
} 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;
}
*
* 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;
task_dequeue(t);
t->process(t, &temp);
- tv_bound(next, &temp);
+ *next = tick_first(*next, temp);
if (!--max_processed)
return;