blob: 3d81759d11754a69a661f25d3b9771e5eb67c764 [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
5 Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
6
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 Tarreaubaaee002006-06-26 02:48:02 +020028
Willy Tarreaua6a6a932007-04-28 22:40:08 +020029/* eternity when exprimed in timeval */
30#ifndef TV_ETERNITY
31#define TV_ETERNITY (~0UL)
32#endif
33
34/* eternity when exprimed in ms */
35#ifndef TV_ETERNITY_MS
36#define TV_ETERNITY_MS (-1)
37#endif
38
39#define TIME_ETERNITY (TV_ETERNITY_MS)
40
Willy Tarreaubaaee002006-06-26 02:48:02 +020041
42/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
43#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
44#define SETNOW(a) (*a=now)
45
46extern struct timeval now; /* the current date at any moment */
47extern struct timeval start_date; /* the process's start date */
48
49
50/*
51 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
52 */
Willy Tarreaufb278672006-10-15 15:38:50 +020053REGPRM3 struct timeval *tv_delayfrom(struct timeval *tv, const struct timeval *from, int ms);
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
55/*
56 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
57 * Must not be used when either argument is eternity. Use tv_cmp2_ms() for that.
58 */
Willy Tarreaufb278672006-10-15 15:38:50 +020059REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020060
61/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020062 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
63 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020064 */
Willy Tarreau8d7d1492007-04-29 10:50:43 +020065REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreau5e8f0662007-02-12 00:59:08 +010066
Willy Tarreaubaaee002006-06-26 02:48:02 +020067/*
Willy Tarreau8d7d1492007-04-29 10:50:43 +020068 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
69 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
70 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
71 * occurrences of (tv_cmp2_ms(tv,now) <= 0).
Willy Tarreaubaaee002006-06-26 02:48:02 +020072 */
Willy Tarreau8d7d1492007-04-29 10:50:43 +020073REGPRM2 int tv_cmp2_le(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020074
75/*
76 * returns the remaining time between tv1=now and event=tv2
77 * if tv2 is passed, 0 is returned.
78 * Returns TIME_ETERNITY if tv2 is eternity.
79 */
Willy Tarreaufb278672006-10-15 15:38:50 +020080REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2);
Willy Tarreaubaaee002006-06-26 02:48:02 +020081
Willy Tarreaubaaee002006-06-26 02:48:02 +020082/* sets <tv> to the current time */
Willy Tarreaufb278672006-10-15 15:38:50 +020083REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +020084{
85 if (tv)
86 gettimeofday(tv, NULL);
87 return tv;
88}
89
90/*
91 * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
Willy Tarreaubaaee002006-06-26 02:48:02 +020092 */
Willy Tarreaufb278672006-10-15 15:38:50 +020093REGPRM2 static inline int tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020094{
Willy Tarreaua6a6a932007-04-28 22:40:08 +020095 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +020096 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020097 else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreaubaaee002006-06-26 02:48:02 +020098 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020099 else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200100 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200101 else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200102 return 1;
103 else
104 return 0;
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100105}
106
107/*
108 * compares <tv1> and <tv2> : returns 0 if tv1 < tv2, 1 if tv1 >= tv2
109 */
110REGPRM2 static inline int tv_cmp_ge(const struct timeval *tv1, const struct timeval *tv2)
111{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200112 if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100113 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200114 if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100115 return 0;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200116 if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec)
Willy Tarreau5e8f0662007-02-12 00:59:08 +0100117 return 1;
118 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200119}
120
121/*
122 * returns the difference, in ms, between tv1 and tv2
123 * Must not be used when either argument is eternity.
124 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200125REGPRM2 static inline unsigned long tv_diff(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126{
127 unsigned long ret;
128
129 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200130 if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200131 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
132 else
133 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
134 return (unsigned long) ret;
135}
136
137/*
138 * returns the remaining time between tv1=now and event=tv2
139 * if tv2 is passed, 0 is returned.
140 * Must not be used when either argument is eternity.
141 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200142REGPRM2 static inline unsigned long tv_remain(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143{
144 unsigned long ret;
145
146 if (tv_cmp_ms(tv1, tv2) >= 0)
147 return 0; /* event elapsed */
148
149 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200150 if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
152 else
153 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
154 return (unsigned long) ret;
155}
156
157
158/*
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200159 * sets a struct timeval to its highest value so that it can never happen
160 * note that only tv_usec is necessary to detect it since a tv_usec > 999999
161 * is normally not possible.
162 *
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 */
164
Willy Tarreaufb278672006-10-15 15:38:50 +0200165REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166{
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200167 tv->tv_sec = tv->tv_usec = TV_ETERNITY;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168 return tv;
169}
170
171/*
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200172 * sets a struct timeval to 0
173 *
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174 */
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200175REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
176 tv->tv_sec = tv->tv_usec = 0;
177 return tv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178}
179
180/*
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200181 * returns non null if tv is [eternity], otherwise 0.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 */
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200183#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200185/*
186 * returns non null if tv is [0], otherwise 0.
187 */
188#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200190/*
191 * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
192 * This should be very fast because it's used in schedulers.
193 * It has been optimized to return 1 (so call it in a loop which continues
194 * as long as tv1<=tv2)
195 */
196
197#define tv_isbefore(tv1, tv2) \
198 (unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
199 (unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
200 unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
201
202/*
203 * returns the first event between <tv1> and <tv2> into <tvmin>.
204 * a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
205 * to be the same as <tv1> or <tv2>, it is recommended to use
206 * tv_bound instead.
207 */
208#define tv_min(tvmin, tv1, tv2) ({ \
209 if (tv_isbefore(tv1, tv2)) { \
210 *tvmin = *tv1; \
211 } \
212 else { \
213 *tvmin = *tv2; \
214 } \
215 tvmin; \
216})
217
218/*
219 * returns the first event between <tv1> and <tv2> into <tvmin>.
220 * a zero tv is ignored. <tvmin> is returned. This function has been
221 * optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
222 */
223#define tv_bound(tv1, tv2) ({ \
224 if (tv_isbefore(tv2, tv1)) \
225 *tv1 = *tv2; \
226 tv1; \
227})
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
229
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200230#endif /* _COMMON_TIME_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
232/*
233 * Local variables:
234 * c-indent-level: 8
235 * c-basic-offset: 8
236 * End:
237 */