blob: 6903674d7520763c264f66a8fa1141bd64cecd92 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
19/* Generic implementation of time calls. */
20
Craig Tillerf40df232016-03-25 13:38:14 -070021#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080022#include <grpc/support/time.h>
23#include <limits.h>
24#include <stdio.h>
25#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080026
27int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
28 int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
Craig Tiller143e7bf2015-07-13 08:41:49 -070029 GPR_ASSERT(a.clock_type == b.clock_type);
yang-g07429fa2017-03-29 10:57:31 -070030 if (cmp == 0 && a.tv_sec != INT64_MAX && a.tv_sec != INT64_MIN) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080031 cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
32 }
33 return cmp;
34}
35
ctiller3bf466f2014-12-19 16:21:57 -080036gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) {
37 return gpr_time_cmp(a, b) < 0 ? a : b;
38}
39
40gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) {
41 return gpr_time_cmp(a, b) > 0 ? a : b;
42}
43
Craig Tiller143e7bf2015-07-13 08:41:49 -070044gpr_timespec gpr_time_0(gpr_clock_type type) {
45 gpr_timespec out;
46 out.tv_sec = 0;
47 out.tv_nsec = 0;
48 out.clock_type = type;
49 return out;
50}
51
52gpr_timespec gpr_inf_future(gpr_clock_type type) {
53 gpr_timespec out;
Jan Tattermusch88086372015-12-10 10:54:12 -080054 out.tv_sec = INT64_MAX;
Craig Tiller143e7bf2015-07-13 08:41:49 -070055 out.tv_nsec = 0;
56 out.clock_type = type;
57 return out;
58}
59
60gpr_timespec gpr_inf_past(gpr_clock_type type) {
61 gpr_timespec out;
Jan Tattermusch88086372015-12-10 10:54:12 -080062 out.tv_sec = INT64_MIN;
Craig Tiller143e7bf2015-07-13 08:41:49 -070063 out.tv_nsec = 0;
64 out.clock_type = type;
65 return out;
66}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080067
thinkerou614e6f92016-07-09 10:11:28 +080068static gpr_timespec to_seconds_from_sub_second_time(int64_t time_in_units,
69 int64_t units_per_sec,
70 gpr_clock_type type) {
thinkeroud4c1abb2016-06-21 10:25:08 +080071 gpr_timespec out;
thinkerou614e6f92016-07-09 10:11:28 +080072 if (time_in_units == INT64_MAX) {
thinkeroud4c1abb2016-06-21 10:25:08 +080073 out = gpr_inf_future(type);
thinkerou614e6f92016-07-09 10:11:28 +080074 } else if (time_in_units == INT64_MIN) {
thinkeroud4c1abb2016-06-21 10:25:08 +080075 out = gpr_inf_past(type);
76 } else {
thinkerou614e6f92016-07-09 10:11:28 +080077 if (time_in_units >= 0) {
78 out.tv_sec = time_in_units / units_per_sec;
thinkeroud4c1abb2016-06-21 10:25:08 +080079 } else {
thinkeroub4338302016-07-09 10:40:44 +080080 out.tv_sec = (-((units_per_sec - 1) - (time_in_units + units_per_sec)) /
81 units_per_sec) -
82 1;
thinkeroud4c1abb2016-06-21 10:25:08 +080083 }
thinkerou614e6f92016-07-09 10:11:28 +080084 out.tv_nsec = (int32_t)((time_in_units - out.tv_sec * units_per_sec) *
85 GPR_NS_PER_SEC / units_per_sec);
thinkeroud4c1abb2016-06-21 10:25:08 +080086 out.clock_type = type;
87 }
88 return out;
89}
90
thinkerou614e6f92016-07-09 10:11:28 +080091static gpr_timespec to_seconds_from_above_second_time(int64_t time_in_units,
92 int64_t secs_per_unit,
93 gpr_clock_type type) {
thinkeroud4c1abb2016-06-21 10:25:08 +080094 gpr_timespec out;
thinkerou614e6f92016-07-09 10:11:28 +080095 if (time_in_units >= INT64_MAX / secs_per_unit) {
thinkeroud4c1abb2016-06-21 10:25:08 +080096 out = gpr_inf_future(type);
thinkerou614e6f92016-07-09 10:11:28 +080097 } else if (time_in_units <= INT64_MIN / secs_per_unit) {
thinkeroud4c1abb2016-06-21 10:25:08 +080098 out = gpr_inf_past(type);
99 } else {
thinkerou614e6f92016-07-09 10:11:28 +0800100 out.tv_sec = time_in_units * secs_per_unit;
thinkeroud4c1abb2016-06-21 10:25:08 +0800101 out.tv_nsec = 0;
102 out.clock_type = type;
103 }
104 return out;
105}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800106
murgatroid99309830f2016-02-05 11:30:00 -0800107gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800108 return to_seconds_from_sub_second_time(ns, GPR_NS_PER_SEC, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109}
110
murgatroid99309830f2016-02-05 11:30:00 -0800111gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800112 return to_seconds_from_sub_second_time(us, GPR_US_PER_SEC, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800113}
114
murgatroid99309830f2016-02-05 11:30:00 -0800115gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800116 return to_seconds_from_sub_second_time(ms, GPR_MS_PER_SEC, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800117}
118
murgatroid99309830f2016-02-05 11:30:00 -0800119gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800120 return to_seconds_from_sub_second_time(s, 1, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800121}
122
murgatroid99309830f2016-02-05 11:30:00 -0800123gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800124 return to_seconds_from_above_second_time(m, 60, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800125}
126
murgatroid99309830f2016-02-05 11:30:00 -0800127gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type type) {
thinkerou614e6f92016-07-09 10:11:28 +0800128 return to_seconds_from_above_second_time(h, 3600, type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129}
130
131gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
132 gpr_timespec sum;
Craig Tiller7536af02015-12-22 13:49:30 -0800133 int64_t inc = 0;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700134 GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
135 sum.clock_type = a.clock_type;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136 sum.tv_nsec = a.tv_nsec + b.tv_nsec;
Nicolas Noble65b07592015-02-23 15:28:04 -0800137 if (sum.tv_nsec >= GPR_NS_PER_SEC) {
138 sum.tv_nsec -= GPR_NS_PER_SEC;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800139 inc++;
140 }
Jan Tattermusch88086372015-12-10 10:54:12 -0800141 if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142 sum = a;
Jan Tattermusch88086372015-12-10 10:54:12 -0800143 } else if (b.tv_sec == INT64_MAX ||
144 (b.tv_sec >= 0 && a.tv_sec >= INT64_MAX - b.tv_sec)) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700145 sum = gpr_inf_future(sum.clock_type);
Jan Tattermusch88086372015-12-10 10:54:12 -0800146 } else if (b.tv_sec == INT64_MIN ||
147 (b.tv_sec <= 0 && a.tv_sec <= INT64_MIN - b.tv_sec)) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700148 sum = gpr_inf_past(sum.clock_type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800149 } else {
150 sum.tv_sec = a.tv_sec + b.tv_sec;
Jan Tattermusch88086372015-12-10 10:54:12 -0800151 if (inc != 0 && sum.tv_sec == INT64_MAX - 1) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700152 sum = gpr_inf_future(sum.clock_type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800153 } else {
154 sum.tv_sec += inc;
155 }
156 }
157 return sum;
158}
159
160gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
161 gpr_timespec diff;
Craig Tiller7536af02015-12-22 13:49:30 -0800162 int64_t dec = 0;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700163 if (b.clock_type == GPR_TIMESPAN) {
164 diff.clock_type = a.clock_type;
165 } else {
166 GPR_ASSERT(a.clock_type == b.clock_type);
167 diff.clock_type = GPR_TIMESPAN;
168 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800169 diff.tv_nsec = a.tv_nsec - b.tv_nsec;
170 if (diff.tv_nsec < 0) {
Nicolas Noble65b07592015-02-23 15:28:04 -0800171 diff.tv_nsec += GPR_NS_PER_SEC;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172 dec++;
173 }
Jan Tattermusch88086372015-12-10 10:54:12 -0800174 if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800175 diff = a;
Jan Tattermusch88086372015-12-10 10:54:12 -0800176 } else if (b.tv_sec == INT64_MIN ||
177 (b.tv_sec <= 0 && a.tv_sec >= INT64_MAX + b.tv_sec)) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700178 diff = gpr_inf_future(GPR_CLOCK_REALTIME);
Jan Tattermusch88086372015-12-10 10:54:12 -0800179 } else if (b.tv_sec == INT64_MAX ||
180 (b.tv_sec >= 0 && a.tv_sec <= INT64_MIN + b.tv_sec)) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700181 diff = gpr_inf_past(GPR_CLOCK_REALTIME);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800182 } else {
183 diff.tv_sec = a.tv_sec - b.tv_sec;
Jan Tattermusch88086372015-12-10 10:54:12 -0800184 if (dec != 0 && diff.tv_sec == INT64_MIN + 1) {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700185 diff = gpr_inf_past(GPR_CLOCK_REALTIME);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800186 } else {
187 diff.tv_sec -= dec;
188 }
189 }
190 return diff;
191}
192
193int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) {
194 int cmp_ab;
195
Craig Tiller143e7bf2015-07-13 08:41:49 -0700196 GPR_ASSERT(a.clock_type == b.clock_type);
197 GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN);
198
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199 cmp_ab = gpr_time_cmp(a, b);
200 if (cmp_ab == 0) return 1;
201 if (cmp_ab < 0) {
202 return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0;
203 } else {
204 return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0;
205 }
206}
207
Craig Tiller7536af02015-12-22 13:49:30 -0800208int32_t gpr_time_to_millis(gpr_timespec t) {
ctiller58393c22015-01-07 14:03:30 -0800209 if (t.tv_sec >= 2147483) {
210 if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) {
211 return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS;
212 }
213 return 2147483647;
214 } else if (t.tv_sec <= -2147483) {
215 /* TODO(ctiller): correct handling here (it's so far in the past do we
216 care?) */
Nicolas "Pixel" Noble6ba50fd2015-01-13 19:25:37 -0800217 return -2147483647;
ctiller58393c22015-01-07 14:03:30 -0800218 } else {
Craig Tiller7536af02015-12-22 13:49:30 -0800219 return (int32_t)(t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS);
ctiller58393c22015-01-07 14:03:30 -0800220 }
221}
hongyu24200d32015-01-08 15:13:49 -0800222
223double gpr_timespec_to_micros(gpr_timespec t) {
murgatroid995e71d7a2015-06-19 12:24:44 -0700224 return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3;
Craig Tiller190d3602015-02-18 09:23:38 -0800225}
Craig Tiller6a7626c2015-07-19 22:21:41 -0700226
227gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
228 if (t.clock_type == clock_type) {
229 return t;
230 }
231
yang-g1aba8692017-03-28 21:41:02 -0700232 if (t.tv_sec == INT64_MAX || t.tv_sec == INT64_MIN) {
233 t.clock_type = clock_type;
234 return t;
Craig Tiller6a7626c2015-07-19 22:21:41 -0700235 }
236
237 if (clock_type == GPR_TIMESPAN) {
238 return gpr_time_sub(t, gpr_now(t.clock_type));
239 }
240
241 if (t.clock_type == GPR_TIMESPAN) {
242 return gpr_time_add(gpr_now(clock_type), t);
243 }
244
Craig Tillerd6c98df2015-08-18 09:33:44 -0700245 return gpr_time_add(gpr_now(clock_type),
246 gpr_time_sub(t, gpr_now(t.clock_type)));
Craig Tiller6a7626c2015-07-19 22:21:41 -0700247}