Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : /* Generic implementation of time calls. */
35 :
36 : #include <grpc/support/time.h>
37 : #include <limits.h>
38 : #include <stdio.h>
39 : #include <string.h>
40 : #include <grpc/support/log.h>
41 :
42 72060920 : int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
43 72060920 : int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
44 72060920 : GPR_ASSERT(a.clock_type == b.clock_type);
45 72060920 : if (cmp == 0) {
46 24255484 : cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
47 : }
48 72060920 : return cmp;
49 : }
50 :
51 6929962 : gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) {
52 6929962 : return gpr_time_cmp(a, b) < 0 ? a : b;
53 : }
54 :
55 264050 : gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) {
56 264050 : return gpr_time_cmp(a, b) > 0 ? a : b;
57 : }
58 :
59 : /* There's no standard TIME_T_MIN and TIME_T_MAX, so we construct them. The
60 : following assumes that signed types are two's-complement and that bytes are
61 : 8 bits. */
62 :
63 : /* The top bit of integral type t. */
64 : #define TOP_BIT_OF_TYPE(t) (((gpr_uintmax)1) << ((8 * sizeof(t)) - 1))
65 :
66 : /* Return whether integral type t is signed. */
67 : #define TYPE_IS_SIGNED(t) (((t)1) > (t) ~(t)0)
68 :
69 : /* The minimum and maximum value of integral type t. */
70 : #define TYPE_MIN(t) ((t)(TYPE_IS_SIGNED(t) ? TOP_BIT_OF_TYPE(t) : 0))
71 : #define TYPE_MAX(t) \
72 : ((t)(TYPE_IS_SIGNED(t) ? (TOP_BIT_OF_TYPE(t) - 1) \
73 : : ((TOP_BIT_OF_TYPE(t) - 1) << 1) + 1))
74 :
75 201226 : gpr_timespec gpr_time_0(gpr_clock_type type) {
76 : gpr_timespec out;
77 201226 : out.tv_sec = 0;
78 201226 : out.tv_nsec = 0;
79 201226 : out.clock_type = type;
80 201226 : return out;
81 : }
82 :
83 81972470 : gpr_timespec gpr_inf_future(gpr_clock_type type) {
84 : gpr_timespec out;
85 81937874 : out.tv_sec = TYPE_MAX(time_t);
86 81937874 : out.tv_nsec = 0;
87 81937874 : out.clock_type = type;
88 81972470 : return out;
89 : }
90 :
91 128017 : gpr_timespec gpr_inf_past(gpr_clock_type type) {
92 : gpr_timespec out;
93 128011 : out.tv_sec = TYPE_MIN(time_t);
94 128011 : out.tv_nsec = 0;
95 128011 : out.clock_type = type;
96 128017 : return out;
97 : }
98 :
99 : /* TODO(ctiller): consider merging _nanos, _micros, _millis into a single
100 : function for maintainability. Similarly for _seconds, _minutes, and _hours */
101 :
102 3229243 : gpr_timespec gpr_time_from_nanos(long ns, gpr_clock_type type) {
103 : gpr_timespec result;
104 3228076 : result.clock_type = type;
105 3229243 : if (ns == LONG_MAX) {
106 0 : result = gpr_inf_future(type);
107 3229243 : } else if (ns == LONG_MIN) {
108 0 : result = gpr_inf_past(type);
109 3229243 : } else if (ns >= 0) {
110 3229231 : result.tv_sec = ns / GPR_NS_PER_SEC;
111 3229231 : result.tv_nsec = (int)(ns - result.tv_sec * GPR_NS_PER_SEC);
112 : } else {
113 : /* Calculation carefully formulated to avoid any possible under/overflow. */
114 12 : result.tv_sec = (-(999999999 - (ns + GPR_NS_PER_SEC)) / GPR_NS_PER_SEC) - 1;
115 12 : result.tv_nsec = (int)(ns - result.tv_sec * GPR_NS_PER_SEC);
116 : }
117 3229247 : return result;
118 : }
119 :
120 4842613 : gpr_timespec gpr_time_from_micros(long us, gpr_clock_type type) {
121 : gpr_timespec result;
122 4841401 : result.clock_type = type;
123 4842613 : if (us == LONG_MAX) {
124 0 : result = gpr_inf_future(type);
125 4842613 : } else if (us == LONG_MIN) {
126 0 : result = gpr_inf_past(type);
127 4842613 : } else if (us >= 0) {
128 4198999 : result.tv_sec = us / 1000000;
129 4198999 : result.tv_nsec = (int)((us - result.tv_sec * 1000000) * 1000);
130 : } else {
131 : /* Calculation carefully formulated to avoid any possible under/overflow. */
132 643614 : result.tv_sec = (-(999999 - (us + 1000000)) / 1000000) - 1;
133 643614 : result.tv_nsec = (int)((us - result.tv_sec * 1000000) * 1000);
134 : }
135 4842759 : return result;
136 : }
137 :
138 2394715 : gpr_timespec gpr_time_from_millis(long ms, gpr_clock_type type) {
139 : gpr_timespec result;
140 2394714 : result.clock_type = type;
141 2394715 : if (ms == LONG_MAX) {
142 0 : result = gpr_inf_future(type);
143 2394715 : } else if (ms == LONG_MIN) {
144 0 : result = gpr_inf_past(type);
145 2394715 : } else if (ms >= 0) {
146 2394439 : result.tv_sec = ms / 1000;
147 2394439 : result.tv_nsec = (int)((ms - result.tv_sec * 1000) * 1000000);
148 : } else {
149 : /* Calculation carefully formulated to avoid any possible under/overflow. */
150 276 : result.tv_sec = (-(999 - (ms + 1000)) / 1000) - 1;
151 276 : result.tv_nsec = (int)((ms - result.tv_sec * 1000) * 1000000);
152 : }
153 2394715 : return result;
154 : }
155 :
156 18996 : gpr_timespec gpr_time_from_seconds(long s, gpr_clock_type type) {
157 : gpr_timespec result;
158 18750 : result.clock_type = type;
159 18996 : if (s == LONG_MAX) {
160 0 : result = gpr_inf_future(type);
161 18996 : } else if (s == LONG_MIN) {
162 0 : result = gpr_inf_past(type);
163 : } else {
164 18750 : result.tv_sec = s;
165 18750 : result.tv_nsec = 0;
166 : }
167 18996 : return result;
168 : }
169 :
170 138 : gpr_timespec gpr_time_from_minutes(long m, gpr_clock_type type) {
171 : gpr_timespec result;
172 138 : result.clock_type = type;
173 138 : if (m >= LONG_MAX / 60) {
174 0 : result = gpr_inf_future(type);
175 138 : } else if (m <= LONG_MIN / 60) {
176 0 : result = gpr_inf_past(type);
177 : } else {
178 138 : result.tv_sec = m * 60;
179 138 : result.tv_nsec = 0;
180 : }
181 138 : return result;
182 : }
183 :
184 143 : gpr_timespec gpr_time_from_hours(long h, gpr_clock_type type) {
185 : gpr_timespec result;
186 143 : result.clock_type = type;
187 143 : if (h >= LONG_MAX / 3600) {
188 0 : result = gpr_inf_future(type);
189 143 : } else if (h <= LONG_MIN / 3600) {
190 0 : result = gpr_inf_past(type);
191 : } else {
192 143 : result.tv_sec = h * 3600;
193 143 : result.tv_nsec = 0;
194 : }
195 143 : return result;
196 : }
197 :
198 14137105 : gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
199 : gpr_timespec sum;
200 14134196 : int inc = 0;
201 14137105 : GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
202 14134196 : sum.clock_type = a.clock_type;
203 14137105 : sum.tv_nsec = a.tv_nsec + b.tv_nsec;
204 14137105 : if (sum.tv_nsec >= GPR_NS_PER_SEC) {
205 3443429 : sum.tv_nsec -= GPR_NS_PER_SEC;
206 3443383 : inc++;
207 : }
208 14137105 : if (a.tv_sec == TYPE_MAX(time_t) || a.tv_sec == TYPE_MIN(time_t)) {
209 111959 : sum = a;
210 28047882 : } else if (b.tv_sec == TYPE_MAX(time_t) ||
211 27686172 : (b.tv_sec >= 0 && a.tv_sec >= TYPE_MAX(time_t) - b.tv_sec)) {
212 1652 : sum = gpr_inf_future(sum.clock_type);
213 28044079 : } else if (b.tv_sec == TYPE_MIN(time_t) ||
214 24390415 : (b.tv_sec <= 0 && a.tv_sec <= TYPE_MIN(time_t) - b.tv_sec)) {
215 0 : sum = gpr_inf_past(sum.clock_type);
216 : } else {
217 14024245 : sum.tv_sec = a.tv_sec + b.tv_sec;
218 14024245 : if (inc != 0 && sum.tv_sec == TYPE_MAX(time_t) - 1) {
219 0 : sum = gpr_inf_future(sum.clock_type);
220 : } else {
221 14024245 : sum.tv_sec += inc;
222 : }
223 : }
224 14135529 : return sum;
225 : }
226 :
227 8985944 : gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
228 : gpr_timespec diff;
229 8984538 : int dec = 0;
230 8985944 : if (b.clock_type == GPR_TIMESPAN) {
231 325663 : diff.clock_type = a.clock_type;
232 : } else {
233 8660281 : GPR_ASSERT(a.clock_type == b.clock_type);
234 8658875 : diff.clock_type = GPR_TIMESPAN;
235 : }
236 8985944 : diff.tv_nsec = a.tv_nsec - b.tv_nsec;
237 8985944 : if (diff.tv_nsec < 0) {
238 7149568 : diff.tv_nsec += GPR_NS_PER_SEC;
239 7149338 : dec++;
240 : }
241 8985944 : if (a.tv_sec == TYPE_MAX(time_t) || a.tv_sec == TYPE_MIN(time_t)) {
242 937 : diff = a;
243 17968613 : } else if (b.tv_sec == TYPE_MIN(time_t) ||
244 9248140 : (b.tv_sec <= 0 && a.tv_sec >= TYPE_MAX(time_t) + b.tv_sec)) {
245 209 : diff = gpr_inf_future(GPR_CLOCK_REALTIME);
246 17968183 : } else if (b.tv_sec == TYPE_MAX(time_t) ||
247 17807717 : (b.tv_sec >= 0 && a.tv_sec <= TYPE_MIN(time_t) + b.tv_sec)) {
248 2888 : diff = gpr_inf_past(GPR_CLOCK_REALTIME);
249 : } else {
250 8981903 : diff.tv_sec = a.tv_sec - b.tv_sec;
251 8981903 : if (dec != 0 && diff.tv_sec == TYPE_MIN(time_t) + 1) {
252 0 : diff = gpr_inf_past(GPR_CLOCK_REALTIME);
253 : } else {
254 8981903 : diff.tv_sec -= dec;
255 : }
256 : }
257 8986891 : return diff;
258 : }
259 :
260 9 : int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) {
261 : int cmp_ab;
262 :
263 9 : GPR_ASSERT(a.clock_type == b.clock_type);
264 9 : GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN);
265 :
266 9 : cmp_ab = gpr_time_cmp(a, b);
267 9 : if (cmp_ab == 0) return 1;
268 6 : if (cmp_ab < 0) {
269 3 : return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0;
270 : } else {
271 3 : return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0;
272 : }
273 : }
274 :
275 3233226 : gpr_int32 gpr_time_to_millis(gpr_timespec t) {
276 3233226 : if (t.tv_sec >= 2147483) {
277 3889 : if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) {
278 0 : return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS;
279 : }
280 3801 : return 2147483647;
281 3229337 : } else if (t.tv_sec <= -2147483) {
282 : /* TODO(ctiller): correct handling here (it's so far in the past do we
283 : care?) */
284 0 : return -2147483647;
285 : } else {
286 3229337 : return (gpr_int32)(t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS);
287 : }
288 : }
289 :
290 0 : double gpr_timespec_to_micros(gpr_timespec t) {
291 0 : return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3;
292 : }
293 :
294 12547803 : gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
295 12547803 : if (t.clock_type == clock_type) {
296 2909695 : return t;
297 : }
298 :
299 9638108 : if (t.tv_nsec == 0) {
300 6523787 : if (t.tv_sec == TYPE_MAX(time_t)) {
301 6321357 : t.clock_type = clock_type;
302 6322204 : return t;
303 : }
304 201583 : if (t.tv_sec == TYPE_MIN(time_t)) {
305 364 : t.clock_type = clock_type;
306 365 : return t;
307 : }
308 : }
309 :
310 3315539 : if (clock_type == GPR_TIMESPAN) {
311 0 : return gpr_time_sub(t, gpr_now(t.clock_type));
312 : }
313 :
314 3315539 : if (t.clock_type == GPR_TIMESPAN) {
315 0 : return gpr_time_add(gpr_now(clock_type), t);
316 : }
317 :
318 3315539 : return gpr_time_add(gpr_now(clock_type),
319 : gpr_time_sub(t, gpr_now(t.clock_type)));
320 : }
|