aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/arch/x86
diff options
context:
space:
mode:
authorPetri Savolainen <petri.savolainen@linaro.org>2017-04-28 15:09:56 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2017-06-16 16:51:11 +0300
commitfbe34c754b7abe15100779ce9833a7f200517d9f (patch)
tree1cfcd9524cd017876cd1124b34728eedacb90065 /platform/linux-generic/arch/x86
parent62f95a564b7b3e08a32e6e72d234eb86292021d0 (diff)
linux-gen: time: use hw time counter when available
Use 64 bit HW time counter when available. It is used on x86 when invariant TSC CPU flag indicates that TSC frequency is constant. Otherwise, the system time is used as before. Direct HW time counter usage avoids system call, and related latency and performance issues. Signed-off-by: Petri Savolainen <petri.savolainen@linaro.org> Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'platform/linux-generic/arch/x86')
-rw-r--r--platform/linux-generic/arch/x86/cpu_flags.c9
-rw-r--r--platform/linux-generic/arch/x86/odp_cpu_arch.c59
2 files changed, 68 insertions, 0 deletions
diff --git a/platform/linux-generic/arch/x86/cpu_flags.c b/platform/linux-generic/arch/x86/cpu_flags.c
index 954dac272..a492a35bf 100644
--- a/platform/linux-generic/arch/x86/cpu_flags.c
+++ b/platform/linux-generic/arch/x86/cpu_flags.c
@@ -39,6 +39,7 @@
#include <arch/x86/cpu_flags.h>
#include <odp_debug_internal.h>
+#include <odp_time_internal.h>
#include <stdio.h>
#include <stdint.h>
@@ -357,3 +358,11 @@ void cpu_flags_print_all(void)
str[len] = '\0';
ODP_PRINT("%s", str);
}
+
+int cpu_has_global_time(void)
+{
+ if (cpu_get_flag_enabled(RTE_CPUFLAG_INVTSC) > 0)
+ return 1;
+
+ return 0;
+}
diff --git a/platform/linux-generic/arch/x86/odp_cpu_arch.c b/platform/linux-generic/arch/x86/odp_cpu_arch.c
index c8cf27b65..9ba601a32 100644
--- a/platform/linux-generic/arch/x86/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/x86/odp_cpu_arch.c
@@ -3,7 +3,14 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+
+#include <odp_posix_extensions.h>
+
#include <odp/api/cpu.h>
+#include <odp_time_internal.h>
+#include <odp_debug_internal.h>
+
+#include <time.h>
uint64_t odp_cpu_cycles(void)
{
@@ -31,3 +38,55 @@ uint64_t odp_cpu_cycles_resolution(void)
{
return 1;
}
+
+uint64_t cpu_global_time(void)
+{
+ return odp_cpu_cycles();
+}
+
+#define SEC_IN_NS 1000000000ULL
+
+/* Measure TSC frequency. Frequency information registers are defined for x86,
+ * but those are often not enumerated. */
+uint64_t cpu_global_time_freq(void)
+{
+ struct timespec sleep, ts1, ts2;
+ uint64_t t1, t2, ts_nsec, cycles, hz;
+ int i;
+ uint64_t avg = 0;
+ int rounds = 4;
+
+ for (i = 0; i < rounds; i++) {
+ sleep.tv_sec = 0;
+ sleep.tv_nsec = SEC_IN_NS / 10;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts1)) {
+ ODP_DBG("clock_gettime failed\n");
+ return 0;
+ }
+
+ t1 = cpu_global_time();
+
+ if (nanosleep(&sleep, NULL) < 0) {
+ ODP_DBG("nanosleep failed\n");
+ return 0;
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts2)) {
+ ODP_DBG("clock_gettime failed\n");
+ return 0;
+ }
+
+ t2 = cpu_global_time();
+
+ ts_nsec = (ts2.tv_sec - ts1.tv_sec) * SEC_IN_NS;
+ ts_nsec += ts2.tv_nsec - ts1.tv_nsec;
+
+ cycles = t2 - t1;
+
+ hz = (cycles * SEC_IN_NS) / ts_nsec;
+ avg += hz;
+ }
+
+ return avg / rounds;
+}