diff options
Diffstat (limited to 'VNFs/DPPD-PROX/clock.c')
-rw-r--r-- | VNFs/DPPD-PROX/clock.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/clock.c b/VNFs/DPPD-PROX/clock.c new file mode 100644 index 00000000..6e057101 --- /dev/null +++ b/VNFs/DPPD-PROX/clock.c @@ -0,0 +1,261 @@ +/* +// Copyright (c) 2010-2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include "clock.h" + +#include <stdio.h> +#include <string.h> + +#include <rte_cycles.h> + +/* Calibrate TSC overhead by reading NB_READ times and take the smallest value. + Bigger values are caused by external influence and can be discarded. The best + estimate is the smallest read value. */ +#define NB_READ 10000 + +uint32_t rdtsc_overhead; +uint32_t rdtsc_overhead_stats; + +uint64_t thresh; +uint64_t tsc_hz; + +/* calculate how much overhead is involved with calling rdtsc. This value has + to be taken into account where the time spent running a small piece of code + is measured */ +static void init_tsc_overhead(void) +{ + volatile uint32_t min_without_overhead = UINT32_MAX; + volatile uint32_t min_with_overhead = UINT32_MAX; + volatile uint32_t min_stats_overhead = UINT32_MAX; + volatile uint64_t start1, end1; + volatile uint64_t start2, end2; + + for (uint32_t i = 0; i < NB_READ; ++i) { + start1 = rte_rdtsc(); + end1 = rte_rdtsc(); + + start2 = rte_rdtsc(); + end2 = rte_rdtsc(); + end2 = rte_rdtsc(); + + if (min_without_overhead > end1 - start1) { + min_without_overhead = end1 - start1; + } + + if (min_with_overhead > end2 - start2) { + min_with_overhead = end2 - start2; + } + } + + rdtsc_overhead = min_with_overhead - min_without_overhead; + + start1 = rte_rdtsc(); + end1 = rte_rdtsc(); + /* forbid the compiler to optimize this dummy variable */ + volatile int dummy = 0; + for (uint32_t i = 0; i < NB_READ; ++i) { + start1 = rte_rdtsc(); + dummy += 32; + end1 = rte_rdtsc(); + + if (min_stats_overhead > end2 - start2) { + min_stats_overhead = end1 - start1; + } + } + + rdtsc_overhead_stats = rdtsc_overhead + min_stats_overhead - min_without_overhead; +} + +void clock_init(void) +{ + init_tsc_overhead(); + tsc_hz = rte_get_tsc_hz(); + thresh = UINT64_MAX/tsc_hz; +} + +uint64_t str_to_tsc(const char *from) +{ + const uint64_t hz = rte_get_tsc_hz(); + uint64_t ret; + char str[16]; + + strncpy(str, from, sizeof(str)); + + char *frac = strchr(str, '.'); + + if (frac) { + *frac = 0; + frac++; + } + + ret = hz * atoi(str); + + if (!frac) + return ret; + + uint64_t nsec = 0; + uint64_t multiplier = 100000000; + + for (size_t i = 0; i < strlen(frac); ++i) { + nsec += (frac[i] - '0') * multiplier; + multiplier /= 10; + } + + /* Wont overflow until CPU freq is ~18.44 GHz */ + ret += hz * nsec/1000000000; + + return ret; +} + +uint64_t sec_to_tsc(uint64_t sec) +{ + if (sec < UINT64_MAX/rte_get_tsc_hz()) + return sec * rte_get_tsc_hz(); + else + return UINT64_MAX; +} + +uint64_t msec_to_tsc(uint64_t msec) +{ + if (msec < UINT64_MAX/rte_get_tsc_hz()) + return msec * rte_get_tsc_hz() / 1000; + else + return msec / 1000 * rte_get_tsc_hz(); +} + +uint64_t usec_to_tsc(uint64_t usec) +{ + if (usec < UINT64_MAX/rte_get_tsc_hz()) + return usec * rte_get_tsc_hz() / 1000000; + else + return usec / 1000000 * rte_get_tsc_hz(); +} + +uint64_t nsec_to_tsc(uint64_t nsec) +{ + if (nsec < UINT64_MAX/rte_get_tsc_hz()) + return nsec * rte_get_tsc_hz() / 1000000000; + else + return nsec / 1000000000 * rte_get_tsc_hz(); +} + +uint64_t tsc_to_msec(uint64_t tsc) +{ + if (tsc < UINT64_MAX / 1000) { + return tsc * 1000 / rte_get_tsc_hz(); + } else { + return tsc / (rte_get_tsc_hz() / 1000); + } +} + +uint64_t tsc_to_usec(uint64_t tsc) +{ + if (tsc < UINT64_MAX / 1000000) { + return tsc * 1000000 / rte_get_tsc_hz(); + } else { + return tsc / (rte_get_tsc_hz() / 1000000); + } +} + +uint64_t tsc_to_nsec(uint64_t tsc) +{ + if (tsc < UINT64_MAX / 1000000000) { + return tsc * 1000000000 / rte_get_tsc_hz(); + } else { + return tsc / (rte_get_tsc_hz() / 1000000000); + } +} + +uint64_t tsc_to_sec(uint64_t tsc) +{ + return tsc / rte_get_tsc_hz(); +} + +struct time_unit tsc_to_time_unit(uint64_t tsc) +{ + struct time_unit ret; + uint64_t hz = rte_get_tsc_hz(); + + ret.sec = tsc/hz; + ret.nsec = (tsc - ret.sec*hz)*1000000000/hz; + + return ret; +} + +uint64_t time_unit_to_usec(struct time_unit *time_unit) +{ + return time_unit->sec * 1000000 + time_unit->nsec/1000; +} + +uint64_t time_unit_to_nsec(struct time_unit *time_unit) +{ + return time_unit->sec * 1000000000 + time_unit->nsec; +} + +int time_unit_cmp(struct time_unit *left, struct time_unit *right) +{ + if (left->sec < right->sec) + return -1; + if (left->sec > right->sec) + return 1; + + if (left->nsec < right->nsec) + return -1; + if (left->nsec > right->nsec) + return -1; + return 0; +} + +uint64_t freq_to_tsc(uint64_t times_per_sec) +{ + return rte_get_tsc_hz()/times_per_sec; +} + +void tsc_to_tv(struct timeval *tv, const uint64_t tsc) +{ + uint64_t hz = rte_get_tsc_hz(); + uint64_t sec = tsc/hz; + + tv->tv_sec = sec; + tv->tv_usec = ((tsc - sec * hz) * 1000000) / hz; +} + +void tv_to_tsc(const struct timeval *tv, uint64_t *tsc) +{ + uint64_t hz = rte_get_tsc_hz(); + *tsc = tv->tv_sec * hz; + *tsc += tv->tv_usec * hz / 1000000; +} + +struct timeval tv_diff(const struct timeval *cur, const struct timeval *next) +{ + uint64_t sec, usec; + + sec = next->tv_sec - cur->tv_sec; + if (next->tv_usec < cur->tv_usec) { + usec = next->tv_usec + 1000000 - cur->tv_usec; + sec -= 1; + } + else + usec = next->tv_usec - cur->tv_usec; + + struct timeval ret = { + .tv_sec = sec, + .tv_usec = usec, + }; + + return ret; +} |