blob: 001d63e95469ca5e06c47802d5663a4f00c1c629 [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 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200160#define tv_iseq __tv_iseq
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200161REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
162{
Willy Tarreau0481c202007-05-13 16:03:27 +0200163 return ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) &&
164 ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200165}
166
167/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200168#define tv_isgt _tv_isgt
169REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200170REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
171{
Willy Tarreau0481c202007-05-13 16:03:27 +0200172 return
173 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
174 ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec) :
175 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200176}
177
178/* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200179#define tv_isge __tv_isge
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200180REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
181{
Willy Tarreau0481c202007-05-13 16:03:27 +0200182 return
183 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
184 ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
185 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200186}
187
188/* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200189#define tv_islt __tv_islt
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200190REGPRM2 static inline int __tv_islt(const struct timeval *tv1, const struct timeval *tv2)
191{
Willy Tarreau0481c202007-05-13 16:03:27 +0200192 return
193 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
194 ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec) :
195 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200196}
197
198/* tv_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200199#define tv_isle _tv_isle
200REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200201REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
202{
Willy Tarreau0481c202007-05-13 16:03:27 +0200203 return
204 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
205 ((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
206 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200207}
208
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100209/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200210 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
211 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100212 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200213#define tv_ms_cmp _tv_ms_cmp
214REGPRM2 int _tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
215REGPRM2 static inline int __tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100216{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200217 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
218 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
219 return -1;
220 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
221 return 1;
222 else
223 return 0;
224 }
225 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
226 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
227 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
228 return -1;
229 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
230 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
231 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100232 return 1;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200233 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100234 return 0;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200235}
236
237/*
238 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
239 * assuming that TV_ETERNITY is greater than everything.
240 */
241#define tv_ms_cmp2 _tv_ms_cmp2
242REGPRM2 int _tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
243REGPRM2 static inline int __tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2)
244{
245 if (tv_iseternity(tv1))
246 if (tv_iseternity(tv2))
247 return 0; /* same */
248 else
249 return 1; /* tv1 later than tv2 */
250 else if (tv_iseternity(tv2))
251 return -1; /* tv2 later than tv1 */
252 return tv_ms_cmp(tv1, tv2);
253}
254
255/*
256 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
257 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
258 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
259 * occurrences of (tv_ms_cmp2(tv,now) <= 0).
260 */
261#define tv_ms_le2 _tv_ms_le2
262REGPRM2 int _tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2);
263REGPRM2 static inline int __tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2)
264{
265 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
266 return 0;
267
268 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
269 return 1;
270
271 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
272 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
273 return 1;
274 else
275 return 0;
276 }
277
278 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
279 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
280 return 0;
281 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100282 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283}
284
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200285
286/**** operators **********************************************************/
287
288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200290 * Returns the time in ms elapsed between tv1 and tv2, assuming that tv1<=tv2.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291 * Must not be used when either argument is eternity.
292 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200293#define tv_ms_elapsed __tv_ms_elapsed
294REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2);
295REGPRM2 static inline unsigned long __tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296{
297 unsigned long ret;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200298
299 ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000;
300 ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000;
301 return ret;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302}
303
304/*
305 * returns the remaining time between tv1=now and event=tv2
306 * if tv2 is passed, 0 is returned.
307 * Must not be used when either argument is eternity.
308 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200309
310#define tv_ms_remain __tv_ms_remain
311REGPRM2 unsigned long _tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2);
312REGPRM2 static inline unsigned long __tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200314 if (tv_ms_cmp(tv1, tv2) >= 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 return 0; /* event elapsed */
316
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200317 return __tv_ms_elapsed(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200321 * returns the remaining time between tv1=now and event=tv2
322 * if tv2 is passed, 0 is returned.
323 * Returns TIME_ETERNITY if tv2 is eternity.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200325#define tv_ms_remain2 _tv_ms_remain2
326REGPRM2 unsigned long _tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2);
327REGPRM2 static inline unsigned long __tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200329 if (tv_iseternity(tv2))
330 return TIME_ETERNITY;
331
332 return tv_ms_remain(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333}
334
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200335/*
336 * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
337 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200338#define tv_add _tv_add
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200339REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
340REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
341{
342 tv->tv_usec = from->tv_usec + inc->tv_usec;
343 tv->tv_sec = from->tv_sec + inc->tv_sec;
344 if (tv->tv_usec >= 1000000) {
345 tv->tv_usec -= 1000000;
346 tv->tv_sec++;
347 }
348 return tv;
349}
350
351
352/*
Willy Tarreau0481c202007-05-13 16:03:27 +0200353 * If <inc> is set, then add it to <from> and set the result to <tv>, then
354 * return 1, otherwise return 0. It is meant to be used in if conditions.
355 */
356#define tv_add_ifset _tv_add_ifset
357REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
358REGPRM3 static inline int __tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
359{
360 if (tv_iseternity(inc))
361 return 0;
362 tv->tv_usec = from->tv_usec + inc->tv_usec;
363 tv->tv_sec = from->tv_sec + inc->tv_sec;
364 if (tv->tv_usec >= 1000000) {
365 tv->tv_usec -= 1000000;
366 tv->tv_sec++;
367 }
368 return 1;
369}
370
371/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200372 * adds <inc> to <tv> and returns a pointer <tv>
373 */
374REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
375{
376 tv->tv_usec += inc->tv_usec;
377 tv->tv_sec += inc->tv_sec;
378 if (tv->tv_usec >= 1000000) {
379 tv->tv_usec -= 1000000;
380 tv->tv_sec++;
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.
389 */
390#define tv_remain _tv_remain
391REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
392REGPRM3 static inline struct timeval *__tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
393{
394 tv->tv_usec = tv2->tv_usec - tv1->tv_usec;
395 tv->tv_sec = tv2->tv_sec - tv1->tv_sec;
396 if ((signed)tv->tv_sec > 0) {
397 if ((signed)tv->tv_usec < 0) {
398 tv->tv_usec += 1000000;
399 tv->tv_sec--;
400 }
401 } else if (tv->tv_sec == 0) {
402 if ((signed)tv->tv_usec < 0)
403 tv->tv_usec = 0;
404 } else {
405 tv->tv_sec = 0;
406 tv->tv_usec = 0;
407 }
408 return tv;
409}
410
411
412/*
413 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
414 * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
415 * eternity.
416 */
417#define tv_remain2 _tv_remain2
418REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
419REGPRM3 static inline struct timeval *__tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
420{
421 if (tv_iseternity(tv2))
422 return tv_eternity(tv);
423 return __tv_remain(tv1, tv2, tv);
424}
425
426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200428 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200430#define tv_ms_add _tv_ms_add
431REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
432REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const struct timeval *from, int ms)
433{
434 tv->tv_usec = from->tv_usec + (ms % 1000) * 1000;
435 tv->tv_sec = from->tv_sec + (ms / 1000);
436 while (tv->tv_usec >= 1000000) {
437 tv->tv_usec -= 1000000;
438 tv->tv_sec++;
439 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200440 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441}
442
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200444/*
445 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
446 * This should be very fast because it's used in schedulers.
447 * It has been optimized to return 1 (so call it in a loop which continues
448 * as long as tv1<=tv2)
449 */
450
451#define tv_isbefore(tv1, tv2) \
452 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
453 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
454 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
455
456/*
457 * returns the first event between <tv1> and <tv2> into <tvmin>.
458 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
459 * to be the same as <tv1> or <tv2>, it is recommended to use
460 * tv_bound instead.
461 */
462#define tv_min(tvmin, tv1, tv2) ({ \
463 if (tv_isbefore(tv1, tv2)) { \
464 *tvmin = *tv1; \
465 } \
466 else { \
467 *tvmin = *tv2; \
468 } \
469 tvmin; \
470})
471
472/*
473 * returns the first event between <tv1> and <tv2> into <tvmin>.
474 * a zero tv is ignored. <tvmin> is returned. This function has been
475 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
476 */
477#define tv_bound(tv1, tv2) ({ \
478 if (tv_isbefore(tv2, tv1)) \
479 *tv1 = *tv2; \
480 tv1; \
481})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482
483
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200484#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485
486/*
487 * Local variables:
488 * c-indent-level: 8
489 * c-basic-offset: 8
490 * End:
491 */