blob: 7fd0bbab26c953629de915f71121c23695783001 [file] [log] [blame]
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001/*
2 include/common/ticks.h
3 Functions and macros for manipulation of expiration timers
4
Willy Tarreaud0a201b2009-03-08 15:53:06 +01005 Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006
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*/
21
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
52#ifndef _COMMON_TICKS_H
53#define _COMMON_TICKS_H
54
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
146#endif /* _COMMON_TICKS_H */
147
148/*
149 * Local variables:
150 * c-indent-level: 8
151 * c-basic-offset: 8
152 * End:
153 */