blob: c1465047174ac4065abedc8c5b33a75060929271 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Time calculation functions.
3 *
4 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <sys/time.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020014
15#include <common/config.h>
Willy Tarreau5e8f0662007-02-12 00:59:08 +010016#include <common/standard.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020017#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020018
19struct timeval now; /* the current date at any moment */
20struct timeval start_date; /* the process's start date */
21
22/*
23 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
24 */
Willy Tarreaufb278672006-10-15 15:38:50 +020025REGPRM3 struct timeval *tv_delayfrom(struct timeval *tv, const struct timeval *from, int ms)
Willy Tarreaubaaee002006-06-26 02:48:02 +020026{
27 if (!tv || !from)
28 return NULL;
29 tv->tv_usec = from->tv_usec + (ms%1000)*1000;
30 tv->tv_sec = from->tv_sec + (ms/1000);
31 while (tv->tv_usec >= 1000000) {
32 tv->tv_usec -= 1000000;
33 tv->tv_sec++;
34 }
35 return tv;
36}
37
38/*
39 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
40 * Must not be used when either argument is eternity. Use tv_cmp2_ms() for that.
41 */
Willy Tarreaufb278672006-10-15 15:38:50 +020042REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020043{
Willy Tarreaua6a6a932007-04-28 22:40:08 +020044 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
45 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
Willy Tarreaubaaee002006-06-26 02:48:02 +020046 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020047 else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
Willy Tarreaubaaee002006-06-26 02:48:02 +020048 return 1;
49 else
50 return 0;
51 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +020052 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
53 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
54 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020055 return -1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020056 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
57 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
58 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020059 return 1;
60 else
61 return 0;
62}
63
64/*
Willy Tarreaubaaee002006-06-26 02:48:02 +020065 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
Willy Tarreaua6a6a932007-04-28 22:40:08 +020066 * assuming that TV_ETERNITY is greater than everything.
Willy Tarreaubaaee002006-06-26 02:48:02 +020067 */
Willy Tarreaufb278672006-10-15 15:38:50 +020068REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020069{
70 if (tv_iseternity(tv1))
71 if (tv_iseternity(tv2))
72 return 0; /* same */
73 else
74 return 1; /* tv1 later than tv2 */
75 else if (tv_iseternity(tv2))
76 return -1; /* tv2 later than tv1 */
77
Willy Tarreaua6a6a932007-04-28 22:40:08 +020078 if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
79 if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
Willy Tarreaubaaee002006-06-26 02:48:02 +020080 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020081 else if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
Willy Tarreaubaaee002006-06-26 02:48:02 +020082 return -1;
83 else
84 return 0;
85 }
Willy Tarreaua6a6a932007-04-28 22:40:08 +020086 else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
87 (((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
88 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020089 return 1;
Willy Tarreaua6a6a932007-04-28 22:40:08 +020090 else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
91 (((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
92 ((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020093 return -1;
94 else
95 return 0;
Willy Tarreau8d7d1492007-04-29 10:50:43 +020096}
97
98/*
99 * compares <tv1> and <tv2> modulo 1 ms: returns 1 if tv1 <= tv2, 0 if tv1 > tv2,
100 * assuming that TV_ETERNITY is greater than everything. Returns 0 if tv1 is
101 * TV_ETERNITY, and always assumes that tv2 != TV_ETERNITY. Designed to replace
102 * occurrences of (tv_cmp2_ms(tv,now) <= 0).
103 */
104REGPRM2 int tv_cmp2_le(const struct timeval *tv1, const struct timeval *tv2)
105{
106 if (likely((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1))
107 return 0;
108
109 if (likely((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec))
110 return 1;
111
112 if (likely((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec)) {
113 if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
114 return 1;
115 else
116 return 0;
117 }
118
119 if (unlikely(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
120 ((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
121 return 0;
122 else
123 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200124}
125
126/*
127 * returns the remaining time between tv1=now and event=tv2
128 * if tv2 is passed, 0 is returned.
129 * Returns TIME_ETERNITY if tv2 is eternity.
130 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200131REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132{
133 unsigned long ret;
134
135 if (tv_iseternity(tv2))
136 return TIME_ETERNITY;
137
138 if (tv_cmp_ms(tv1, tv2) >= 0)
139 return 0; /* event elapsed */
140
141 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200142 if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
144 else
145 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
146 return (unsigned long) ret;
147}
148
149
150/*
151 * returns the absolute difference, in ms, between tv1 and tv2
152 * Must not be used when either argument is eternity.
153 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200154REGPRM2 unsigned long tv_delta(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155{
156 int cmp;
157 unsigned long ret;
158
159
160 cmp = tv_cmp(tv1, tv2);
161 if (!cmp)
162 return 0; /* same dates, null diff */
163 else if (cmp < 0) {
Willy Tarreaub17916e2006-10-15 15:17:57 +0200164 const struct timeval *tmp = tv1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165 tv1 = tv2;
166 tv2 = tmp;
167 }
168 ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
Willy Tarreaua6a6a932007-04-28 22:40:08 +0200169 if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170 ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
171 else
172 ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;
173 return (unsigned long) ret;
174}
175
176/*
177 * Local variables:
178 * c-indent-level: 8
179 * c-basic-offset: 8
180 * End:
181 */