blob: 2a4a14264ea75d84ffd8bafea705faa33cee879e [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 Tarreau42aae5c2007-04-29 17:43:56 +02005 Copyright (C) 2000-2007 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 Tarreaubaaee002006-06-26 02:48:02 +020047
48/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
49#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
50#define SETNOW(a) (*a=now)
51
52extern struct timeval now; /* the current date at any moment */
53extern struct timeval start_date; /* the process's start date */
54
55
Willy Tarreau42aae5c2007-04-29 17:43:56 +020056/**** exported functions *************************************************/
57
58
Willy Tarreaubaaee002006-06-26 02:48:02 +020059/*
60 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
61 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020062REGPRM3 struct timeval *tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
Willy Tarreaubaaee002006-06-26 02:48:02 +020063
64/*
65 * 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 +020066 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreaubaaee002006-06-26 02:48:02 +020067 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020068REGPRM2 int tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
70/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020071 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
72 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020073 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020074REGPRM2 int tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau5e8f0662007-02-12 00:59:08 +010075
Willy Tarreau42aae5c2007-04-29 17:43:56 +020076/**** general purpose functions and macros *******************************/
77
78
79/* tv_now: sets <tv> to the current time */
80REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
81{
82 gettimeofday(tv, NULL);
83 return tv;
84}
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
86/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +020087 * sets a struct timeval to its highest value so that it can never happen
88 * note that only tv_usec is necessary to detect it since a tv_usec > 999999
89 * is normally not possible.
90 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020091 */
Willy Tarreaubaaee002006-06-26 02:48:02 +020092
Willy Tarreau42aae5c2007-04-29 17:43:56 +020093REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +020094{
Willy Tarreau42aae5c2007-04-29 17:43:56 +020095 tv->tv_sec = tv->tv_usec = TV_ETERNITY;
Willy Tarreaubaaee002006-06-26 02:48:02 +020096 return tv;
97}
98
99/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200100 * sets a struct timeval to 0
101 *
Willy Tarreaubaaee002006-06-26 02:48:02 +0200102 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200103REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
104 tv->tv_sec = tv->tv_usec = 0;
105 return tv;
106}
107
108/*
109 * returns non null if tv is [eternity], otherwise 0.
110 */
111#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
112
113/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200114 * returns 0 if tv is [eternity], otherwise non-zero.
115 */
116#define tv_isset(tv) ((tv)->tv_usec != TV_ETERNITY)
117
118/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200119 * returns non null if tv is [0], otherwise 0.
120 */
121#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
122
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200123/*
124 * Converts a struct timeval to a number of milliseconds.
125 */
126REGPRM1 static inline unsigned long __tv_to_ms(const struct timeval *tv)
127{
128 unsigned long ret;
129
130 ret = tv->tv_sec * 1000;
131 ret += tv->tv_usec / 1000;
132 return ret;
133}
134
135/*
136 * Converts a struct timeval to a number of milliseconds.
137 */
138REGPRM2 static inline struct timeval * __tv_from_ms(struct timeval *tv, unsigned long ms)
139{
140 tv->tv_sec = ms / 1000;
141 tv->tv_usec = (ms % 1000) * 1000;
142 return tv;
143}
144
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200145
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200146/**** comparison functions and macros ***********************************/
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200147
148
149/* tv_cmp: compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2. */
150REGPRM2 static inline int __tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200152 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200154 else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200156 else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200158 else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159 return 1;
160 else
161 return 0;
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100162}
163
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200164/* tv_iseq: compares <tv1> and <tv2> : returns 1 if tv1 == tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200165#define tv_iseq __tv_iseq
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200166REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
167{
Willy Tarreau0481c202007-05-13 16:03:27 +0200168 return ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) &&
169 ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200170}
171
172/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200173#define tv_isgt _tv_isgt
174REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200175REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
176{
Willy Tarreau0481c202007-05-13 16:03:27 +0200177 return
178 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
179 ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec) :
180 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200181}
182
183/* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200184#define tv_isge __tv_isge
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200185REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
186{
Willy Tarreau0481c202007-05-13 16:03:27 +0200187 return
188 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
189 ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
190 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200191}
192
193/* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200194#define tv_islt __tv_islt
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200195REGPRM2 static inline int __tv_islt(const struct timeval *tv1, const struct timeval *tv2)
196{
Willy Tarreau0481c202007-05-13 16:03:27 +0200197 return
198 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
199 ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec) :
200 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200201}
202
203/* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200204#define tv_isle _tv_isle
205REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200206REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
207{
Willy Tarreau0481c202007-05-13 16:03:27 +0200208 return
209 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
210 ((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
211 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200212}
213
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100214/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200215 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
216 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100217 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200218#define tv_ms_cmp _tv_ms_cmp
219REGPRM2 int _tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
220REGPRM2 static inline int __tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100221{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200222 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
223 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
224 return -1;
225 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
226 return 1;
227 else
228 return 0;
229 }
230 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
231 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
232 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
233 return -1;
234 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
235 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
236 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100237 return 1;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200238 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100239 return 0;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200240}
241
242/*
243 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
244 * assuming that TV_ETERNITY is greater than everything.
245 */
246#define tv_ms_cmp2 _tv_ms_cmp2
247REGPRM2 int _tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
248REGPRM2 static inline int __tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2)
249{
250 if (tv_iseternity(tv1))
251 if (tv_iseternity(tv2))
252 return 0; /* same */
253 else
254 return 1; /* tv1 later than tv2 */
255 else if (tv_iseternity(tv2))
256 return -1; /* tv2 later than tv1 */
257 return tv_ms_cmp(tv1, tv2);
258}
259
260/*
261 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
262 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
263 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
264 * occurrences of (tv_ms_cmp2(tv,now) <= 0).
265 */
266#define tv_ms_le2 _tv_ms_le2
267REGPRM2 int _tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2);
268REGPRM2 static inline int __tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2)
269{
270 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
271 return 0;
272
273 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
274 return 1;
275
276 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
277 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
278 return 1;
279 else
280 return 0;
281 }
282
283 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
284 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
285 return 0;
286 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100287 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288}
289
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200290
291/**** operators **********************************************************/
292
293
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200295 * Returns the time in ms elapsed between tv1 and tv2, assuming that tv1<=tv2.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 * Must not be used when either argument is eternity.
297 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200298#define tv_ms_elapsed __tv_ms_elapsed
299REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2);
300REGPRM2 static inline unsigned long __tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301{
302 unsigned long ret;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200303
304 ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000;
305 ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000;
306 return ret;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307}
308
309/*
310 * returns the remaining time between tv1=now and event=tv2
311 * if tv2 is passed, 0 is returned.
312 * Must not be used when either argument is eternity.
313 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200314
315#define tv_ms_remain __tv_ms_remain
316REGPRM2 unsigned long _tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2);
317REGPRM2 static inline unsigned long __tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200319 if (tv_ms_cmp(tv1, tv2) >= 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 return 0; /* event elapsed */
321
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200322 return __tv_ms_elapsed(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323}
324
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200326 * returns the remaining time between tv1=now and event=tv2
327 * if tv2 is passed, 0 is returned.
328 * Returns TIME_ETERNITY if tv2 is eternity.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200329 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200330#define tv_ms_remain2 _tv_ms_remain2
331REGPRM2 unsigned long _tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2);
332REGPRM2 static inline unsigned long __tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200334 if (tv_iseternity(tv2))
335 return TIME_ETERNITY;
336
337 return tv_ms_remain(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200338}
339
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200340/*
341 * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
342 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200343#define tv_add _tv_add
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200344REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
345REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
346{
347 tv->tv_usec = from->tv_usec + inc->tv_usec;
348 tv->tv_sec = from->tv_sec + inc->tv_sec;
349 if (tv->tv_usec >= 1000000) {
350 tv->tv_usec -= 1000000;
351 tv->tv_sec++;
352 }
353 return tv;
354}
355
356
357/*
Willy Tarreau0481c202007-05-13 16:03:27 +0200358 * If <inc> is set, then add it to <from> and set the result to <tv>, then
359 * return 1, otherwise return 0. It is meant to be used in if conditions.
360 */
361#define tv_add_ifset _tv_add_ifset
362REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
363REGPRM3 static inline int __tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
364{
365 if (tv_iseternity(inc))
366 return 0;
367 tv->tv_usec = from->tv_usec + inc->tv_usec;
368 tv->tv_sec = from->tv_sec + inc->tv_sec;
369 if (tv->tv_usec >= 1000000) {
370 tv->tv_usec -= 1000000;
371 tv->tv_sec++;
372 }
373 return 1;
374}
375
376/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200377 * adds <inc> to <tv> and returns a pointer <tv>
378 */
379REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
380{
381 tv->tv_usec += inc->tv_usec;
382 tv->tv_sec += inc->tv_sec;
383 if (tv->tv_usec >= 1000000) {
384 tv->tv_usec -= 1000000;
385 tv->tv_sec++;
386 }
387 return tv;
388}
389
390
391/*
392 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
393 * 0 is returned. The result is stored into tv.
394 */
395#define tv_remain _tv_remain
396REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
397REGPRM3 static inline struct timeval *__tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
398{
399 tv->tv_usec = tv2->tv_usec - tv1->tv_usec;
400 tv->tv_sec = tv2->tv_sec - tv1->tv_sec;
401 if ((signed)tv->tv_sec > 0) {
402 if ((signed)tv->tv_usec < 0) {
403 tv->tv_usec += 1000000;
404 tv->tv_sec--;
405 }
406 } else if (tv->tv_sec == 0) {
407 if ((signed)tv->tv_usec < 0)
408 tv->tv_usec = 0;
409 } else {
410 tv->tv_sec = 0;
411 tv->tv_usec = 0;
412 }
413 return tv;
414}
415
416
417/*
418 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
419 * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
420 * eternity.
421 */
422#define tv_remain2 _tv_remain2
423REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
424REGPRM3 static inline struct timeval *__tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
425{
426 if (tv_iseternity(tv2))
427 return tv_eternity(tv);
428 return __tv_remain(tv1, tv2, tv);
429}
430
431
Willy Tarreaubaaee002006-06-26 02:48:02 +0200432/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200433 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200434 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200435#define tv_ms_add _tv_ms_add
436REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
437REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const struct timeval *from, int ms)
438{
439 tv->tv_usec = from->tv_usec + (ms % 1000) * 1000;
440 tv->tv_sec = from->tv_sec + (ms / 1000);
441 while (tv->tv_usec >= 1000000) {
442 tv->tv_usec -= 1000000;
443 tv->tv_sec++;
444 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200445 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200446}
447
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200449/*
450 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
451 * This should be very fast because it's used in schedulers.
452 * It has been optimized to return 1 (so call it in a loop which continues
453 * as long as tv1<=tv2)
454 */
455
456#define tv_isbefore(tv1, tv2) \
457 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
458 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
459 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
460
461/*
462 * returns the first event between <tv1> and <tv2> into <tvmin>.
463 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
464 * to be the same as <tv1> or <tv2>, it is recommended to use
465 * tv_bound instead.
466 */
467#define tv_min(tvmin, tv1, tv2) ({ \
468 if (tv_isbefore(tv1, tv2)) { \
469 *tvmin = *tv1; \
470 } \
471 else { \
472 *tvmin = *tv2; \
473 } \
474 tvmin; \
475})
476
477/*
478 * returns the first event between <tv1> and <tv2> into <tvmin>.
479 * a zero tv is ignored. <tvmin> is returned. This function has been
480 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
481 */
482#define tv_bound(tv1, tv2) ({ \
483 if (tv_isbefore(tv2, tv1)) \
484 *tv1 = *tv2; \
485 tv1; \
486})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487
Willy Tarreauc8f24f82007-11-30 18:38:35 +0100488char *human_time(int t, short hz_div);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200490#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491
492/*
493 * Local variables:
494 * c-indent-level: 8
495 * c-basic-offset: 8
496 * End:
497 */