blob: 52344ae256107c942d03a77584174351d2fa0030 [file] [log] [blame]
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001/*
Willy Tarreauc2f7c582020-06-02 18:15:32 +02002 * include/haproxy/ticks.h
3 * Functions and macros for manipulation of expiration timers
4 *
5 * Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation, version 2.1
10 * exclusively.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +020021
22/*
23 * Using a mix of milliseconds and timeval for internal timers is expensive and
24 * overkill, because we don't need such a precision to compute timeouts.
Willy Tarreaud0a201b2009-03-08 15:53:06 +010025 * So we're converting them to "ticks".
Willy Tarreau0c303ee2008-07-07 00:09:58 +020026 *
Willy Tarreaud0a201b2009-03-08 15:53:06 +010027 * A tick is a representation of a date relative to another one, and is
28 * measured in milliseconds. The natural usage is to represent an absolute date
29 * relative to the current date. Since it is not practical to update all values
30 * each time the current date changes, instead we use the absolute date rounded
31 * down to fit in a tick. We then have to compare a tick to the current date to
32 * know whether it is in the future or in the past. If a tick is below the
33 * current date, it is in the past. If it is above, it is in the future. The
34 * values will wrap so we can't compare that easily, instead we check the sign
35 * of the difference between a tick and the current date.
36 *
37 * Proceeding like this allows us to manipulate dates that are stored in
38 * scalars with enough precision and range. For this reason, we store ticks in
39 * 32-bit integers. This is enough to handle dates that are between 24.85 days
40 * in the past and as much in the future.
41 *
Willy Tarreau0c303ee2008-07-07 00:09:58 +020042 * We must both support absolute dates (well in fact, dates relative to now+/-
Willy Tarreaue35c94a2009-03-21 10:01:42 +010043 * 24 days), and intervals (for timeouts). Both types need an "eternity" magic
Willy Tarreau0c303ee2008-07-07 00:09:58 +020044 * value. For optimal code generation, we'll use zero as the magic value
45 * indicating that an expiration timer or a timeout is not set. We have to
46 * check that we don't return this value when adding timeouts to <now>. If a
47 * computation returns 0, we must increase it to 1 (which will push the timeout
Willy Tarreaud0a201b2009-03-08 15:53:06 +010048 * 1 ms further). For this reason, timeouts must not be added by hand but via
49 * the dedicated tick_add() function.
Willy Tarreau0c303ee2008-07-07 00:09:58 +020050 */
51
Willy Tarreauc2f7c582020-06-02 18:15:32 +020052#ifndef _HAPROXY_TICKS_H
53#define _HAPROXY_TICKS_H
Willy Tarreau0c303ee2008-07-07 00:09:58 +020054
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020055#include <haproxy/api.h>
Willy Tarreau0c303ee2008-07-07 00:09:58 +020056
57#define TICK_ETERNITY 0
58
59/* right now, ticks are milliseconds. Both negative ms and negative ticks
60 * indicate eternity.
61 */
62#define MS_TO_TICKS(ms) (ms)
63#define TICKS_TO_MS(tk) (tk)
64
65/* return 1 if tick is set, otherwise 0 */
66static inline int tick_isset(int expire)
67{
68 return expire != 0;
69}
70
71/* Add <timeout> to <now>, and return the resulting expiration date.
72 * <timeout> will not be checked for null values.
73 */
74static inline int tick_add(int now, int timeout)
75{
76 now += timeout;
77 if (unlikely(!now))
78 now++; /* unfortunate value */
79 return now;
80}
81
82/* add <timeout> to <now> if it is set, otherwise set it to eternity.
83 * Return the resulting expiration date.
84 */
85static inline int tick_add_ifset(int now, int timeout)
86{
87 if (!timeout)
88 return TICK_ETERNITY;
89 return tick_add(now, timeout);
90}
91
Willy Tarreaue35c94a2009-03-21 10:01:42 +010092/* return 1 if timer <t1> is before <t2>, none of which can be infinite. */
93static inline int tick_is_lt(int t1, int t2)
94{
95 return (t1 - t2) < 0;
96}
97
98/* return 1 if timer <t1> is before or equal to <t2>, none of which can be infinite. */
99static inline int tick_is_le(int t1, int t2)
100{
101 return (t1 - t2) <= 0;
102}
103
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200104/* return 1 if timer <timer> is expired at date <now>, otherwise zero */
105static inline int tick_is_expired(int timer, int now)
106{
Willy Tarreau534c5a22008-09-04 09:00:24 +0200107 if (unlikely(!tick_isset(timer)))
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200108 return 0;
Willy Tarreau534c5a22008-09-04 09:00:24 +0200109 if (unlikely((timer - now) <= 0))
110 return 1;
111 return 0;
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200112}
113
114/* return the first one of the two timers, both of which may be infinite */
115static inline int tick_first(int t1, int t2)
116{
117 if (!tick_isset(t1))
118 return t2;
119 if (!tick_isset(t2))
120 return t1;
121 if ((t1 - t2) <= 0)
122 return t1;
123 else
124 return t2;
125}
126
Willy Tarreau531cf0c2009-03-08 16:35:27 +0100127/* return the first one of the two timers, where only the first one may be infinite */
128static inline int tick_first_2nz(int t1, int t2)
129{
130 if (!tick_isset(t1))
131 return t2;
132 if ((t1 - t2) <= 0)
133 return t1;
134 else
135 return t2;
136}
137
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200138/* return the number of ticks remaining from <now> to <exp>, or zero if expired */
139static inline int tick_remain(int now, int exp)
140{
141 if (tick_is_expired(exp, now))
142 return 0;
143 return exp - now;
144}
145
Willy Tarreauc2f7c582020-06-02 18:15:32 +0200146#endif /* _HAPROXY_TICKS_H */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200147
148/*
149 * Local variables:
150 * c-indent-level: 8
151 * c-basic-offset: 8
152 * End:
153 */