2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
22 #include <rte_cycles.h>
24 /* Calibrate TSC overhead by reading NB_READ times and take the smallest value.
25 Bigger values are caused by external influence and can be discarded. The best
26 estimate is the smallest read value. */
29 uint32_t rdtsc_overhead;
30 uint32_t rdtsc_overhead_stats;
35 /* calculate how much overhead is involved with calling rdtsc. This value has
36 to be taken into account where the time spent running a small piece of code
38 static void init_tsc_overhead(void)
40 volatile uint32_t min_without_overhead = UINT32_MAX;
41 volatile uint32_t min_with_overhead = UINT32_MAX;
42 volatile uint32_t min_stats_overhead = UINT32_MAX;
43 volatile uint64_t start1, end1;
44 volatile uint64_t start2, end2;
46 for (uint32_t i = 0; i < NB_READ; ++i) {
54 if (min_without_overhead > end1 - start1) {
55 min_without_overhead = end1 - start1;
58 if (min_with_overhead > end2 - start2) {
59 min_with_overhead = end2 - start2;
63 rdtsc_overhead = min_with_overhead - min_without_overhead;
67 /* forbid the compiler to optimize this dummy variable */
68 volatile int dummy = 0;
69 for (uint32_t i = 0; i < NB_READ; ++i) {
74 if (min_stats_overhead > end2 - start2) {
75 min_stats_overhead = end1 - start1;
79 rdtsc_overhead_stats = rdtsc_overhead + min_stats_overhead - min_without_overhead;
85 tsc_hz = rte_get_tsc_hz();
86 thresh = UINT64_MAX/tsc_hz;
89 uint64_t str_to_tsc(const char *from)
91 const uint64_t hz = rte_get_tsc_hz();
95 strncpy(str, from, sizeof(str));
97 char *frac = strchr(str, '.');
104 ret = hz * atoi(str);
110 uint64_t multiplier = 100000000;
112 for (size_t i = 0; i < strlen(frac); ++i) {
113 nsec += (frac[i] - '0') * multiplier;
117 /* Wont overflow until CPU freq is ~18.44 GHz */
118 ret += hz * nsec/1000000000;
123 uint64_t sec_to_tsc(uint64_t sec)
125 if (sec < UINT64_MAX/rte_get_tsc_hz())
126 return sec * rte_get_tsc_hz();
131 uint64_t msec_to_tsc(uint64_t msec)
133 if (msec < UINT64_MAX/rte_get_tsc_hz())
134 return msec * rte_get_tsc_hz() / 1000;
136 return msec / 1000 * rte_get_tsc_hz();
139 uint64_t usec_to_tsc(uint64_t usec)
141 if (usec < UINT64_MAX/rte_get_tsc_hz())
142 return usec * rte_get_tsc_hz() / 1000000;
144 return usec / 1000000 * rte_get_tsc_hz();
147 uint64_t nsec_to_tsc(uint64_t nsec)
149 if (nsec < UINT64_MAX/rte_get_tsc_hz())
150 return nsec * rte_get_tsc_hz() / 1000000000;
152 return nsec / 1000000000 * rte_get_tsc_hz();
155 uint64_t tsc_to_msec(uint64_t tsc)
157 if (tsc < UINT64_MAX / 1000) {
158 return tsc * 1000 / rte_get_tsc_hz();
160 return tsc / (rte_get_tsc_hz() / 1000);
164 uint64_t tsc_to_usec(uint64_t tsc)
166 if (tsc < UINT64_MAX / 1000000) {
167 return tsc * 1000000 / rte_get_tsc_hz();
169 return tsc / (rte_get_tsc_hz() / 1000000);
173 uint64_t tsc_to_nsec(uint64_t tsc)
175 if (tsc < UINT64_MAX / 1000000000) {
176 return tsc * 1000000000 / rte_get_tsc_hz();
178 return tsc / (rte_get_tsc_hz() / 1000000000);
182 uint64_t tsc_to_sec(uint64_t tsc)
184 return tsc / rte_get_tsc_hz();
187 struct time_unit tsc_to_time_unit(uint64_t tsc)
189 struct time_unit ret;
190 uint64_t hz = rte_get_tsc_hz();
193 ret.nsec = (tsc - ret.sec*hz)*1000000000/hz;
198 uint64_t time_unit_to_usec(struct time_unit *time_unit)
200 return time_unit->sec * 1000000 + time_unit->nsec/1000;
203 uint64_t time_unit_to_nsec(struct time_unit *time_unit)
205 return time_unit->sec * 1000000000 + time_unit->nsec;
208 int time_unit_cmp(struct time_unit *left, struct time_unit *right)
210 if (left->sec < right->sec)
212 if (left->sec > right->sec)
215 if (left->nsec < right->nsec)
217 if (left->nsec > right->nsec)
222 uint64_t freq_to_tsc(uint64_t times_per_sec)
224 return rte_get_tsc_hz()/times_per_sec;
227 void tsc_to_tv(struct timeval *tv, const uint64_t tsc)
229 uint64_t hz = rte_get_tsc_hz();
230 uint64_t sec = tsc/hz;
233 tv->tv_usec = ((tsc - sec * hz) * 1000000) / hz;
236 void tv_to_tsc(const struct timeval *tv, uint64_t *tsc)
238 uint64_t hz = rte_get_tsc_hz();
239 *tsc = tv->tv_sec * hz;
240 *tsc += tv->tv_usec * hz / 1000000;
243 struct timeval tv_diff(const struct timeval *cur, const struct timeval *next)
247 sec = next->tv_sec - cur->tv_sec;
248 if (next->tv_usec < cur->tv_usec) {
249 usec = next->tv_usec + 1000000 - cur->tv_usec;
253 usec = next->tv_usec - cur->tv_usec;
255 struct timeval ret = {