blob: 07d3070eb64989f7435eab7042644bcc5374709d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau2dd0d472006-06-29 17:53:05 +02002 include/common/time.h
Willy Tarreaubaaee002006-06-26 02:48:02 +02003 Time calculation functions and macros.
4
Willy Tarreaub7f694f2008-06-22 17:18:02 +02005 Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
Willy Tarreaubaaee002006-06-26 02:48:02 +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
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#ifndef _COMMON_TIME_H
23#define _COMMON_TIME_H
Willy Tarreaubaaee002006-06-26 02:48:02 +020024
25#include <stdlib.h>
26#include <sys/time.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020027#include <common/config.h>
Willy Tarreau42aae5c2007-04-29 17:43:56 +020028#include <common/standard.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020029
Krzysztof Oledzki85130942007-10-22 16:21:10 +020030#define SEC 1
31#define MINUTE (60 * SEC)
32#define HOUR (60 * MINUTE)
33#define DAY (24 * HOUR)
34
Willy Tarreaua6a6a932007-04-28 22:40:08 +020035/* eternity when exprimed in timeval */
36#ifndef TV_ETERNITY
37#define TV_ETERNITY (~0UL)
38#endif
39
40/* eternity when exprimed in ms */
41#ifndef TV_ETERNITY_MS
42#define TV_ETERNITY_MS (-1)
43#endif
44
45#define TIME_ETERNITY (TV_ETERNITY_MS)
46
Willy Tarreaub0b37bc2008-06-23 14:00:57 +020047/* we want to be able to detect time jumps. Fix the maximum wait time to a low
48 * value so that we know the time has changed if we wait longer.
49 */
50#define MAX_DELAY_MS 1000
51
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
53/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
54#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
55#define SETNOW(a) (*a=now)
56
Willy Tarreaue6313a32008-06-29 13:47:25 +020057extern unsigned int now_ms; /* internal date in milliseconds (may wrap) */
Willy Tarreaub7f694f2008-06-22 17:18:02 +020058extern struct timeval now; /* internal date is a monotonic function of real clock */
59extern struct timeval date; /* the real current date */
Willy Tarreaubaaee002006-06-26 02:48:02 +020060extern struct timeval start_date; /* the process's start date */
61
62
Willy Tarreau42aae5c2007-04-29 17:43:56 +020063/**** exported functions *************************************************/
64
65
Willy Tarreaubaaee002006-06-26 02:48:02 +020066/*
67 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
68 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020069REGPRM3 struct timeval *tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
71/*
72 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
Willy Tarreau42aae5c2007-04-29 17:43:56 +020073 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreaubaaee002006-06-26 02:48:02 +020074 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020075REGPRM2 int tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
77/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020078 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
79 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020080 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020081REGPRM2 int tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau5e8f0662007-02-12 00:59:08 +010082
Willy Tarreau42aae5c2007-04-29 17:43:56 +020083/**** general purpose functions and macros *******************************/
84
85
86/* tv_now: sets <tv> to the current time */
87REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
88{
89 gettimeofday(tv, NULL);
90 return tv;
91}
Willy Tarreaubaaee002006-06-26 02:48:02 +020092
Willy Tarreaub0b37bc2008-06-23 14:00:57 +020093/* tv_udpate_date: sets <date> to system time, and sets <now> to something as
94 * close as possible to real time, following a monotonic function. The main
95 * principle consists in detecting backwards and forwards time jumps and adjust
96 * an offset to correct them. This function should be called only once after
97 * each poll. The poll's timeout should be passed in <max_wait>, and the return
98 * value in <interrupted> (a non-zero value means that we have not expired the
99 * timeout).
Willy Tarreaub7f694f2008-06-22 17:18:02 +0200100 */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +0200101REGPRM2 void tv_update_date(int max_wait, int interrupted);
Willy Tarreaub7f694f2008-06-22 17:18:02 +0200102
Willy Tarreaubaaee002006-06-26 02:48:02 +0200103/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200104 * sets a struct timeval to its highest value so that it can never happen
105 * note that only tv_usec is necessary to detect it since a tv_usec > 999999
106 * is normally not possible.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200107 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200108REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200109{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200110 tv->tv_sec = tv->tv_usec = TV_ETERNITY;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200111 return tv;
112}
113
114/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200115 * sets a struct timeval to 0
116 *
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200118REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
119 tv->tv_sec = tv->tv_usec = 0;
120 return tv;
121}
122
123/*
124 * returns non null if tv is [eternity], otherwise 0.
125 */
126#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
127
128/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200129 * returns 0 if tv is [eternity], otherwise non-zero.
130 */
131#define tv_isset(tv) ((tv)->tv_usec != TV_ETERNITY)
132
133/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200134 * returns non null if tv is [0], otherwise 0.
135 */
136#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
137
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200138/*
139 * Converts a struct timeval to a number of milliseconds.
140 */
141REGPRM1 static inline unsigned long __tv_to_ms(const struct timeval *tv)
142{
143 unsigned long ret;
144
145 ret = tv->tv_sec * 1000;
146 ret += tv->tv_usec / 1000;
147 return ret;
148}
149
150/*
151 * Converts a struct timeval to a number of milliseconds.
152 */
153REGPRM2 static inline struct timeval * __tv_from_ms(struct timeval *tv, unsigned long ms)
154{
155 tv->tv_sec = ms / 1000;
156 tv->tv_usec = (ms % 1000) * 1000;
157 return tv;
158}
159
Willy Tarreau776cd872009-03-05 00:34:01 +0100160/* Return a number of 1024Hz ticks between 0 and 1023 for input number of
161 * usecs between 0 and 999999. This function has been optimized to remove
162 * any divide and multiply, as it is completely optimized away by the compiler
163 * on CPUs which don't have a fast multiply. Its avg error rate is 305 ppm,
164 * which is almost twice as low as a direct usec to ms conversion. This version
165 * also has the benefit of returning 1024 for 1000000.
166 */
167REGPRM1 static inline unsigned int __usec_to_1024th(unsigned int usec)
168{
169 return (usec * 1073 + 742516) >> 20;
170}
171
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200172
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200173/**** comparison functions and macros ***********************************/
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200174
175
176/* tv_cmp: compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2. */
177REGPRM2 static inline int __tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200179 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200181 else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200183 else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200185 else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 return 1;
187 else
188 return 0;
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100189}
190
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200191/* tv_iseq: compares <tv1> and <tv2> : returns 1 if tv1 == tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200192#define tv_iseq __tv_iseq
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200193REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
194{
Willy Tarreau0481c202007-05-13 16:03:27 +0200195 return ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) &&
196 ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200197}
198
199/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200200#define tv_isgt _tv_isgt
201REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200202REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
203{
Willy Tarreau0481c202007-05-13 16:03:27 +0200204 return
205 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
206 ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec) :
207 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200208}
209
210/* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200211#define tv_isge __tv_isge
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200212REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
213{
Willy Tarreau0481c202007-05-13 16:03:27 +0200214 return
215 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
216 ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
217 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200218}
219
220/* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200221#define tv_islt __tv_islt
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200222REGPRM2 static inline int __tv_islt(const struct timeval *tv1, const struct timeval *tv2)
223{
Willy Tarreau0481c202007-05-13 16:03:27 +0200224 return
225 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
226 ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec) :
227 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200228}
229
230/* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200231#define tv_isle _tv_isle
232REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200233REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
234{
Willy Tarreau0481c202007-05-13 16:03:27 +0200235 return
236 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
237 ((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
238 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200239}
240
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100241/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200242 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
243 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100244 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200245#define tv_ms_cmp _tv_ms_cmp
246REGPRM2 int _tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
247REGPRM2 static inline int __tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100248{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200249 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
250 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
251 return -1;
252 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
253 return 1;
254 else
255 return 0;
256 }
257 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
258 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
259 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
260 return -1;
261 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
262 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
263 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100264 return 1;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200265 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100266 return 0;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200267}
268
269/*
270 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
271 * assuming that TV_ETERNITY is greater than everything.
272 */
273#define tv_ms_cmp2 _tv_ms_cmp2
274REGPRM2 int _tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
275REGPRM2 static inline int __tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2)
276{
277 if (tv_iseternity(tv1))
278 if (tv_iseternity(tv2))
279 return 0; /* same */
280 else
281 return 1; /* tv1 later than tv2 */
282 else if (tv_iseternity(tv2))
283 return -1; /* tv2 later than tv1 */
284 return tv_ms_cmp(tv1, tv2);
285}
286
287/*
288 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
289 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
290 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
291 * occurrences of (tv_ms_cmp2(tv,now) <= 0).
292 */
293#define tv_ms_le2 _tv_ms_le2
294REGPRM2 int _tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2);
295REGPRM2 static inline int __tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2)
296{
297 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
298 return 0;
299
300 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
301 return 1;
302
303 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
304 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
305 return 1;
306 else
307 return 0;
308 }
309
310 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
311 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
312 return 0;
313 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315}
316
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200317
318/**** operators **********************************************************/
319
320
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200322 * Returns the time in ms elapsed between tv1 and tv2, assuming that tv1<=tv2.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 * Must not be used when either argument is eternity.
324 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200325#define tv_ms_elapsed __tv_ms_elapsed
326REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2);
327REGPRM2 static inline unsigned long __tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328{
329 unsigned long ret;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200330
331 ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000;
332 ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000;
333 return ret;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334}
335
336/*
337 * returns the remaining time between tv1=now and event=tv2
338 * if tv2 is passed, 0 is returned.
339 * Must not be used when either argument is eternity.
340 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200341
342#define tv_ms_remain __tv_ms_remain
343REGPRM2 unsigned long _tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2);
344REGPRM2 static inline unsigned long __tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200346 if (tv_ms_cmp(tv1, tv2) >= 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200347 return 0; /* event elapsed */
348
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200349 return __tv_ms_elapsed(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200350}
351
Willy Tarreaubaaee002006-06-26 02:48:02 +0200352/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200353 * returns the remaining time between tv1=now and event=tv2
354 * if tv2 is passed, 0 is returned.
355 * Returns TIME_ETERNITY if tv2 is eternity.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200356 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200357#define tv_ms_remain2 _tv_ms_remain2
358REGPRM2 unsigned long _tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2);
359REGPRM2 static inline unsigned long __tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200360{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200361 if (tv_iseternity(tv2))
362 return TIME_ETERNITY;
363
364 return tv_ms_remain(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200365}
366
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200367/*
368 * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
369 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200370#define tv_add _tv_add
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200371REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
372REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
373{
374 tv->tv_usec = from->tv_usec + inc->tv_usec;
375 tv->tv_sec = from->tv_sec + inc->tv_sec;
376 if (tv->tv_usec >= 1000000) {
377 tv->tv_usec -= 1000000;
378 tv->tv_sec++;
379 }
380 return tv;
381}
382
383
384/*
Willy Tarreau0481c202007-05-13 16:03:27 +0200385 * If <inc> is set, then add it to <from> and set the result to <tv>, then
386 * return 1, otherwise return 0. It is meant to be used in if conditions.
387 */
388#define tv_add_ifset _tv_add_ifset
389REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
390REGPRM3 static inline int __tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
391{
392 if (tv_iseternity(inc))
393 return 0;
394 tv->tv_usec = from->tv_usec + inc->tv_usec;
395 tv->tv_sec = from->tv_sec + inc->tv_sec;
396 if (tv->tv_usec >= 1000000) {
397 tv->tv_usec -= 1000000;
398 tv->tv_sec++;
399 }
400 return 1;
401}
402
403/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200404 * adds <inc> to <tv> and returns a pointer <tv>
405 */
406REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
407{
408 tv->tv_usec += inc->tv_usec;
409 tv->tv_sec += inc->tv_sec;
410 if (tv->tv_usec >= 1000000) {
411 tv->tv_usec -= 1000000;
412 tv->tv_sec++;
413 }
414 return tv;
415}
416
417
418/*
419 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
420 * 0 is returned. The result is stored into tv.
421 */
422#define tv_remain _tv_remain
423REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
424REGPRM3 static inline struct timeval *__tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
425{
426 tv->tv_usec = tv2->tv_usec - tv1->tv_usec;
427 tv->tv_sec = tv2->tv_sec - tv1->tv_sec;
428 if ((signed)tv->tv_sec > 0) {
429 if ((signed)tv->tv_usec < 0) {
430 tv->tv_usec += 1000000;
431 tv->tv_sec--;
432 }
433 } else if (tv->tv_sec == 0) {
434 if ((signed)tv->tv_usec < 0)
435 tv->tv_usec = 0;
436 } else {
437 tv->tv_sec = 0;
438 tv->tv_usec = 0;
439 }
440 return tv;
441}
442
443
444/*
445 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
446 * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
447 * eternity.
448 */
449#define tv_remain2 _tv_remain2
450REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
451REGPRM3 static inline struct timeval *__tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
452{
453 if (tv_iseternity(tv2))
454 return tv_eternity(tv);
455 return __tv_remain(tv1, tv2, tv);
456}
457
458
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200460 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200462#define tv_ms_add _tv_ms_add
463REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
464REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const struct timeval *from, int ms)
465{
466 tv->tv_usec = from->tv_usec + (ms % 1000) * 1000;
467 tv->tv_sec = from->tv_sec + (ms / 1000);
468 while (tv->tv_usec >= 1000000) {
469 tv->tv_usec -= 1000000;
470 tv->tv_sec++;
471 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200472 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473}
474
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200476/*
477 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
478 * This should be very fast because it's used in schedulers.
479 * It has been optimized to return 1 (so call it in a loop which continues
480 * as long as tv1<=tv2)
481 */
482
483#define tv_isbefore(tv1, tv2) \
484 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
485 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
486 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
487
488/*
489 * returns the first event between <tv1> and <tv2> into <tvmin>.
490 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
491 * to be the same as <tv1> or <tv2>, it is recommended to use
492 * tv_bound instead.
493 */
494#define tv_min(tvmin, tv1, tv2) ({ \
495 if (tv_isbefore(tv1, tv2)) { \
496 *tvmin = *tv1; \
497 } \
498 else { \
499 *tvmin = *tv2; \
500 } \
501 tvmin; \
502})
503
504/*
505 * returns the first event between <tv1> and <tv2> into <tvmin>.
506 * a zero tv is ignored. <tvmin> is returned. This function has been
507 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
508 */
509#define tv_bound(tv1, tv2) ({ \
510 if (tv_isbefore(tv2, tv1)) \
511 *tv1 = *tv2; \
512 tv1; \
513})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514
Willy Tarreauc8f24f82007-11-30 18:38:35 +0100515char *human_time(int t, short hz_div);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200516
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200517#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518
519/*
520 * Local variables:
521 * c-indent-level: 8
522 * c-basic-offset: 8
523 * End:
524 */