blob: d6155265d6108ca92572e547c42aac3960079834 [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 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
Willy Tarreaub7f694f2008-06-22 17:18:02 +020052extern struct timeval now; /* internal date is a monotonic function of real clock */
53extern struct timeval date; /* the real current date */
Willy Tarreaubaaee002006-06-26 02:48:02 +020054extern struct timeval start_date; /* the process's start date */
55
56
Willy Tarreau42aae5c2007-04-29 17:43:56 +020057/**** exported functions *************************************************/
58
59
Willy Tarreaubaaee002006-06-26 02:48:02 +020060/*
61 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
62 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020063REGPRM3 struct timeval *tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65/*
66 * 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 +020067 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreaubaaee002006-06-26 02:48:02 +020068 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020069REGPRM2 int tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
71/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020072 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
73 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020074 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +020075REGPRM2 int tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau5e8f0662007-02-12 00:59:08 +010076
Willy Tarreau42aae5c2007-04-29 17:43:56 +020077/**** general purpose functions and macros *******************************/
78
79
80/* tv_now: sets <tv> to the current time */
81REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
82{
83 gettimeofday(tv, NULL);
84 return tv;
85}
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Willy Tarreaub7f694f2008-06-22 17:18:02 +020087/* tv_now_mono: sets <date> to the current time (wall clock), <mono> to a value
88 * following a monotonic function, and applies any required correction if the
89 * time goes backwards. Note that while we could improve it a bit by checking
90 * that the new date is not too far in the future, it is not much necessary to
91 * do so.
92 */
93REGPRM2 struct timeval *tv_now_mono(struct timeval *mono, struct timeval *wall);
94
Willy Tarreaubaaee002006-06-26 02:48:02 +020095/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +020096 * sets a struct timeval to its highest value so that it can never happen
97 * note that only tv_usec is necessary to detect it since a tv_usec > 999999
98 * is normally not possible.
Willy Tarreaubaaee002006-06-26 02:48:02 +020099 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200100REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200101{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200102 tv->tv_sec = tv->tv_usec = TV_ETERNITY;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200103 return tv;
104}
105
106/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200107 * sets a struct timeval to 0
108 *
Willy Tarreaubaaee002006-06-26 02:48:02 +0200109 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200110REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
111 tv->tv_sec = tv->tv_usec = 0;
112 return tv;
113}
114
115/*
116 * returns non null if tv is [eternity], otherwise 0.
117 */
118#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
119
120/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200121 * returns 0 if tv is [eternity], otherwise non-zero.
122 */
123#define tv_isset(tv) ((tv)->tv_usec != TV_ETERNITY)
124
125/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200126 * returns non null if tv is [0], otherwise 0.
127 */
128#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
129
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200130/*
131 * Converts a struct timeval to a number of milliseconds.
132 */
133REGPRM1 static inline unsigned long __tv_to_ms(const struct timeval *tv)
134{
135 unsigned long ret;
136
137 ret = tv->tv_sec * 1000;
138 ret += tv->tv_usec / 1000;
139 return ret;
140}
141
142/*
143 * Converts a struct timeval to a number of milliseconds.
144 */
145REGPRM2 static inline struct timeval * __tv_from_ms(struct timeval *tv, unsigned long ms)
146{
147 tv->tv_sec = ms / 1000;
148 tv->tv_usec = (ms % 1000) * 1000;
149 return tv;
150}
151
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200152
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200153/**** comparison functions and macros ***********************************/
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200154
155
156/* tv_cmp: compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2. */
157REGPRM2 static inline int __tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200159 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200160 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200161 else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200162 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200163 else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200165 else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166 return 1;
167 else
168 return 0;
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100169}
170
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200171/* tv_iseq: compares <tv1> and <tv2> : returns 1 if tv1 == tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200172#define tv_iseq __tv_iseq
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200173REGPRM2 static inline int __tv_iseq(const struct timeval *tv1, const struct timeval *tv2)
174{
Willy Tarreau0481c202007-05-13 16:03:27 +0200175 return ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) &&
176 ((unsigned)tv1->tv_usec == (unsigned)tv2->tv_usec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200177}
178
179/* tv_isgt: compares <tv1> and <tv2> : returns 1 if tv1 > tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200180#define tv_isgt _tv_isgt
181REGPRM2 int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200182REGPRM2 static inline int __tv_isgt(const struct timeval *tv1, const struct timeval *tv2)
183{
Willy Tarreau0481c202007-05-13 16:03:27 +0200184 return
185 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
186 ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec) :
187 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200188}
189
190/* tv_isge: compares <tv1> and <tv2> : returns 1 if tv1 >= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200191#define tv_isge __tv_isge
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200192REGPRM2 static inline int __tv_isge(const struct timeval *tv1, const struct timeval *tv2)
193{
Willy Tarreau0481c202007-05-13 16:03:27 +0200194 return
195 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
196 ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec) :
197 ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200198}
199
200/* tv_islt: compares <tv1> and <tv2> : returns 1 if tv1 < tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200201#define tv_islt __tv_islt
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200202REGPRM2 static inline int __tv_islt(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_isle: compares <tv1> and <tv2> : returns 1 if tv1 <= tv2, otherwise 0 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200211#define tv_isle _tv_isle
212REGPRM2 int _tv_isle(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200213REGPRM2 static inline int __tv_isle(const struct timeval *tv1, const struct timeval *tv2)
214{
Willy Tarreau0481c202007-05-13 16:03:27 +0200215 return
216 ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) ?
217 ((unsigned)tv1->tv_usec <= (unsigned)tv2->tv_usec) :
218 ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200219}
220
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100221/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200222 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
223 * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100224 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200225#define tv_ms_cmp _tv_ms_cmp
226REGPRM2 int _tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
227REGPRM2 static inline int __tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100228{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200229 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
230 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
231 return -1;
232 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
233 return 1;
234 else
235 return 0;
236 }
237 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
238 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
239 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
240 return -1;
241 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
242 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
243 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100244 return 1;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200245 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100246 return 0;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200247}
248
249/*
250 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
251 * assuming that TV_ETERNITY is greater than everything.
252 */
253#define tv_ms_cmp2 _tv_ms_cmp2
254REGPRM2 int _tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
255REGPRM2 static inline int __tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2)
256{
257 if (tv_iseternity(tv1))
258 if (tv_iseternity(tv2))
259 return 0; /* same */
260 else
261 return 1; /* tv1 later than tv2 */
262 else if (tv_iseternity(tv2))
263 return -1; /* tv2 later than tv1 */
264 return tv_ms_cmp(tv1, tv2);
265}
266
267/*
268 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
269 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
270 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
271 * occurrences of (tv_ms_cmp2(tv,now) <= 0).
272 */
273#define tv_ms_le2 _tv_ms_le2
274REGPRM2 int _tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2);
275REGPRM2 static inline int __tv_ms_le2(const struct timeval *tv1, const struct timeval *tv2)
276{
277 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
278 return 0;
279
280 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
281 return 1;
282
283 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
284 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
285 return 1;
286 else
287 return 0;
288 }
289
290 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
291 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
292 return 0;
293 else
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100294 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295}
296
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200297
298/**** operators **********************************************************/
299
300
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200302 * Returns the time in ms elapsed between tv1 and tv2, assuming that tv1<=tv2.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 * Must not be used when either argument is eternity.
304 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200305#define tv_ms_elapsed __tv_ms_elapsed
306REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2);
307REGPRM2 static inline unsigned long __tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308{
309 unsigned long ret;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200310
311 ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000;
312 ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000;
313 return ret;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314}
315
316/*
317 * returns the remaining time between tv1=now and event=tv2
318 * if tv2 is passed, 0 is returned.
319 * Must not be used when either argument is eternity.
320 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200321
322#define tv_ms_remain __tv_ms_remain
323REGPRM2 unsigned long _tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2);
324REGPRM2 static inline unsigned long __tv_ms_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200326 if (tv_ms_cmp(tv1, tv2) >= 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327 return 0; /* event elapsed */
328
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200329 return __tv_ms_elapsed(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200330}
331
Willy Tarreaubaaee002006-06-26 02:48:02 +0200332/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200333 * returns the remaining time between tv1=now and event=tv2
334 * if tv2 is passed, 0 is returned.
335 * Returns TIME_ETERNITY if tv2 is eternity.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200337#define tv_ms_remain2 _tv_ms_remain2
338REGPRM2 unsigned long _tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2);
339REGPRM2 static inline unsigned long __tv_ms_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200340{
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200341 if (tv_iseternity(tv2))
342 return TIME_ETERNITY;
343
344 return tv_ms_remain(tv1, tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345}
346
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200347/*
348 * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
349 */
Willy Tarreau0481c202007-05-13 16:03:27 +0200350#define tv_add _tv_add
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200351REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
352REGPRM3 static inline struct timeval *__tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
353{
354 tv->tv_usec = from->tv_usec + inc->tv_usec;
355 tv->tv_sec = from->tv_sec + inc->tv_sec;
356 if (tv->tv_usec >= 1000000) {
357 tv->tv_usec -= 1000000;
358 tv->tv_sec++;
359 }
360 return tv;
361}
362
363
364/*
Willy Tarreau0481c202007-05-13 16:03:27 +0200365 * If <inc> is set, then add it to <from> and set the result to <tv>, then
366 * return 1, otherwise return 0. It is meant to be used in if conditions.
367 */
368#define tv_add_ifset _tv_add_ifset
369REGPRM3 int _tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc);
370REGPRM3 static inline int __tv_add_ifset(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
371{
372 if (tv_iseternity(inc))
373 return 0;
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 1;
381}
382
383/*
Willy Tarreau49fa3a12007-05-12 22:29:44 +0200384 * adds <inc> to <tv> and returns a pointer <tv>
385 */
386REGPRM2 static inline struct timeval *__tv_add2(struct timeval *tv, const struct timeval *inc)
387{
388 tv->tv_usec += inc->tv_usec;
389 tv->tv_sec += inc->tv_sec;
390 if (tv->tv_usec >= 1000000) {
391 tv->tv_usec -= 1000000;
392 tv->tv_sec++;
393 }
394 return tv;
395}
396
397
398/*
399 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
400 * 0 is returned. The result is stored into tv.
401 */
402#define tv_remain _tv_remain
403REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
404REGPRM3 static inline struct timeval *__tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
405{
406 tv->tv_usec = tv2->tv_usec - tv1->tv_usec;
407 tv->tv_sec = tv2->tv_sec - tv1->tv_sec;
408 if ((signed)tv->tv_sec > 0) {
409 if ((signed)tv->tv_usec < 0) {
410 tv->tv_usec += 1000000;
411 tv->tv_sec--;
412 }
413 } else if (tv->tv_sec == 0) {
414 if ((signed)tv->tv_usec < 0)
415 tv->tv_usec = 0;
416 } else {
417 tv->tv_sec = 0;
418 tv->tv_usec = 0;
419 }
420 return tv;
421}
422
423
424/*
425 * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
426 * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
427 * eternity.
428 */
429#define tv_remain2 _tv_remain2
430REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv);
431REGPRM3 static inline struct timeval *__tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
432{
433 if (tv_iseternity(tv2))
434 return tv_eternity(tv);
435 return __tv_remain(tv1, tv2, tv);
436}
437
438
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439/*
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200440 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 */
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200442#define tv_ms_add _tv_ms_add
443REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *from, int ms);
444REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const struct timeval *from, int ms)
445{
446 tv->tv_usec = from->tv_usec + (ms % 1000) * 1000;
447 tv->tv_sec = from->tv_sec + (ms / 1000);
448 while (tv->tv_usec >= 1000000) {
449 tv->tv_usec -= 1000000;
450 tv->tv_sec++;
451 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200452 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453}
454
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200456/*
457 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
458 * This should be very fast because it's used in schedulers.
459 * It has been optimized to return 1 (so call it in a loop which continues
460 * as long as tv1<=tv2)
461 */
462
463#define tv_isbefore(tv1, tv2) \
464 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
465 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
466 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
467
468/*
469 * returns the first event between <tv1> and <tv2> into <tvmin>.
470 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
471 * to be the same as <tv1> or <tv2>, it is recommended to use
472 * tv_bound instead.
473 */
474#define tv_min(tvmin, tv1, tv2) ({ \
475 if (tv_isbefore(tv1, tv2)) { \
476 *tvmin = *tv1; \
477 } \
478 else { \
479 *tvmin = *tv2; \
480 } \
481 tvmin; \
482})
483
484/*
485 * returns the first event between <tv1> and <tv2> into <tvmin>.
486 * a zero tv is ignored. <tvmin> is returned. This function has been
487 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
488 */
489#define tv_bound(tv1, tv2) ({ \
490 if (tv_isbefore(tv2, tv1)) \
491 *tv1 = *tv2; \
492 tv1; \
493})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494
Willy Tarreauc8f24f82007-11-30 18:38:35 +0100495char *human_time(int t, short hz_div);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200497#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498
499/*
500 * Local variables:
501 * c-indent-level: 8
502 * c-basic-offset: 8
503 * End:
504 */