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