blob: 33a62f84123f522d0a7f314b63cd69a08a2e6303 [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
Willy Tarreaua6a6a932007-04-28 22:40:08 +020030/* eternity when exprimed in timeval */
31#ifndef TV_ETERNITY
32#define TV_ETERNITY (~0UL)
33#endif
34
35/* eternity when exprimed in ms */
36#ifndef TV_ETERNITY_MS
37#define TV_ETERNITY_MS (-1)
38#endif
39
40#define TIME_ETERNITY (TV_ETERNITY_MS)
41
Willy Tarreaubaaee002006-06-26 02:48:02 +020042
43/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
44#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
45#define SETNOW(a) (*a=now)
46
47extern struct timeval now; /* the current date at any moment */
48extern struct timeval start_date; /* the process's start date */
49
50
Willy Tarreau42aae5c2007-04-29 17:43:56 +020051/**** exported functions *************************************************/
52
53
Willy Tarreaubaaee002006-06-26 02:48:02 +020054/*
55 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
56 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020057REGPRM3 struct timeval *tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
Willy Tarreaubaaee002006-06-26 02:48:02 +020058
59/*
60 * 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 +020061 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreaubaaee002006-06-26 02:48:02 +020062 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020063REGPRM2 int tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020066 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
67 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020068 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020069REGPRM2 int tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau5e8f0662007-02-12 00:59:08 +010070
Willy Tarreau42aae5c2007-04-29 17:43:56 +020071/**** general purpose functions and macros *******************************/
72
73
74/* tv_now: sets <tv> to the current time */
75REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
76{
77 gettimeofday(tv, NULL);
78 return tv;
79}
Willy Tarreaubaaee002006-06-26 02:48:02 +020080
81/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +020082 * sets a struct timeval to its highest value so that it can never happen
83 * note that only tv_usec is necessary to detect it since a tv_usec > 999999
84 * is normally not possible.
85 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020086 */
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
Willy Tarreau42aae5c2007-04-29 17:43:56 +020088REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +020089{
Willy Tarreau42aae5c2007-04-29 17:43:56 +020090 tv->tv_sec = tv->tv_usec = TV_ETERNITY;
Willy Tarreaubaaee002006-06-26 02:48:02 +020091 return tv;
92}
93
94/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +020095 * sets a struct timeval to 0
96 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020097 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020098REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
99 tv->tv_sec = tv->tv_usec = 0;
100 return tv;
101}
102
103/*
104 * returns non null if tv is [eternity], otherwise 0.
105 */
106#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
107
108/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200109 * returns 0 if tv is [eternity], otherwise non-zero.
110 */
111#define tv_isset(tv) ((tv)->tv_usec != TV_ETERNITY)
112
113/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200114 * returns non null if tv is [0], otherwise 0.
115 */
116#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
117
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200118/*
119 * Converts a struct timeval to a number of milliseconds.
120 */
121REGPRM1 static inline unsigned long __tv_to_ms(const struct timeval *tv)
122{
123 unsigned long ret;
124
125 ret = tv->tv_sec * 1000;
126 ret += tv->tv_usec / 1000;
127 return ret;
128}
129
130/*
131 * Converts a struct timeval to a number of milliseconds.
132 */
133REGPRM2 static inline struct timeval * __tv_from_ms(struct timeval *tv, unsigned long ms)
134{
135 tv->tv_sec = ms / 1000;
136 tv->tv_usec = (ms % 1000) * 1000;
137 return tv;
138}
139
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200140
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200141/**** comparison functions and macros ***********************************/
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200142
143
144/* tv_cmp: compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2. */
145REGPRM2 static inline int __tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200147 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200148 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200149 else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200151 else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200153 else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154 return 1;
155 else
156 return 0;
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100157}
158
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200159/* tv_iseq: compares <tv1> and <tv2> : returns 1 if tv1 == tv2, otherwise 0 */
160REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
161{
162 return ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) &&
163 ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
164}
165
166/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
167REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
168{
169 return
170 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
171 ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec) :
172 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
173}
174
175/* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
176REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
177{
178 return
179 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
180 ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
181 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
182}
183
184/* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
185REGPRM2 static inline int __tv_islt(const struct timeval *tv1, const struct timeval *tv2)
186{
187 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);
191}
192
193/* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
194REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
195{
196 return
197 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
198 ((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
199 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
200}
201
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100202/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200203 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
204 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100205 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200206#define tv_ms_cmp _tv_ms_cmp
207REGPRM2 int _tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
208REGPRM2 static inline int __tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100209{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200210 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
211 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
212 return -1;
213 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
214 return 1;
215 else
216 return 0;
217 }
218 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
219 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
220 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
221 return -1;
222 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
223 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
224 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100225 return 1;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200226 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100227 return 0;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200228}
229
230/*
231 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
232 * assuming that TV_ETERNITY is greater than everything.
233 */
234#define tv_ms_cmp2 _tv_ms_cmp2
235REGPRM2 int _tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
236REGPRM2 static inline int __tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2)
237{
238 if (tv_iseternity(tv1))
239 if (tv_iseternity(tv2))
240 return 0; /* same */
241 else
242 return 1; /* tv1 later than tv2 */
243 else if (tv_iseternity(tv2))
244 return -1; /* tv2 later than tv1 */
245 return tv_ms_cmp(tv1, tv2);
246}
247
248/*
249 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
250 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
251 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
252 * occurrences of (tv_ms_cmp2(tv,now) <= 0).
253 */
254#define tv_ms_le2 _tv_ms_le2
255REGPRM2 int _tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2);
256REGPRM2 static inline int __tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2)
257{
258 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
259 return 0;
260
261 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
262 return 1;
263
264 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
265 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
266 return 1;
267 else
268 return 0;
269 }
270
271 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
272 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
273 return 0;
274 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100275 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276}
277
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200278
279/**** operators **********************************************************/
280
281
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200283 * Returns the time in ms elapsed between tv1 and tv2, assuming that tv1<=tv2.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 * Must not be used when either argument is eternity.
285 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200286#define tv_ms_elapsed __tv_ms_elapsed
287REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2);
288REGPRM2 static inline unsigned long __tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289{
290 unsigned long ret;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200291
292 ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000;
293 ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000;
294 return ret;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295}
296
297/*
298 * returns the remaining time between tv1=now and event=tv2
299 * if tv2 is passed, 0 is returned.
300 * Must not be used when either argument is eternity.
301 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200302
303#define tv_ms_remain __tv_ms_remain
304REGPRM2 unsigned long _tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2);
305REGPRM2 static inline unsigned long __tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200307 if (tv_ms_cmp(tv1, tv2) >= 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 return 0; /* event elapsed */
309
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200310 return __tv_ms_elapsed(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311}
312
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200314 * returns the remaining time between tv1=now and event=tv2
315 * if tv2 is passed, 0 is returned.
316 * Returns TIME_ETERNITY if tv2 is eternity.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200318#define tv_ms_remain2 _tv_ms_remain2
319REGPRM2 unsigned long _tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2);
320REGPRM2 static inline unsigned long __tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200322 if (tv_iseternity(tv2))
323 return TIME_ETERNITY;
324
325 return tv_ms_remain(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200328/*
329 * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
330 */
331#define tv_add __tv_add
332REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
333REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
334{
335 tv->tv_usec = from->tv_usec + inc->tv_usec;
336 tv->tv_sec = from->tv_sec + inc->tv_sec;
337 if (tv->tv_usec >= 1000000) {
338 tv->tv_usec -= 1000000;
339 tv->tv_sec++;
340 }
341 return tv;
342}
343
344
345/*
346 * adds <inc> to <tv> and returns a pointer <tv>
347 */
348REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
349{
350 tv->tv_usec += inc->tv_usec;
351 tv->tv_sec += inc->tv_sec;
352 if (tv->tv_usec >= 1000000) {
353 tv->tv_usec -= 1000000;
354 tv->tv_sec++;
355 }
356 return tv;
357}
358
359
360/*
361 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
362 * 0 is returned. The result is stored into tv.
363 */
364#define tv_remain _tv_remain
365REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
366REGPRM3 static inline struct timeval *__tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
367{
368 tv->tv_usec = tv2->tv_usec - tv1->tv_usec;
369 tv->tv_sec = tv2->tv_sec - tv1->tv_sec;
370 if ((signed)tv->tv_sec > 0) {
371 if ((signed)tv->tv_usec < 0) {
372 tv->tv_usec += 1000000;
373 tv->tv_sec--;
374 }
375 } else if (tv->tv_sec == 0) {
376 if ((signed)tv->tv_usec < 0)
377 tv->tv_usec = 0;
378 } else {
379 tv->tv_sec = 0;
380 tv->tv_usec = 0;
381 }
382 return tv;
383}
384
385
386/*
387 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
388 * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
389 * eternity.
390 */
391#define tv_remain2 _tv_remain2
392REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
393REGPRM3 static inline struct timeval *__tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
394{
395 if (tv_iseternity(tv2))
396 return tv_eternity(tv);
397 return __tv_remain(tv1, tv2, tv);
398}
399
400
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200402 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200403 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200404#define tv_ms_add _tv_ms_add
405REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
406REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const struct timeval *from, int ms)
407{
408 tv->tv_usec = from->tv_usec + (ms % 1000) * 1000;
409 tv->tv_sec = from->tv_sec + (ms / 1000);
410 while (tv->tv_usec >= 1000000) {
411 tv->tv_usec -= 1000000;
412 tv->tv_sec++;
413 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200414 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200415}
416
Willy Tarreaubaaee002006-06-26 02:48:02 +0200417
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200418/*
419 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
420 * This should be very fast because it's used in schedulers.
421 * It has been optimized to return 1 (so call it in a loop which continues
422 * as long as tv1<=tv2)
423 */
424
425#define tv_isbefore(tv1, tv2) \
426 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
427 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
428 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
429
430/*
431 * returns the first event between <tv1> and <tv2> into <tvmin>.
432 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
433 * to be the same as <tv1> or <tv2>, it is recommended to use
434 * tv_bound instead.
435 */
436#define tv_min(tvmin, tv1, tv2) ({ \
437 if (tv_isbefore(tv1, tv2)) { \
438 *tvmin = *tv1; \
439 } \
440 else { \
441 *tvmin = *tv2; \
442 } \
443 tvmin; \
444})
445
446/*
447 * returns the first event between <tv1> and <tv2> into <tvmin>.
448 * a zero tv is ignored. <tvmin> is returned. This function has been
449 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
450 */
451#define tv_bound(tv1, tv2) ({ \
452 if (tv_isbefore(tv2, tv1)) \
453 *tv1 = *tv2; \
454 tv1; \
455})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456
457
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200458#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459
460/*
461 * Local variables:
462 * c-indent-level: 8
463 * c-basic-offset: 8
464 * End:
465 */