blob: 1c5732f3eb46307477ca2ccc97f0045e9fcfb3c6 [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{
44 if (tv1->tv_sec == tv2->tv_sec) {
45 if (tv2->tv_usec >= tv1->tv_usec + 1000)
46 return -1;
47 else if (tv1->tv_usec >= tv2->tv_usec + 1000)
48 return 1;
49 else
50 return 0;
51 }
52 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
53 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
54 return -1;
55 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
56 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
57 return 1;
58 else
59 return 0;
60}
61
62/*
Willy Tarreau5e8f0662007-02-12 00:59:08 +010063 * compares <tv1> and <tv2> : returns 0 if tv1 < tv2, 1 if tv1 >= tv2,
64 * considering that 0 is the eternity.
65 */
66REGPRM2 int tv_cmp_ge2(const struct timeval *tv1, const struct timeval *tv2)
67{
68 if (unlikely(tv_iseternity(tv1)))
69 return 1;
70 if (unlikely(tv_iseternity(tv2)))
71 return 0; /* same */
72
73 if (tv1->tv_sec > tv2->tv_sec)
74 return 1;
75 if (tv1->tv_sec < tv2->tv_sec)
76 return 0;
77 if (tv1->tv_usec >= tv2->tv_usec)
78 return 1;
79 return 0;
80}
81
82/*
Willy Tarreaubaaee002006-06-26 02:48:02 +020083 * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
84 * considering that 0 is the eternity.
85 */
Willy Tarreaufb278672006-10-15 15:38:50 +020086REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020087{
Willy Tarreau5e8f0662007-02-12 00:59:08 +010088 if (unlikely(tv_iseternity(tv1)))
89 if (unlikely(tv_iseternity(tv2)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020090 return 0; /* same */
91 else
92 return 1; /* tv1 later than tv2 */
Willy Tarreau5e8f0662007-02-12 00:59:08 +010093 else if (likely(tv_iseternity(tv2)))
Willy Tarreaubaaee002006-06-26 02:48:02 +020094 return -1; /* tv2 later than tv1 */
95
96 if (tv1->tv_sec > tv2->tv_sec)
97 return 1;
98 else if (tv1->tv_sec < tv2->tv_sec)
99 return -1;
100 else if (tv1->tv_usec > tv2->tv_usec)
101 return 1;
102 else if (tv1->tv_usec < tv2->tv_usec)
103 return -1;
104 else
105 return 0;
106}
107
108/*
109 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
110 * considering that 0 is the eternity.
111 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200112REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200113{
114 if (tv_iseternity(tv1))
115 if (tv_iseternity(tv2))
116 return 0; /* same */
117 else
118 return 1; /* tv1 later than tv2 */
119 else if (tv_iseternity(tv2))
120 return -1; /* tv2 later than tv1 */
121
122 if (tv1->tv_sec == tv2->tv_sec) {
123 if (tv1->tv_usec >= tv2->tv_usec + 1000)
124 return 1;
125 else if (tv2->tv_usec >= tv1->tv_usec + 1000)
126 return -1;
127 else
128 return 0;
129 }
130 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
131 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
132 return 1;
133 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
134 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
135 return -1;
136 else
137 return 0;
138}
139
140/*
141 * returns the remaining time between tv1=now and event=tv2
142 * if tv2 is passed, 0 is returned.
143 * Returns TIME_ETERNITY if tv2 is eternity.
144 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200145REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146{
147 unsigned long ret;
148
149 if (tv_iseternity(tv2))
150 return TIME_ETERNITY;
151
152 if (tv_cmp_ms(tv1, tv2) >= 0)
153 return 0; /* event elapsed */
154
155 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
156 if (tv2->tv_usec > tv1->tv_usec)
157 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
158 else
159 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
160 return (unsigned long) ret;
161}
162
163
164/*
165 * returns the absolute difference, in ms, between tv1 and tv2
166 * Must not be used when either argument is eternity.
167 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200168REGPRM2 unsigned long tv_delta(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169{
170 int cmp;
171 unsigned long ret;
172
173
174 cmp = tv_cmp(tv1, tv2);
175 if (!cmp)
176 return 0; /* same dates, null diff */
177 else if (cmp < 0) {
Willy Tarreaub17916e2006-10-15 15:17:57 +0200178 const struct timeval *tmp = tv1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179 tv1 = tv2;
180 tv2 = tmp;
181 }
182 ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
183 if (tv1->tv_usec > tv2->tv_usec)
184 ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
185 else
186 ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;
187 return (unsigned long) ret;
188}
189
190/*
191 * Local variables:
192 * c-indent-level: 8
193 * c-basic-offset: 8
194 * End:
195 */