1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /**************************************************************************
25
26 ink_hrtime.h
27
28 This file contains code supporting the Inktomi high-resolution timer.
29 **************************************************************************/
30
31 #pragma once
32
33 #include "tscore/ink_config.h"
34 #include "tscore/ink_assert.h"
35 #include <ctime>
36 #include <cstdint>
37 #include <sys/time.h>
38 #include <cstdlib>
39 typedef int64_t ink_hrtime;
40
41 int squid_timestamp_to_buf(char *buf, unsigned int buf_size, long timestamp_sec, long timestamp_usec);
42 char *int64_to_str(char *buf, unsigned int buf_size, int64_t val, unsigned int *total_chars, unsigned int req_width = 0,
43 char pad_char = '0');
44
45 //////////////////////////////////////////////////////////////////////////////
46 //
47 // Factors to multiply units by to obtain corresponding ink_hrtime values.
48 //
49 //////////////////////////////////////////////////////////////////////////////
50
51 #define HRTIME_FOREVER (10 * HRTIME_DECADE)
52 #define HRTIME_DECADE (10 * HRTIME_YEAR)
53 #define HRTIME_YEAR (365 * HRTIME_DAY + HRTIME_DAY / 4)
54 #define HRTIME_WEEK (7 * HRTIME_DAY)
55 #define HRTIME_DAY (24 * HRTIME_HOUR)
56 #define HRTIME_HOUR (60 * HRTIME_MINUTE)
57 #define HRTIME_MINUTE (60 * HRTIME_SECOND)
58 #define HRTIME_SECOND (1000 * HRTIME_MSECOND)
59 #define HRTIME_MSECOND (1000 * HRTIME_USECOND)
60 #define HRTIME_USECOND (1000 * HRTIME_NSECOND)
61 #define HRTIME_NSECOND (static_cast<ink_hrtime>(1))
62
63 #define HRTIME_APPROX_SECONDS(_x) ((_x) >> 30) // off by 7.3%
64 #define HRTIME_APPROX_FACTOR (((float)(1 << 30)) / (((float)HRTIME_SECOND)))
65
66 //////////////////////////////////////////////////////////////////////////////
67 //
68 // Map from units to ink_hrtime values
69 //
70 //////////////////////////////////////////////////////////////////////////////
71
72 // simple macros
73
74 #define HRTIME_YEARS(_x) ((_x)*HRTIME_YEAR)
75 #define HRTIME_WEEKS(_x) ((_x)*HRTIME_WEEK)
76 #define HRTIME_DAYS(_x) ((_x)*HRTIME_DAY)
77 #define HRTIME_HOURS(_x) ((_x)*HRTIME_HOUR)
78 #define HRTIME_MINUTES(_x) ((_x)*HRTIME_MINUTE)
79 #define HRTIME_SECONDS(_x) ((_x)*HRTIME_SECOND)
80 #define HRTIME_MSECONDS(_x) ((_x)*HRTIME_MSECOND)
81 #define HRTIME_USECONDS(_x) ((_x)*HRTIME_USECOND)
82 #define HRTIME_NSECONDS(_x) ((_x)*HRTIME_NSECOND)
83
84 // gratuitous wrappers
85
86 static inline ink_hrtime
ink_hrtime_from_years(unsigned int years)87 ink_hrtime_from_years(unsigned int years)
88 {
89 return (HRTIME_YEARS(years));
90 }
91
92 static inline ink_hrtime
ink_hrtime_from_weeks(unsigned int weeks)93 ink_hrtime_from_weeks(unsigned int weeks)
94 {
95 return (HRTIME_WEEKS(weeks));
96 }
97
98 static inline ink_hrtime
ink_hrtime_from_days(unsigned int days)99 ink_hrtime_from_days(unsigned int days)
100 {
101 return (HRTIME_DAYS(days));
102 }
103
104 static inline ink_hrtime
ink_hrtime_from_mins(unsigned int mins)105 ink_hrtime_from_mins(unsigned int mins)
106 {
107 return (HRTIME_MINUTES(mins));
108 }
109
110 static inline ink_hrtime
ink_hrtime_from_sec(unsigned int sec)111 ink_hrtime_from_sec(unsigned int sec)
112 {
113 return (HRTIME_SECONDS(sec));
114 }
115
116 static inline ink_hrtime
ink_hrtime_from_msec(unsigned int msec)117 ink_hrtime_from_msec(unsigned int msec)
118 {
119 return (HRTIME_MSECONDS(msec));
120 }
121
122 static inline ink_hrtime
ink_hrtime_from_usec(unsigned int usec)123 ink_hrtime_from_usec(unsigned int usec)
124 {
125 return (HRTIME_USECONDS(usec));
126 }
127
128 static inline ink_hrtime
ink_hrtime_from_nsec(unsigned int nsec)129 ink_hrtime_from_nsec(unsigned int nsec)
130 {
131 return (HRTIME_NSECONDS(nsec));
132 }
133
134 static inline ink_hrtime
ink_hrtime_from_timespec(const struct timespec * ts)135 ink_hrtime_from_timespec(const struct timespec *ts)
136 {
137 return ink_hrtime_from_sec(ts->tv_sec) + ink_hrtime_from_nsec(ts->tv_nsec);
138 }
139
140 static inline ink_hrtime
ink_hrtime_from_timeval(const struct timeval * tv)141 ink_hrtime_from_timeval(const struct timeval *tv)
142 {
143 return ink_hrtime_from_sec(tv->tv_sec) + ink_hrtime_from_usec(tv->tv_usec);
144 }
145
146 //////////////////////////////////////////////////////////////////////////////
147 //
148 // Map from ink_hrtime values to other units
149 //
150 //////////////////////////////////////////////////////////////////////////////
151
152 static inline ink_hrtime
ink_hrtime_to_years(ink_hrtime t)153 ink_hrtime_to_years(ink_hrtime t)
154 {
155 return ((ink_hrtime)(t / HRTIME_YEAR));
156 }
157
158 static inline ink_hrtime
ink_hrtime_to_weeks(ink_hrtime t)159 ink_hrtime_to_weeks(ink_hrtime t)
160 {
161 return ((ink_hrtime)(t / HRTIME_WEEK));
162 }
163
164 static inline ink_hrtime
ink_hrtime_to_days(ink_hrtime t)165 ink_hrtime_to_days(ink_hrtime t)
166 {
167 return ((ink_hrtime)(t / HRTIME_DAY));
168 }
169
170 static inline ink_hrtime
ink_hrtime_to_mins(ink_hrtime t)171 ink_hrtime_to_mins(ink_hrtime t)
172 {
173 return ((ink_hrtime)(t / HRTIME_MINUTE));
174 }
175
176 static inline ink_hrtime
ink_hrtime_to_sec(ink_hrtime t)177 ink_hrtime_to_sec(ink_hrtime t)
178 {
179 return ((ink_hrtime)(t / HRTIME_SECOND));
180 }
181
182 static inline ink_hrtime
ink_hrtime_to_msec(ink_hrtime t)183 ink_hrtime_to_msec(ink_hrtime t)
184 {
185 return ((ink_hrtime)(t / HRTIME_MSECOND));
186 }
187
188 static inline ink_hrtime
ink_hrtime_to_usec(ink_hrtime t)189 ink_hrtime_to_usec(ink_hrtime t)
190 {
191 return ((ink_hrtime)(t / HRTIME_USECOND));
192 }
193
194 static inline ink_hrtime
ink_hrtime_to_nsec(ink_hrtime t)195 ink_hrtime_to_nsec(ink_hrtime t)
196 {
197 return ((ink_hrtime)(t / HRTIME_NSECOND));
198 }
199
200 static inline struct timespec
ink_hrtime_to_timespec(ink_hrtime t)201 ink_hrtime_to_timespec(ink_hrtime t)
202 {
203 struct timespec ts;
204
205 ts.tv_sec = ink_hrtime_to_sec(t);
206 ts.tv_nsec = t % HRTIME_SECOND;
207 return (ts);
208 }
209
210 static inline struct timeval
ink_hrtime_to_timeval(ink_hrtime t)211 ink_hrtime_to_timeval(ink_hrtime t)
212 {
213 int64_t usecs;
214 struct timeval tv;
215
216 usecs = ink_hrtime_to_usec(t);
217 tv.tv_sec = usecs / 1000000;
218 tv.tv_usec = usecs % 1000000;
219 return (tv);
220 }
221
222 /*
223 using Jan 1 1970 as the base year, instead of Jan 1 1601,
224 which translates to (365 + 0.25)369*24*60*60 seconds */
225 #define NT_TIMEBASE_DIFFERENCE_100NSECS 116444736000000000i64
226
227 static inline ink_hrtime
ink_get_hrtime_internal()228 ink_get_hrtime_internal()
229 {
230 #if defined(freebsd) || HAVE_CLOCK_GETTIME
231 timespec ts;
232 clock_gettime(CLOCK_REALTIME, &ts);
233 return ink_hrtime_from_timespec(&ts);
234 #else
235 timeval tv;
236 gettimeofday(&tv, nullptr);
237 return ink_hrtime_from_timeval(&tv);
238 #endif
239 }
240
241 static inline struct timeval
ink_gettimeofday()242 ink_gettimeofday()
243 {
244 return ink_hrtime_to_timeval(ink_get_hrtime_internal());
245 }
246
247 static inline int
ink_time()248 ink_time()
249 {
250 return (int)ink_hrtime_to_sec(ink_get_hrtime_internal());
251 }
252
253 static inline int
ink_hrtime_diff_msec(ink_hrtime t1,ink_hrtime t2)254 ink_hrtime_diff_msec(ink_hrtime t1, ink_hrtime t2)
255 {
256 return (int)ink_hrtime_to_msec(t1 - t2);
257 }
258
259 static inline ink_hrtime
ink_hrtime_diff(ink_hrtime t1,ink_hrtime t2)260 ink_hrtime_diff(ink_hrtime t1, ink_hrtime t2)
261 {
262 return (t1 - t2);
263 }
264
265 static inline ink_hrtime
ink_hrtime_add(ink_hrtime t1,ink_hrtime t2)266 ink_hrtime_add(ink_hrtime t1, ink_hrtime t2)
267 {
268 return (t1 + t2);
269 }
270
271 static inline void
ink_hrtime_sleep(ink_hrtime delay)272 ink_hrtime_sleep(ink_hrtime delay)
273 {
274 struct timespec ts = ink_hrtime_to_timespec(delay);
275 nanosleep(&ts, nullptr);
276 }
277