1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * 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 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * 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. 16 * 17 */ 18 19 /* Generic implementation of time calls. */ 20 21 #include <grpc/support/port_platform.h> 22 23 #include <grpc/support/log.h> 24 #include <grpc/support/time.h> 25 #include <limits.h> 26 #include <stdio.h> 27 #include <string.h> 28 29 int gpr_time_cmp(gpr_timespec a, gpr_timespec b) { 30 int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec); 31 GPR_ASSERT(a.clock_type == b.clock_type); 32 if (cmp == 0 && a.tv_sec != INT64_MAX && a.tv_sec != INT64_MIN) { 33 cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec); 34 } 35 return cmp; 36 } 37 38 gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) { 39 return gpr_time_cmp(a, b) < 0 ? a : b; 40 } 41 42 gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) { 43 return gpr_time_cmp(a, b) > 0 ? a : b; 44 } 45 46 gpr_timespec gpr_time_0(gpr_clock_type type) { 47 gpr_timespec out; 48 out.tv_sec = 0; 49 out.tv_nsec = 0; 50 out.clock_type = type; 51 return out; 52 } 53 54 gpr_timespec gpr_inf_future(gpr_clock_type type) { 55 gpr_timespec out; 56 out.tv_sec = INT64_MAX; 57 out.tv_nsec = 0; 58 out.clock_type = type; 59 return out; 60 } 61 62 gpr_timespec gpr_inf_past(gpr_clock_type type) { 63 gpr_timespec out; 64 out.tv_sec = INT64_MIN; 65 out.tv_nsec = 0; 66 out.clock_type = type; 67 return out; 68 } 69 70 static gpr_timespec to_seconds_from_sub_second_time(int64_t time_in_units, 71 int64_t units_per_sec, 72 gpr_clock_type type) { 73 gpr_timespec out; 74 if (time_in_units == INT64_MAX) { 75 out = gpr_inf_future(type); 76 } else if (time_in_units == INT64_MIN) { 77 out = gpr_inf_past(type); 78 } else { 79 if (time_in_units >= 0) { 80 out.tv_sec = time_in_units / units_per_sec; 81 } else { 82 out.tv_sec = (-((units_per_sec - 1) - (time_in_units + units_per_sec)) / 83 units_per_sec) - 84 1; 85 } 86 out.tv_nsec = 87 static_cast<int32_t>((time_in_units - out.tv_sec * units_per_sec) * 88 GPR_NS_PER_SEC / units_per_sec); 89 out.clock_type = type; 90 } 91 return out; 92 } 93 94 static gpr_timespec to_seconds_from_above_second_time(int64_t time_in_units, 95 int64_t secs_per_unit, 96 gpr_clock_type type) { 97 gpr_timespec out; 98 if (time_in_units >= INT64_MAX / secs_per_unit) { 99 out = gpr_inf_future(type); 100 } else if (time_in_units <= INT64_MIN / secs_per_unit) { 101 out = gpr_inf_past(type); 102 } else { 103 out.tv_sec = time_in_units * secs_per_unit; 104 out.tv_nsec = 0; 105 out.clock_type = type; 106 } 107 return out; 108 } 109 110 gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type type) { 111 return to_seconds_from_sub_second_time(ns, GPR_NS_PER_SEC, type); 112 } 113 114 gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type type) { 115 return to_seconds_from_sub_second_time(us, GPR_US_PER_SEC, type); 116 } 117 118 gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) { 119 return to_seconds_from_sub_second_time(ms, GPR_MS_PER_SEC, type); 120 } 121 122 gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type type) { 123 return to_seconds_from_sub_second_time(s, 1, type); 124 } 125 126 gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type type) { 127 return to_seconds_from_above_second_time(m, 60, type); 128 } 129 130 gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type type) { 131 return to_seconds_from_above_second_time(h, 3600, type); 132 } 133 134 gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) { 135 gpr_timespec sum; 136 int64_t inc = 0; 137 GPR_ASSERT(b.clock_type == GPR_TIMESPAN); 138 sum.clock_type = a.clock_type; 139 sum.tv_nsec = a.tv_nsec + b.tv_nsec; 140 if (sum.tv_nsec >= GPR_NS_PER_SEC) { 141 sum.tv_nsec -= GPR_NS_PER_SEC; 142 inc++; 143 } 144 if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) { 145 sum = a; 146 } else if (b.tv_sec == INT64_MAX || 147 (b.tv_sec >= 0 && a.tv_sec >= INT64_MAX - b.tv_sec)) { 148 sum = gpr_inf_future(sum.clock_type); 149 } else if (b.tv_sec == INT64_MIN || 150 (b.tv_sec <= 0 && a.tv_sec <= INT64_MIN - b.tv_sec)) { 151 sum = gpr_inf_past(sum.clock_type); 152 } else { 153 sum.tv_sec = a.tv_sec + b.tv_sec; 154 if (inc != 0 && sum.tv_sec == INT64_MAX - 1) { 155 sum = gpr_inf_future(sum.clock_type); 156 } else { 157 sum.tv_sec += inc; 158 } 159 } 160 return sum; 161 } 162 163 gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) { 164 gpr_timespec diff; 165 int64_t dec = 0; 166 if (b.clock_type == GPR_TIMESPAN) { 167 diff.clock_type = a.clock_type; 168 } else { 169 GPR_ASSERT(a.clock_type == b.clock_type); 170 diff.clock_type = GPR_TIMESPAN; 171 } 172 diff.tv_nsec = a.tv_nsec - b.tv_nsec; 173 if (diff.tv_nsec < 0) { 174 diff.tv_nsec += GPR_NS_PER_SEC; 175 dec++; 176 } 177 if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) { 178 diff = a; 179 } else if (b.tv_sec == INT64_MIN || 180 (b.tv_sec <= 0 && a.tv_sec >= INT64_MAX + b.tv_sec)) { 181 diff = gpr_inf_future(GPR_CLOCK_REALTIME); 182 } else if (b.tv_sec == INT64_MAX || 183 (b.tv_sec >= 0 && a.tv_sec <= INT64_MIN + b.tv_sec)) { 184 diff = gpr_inf_past(GPR_CLOCK_REALTIME); 185 } else { 186 diff.tv_sec = a.tv_sec - b.tv_sec; 187 if (dec != 0 && diff.tv_sec == INT64_MIN + 1) { 188 diff = gpr_inf_past(GPR_CLOCK_REALTIME); 189 } else { 190 diff.tv_sec -= dec; 191 } 192 } 193 return diff; 194 } 195 196 int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) { 197 int cmp_ab; 198 199 GPR_ASSERT(a.clock_type == b.clock_type); 200 GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN); 201 202 cmp_ab = gpr_time_cmp(a, b); 203 if (cmp_ab == 0) return 1; 204 if (cmp_ab < 0) { 205 return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0; 206 } else { 207 return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0; 208 } 209 } 210 211 int32_t gpr_time_to_millis(gpr_timespec t) { 212 if (t.tv_sec >= 2147483) { 213 if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) { 214 return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; 215 } 216 return 2147483647; 217 } else if (t.tv_sec <= -2147483) { 218 /* TODO(ctiller): correct handling here (it's so far in the past do we 219 care?) */ 220 return -2147483647; 221 } else { 222 return static_cast<int32_t>(t.tv_sec * GPR_MS_PER_SEC + 223 t.tv_nsec / GPR_NS_PER_MS); 224 } 225 } 226 227 double gpr_timespec_to_micros(gpr_timespec t) { 228 return static_cast<double>(t.tv_sec) * GPR_US_PER_SEC + t.tv_nsec * 1e-3; 229 } 230 231 gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) { 232 if (t.clock_type == clock_type) { 233 return t; 234 } 235 236 if (t.tv_sec == INT64_MAX || t.tv_sec == INT64_MIN) { 237 t.clock_type = clock_type; 238 return t; 239 } 240 241 if (clock_type == GPR_TIMESPAN) { 242 return gpr_time_sub(t, gpr_now(t.clock_type)); 243 } 244 245 if (t.clock_type == GPR_TIMESPAN) { 246 return gpr_time_add(gpr_now(clock_type), t); 247 } 248 249 return gpr_time_add(gpr_now(clock_type), 250 gpr_time_sub(t, gpr_now(t.clock_type))); 251 } 252