blob: 75f385ef812f7f7c77c987dab197f3ef03d25b10 [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 Tarreau2dd0d472006-06-29 17:53:05 +020016#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020017
18struct timeval now; /* the current date at any moment */
19struct timeval start_date; /* the process's start date */
20
21/*
22 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
23 */
Willy Tarreaufb278672006-10-15 15:38:50 +020024REGPRM3 struct timeval *tv_delayfrom(struct timeval *tv, const struct timeval *from, int ms)
Willy Tarreaubaaee002006-06-26 02:48:02 +020025{
26 if (!tv || !from)
27 return NULL;
28 tv->tv_usec = from->tv_usec + (ms%1000)*1000;
29 tv->tv_sec = from->tv_sec + (ms/1000);
30 while (tv->tv_usec >= 1000000) {
31 tv->tv_usec -= 1000000;
32 tv->tv_sec++;
33 }
34 return tv;
35}
36
37/*
38 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
39 * Must not be used when either argument is eternity. Use tv_cmp2_ms() for that.
40 */
Willy Tarreaufb278672006-10-15 15:38:50 +020041REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020042{
43 if (tv1->tv_sec == tv2->tv_sec) {
44 if (tv2->tv_usec >= tv1->tv_usec + 1000)
45 return -1;
46 else if (tv1->tv_usec >= tv2->tv_usec + 1000)
47 return 1;
48 else
49 return 0;
50 }
51 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
52 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
53 return -1;
54 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
55 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
56 return 1;
57 else
58 return 0;
59}
60
61/*
62 * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
63 * considering that 0 is the eternity.
64 */
Willy Tarreaufb278672006-10-15 15:38:50 +020065REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020066{
67 if (tv_iseternity(tv1))
68 if (tv_iseternity(tv2))
69 return 0; /* same */
70 else
71 return 1; /* tv1 later than tv2 */
72 else if (tv_iseternity(tv2))
73 return -1; /* tv2 later than tv1 */
74
75 if (tv1->tv_sec > tv2->tv_sec)
76 return 1;
77 else if (tv1->tv_sec < tv2->tv_sec)
78 return -1;
79 else if (tv1->tv_usec > tv2->tv_usec)
80 return 1;
81 else if (tv1->tv_usec < tv2->tv_usec)
82 return -1;
83 else
84 return 0;
85}
86
87/*
88 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
89 * considering that 0 is the eternity.
90 */
Willy Tarreaufb278672006-10-15 15:38:50 +020091REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +020092{
93 if (tv_iseternity(tv1))
94 if (tv_iseternity(tv2))
95 return 0; /* same */
96 else
97 return 1; /* tv1 later than tv2 */
98 else if (tv_iseternity(tv2))
99 return -1; /* tv2 later than tv1 */
100
101 if (tv1->tv_sec == tv2->tv_sec) {
102 if (tv1->tv_usec >= tv2->tv_usec + 1000)
103 return 1;
104 else if (tv2->tv_usec >= tv1->tv_usec + 1000)
105 return -1;
106 else
107 return 0;
108 }
109 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
110 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
111 return 1;
112 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
113 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
114 return -1;
115 else
116 return 0;
117}
118
119/*
120 * returns the remaining time between tv1=now and event=tv2
121 * if tv2 is passed, 0 is returned.
122 * Returns TIME_ETERNITY if tv2 is eternity.
123 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200124REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200125{
126 unsigned long ret;
127
128 if (tv_iseternity(tv2))
129 return TIME_ETERNITY;
130
131 if (tv_cmp_ms(tv1, tv2) >= 0)
132 return 0; /* event elapsed */
133
134 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
135 if (tv2->tv_usec > tv1->tv_usec)
136 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
137 else
138 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
139 return (unsigned long) ret;
140}
141
142
143/*
144 * returns the absolute difference, in ms, between tv1 and tv2
145 * Must not be used when either argument is eternity.
146 */
Willy Tarreaufb278672006-10-15 15:38:50 +0200147REGPRM2 unsigned long tv_delta(const struct timeval *tv1, const struct timeval *tv2)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200148{
149 int cmp;
150 unsigned long ret;
151
152
153 cmp = tv_cmp(tv1, tv2);
154 if (!cmp)
155 return 0; /* same dates, null diff */
156 else if (cmp < 0) {
Willy Tarreaub17916e2006-10-15 15:17:57 +0200157 const struct timeval *tmp = tv1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158 tv1 = tv2;
159 tv2 = tmp;
160 }
161 ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
162 if (tv1->tv_usec > tv2->tv_usec)
163 ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
164 else
165 ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;
166 return (unsigned long) ret;
167}
168
169/*
170 * Local variables:
171 * c-indent-level: 8
172 * c-basic-offset: 8
173 * End:
174 */