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 63432453 : int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
43 63432453 : int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
44 63432453 : GPR_ASSERT(a.clock_type == b.clock_type);
45 63432453 : if (cmp == 0) {
46 23314376 : cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
47 : }
48 63432453 : return cmp;
49 : }
50 :
51 9057296 : gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) {
52 9057296 : return gpr_time_cmp(a, b) < 0 ? a : b;
53 : }
54 :
55 190963 : gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) {
56 190963 : 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 101861 : gpr_timespec gpr_time_0(gpr_clock_type type) {
76 : gpr_timespec out;
77 101861 : out.tv_sec = 0;
78 101861 : out.tv_nsec = 0;
79 101861 : out.clock_type = type;
80 101861 : return out;
81 : }
82 :
83 51780478 : gpr_timespec gpr_inf_future(gpr_clock_type type) {
84 : gpr_timespec out;
85 51780478 : out.tv_sec = TYPE_MAX(time_t);
86 51780478 : out.tv_nsec = 0;
87 51780478 : out.clock_type = type;
88 51780478 : return out;
89 : }
90 :
91 51438 : gpr_timespec gpr_inf_past(gpr_clock_type type) {
92 : gpr_timespec out;
93 51438 : out.tv_sec = TYPE_MIN(time_t);
94 51438 : out.tv_nsec = 0;
95 51438 : out.clock_type = type;
96 51438 : 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 2629632 : gpr_timespec gpr_time_from_nanos(long ns, gpr_clock_type type) {
103 : gpr_timespec result;
104 2629632 : result.clock_type = type;
105 2629632 : if (ns == LONG_MAX) {
106 0 : result = gpr_inf_future(type);
107 2629632 : } else if (ns == LONG_MIN) {
108 0 : result = gpr_inf_past(type);
109 2629632 : } else if (ns >= 0) {
110 2629620 : result.tv_sec = ns / GPR_NS_PER_SEC;
111 2629620 : 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 2629645 : return result;
118 : }
119 :
120 6322200 : gpr_timespec gpr_time_from_micros(long us, gpr_clock_type type) {
121 : gpr_timespec result;
122 6322200 : result.clock_type = type;
123 6322200 : if (us == LONG_MAX) {
124 0 : result = gpr_inf_future(type);
125 6322200 : } else if (us == LONG_MIN) {
126 0 : result = gpr_inf_past(type);
127 6322200 : } else if (us >= 0) {
128 5678586 : result.tv_sec = us / 1000000;
129 5678586 : 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 6324683 : return result;
136 : }
137 :
138 273233 : gpr_timespec gpr_time_from_millis(long ms, gpr_clock_type type) {
139 : gpr_timespec result;
140 273233 : result.clock_type = type;
141 273233 : if (ms == LONG_MAX) {
142 0 : result = gpr_inf_future(type);
143 273233 : } else if (ms == LONG_MIN) {
144 0 : result = gpr_inf_past(type);
145 273233 : } else if (ms >= 0) {
146 273106 : result.tv_sec = ms / 1000;
147 273106 : result.tv_nsec = (int)((ms - result.tv_sec * 1000) * 1000000);
148 : } else {
149 : /* Calculation carefully formulated to avoid any possible under/overflow. */
150 127 : result.tv_sec = (-(999 - (ms + 1000)) / 1000) - 1;
151 127 : result.tv_nsec = (int)((ms - result.tv_sec * 1000) * 1000000);
152 : }
153 273233 : return result;
154 : }
155 :
156 15425 : gpr_timespec gpr_time_from_seconds(long s, gpr_clock_type type) {
157 : gpr_timespec result;
158 15425 : result.clock_type = type;
159 15425 : if (s == LONG_MAX) {
160 0 : result = gpr_inf_future(type);
161 15425 : } else if (s == LONG_MIN) {
162 0 : result = gpr_inf_past(type);
163 : } else {
164 15425 : result.tv_sec = s;
165 15425 : result.tv_nsec = 0;
166 : }
167 15425 : 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 150 : gpr_timespec gpr_time_from_hours(long h, gpr_clock_type type) {
185 : gpr_timespec result;
186 150 : result.clock_type = type;
187 150 : if (h >= LONG_MAX / 3600) {
188 0 : result = gpr_inf_future(type);
189 150 : } else if (h <= LONG_MIN / 3600) {
190 0 : result = gpr_inf_past(type);
191 : } else {
192 150 : result.tv_sec = h * 3600;
193 150 : result.tv_nsec = 0;
194 : }
195 150 : return result;
196 : }
197 :
198 13119724 : gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
199 : gpr_timespec sum;
200 13119724 : int inc = 0;
201 13119724 : GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
202 13119724 : sum.clock_type = a.clock_type;
203 13119724 : sum.tv_nsec = a.tv_nsec + b.tv_nsec;
204 13119724 : if (sum.tv_nsec >= GPR_NS_PER_SEC) {
205 4591381 : sum.tv_nsec -= GPR_NS_PER_SEC;
206 4591381 : inc++;
207 : }
208 13119724 : if (a.tv_sec == TYPE_MAX(time_t) || a.tv_sec == TYPE_MIN(time_t)) {
209 81462 : sum = a;
210 26074174 : } else if (b.tv_sec == TYPE_MAX(time_t) ||
211 23072444 : (b.tv_sec >= 0 && a.tv_sec >= TYPE_MAX(time_t) - b.tv_sec)) {
212 18036 : sum = gpr_inf_future(sum.clock_type);
213 26040452 : } else if (b.tv_sec == TYPE_MIN(time_t) ||
214 25611306 : (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 13041732 : sum.tv_sec = a.tv_sec + b.tv_sec;
218 13041732 : if (inc != 0 && sum.tv_sec == TYPE_MAX(time_t) - 1) {
219 0 : sum = gpr_inf_future(sum.clock_type);
220 : } else {
221 13041732 : sum.tv_sec += inc;
222 : }
223 : }
224 13122392 : return sum;
225 : }
226 :
227 7648442 : gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
228 : gpr_timespec diff;
229 7648442 : int dec = 0;
230 7648442 : if (b.clock_type == GPR_TIMESPAN) {
231 331054 : diff.clock_type = a.clock_type;
232 : } else {
233 7317388 : GPR_ASSERT(a.clock_type == b.clock_type);
234 7317388 : diff.clock_type = GPR_TIMESPAN;
235 : }
236 7648442 : diff.tv_nsec = a.tv_nsec - b.tv_nsec;
237 7648442 : if (diff.tv_nsec < 0) {
238 4226349 : diff.tv_nsec += GPR_NS_PER_SEC;
239 4226349 : dec++;
240 : }
241 7648442 : if (a.tv_sec == TYPE_MAX(time_t) || a.tv_sec == TYPE_MIN(time_t)) {
242 814 : diff = a;
243 15297618 : } else if (b.tv_sec == TYPE_MIN(time_t) ||
244 7914515 : (b.tv_sec <= 0 && a.tv_sec >= TYPE_MAX(time_t) + b.tv_sec)) {
245 0 : diff = gpr_inf_future(GPR_CLOCK_REALTIME);
246 15298984 : } else if (b.tv_sec == TYPE_MAX(time_t) ||
247 15138351 : (b.tv_sec >= 0 && a.tv_sec <= TYPE_MIN(time_t) + b.tv_sec)) {
248 3085 : diff = gpr_inf_past(GPR_CLOCK_REALTIME);
249 : } else {
250 7646407 : diff.tv_sec = a.tv_sec - b.tv_sec;
251 7646407 : if (dec != 0 && diff.tv_sec == TYPE_MIN(time_t) + 1) {
252 0 : diff = gpr_inf_past(GPR_CLOCK_REALTIME);
253 : } else {
254 7646407 : diff.tv_sec -= dec;
255 : }
256 : }
257 7656897 : 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 2631055 : gpr_int32 gpr_time_to_millis(gpr_timespec t) {
276 2631055 : if (t.tv_sec >= 2147483) {
277 1470 : 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 1470 : return 2147483647;
281 2629585 : } 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 2629585 : 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 9840476 : gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
295 9840476 : if (t.clock_type == clock_type) {
296 293020 : return t;
297 : }
298 :
299 9547456 : if (t.tv_nsec == 0) {
300 4987563 : if (t.tv_sec == TYPE_MAX(time_t)) {
301 4885446 : t.clock_type = clock_type;
302 4885446 : return t;
303 : }
304 102117 : if (t.tv_sec == TYPE_MIN(time_t)) {
305 262 : t.clock_type = clock_type;
306 262 : return t;
307 : }
308 : }
309 :
310 4661748 : if (clock_type == GPR_TIMESPAN) {
311 0 : return gpr_time_sub(t, gpr_now(t.clock_type));
312 : }
313 :
314 4661748 : if (t.clock_type == GPR_TIMESPAN) {
315 0 : return gpr_time_add(gpr_now(clock_type), t);
316 : }
317 :
318 4661748 : return gpr_time_add(gpr_now(clock_type),
319 : gpr_time_sub(t, gpr_now(t.clock_type)));
320 : }
|