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>
23 #include "prox_compat.h"
25 /* Calibrate TSC overhead by reading NB_READ times and take the smallest value.
26 Bigger values are caused by external influence and can be discarded. The best
27 estimate is the smallest read value. */
30 uint32_t rdtsc_overhead;
31 uint32_t rdtsc_overhead_stats;
36 /* calculate how much overhead is involved with calling rdtsc. This value has
37 to be taken into account where the time spent running a small piece of code
39 static void init_tsc_overhead(void)
41 volatile uint32_t min_without_overhead = UINT32_MAX;
42 volatile uint32_t min_with_overhead = UINT32_MAX;
43 volatile uint32_t min_stats_overhead = UINT32_MAX;
44 volatile uint64_t start1, end1;
45 volatile uint64_t start2, end2;
47 for (uint32_t i = 0; i < NB_READ; ++i) {
55 if (min_without_overhead > end1 - start1) {
56 min_without_overhead = end1 - start1;
59 if (min_with_overhead > end2 - start2) {
60 min_with_overhead = end2 - start2;
64 rdtsc_overhead = min_with_overhead - min_without_overhead;
68 /* forbid the compiler to optimize this dummy variable */
69 volatile int dummy = 0;
70 for (uint32_t i = 0; i < NB_READ; ++i) {
75 if (min_stats_overhead > end2 - start2) {
76 min_stats_overhead = end1 - start1;
80 rdtsc_overhead_stats = rdtsc_overhead + min_stats_overhead - min_without_overhead;
86 tsc_hz = rte_get_tsc_hz();
87 thresh = UINT64_MAX/tsc_hz;
90 uint64_t str_to_tsc(const char *from)
92 const uint64_t hz = rte_get_tsc_hz();
96 prox_strncpy(str, from, sizeof(str));
98 char *frac = strchr(str, '.');
105 ret = hz * atoi(str);
111 uint64_t multiplier = 100000000;
113 for (size_t i = 0; i < strlen(frac); ++i) {
114 nsec += (frac[i] - '0') * multiplier;
118 /* Wont overflow until CPU freq is ~18.44 GHz */
119 ret += hz * nsec/1000000000;
124 uint64_t sec_to_tsc(uint64_t sec)
126 if (sec < UINT64_MAX/rte_get_tsc_hz())
127 return sec * rte_get_tsc_hz();
132 uint64_t msec_to_tsc(uint64_t msec)
134 if (msec < UINT64_MAX/rte_get_tsc_hz())
135 return msec * rte_get_tsc_hz() / 1000;
137 return msec / 1000 * rte_get_tsc_hz();
140 uint64_t usec_to_tsc(uint64_t usec)
142 if (usec < UINT64_MAX/rte_get_tsc_hz())
143 return usec * rte_get_tsc_hz() / 1000000;
145 return usec / 1000000 * rte_get_tsc_hz();
148 uint64_t nsec_to_tsc(uint64_t nsec)
150 if (nsec < UINT64_MAX/rte_get_tsc_hz())
151 return nsec * rte_get_tsc_hz() / 1000000000;
153 return nsec / 1000000000 * rte_get_tsc_hz();
156 uint64_t tsc_to_msec(uint64_t tsc)
158 if (tsc < UINT64_MAX / 1000) {
159 return tsc * 1000 / rte_get_tsc_hz();
161 return tsc / (rte_get_tsc_hz() / 1000);
165 uint64_t tsc_to_usec(uint64_t tsc)
167 if (tsc < UINT64_MAX / 1000000) {
168 return tsc * 1000000 / rte_get_tsc_hz();
170 return tsc / (rte_get_tsc_hz() / 1000000);
174 uint64_t tsc_to_nsec(uint64_t tsc)
176 if (tsc < UINT64_MAX / 1000000000) {
177 return tsc * 1000000000 / rte_get_tsc_hz();
179 return tsc / (rte_get_tsc_hz() / 1000000000);
183 uint64_t tsc_to_sec(uint64_t tsc)
185 return tsc / rte_get_tsc_hz();
188 struct time_unit tsc_to_time_unit(uint64_t tsc)
190 struct time_unit ret;
191 uint64_t hz = rte_get_tsc_hz();
194 ret.nsec = (tsc - ret.sec*hz)*1000000000/hz;
199 uint64_t time_unit_to_usec(struct time_unit *time_unit)
201 return time_unit->sec * 1000000 + time_unit->nsec/1000;
204 uint64_t time_unit_to_nsec(struct time_unit *time_unit)
206 return time_unit->sec * 1000000000 + time_unit->nsec;
209 int time_unit_cmp(struct time_unit *left, struct time_unit *right)
211 if (left->sec < right->sec)
213 if (left->sec > right->sec)
216 if (left->nsec < right->nsec)
218 if (left->nsec > right->nsec)
223 uint64_t freq_to_tsc(uint64_t times_per_sec)
225 return rte_get_tsc_hz()/times_per_sec;
228 void tsc_to_tv(struct timeval *tv, const uint64_t tsc)
230 uint64_t hz = rte_get_tsc_hz();
231 uint64_t sec = tsc/hz;
234 tv->tv_usec = ((tsc - sec * hz) * 1000000) / hz;
237 void tv_to_tsc(const struct timeval *tv, uint64_t *tsc)
239 uint64_t hz = rte_get_tsc_hz();
240 *tsc = tv->tv_sec * hz;
241 *tsc += tv->tv_usec * hz / 1000000;
244 struct timeval tv_diff(const struct timeval *cur, const struct timeval *next)
248 sec = next->tv_sec - cur->tv_sec;
249 if (next->tv_usec < cur->tv_usec) {
250 usec = next->tv_usec + 1000000 - cur->tv_usec;
254 usec = next->tv_usec - cur->tv_usec;
256 struct timeval ret = {