This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, api-next has been updated via 467285f59991e0f28d22a50c99e56f07a4380b8d (commit) via e0e038bab9fc2a9641e1eddd50d115ace2a66cef (commit) via 4584e90f7b19a1f7456f46e61f818e73ff0c7377 (commit) via 419cab0fcfccc7b702a7592dff98d108c24e49bf (commit) via 8b29e0ad33bb176374f47ae0bc2388b0d8d2b926 (commit) via 09a0e859caa4dbd68deb459e0160aed1ff8b5168 (commit) via 617999503a54c52daf86abcaef12542e67c3d47a (commit) via 54e52ac90cc564e83d9fd3d22e5fd0d084fec1c3 (commit) via 4fd46d42fb7fb7867ef269fc491eae7a7b303630 (commit) via b8c3fffa30ff5c07fe28bab562510157050ebeff (commit) from 0b1dbf37b4030c6da4c6f13645c63fd4ac8ff923 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 467285f59991e0f28d22a50c99e56f07a4380b8d Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:58 2017 +0300
linux-gen: time: store timespec as nsec
Use single 64 bit nanosecond value to store time when using posix time. Posix time stamp is converted directly from timespec (sec + nsec) to nsec time. Storage space for odp_time_t is halved as both posix and HW time use single u64. Some functions (sum, diff, cmp) are generic for both time sources.
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
diff --git a/platform/linux-generic/include/odp/api/plat/time_types.h b/platform/linux-generic/include/odp/api/plat/time_types.h index 1cafb1f7..71e354e6 100644 --- a/platform/linux-generic/include/odp/api/plat/time_types.h +++ b/platform/linux-generic/include/odp/api/plat/time_types.h @@ -22,32 +22,24 @@ extern "C" { **/
/** - * @internal Time structure used to isolate odp-linux implementation from - * the linux timespec structure, which is dependent on POSIX extension level. + * @internal Time structure used for both POSIX timespec and HW counter + * implementations. */ typedef struct odp_time_t { union { - /** @internal Posix timespec */ - struct { - /** @internal Seconds */ - int64_t tv_sec; - - /** @internal Nanoseconds */ - int64_t tv_nsec; - } spec; - - /** @internal HW time counter */ - struct { - /** @internal Counter value */ - uint64_t count; - - /** @internal Reserved */ - uint64_t reserved; - } hw; + /** @internal Used with generic 64 bit operations */ + uint64_t u64; + + /** @internal Nanoseconds */ + uint64_t nsec; + + /** @internal HW timer counter value */ + uint64_t count; + }; } odp_time_t;
-#define ODP_TIME_NULL ((odp_time_t){.spec = {0, 0} }) +#define ODP_TIME_NULL ((odp_time_t){.u64 = 0})
/** * @} diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c index ac82175d..2bbe5666 100644 --- a/platform/linux-generic/odp_time.c +++ b/platform/linux-generic/odp_time.c @@ -15,10 +15,10 @@ #include <inttypes.h>
typedef struct time_global_t { - odp_time_t start_time; - int use_hw; - uint64_t hw_start; - uint64_t hw_freq_hz; + struct timespec spec_start; + int use_hw; + uint64_t hw_start; + uint64_t hw_freq_hz; } time_global_t;
static time_global_t global; @@ -27,19 +27,23 @@ static time_global_t global; * Posix timespec based functions */
-static inline odp_time_t time_spec_diff(odp_time_t t2, odp_time_t t1) +static inline uint64_t time_spec_diff_nsec(struct timespec *t2, + struct timespec *t1) { - odp_time_t time; + struct timespec diff; + uint64_t nsec;
- time.spec.tv_sec = t2.spec.tv_sec - t1.spec.tv_sec; - time.spec.tv_nsec = t2.spec.tv_nsec - t1.spec.tv_nsec; + diff.tv_sec = t2->tv_sec - t1->tv_sec; + diff.tv_nsec = t2->tv_nsec - t1->tv_nsec;
- if (time.spec.tv_nsec < 0) { - time.spec.tv_nsec += ODP_TIME_SEC_IN_NS; - --time.spec.tv_sec; + if (diff.tv_nsec < 0) { + diff.tv_nsec += ODP_TIME_SEC_IN_NS; + diff.tv_sec -= 1; }
- return time; + nsec = (diff.tv_sec * ODP_TIME_SEC_IN_NS) + diff.tv_nsec; + + return nsec; }
static inline odp_time_t time_spec_cur(void) @@ -52,10 +56,9 @@ static inline odp_time_t time_spec_cur(void) if (odp_unlikely(ret != 0)) ODP_ABORT("clock_gettime failed\n");
- time.spec.tv_sec = sys_time.tv_sec; - time.spec.tv_nsec = sys_time.tv_nsec; + time.nsec = time_spec_diff_nsec(&sys_time, &global.spec_start);
- return time_spec_diff(time, global.start_time); + return time; }
static inline uint64_t time_spec_res(void) @@ -70,48 +73,16 @@ static inline uint64_t time_spec_res(void) return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; }
-static inline int time_spec_cmp(odp_time_t t2, odp_time_t t1) -{ - if (t2.spec.tv_sec < t1.spec.tv_sec) - return -1; - - if (t2.spec.tv_sec > t1.spec.tv_sec) - return 1; - - return t2.spec.tv_nsec - t1.spec.tv_nsec; -} - -static inline odp_time_t time_spec_sum(odp_time_t t1, odp_time_t t2) -{ - odp_time_t time; - - time.spec.tv_sec = t2.spec.tv_sec + t1.spec.tv_sec; - time.spec.tv_nsec = t2.spec.tv_nsec + t1.spec.tv_nsec; - - if (time.spec.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) { - time.spec.tv_nsec -= ODP_TIME_SEC_IN_NS; - ++time.spec.tv_sec; - } - - return time; -} - static inline uint64_t time_spec_to_ns(odp_time_t time) { - uint64_t ns; - - ns = time.spec.tv_sec * ODP_TIME_SEC_IN_NS; - ns += time.spec.tv_nsec; - - return ns; + return time.nsec; }
static inline odp_time_t time_spec_from_ns(uint64_t ns) { odp_time_t time;
- time.spec.tv_sec = ns / ODP_TIME_SEC_IN_NS; - time.spec.tv_nsec = ns - time.spec.tv_sec * ODP_TIME_SEC_IN_NS; + time.nsec = ns;
return time; } @@ -124,7 +95,7 @@ static inline odp_time_t time_hw_cur(void) { odp_time_t time;
- time.hw.count = cpu_global_time() - global.hw_start; + time.count = cpu_global_time() - global.hw_start;
return time; } @@ -136,40 +107,11 @@ static inline uint64_t time_hw_res(void) return global.hw_freq_hz / 10; }
-static inline int time_hw_cmp(odp_time_t t2, odp_time_t t1) -{ - if (odp_likely(t2.hw.count > t1.hw.count)) - return 1; - - if (t2.hw.count < t1.hw.count) - return -1; - - return 0; -} - -static inline odp_time_t time_hw_diff(odp_time_t t2, odp_time_t t1) -{ - odp_time_t time; - - time.hw.count = t2.hw.count - t1.hw.count; - - return time; -} - -static inline odp_time_t time_hw_sum(odp_time_t t1, odp_time_t t2) -{ - odp_time_t time; - - time.hw.count = t1.hw.count + t2.hw.count; - - return time; -} - static inline uint64_t time_hw_to_ns(odp_time_t time) { uint64_t nsec; uint64_t freq_hz = global.hw_freq_hz; - uint64_t count = time.hw.count; + uint64_t count = time.count; uint64_t sec = 0;
if (count >= freq_hz) { @@ -197,8 +139,7 @@ static inline odp_time_t time_hw_from_ns(uint64_t ns) count = sec * freq_hz; count += (ns * freq_hz) / ODP_TIME_SEC_IN_NS;
- time.hw.reserved = 0; - time.hw.count = count; + time.count = count;
return time; } @@ -225,26 +166,22 @@ static inline uint64_t time_res(void)
static inline int time_cmp(odp_time_t t2, odp_time_t t1) { - if (global.use_hw) - return time_hw_cmp(t2, t1); - - return time_spec_cmp(t2, t1); -} + if (odp_likely(t2.u64 > t1.u64)) + return 1;
-static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1) -{ - if (global.use_hw) - return time_hw_diff(t2, t1); + if (t2.u64 < t1.u64) + return -1;
- return time_spec_diff(t2, t1); + return 0; }
static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) { - if (global.use_hw) - return time_hw_sum(t1, t2); + odp_time_t time; + + time.u64 = t1.u64 + t2.u64;
- return time_spec_sum(t1, t2); + return time; }
static inline uint64_t time_to_ns(odp_time_t time) @@ -284,7 +221,11 @@ odp_time_t odp_time_global(void)
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1) { - return time_diff(t2, t1); + odp_time_t time; + + time.u64 = t2.u64 - t1.u64; + + return time; }
uint64_t odp_time_to_ns(odp_time_t time) @@ -338,7 +279,6 @@ void odp_time_wait_until(odp_time_t time)
int odp_time_init_global(void) { - struct timespec sys_time; int ret = 0;
memset(&global, 0, sizeof(time_global_t)); @@ -357,13 +297,10 @@ int odp_time_init_global(void) return 0; }
- global.start_time = ODP_TIME_NULL; + global.spec_start.tv_sec = 0; + global.spec_start.tv_nsec = 0;
- ret = clock_gettime(CLOCK_MONOTONIC_RAW, &sys_time); - if (ret == 0) { - global.start_time.spec.tv_sec = sys_time.tv_sec; - global.start_time.spec.tv_nsec = sys_time.tv_nsec; - } + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &global.spec_start);
return ret; }
commit e0e038bab9fc2a9641e1eddd50d115ace2a66cef Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:57 2017 +0300
linux-gen: time: improve x86 TSC freq measurement accuracy
Add short warm up round and measure over a longer period of time (250ms vs 100ms).
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
diff --git a/platform/linux-generic/arch/x86/odp_cpu_arch.c b/platform/linux-generic/arch/x86/odp_cpu_arch.c index 9ba601a3..b1da428b 100644 --- a/platform/linux-generic/arch/x86/odp_cpu_arch.c +++ b/platform/linux-generic/arch/x86/odp_cpu_arch.c @@ -54,11 +54,16 @@ uint64_t cpu_global_time_freq(void) uint64_t t1, t2, ts_nsec, cycles, hz; int i; uint64_t avg = 0; - int rounds = 4; + int rounds = 3; + int warm_up = 1;
for (i = 0; i < rounds; i++) { - sleep.tv_sec = 0; - sleep.tv_nsec = SEC_IN_NS / 10; + sleep.tv_sec = 0; + + if (warm_up) + sleep.tv_nsec = SEC_IN_NS / 1000; + else + sleep.tv_nsec = SEC_IN_NS / 4;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts1)) { ODP_DBG("clock_gettime failed\n"); @@ -85,8 +90,12 @@ uint64_t cpu_global_time_freq(void) cycles = t2 - t1;
hz = (cycles * SEC_IN_NS) / ts_nsec; - avg += hz; + + if (warm_up) + warm_up = 0; + else + avg += hz; }
- return avg / rounds; + return avg / (rounds - 1); }
commit 4584e90f7b19a1f7456f46e61f818e73ff0c7377 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:56 2017 +0300
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
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 4015499e..834a58e6 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -172,6 +172,7 @@ noinst_HEADERS = \ ${srcdir}/include/odp_schedule_if.h \ ${srcdir}/include/odp_sorted_list_internal.h \ ${srcdir}/include/odp_shm_internal.h \ + ${srcdir}/include/odp_time_internal.h \ ${srcdir}/include/odp_timer_internal.h \ ${srcdir}/include/odp_timer_wheel_internal.h \ ${srcdir}/include/odp_traffic_mngr_internal.h \ diff --git a/platform/linux-generic/arch/arm/odp_cpu_arch.c b/platform/linux-generic/arch/arm/odp_cpu_arch.c index 2ac223e0..c31f9084 100644 --- a/platform/linux-generic/arch/arm/odp_cpu_arch.c +++ b/platform/linux-generic/arch/arm/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h>
#define GIGA 1000000000
@@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/default/odp_cpu_arch.c b/platform/linux-generic/arch/default/odp_cpu_arch.c index 2ac223e0..c31f9084 100644 --- a/platform/linux-generic/arch/default/odp_cpu_arch.c +++ b/platform/linux-generic/arch/default/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h>
#define GIGA 1000000000
@@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/mips64/odp_cpu_arch.c b/platform/linux-generic/arch/mips64/odp_cpu_arch.c index 646acf9c..f7eafa0f 100644 --- a/platform/linux-generic/arch/mips64/odp_cpu_arch.c +++ b/platform/linux-generic/arch/mips64/odp_cpu_arch.c @@ -7,6 +7,7 @@ #include <odp/api/cpu.h> #include <odp/api/hints.h> #include <odp/api/system_info.h> +#include <odp_time_internal.h>
uint64_t odp_cpu_cycles(void) { @@ -29,3 +30,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c index 2ac223e0..c31f9084 100644 --- a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c +++ b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h>
#define GIGA 1000000000
@@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/x86/cpu_flags.c b/platform/linux-generic/arch/x86/cpu_flags.c index 954dac27..a492a35b 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 c8cf27b6..9ba601a3 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; +} diff --git a/platform/linux-generic/include/odp/api/plat/time_types.h b/platform/linux-generic/include/odp/api/plat/time_types.h index 4847f3b1..1cafb1f7 100644 --- a/platform/linux-generic/include/odp/api/plat/time_types.h +++ b/platform/linux-generic/include/odp/api/plat/time_types.h @@ -26,11 +26,28 @@ extern "C" { * the linux timespec structure, which is dependent on POSIX extension level. */ typedef struct odp_time_t { - int64_t tv_sec; /**< @internal Seconds */ - int64_t tv_nsec; /**< @internal Nanoseconds */ + union { + /** @internal Posix timespec */ + struct { + /** @internal Seconds */ + int64_t tv_sec; + + /** @internal Nanoseconds */ + int64_t tv_nsec; + } spec; + + /** @internal HW time counter */ + struct { + /** @internal Counter value */ + uint64_t count; + + /** @internal Reserved */ + uint64_t reserved; + } hw; + }; } odp_time_t;
-#define ODP_TIME_NULL ((odp_time_t){0, 0}) +#define ODP_TIME_NULL ((odp_time_t){.spec = {0, 0} })
/** * @} diff --git a/platform/linux-generic/include/odp_time_internal.h b/platform/linux-generic/include/odp_time_internal.h new file mode 100644 index 00000000..99ac7977 --- /dev/null +++ b/platform/linux-generic/include/odp_time_internal.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_TIME_INTERNAL_H_ +#define ODP_TIME_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +int cpu_has_global_time(void); +uint64_t cpu_global_time(void); +uint64_t cpu_global_time_freq(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c index 0e5966c0..ac82175d 100644 --- a/platform/linux-generic/odp_time.c +++ b/platform/linux-generic/odp_time.c @@ -10,36 +10,39 @@ #include <odp/api/time.h> #include <odp/api/hints.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h> +#include <string.h> +#include <inttypes.h>
-static odp_time_t start_time; +typedef struct time_global_t { + odp_time_t start_time; + int use_hw; + uint64_t hw_start; + uint64_t hw_freq_hz; +} time_global_t;
-static inline -uint64_t time_to_ns(odp_time_t time) -{ - uint64_t ns; - - ns = time.tv_sec * ODP_TIME_SEC_IN_NS; - ns += time.tv_nsec; +static time_global_t global;
- return ns; -} +/* + * Posix timespec based functions + */
-static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1) +static inline odp_time_t time_spec_diff(odp_time_t t2, odp_time_t t1) { odp_time_t time;
- time.tv_sec = t2.tv_sec - t1.tv_sec; - time.tv_nsec = t2.tv_nsec - t1.tv_nsec; + time.spec.tv_sec = t2.spec.tv_sec - t1.spec.tv_sec; + time.spec.tv_nsec = t2.spec.tv_nsec - t1.spec.tv_nsec;
- if (time.tv_nsec < 0) { - time.tv_nsec += ODP_TIME_SEC_IN_NS; - --time.tv_sec; + if (time.spec.tv_nsec < 0) { + time.spec.tv_nsec += ODP_TIME_SEC_IN_NS; + --time.spec.tv_sec; }
return time; }
-static inline odp_time_t time_local(void) +static inline odp_time_t time_spec_cur(void) { int ret; odp_time_t time; @@ -49,77 +52,234 @@ static inline odp_time_t time_local(void) if (odp_unlikely(ret != 0)) ODP_ABORT("clock_gettime failed\n");
- time.tv_sec = sys_time.tv_sec; - time.tv_nsec = sys_time.tv_nsec; + time.spec.tv_sec = sys_time.tv_sec; + time.spec.tv_nsec = sys_time.tv_nsec;
- return time_diff(time, start_time); + return time_spec_diff(time, global.start_time); }
-static inline int time_cmp(odp_time_t t2, odp_time_t t1) +static inline uint64_t time_spec_res(void) { - if (t2.tv_sec < t1.tv_sec) + int ret; + struct timespec tres; + + ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); + if (odp_unlikely(ret != 0)) + ODP_ABORT("clock_getres failed\n"); + + return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; +} + +static inline int time_spec_cmp(odp_time_t t2, odp_time_t t1) +{ + if (t2.spec.tv_sec < t1.spec.tv_sec) return -1;
- if (t2.tv_sec > t1.tv_sec) + if (t2.spec.tv_sec > t1.spec.tv_sec) return 1;
- return t2.tv_nsec - t1.tv_nsec; + return t2.spec.tv_nsec - t1.spec.tv_nsec; }
-static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) +static inline odp_time_t time_spec_sum(odp_time_t t1, odp_time_t t2) { odp_time_t time;
- time.tv_sec = t2.tv_sec + t1.tv_sec; - time.tv_nsec = t2.tv_nsec + t1.tv_nsec; + time.spec.tv_sec = t2.spec.tv_sec + t1.spec.tv_sec; + time.spec.tv_nsec = t2.spec.tv_nsec + t1.spec.tv_nsec;
- if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) { - time.tv_nsec -= ODP_TIME_SEC_IN_NS; - ++time.tv_sec; + if (time.spec.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) { + time.spec.tv_nsec -= ODP_TIME_SEC_IN_NS; + ++time.spec.tv_sec; }
return time; }
-static inline odp_time_t time_local_from_ns(uint64_t ns) +static inline uint64_t time_spec_to_ns(odp_time_t time) +{ + uint64_t ns; + + ns = time.spec.tv_sec * ODP_TIME_SEC_IN_NS; + ns += time.spec.tv_nsec; + + return ns; +} + +static inline odp_time_t time_spec_from_ns(uint64_t ns) { odp_time_t time;
- time.tv_sec = ns / ODP_TIME_SEC_IN_NS; - time.tv_nsec = ns - time.tv_sec * ODP_TIME_SEC_IN_NS; + time.spec.tv_sec = ns / ODP_TIME_SEC_IN_NS; + time.spec.tv_nsec = ns - time.spec.tv_sec * ODP_TIME_SEC_IN_NS;
return time; }
-static inline void time_wait_until(odp_time_t time) +/* + * HW time counter based functions + */ + +static inline odp_time_t time_hw_cur(void) { - odp_time_t cur; + odp_time_t time;
- do { - cur = time_local(); - } while (time_cmp(time, cur) > 0); + time.hw.count = cpu_global_time() - global.hw_start; + + return time; }
-static inline uint64_t time_local_res(void) +static inline uint64_t time_hw_res(void) { - int ret; - struct timespec tres; + /* Promise a bit lower resolution than average cycle counter + * frequency */ + return global.hw_freq_hz / 10; +}
- ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_getres failed\n"); +static inline int time_hw_cmp(odp_time_t t2, odp_time_t t1) +{ + if (odp_likely(t2.hw.count > t1.hw.count)) + return 1;
- return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; + if (t2.hw.count < t1.hw.count) + return -1; + + return 0; +} + +static inline odp_time_t time_hw_diff(odp_time_t t2, odp_time_t t1) +{ + odp_time_t time; + + time.hw.count = t2.hw.count - t1.hw.count; + + return time; +} + +static inline odp_time_t time_hw_sum(odp_time_t t1, odp_time_t t2) +{ + odp_time_t time; + + time.hw.count = t1.hw.count + t2.hw.count; + + return time; +} + +static inline uint64_t time_hw_to_ns(odp_time_t time) +{ + uint64_t nsec; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t count = time.hw.count; + uint64_t sec = 0; + + if (count >= freq_hz) { + sec = count / freq_hz; + count = count - sec * freq_hz; + } + + nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz; + + return (sec * ODP_TIME_SEC_IN_NS) + nsec; +} + +static inline odp_time_t time_hw_from_ns(uint64_t ns) +{ + odp_time_t time; + uint64_t count; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t sec = 0; + + if (ns >= ODP_TIME_SEC_IN_NS) { + sec = ns / ODP_TIME_SEC_IN_NS; + ns = ns - sec * ODP_TIME_SEC_IN_NS; + } + + count = sec * freq_hz; + count += (ns * freq_hz) / ODP_TIME_SEC_IN_NS; + + time.hw.reserved = 0; + time.hw.count = count; + + return time; +} + +/* + * Common functions + */ + +static inline odp_time_t time_cur(void) +{ + if (global.use_hw) + return time_hw_cur(); + + return time_spec_cur(); +} + +static inline uint64_t time_res(void) +{ + if (global.use_hw) + return time_hw_res(); + + return time_spec_res(); +} + +static inline int time_cmp(odp_time_t t2, odp_time_t t1) +{ + if (global.use_hw) + return time_hw_cmp(t2, t1); + + return time_spec_cmp(t2, t1); +} + +static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1) +{ + if (global.use_hw) + return time_hw_diff(t2, t1); + + return time_spec_diff(t2, t1); +} + +static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) +{ + if (global.use_hw) + return time_hw_sum(t1, t2); + + return time_spec_sum(t1, t2); +} + +static inline uint64_t time_to_ns(odp_time_t time) +{ + if (global.use_hw) + return time_hw_to_ns(time); + + return time_spec_to_ns(time); +} + +static inline odp_time_t time_from_ns(uint64_t ns) +{ + if (global.use_hw) + return time_hw_from_ns(ns); + + return time_spec_from_ns(ns); +} + +static inline void time_wait_until(odp_time_t time) +{ + odp_time_t cur; + + do { + cur = time_cur(); + } while (time_cmp(time, cur) > 0); }
odp_time_t odp_time_local(void) { - return time_local(); + return time_cur(); }
odp_time_t odp_time_global(void) { - return time_local(); + return time_cur(); }
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1) @@ -134,12 +294,12 @@ uint64_t odp_time_to_ns(odp_time_t time)
odp_time_t odp_time_local_from_ns(uint64_t ns) { - return time_local_from_ns(ns); + return time_from_ns(ns); }
odp_time_t odp_time_global_from_ns(uint64_t ns) { - return time_local_from_ns(ns); + return time_from_ns(ns); }
int odp_time_cmp(odp_time_t t2, odp_time_t t1) @@ -154,18 +314,18 @@ odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
uint64_t odp_time_local_res(void) { - return time_local_res(); + return time_res(); }
uint64_t odp_time_global_res(void) { - return time_local_res(); + return time_res(); }
void odp_time_wait_ns(uint64_t ns) { - odp_time_t cur = time_local(); - odp_time_t wait = time_local_from_ns(ns); + odp_time_t cur = time_cur(); + odp_time_t wait = time_from_ns(ns); odp_time_t end_time = time_sum(cur, wait);
time_wait_until(end_time); @@ -178,15 +338,31 @@ void odp_time_wait_until(odp_time_t time)
int odp_time_init_global(void) { - int ret; - struct timespec time; - - ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time); - if (ret) { - start_time = ODP_TIME_NULL; - } else { - start_time.tv_sec = time.tv_sec; - start_time.tv_nsec = time.tv_nsec; + struct timespec sys_time; + int ret = 0; + + memset(&global, 0, sizeof(time_global_t)); + + if (cpu_has_global_time()) { + global.use_hw = 1; + global.hw_freq_hz = cpu_global_time_freq(); + + if (global.hw_freq_hz == 0) + return -1; + + printf("HW time counter freq: %" PRIu64 " hz\n\n", + global.hw_freq_hz); + + global.hw_start = cpu_global_time(); + return 0; + } + + global.start_time = ODP_TIME_NULL; + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &sys_time); + if (ret == 0) { + global.start_time.spec.tv_sec = sys_time.tv_sec; + global.start_time.spec.tv_nsec = sys_time.tv_nsec; }
return ret;
commit 419cab0fcfccc7b702a7592dff98d108c24e49bf Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:55 2017 +0300
test: validation: add time accuracy test
Test ODP time keeping accuracy against system time.
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
diff --git a/test/common_plat/validation/api/time/time.c b/test/common_plat/validation/api/time/time.c index 36c419cb..e2ca2e17 100644 --- a/test/common_plat/validation/api/time/time.c +++ b/test/common_plat/validation/api/time/time.c @@ -7,6 +7,7 @@ #include <odp_api.h> #include "odp_cunit_common.h" #include "time_test.h" +#include <time.h>
#define BUSY_LOOP_CNT 30000000 /* used for t > min resolution */ #define BUSY_LOOP_CNT_LONG 6000000000 /* used for t > 4 sec */ @@ -140,25 +141,25 @@ void time_test_monotony(void) CU_ASSERT(ns3 > ns2); }
-static void time_test_cmp(time_cb time, time_from_ns_cb time_from_ns) +static void time_test_cmp(time_cb time_cur, time_from_ns_cb time_from_ns) { /* volatile to stop optimization of busy loop */ volatile int count = 0; odp_time_t t1, t2, t3;
- t1 = time(); + t1 = time_cur();
while (count < BUSY_LOOP_CNT) { count++; };
- t2 = time(); + t2 = time_cur();
while (count < BUSY_LOOP_CNT * 2) { count++; };
- t3 = time(); + t3 = time_cur();
CU_ASSERT(odp_time_cmp(t2, t1) > 0); CU_ASSERT(odp_time_cmp(t3, t2) > 0); @@ -191,7 +192,7 @@ void time_test_global_cmp(void) }
/* check that a time difference gives a reasonable result */ -static void time_test_diff(time_cb time, +static void time_test_diff(time_cb time_cur, time_from_ns_cb time_from_ns, uint64_t res) { @@ -202,13 +203,13 @@ static void time_test_diff(time_cb time, uint64_t upper_limit, lower_limit;
/* test timestamp diff */ - t1 = time(); + t1 = time_cur();
while (count < BUSY_LOOP_CNT) { count++; };
- t2 = time(); + t2 = time_cur(); CU_ASSERT(odp_time_cmp(t2, t1) > 0);
diff = odp_time_diff(t2, t1); @@ -268,7 +269,7 @@ void time_test_global_diff(void) }
/* check that a time sum gives a reasonable result */ -static void time_test_sum(time_cb time, +static void time_test_sum(time_cb time_cur, time_from_ns_cb time_from_ns, uint64_t res) { @@ -277,7 +278,7 @@ static void time_test_sum(time_cb time, uint64_t upper_limit, lower_limit;
/* sum timestamp and interval */ - t1 = time(); + t1 = time_cur(); ns2 = 103; t2 = time_from_ns(ns2); ns1 = odp_time_to_ns(t1); @@ -319,20 +320,20 @@ void time_test_global_sum(void) time_test_sum(odp_time_global, odp_time_global_from_ns, global_res); }
-static void time_test_wait_until(time_cb time, time_from_ns_cb time_from_ns) +static void time_test_wait_until(time_cb time_cur, time_from_ns_cb time_from_ns) { int i; odp_time_t lower_limit, upper_limit; odp_time_t start_time, end_time, wait; odp_time_t second = time_from_ns(ODP_TIME_SEC_IN_NS);
- start_time = time(); + start_time = time_cur(); wait = start_time; for (i = 0; i < WAIT_SECONDS; i++) { wait = odp_time_sum(wait, second); odp_time_wait_until(wait); } - end_time = time(); + end_time = time_cur();
wait = odp_time_diff(end_time, start_time); lower_limit = time_from_ns(WAIT_SECONDS * ODP_TIME_SEC_IN_NS - @@ -398,6 +399,45 @@ void time_test_wait_ns(void) } }
+static void time_test_accuracy(time_cb time_cur, time_from_ns_cb time_from_ns) +{ + int i; + odp_time_t t1, t2, wait, diff; + clock_t c1, c2; + double sec_t, sec_c; + odp_time_t sec = time_from_ns(ODP_TIME_SEC_IN_NS); + + c1 = clock(); + t1 = time_cur(); + + wait = odp_time_sum(t1, sec); + for (i = 0; i < 5; i++) { + odp_time_wait_until(wait); + wait = odp_time_sum(wait, sec); + } + + t2 = time_cur(); + c2 = clock(); + + diff = odp_time_diff(t2, t1); + sec_t = ((double)odp_time_to_ns(diff)) / ODP_TIME_SEC_IN_NS; + sec_c = ((double)(c2 - c1)) / CLOCKS_PER_SEC; + + /* Check that ODP time is within +-5% of system time */ + CU_ASSERT(sec_t < sec_c * 1.05); + CU_ASSERT(sec_t > sec_c * 0.95); +} + +static void time_test_local_accuracy(void) +{ + time_test_accuracy(odp_time_local, odp_time_local_from_ns); +} + +static void time_test_global_accuracy(void) +{ + time_test_accuracy(odp_time_global, odp_time_global_from_ns); +} + odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_constants), ODP_TEST_INFO(time_test_local_res), @@ -408,12 +448,14 @@ odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_local_sum), ODP_TEST_INFO(time_test_local_wait_until), ODP_TEST_INFO(time_test_wait_ns), + ODP_TEST_INFO(time_test_local_accuracy), ODP_TEST_INFO(time_test_global_res), ODP_TEST_INFO(time_test_global_conversion), ODP_TEST_INFO(time_test_global_cmp), ODP_TEST_INFO(time_test_global_diff), ODP_TEST_INFO(time_test_global_sum), ODP_TEST_INFO(time_test_global_wait_until), + ODP_TEST_INFO(time_test_global_accuracy), ODP_TEST_INFO_NULL };
commit 8b29e0ad33bb176374f47ae0bc2388b0d8d2b926 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:54 2017 +0300
test: validation: rename time test header file
Header file name time.h is ambiguos since C has a library header file with the same name.
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
diff --git a/test/common_plat/validation/api/time/Makefile.am b/test/common_plat/validation/api/time/Makefile.am index bf2d0268..999fcf15 100644 --- a/test/common_plat/validation/api/time/Makefile.am +++ b/test/common_plat/validation/api/time/Makefile.am @@ -7,4 +7,4 @@ test_PROGRAMS = time_main$(EXEEXT) dist_time_main_SOURCES = time_main.c time_main_LDADD = libtesttime.la $(LIBCUNIT_COMMON) $(LIBODP)
-EXTRA_DIST = time.h +EXTRA_DIST = time_test.h diff --git a/test/common_plat/validation/api/time/time.c b/test/common_plat/validation/api/time/time.c index df65c719..36c419cb 100644 --- a/test/common_plat/validation/api/time/time.c +++ b/test/common_plat/validation/api/time/time.c @@ -6,7 +6,7 @@
#include <odp_api.h> #include "odp_cunit_common.h" -#include "time.h" +#include "time_test.h"
#define BUSY_LOOP_CNT 30000000 /* used for t > min resolution */ #define BUSY_LOOP_CNT_LONG 6000000000 /* used for t > 4 sec */ diff --git a/test/common_plat/validation/api/time/time_main.c b/test/common_plat/validation/api/time/time_main.c index f86d638a..bf1cfe7b 100644 --- a/test/common_plat/validation/api/time/time_main.c +++ b/test/common_plat/validation/api/time/time_main.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */
-#include "time.h" +#include "time_test.h"
int main(int argc, char *argv[]) { diff --git a/test/common_plat/validation/api/time/time.h b/test/common_plat/validation/api/time/time_test.h similarity index 100% rename from test/common_plat/validation/api/time/time.h rename to test/common_plat/validation/api/time/time_test.h
commit 09a0e859caa4dbd68deb459e0160aed1ff8b5168 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:53 2017 +0300
test: sched_latency: use sys_info_print
Use the new system info print function.
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
diff --git a/test/common_plat/performance/odp_sched_latency.c b/test/common_plat/performance/odp_sched_latency.c index b4018687..026f2f6c 100644 --- a/test/common_plat/performance/odp_sched_latency.c +++ b/test/common_plat/performance/odp_sched_latency.c @@ -667,16 +667,7 @@ int main(int argc, char *argv[]) return -1; }
- printf("\n"); - printf("ODP system info\n"); - printf("---------------\n"); - printf("ODP API version: %s\n", odp_version_api_str()); - printf("ODP impl name: %s\n", odp_version_impl_name()); - printf("ODP impl details: %s\n", odp_version_impl_str()); - printf("CPU model: %s\n", odp_cpu_model_str()); - printf("CPU freq (hz): %" PRIu64 "\n", odp_cpu_hz_max()); - printf("Cache line size: %i\n", odp_sys_cache_line_size()); - printf("Max CPU count: %i\n", odp_cpu_count()); + odp_sys_info_print();
/* Get default worker cpumask */ if (args.cpu_count) @@ -687,9 +678,10 @@ int main(int argc, char *argv[])
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
- printf("Worker threads: %i\n", num_workers); - printf("First CPU: %i\n", odp_cpumask_first(&cpumask)); - printf("CPU mask: %s\n\n", cpumaskstr); + printf("CPU mask info:\n"); + printf(" Worker threads: %i\n", num_workers); + printf(" First CPU: %i\n", odp_cpumask_first(&cpumask)); + printf(" CPU mask: %s\n", cpumaskstr);
thread_tbl = calloc(sizeof(odph_odpthread_t), num_workers); if (!thread_tbl) {
commit 617999503a54c52daf86abcaef12542e67c3d47a Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:52 2017 +0300
test: validation: add odp_sys_info_print test
Added validation test for the new system info print call.
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
diff --git a/test/common_plat/validation/api/system/system.c b/test/common_plat/validation/api/system/system.c index 57ff34eb..5b7ca01a 100644 --- a/test/common_plat/validation/api/system/system.c +++ b/test/common_plat/validation/api/system/system.c @@ -301,6 +301,13 @@ void system_test_odp_cpu_hz_max_id(void) } }
+void system_test_info_print(void) +{ + printf("\n\nCalling system info print...\n"); + odp_sys_info_print(); + printf("...done. "); +} + odp_testinfo_t system_suite[] = { ODP_TEST_INFO(system_test_odp_version_numbers), ODP_TEST_INFO(system_test_odp_cpu_count), @@ -319,6 +326,7 @@ odp_testinfo_t system_suite[] = { ODP_TEST_INFO(system_test_odp_cpu_cycles_max), ODP_TEST_INFO(system_test_odp_cpu_cycles_resolution), ODP_TEST_INFO(system_test_odp_cpu_cycles_diff), + ODP_TEST_INFO(system_test_info_print), ODP_TEST_INFO_NULL, };
diff --git a/test/common_plat/validation/api/system/system.h b/test/common_plat/validation/api/system/system.h index cbb994eb..c33729b9 100644 --- a/test/common_plat/validation/api/system/system.h +++ b/test/common_plat/validation/api/system/system.h @@ -30,6 +30,7 @@ void system_test_odp_cpu_cycles_max(void); void system_test_odp_cpu_cycles(void); void system_test_odp_cpu_cycles_diff(void); void system_test_odp_cpu_cycles_resolution(void); +void system_test_info_print(void);
/* test arrays: */ extern odp_testinfo_t system_suite[];
commit 54e52ac90cc564e83d9fd3d22e5fd0d084fec1c3 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:51 2017 +0300
linux-gen: system: implement system info print
Print API, impl name, CPU model/freq, cache line size and CPU count by default. Print CPU flags in case of x86.
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
diff --git a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c index 53e2aaea..8ae2022a 100644 --- a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c @@ -25,3 +25,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/default/odp_sysinfo_parse.c b/platform/linux-generic/arch/default/odp_sysinfo_parse.c index 53e2aaea..8ae2022a 100644 --- a/platform/linux-generic/arch/default/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/default/odp_sysinfo_parse.c @@ -25,3 +25,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c b/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c index 407264b7..d6f75f28 100644 --- a/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c @@ -62,3 +62,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c b/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c index 3b88d55b..bd4b9b42 100644 --- a/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c @@ -61,3 +61,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/x86/odp_sysinfo_parse.c b/platform/linux-generic/arch/x86/odp_sysinfo_parse.c index 96127ec6..d77165a4 100644 --- a/platform/linux-generic/arch/x86/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/x86/odp_sysinfo_parse.c @@ -5,6 +5,7 @@ */
#include <odp_internal.h> +#include <arch/x86/cpu_flags.h> #include <string.h>
int cpuinfo_parser(FILE *file, system_info_t *sysinfo) @@ -73,3 +74,8 @@ uint64_t odp_cpu_hz_current(int id)
return 0; } + +void sys_info_print_arch(void) +{ + cpu_flags_print_all(); +} diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index acfc3012..90e2a629 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -133,6 +133,7 @@ int _odp_modules_init_global(void);
int cpuinfo_parser(FILE *file, system_info_t *sysinfo); uint64_t odp_cpu_hz_current(int id); +void sys_info_print_arch(void);
#ifdef __cplusplus } diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index 18c61dbe..40ffca07 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -14,6 +14,7 @@ #include <odp_posix_extensions.h>
#include <odp/api/system_info.h> +#include <odp/api/version.h> #include <odp_internal.h> #include <odp_debug_internal.h> #include <odp/api/align.h> @@ -405,3 +406,32 @@ int odp_cpu_count(void) { return odp_global_data.system_info.cpu_count; } + +void odp_sys_info_print(void) +{ + int len; + int max_len = 512; + char str[max_len]; + + len = snprintf(str, max_len, "\n" + "ODP system info\n" + "---------------\n" + "ODP API version: %s\n" + "ODP impl name: %s\n" + "CPU model: %s\n" + "CPU freq (hz): %" PRIu64 "\n" + "Cache line size: %i\n" + "CPU count: %i\n" + "\n", + odp_version_api_str(), + odp_version_impl_name(), + odp_cpu_model_str(), + odp_cpu_hz_max(), + odp_sys_cache_line_size(), + odp_cpu_count()); + + str[len] = '\0'; + ODP_PRINT("%s", str); + + sys_info_print_arch(); +}
commit 4fd46d42fb7fb7867ef269fc491eae7a7b303630 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:50 2017 +0300
linux-gen: cpu_flags: added x86 cpu flag read functions
When building on x86 CPU flags can be used to determine which CPU features are supported. CPU flag definitions and the code to read the flags is from DPDK.
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
diff --git a/configure.ac b/configure.ac index e86e2dca..38129030 100644 --- a/configure.ac +++ b/configure.ac @@ -224,6 +224,7 @@ AM_CONDITIONAL([HAVE_DOXYGEN], [test "x${DOXYGEN}" = "xdoxygen"]) AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ]) AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"]) AM_CONDITIONAL([helper_linux], [test x$helper_linux = xyes ]) +AM_CONDITIONAL([ARCH_IS_X86], [test "x${ARCH_DIR}" = "xx86"])
########################################################################## # Setup doxygen documentation diff --git a/platform/Makefile.inc b/platform/Makefile.inc index b4cc2433..c5b17b57 100644 --- a/platform/Makefile.inc +++ b/platform/Makefile.inc @@ -112,4 +112,6 @@ EXTRA_DIST = \ arch/powerpc/odp_sysinfo_parse.c \ arch/x86/odp/api/cpu_arch.h \ arch/x86/odp_cpu_arch.c \ - arch/x86/odp_sysinfo_parse.c + arch/x86/odp_sysinfo_parse.c \ + arch/x86/cpu_flags.c \ + arch/x86/cpu_flags.h diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 1bb09f1f..4015499e 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -253,6 +253,10 @@ __LIB__libodp_linux_la_SOURCES = \ arch/@ARCH_DIR@/odp_cpu_arch.c \ arch/@ARCH_DIR@/odp_sysinfo_parse.c
+if ARCH_IS_X86 +__LIB__libodp_linux_la_SOURCES += arch/@ARCH_DIR@/cpu_flags.c +endif + if HAVE_PCAP __LIB__libodp_linux_la_SOURCES += pktio/pcap.c endif diff --git a/platform/linux-generic/arch/x86/cpu_flags.c b/platform/linux-generic/arch/x86/cpu_flags.c new file mode 100644 index 00000000..954dac27 --- /dev/null +++ b/platform/linux-generic/arch/x86/cpu_flags.c @@ -0,0 +1,359 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch/x86/cpu_flags.h> +#include <odp_debug_internal.h> +#include <stdio.h> +#include <stdint.h> + +enum rte_cpu_flag_t { + /* (EAX 01h) ECX features*/ + RTE_CPUFLAG_SSE3 = 0, /**< SSE3 */ + RTE_CPUFLAG_PCLMULQDQ, /**< PCLMULQDQ */ + RTE_CPUFLAG_DTES64, /**< DTES64 */ + RTE_CPUFLAG_MONITOR, /**< MONITOR */ + RTE_CPUFLAG_DS_CPL, /**< DS_CPL */ + RTE_CPUFLAG_VMX, /**< VMX */ + RTE_CPUFLAG_SMX, /**< SMX */ + RTE_CPUFLAG_EIST, /**< EIST */ + RTE_CPUFLAG_TM2, /**< TM2 */ + RTE_CPUFLAG_SSSE3, /**< SSSE3 */ + RTE_CPUFLAG_CNXT_ID, /**< CNXT_ID */ + RTE_CPUFLAG_FMA, /**< FMA */ + RTE_CPUFLAG_CMPXCHG16B, /**< CMPXCHG16B */ + RTE_CPUFLAG_XTPR, /**< XTPR */ + RTE_CPUFLAG_PDCM, /**< PDCM */ + RTE_CPUFLAG_PCID, /**< PCID */ + RTE_CPUFLAG_DCA, /**< DCA */ + RTE_CPUFLAG_SSE4_1, /**< SSE4_1 */ + RTE_CPUFLAG_SSE4_2, /**< SSE4_2 */ + RTE_CPUFLAG_X2APIC, /**< X2APIC */ + RTE_CPUFLAG_MOVBE, /**< MOVBE */ + RTE_CPUFLAG_POPCNT, /**< POPCNT */ + RTE_CPUFLAG_TSC_DEADLINE, /**< TSC_DEADLINE */ + RTE_CPUFLAG_AES, /**< AES */ + RTE_CPUFLAG_XSAVE, /**< XSAVE */ + RTE_CPUFLAG_OSXSAVE, /**< OSXSAVE */ + RTE_CPUFLAG_AVX, /**< AVX */ + RTE_CPUFLAG_F16C, /**< F16C */ + RTE_CPUFLAG_RDRAND, /**< RDRAND */ + + /* (EAX 01h) EDX features */ + RTE_CPUFLAG_FPU, /**< FPU */ + RTE_CPUFLAG_VME, /**< VME */ + RTE_CPUFLAG_DE, /**< DE */ + RTE_CPUFLAG_PSE, /**< PSE */ + RTE_CPUFLAG_TSC, /**< TSC */ + RTE_CPUFLAG_MSR, /**< MSR */ + RTE_CPUFLAG_PAE, /**< PAE */ + RTE_CPUFLAG_MCE, /**< MCE */ + RTE_CPUFLAG_CX8, /**< CX8 */ + RTE_CPUFLAG_APIC, /**< APIC */ + RTE_CPUFLAG_SEP, /**< SEP */ + RTE_CPUFLAG_MTRR, /**< MTRR */ + RTE_CPUFLAG_PGE, /**< PGE */ + RTE_CPUFLAG_MCA, /**< MCA */ + RTE_CPUFLAG_CMOV, /**< CMOV */ + RTE_CPUFLAG_PAT, /**< PAT */ + RTE_CPUFLAG_PSE36, /**< PSE36 */ + RTE_CPUFLAG_PSN, /**< PSN */ + RTE_CPUFLAG_CLFSH, /**< CLFSH */ + RTE_CPUFLAG_DS, /**< DS */ + RTE_CPUFLAG_ACPI, /**< ACPI */ + RTE_CPUFLAG_MMX, /**< MMX */ + RTE_CPUFLAG_FXSR, /**< FXSR */ + RTE_CPUFLAG_SSE, /**< SSE */ + RTE_CPUFLAG_SSE2, /**< SSE2 */ + RTE_CPUFLAG_SS, /**< SS */ + RTE_CPUFLAG_HTT, /**< HTT */ + RTE_CPUFLAG_TM, /**< TM */ + RTE_CPUFLAG_PBE, /**< PBE */ + + /* (EAX 06h) EAX features */ + RTE_CPUFLAG_DIGTEMP, /**< DIGTEMP */ + RTE_CPUFLAG_TRBOBST, /**< TRBOBST */ + RTE_CPUFLAG_ARAT, /**< ARAT */ + RTE_CPUFLAG_PLN, /**< PLN */ + RTE_CPUFLAG_ECMD, /**< ECMD */ + RTE_CPUFLAG_PTM, /**< PTM */ + + /* (EAX 06h) ECX features */ + RTE_CPUFLAG_MPERF_APERF_MSR, /**< MPERF_APERF_MSR */ + RTE_CPUFLAG_ACNT2, /**< ACNT2 */ + RTE_CPUFLAG_ENERGY_EFF, /**< ENERGY_EFF */ + + /* (EAX 07h, ECX 0h) EBX features */ + RTE_CPUFLAG_FSGSBASE, /**< FSGSBASE */ + RTE_CPUFLAG_BMI1, /**< BMI1 */ + RTE_CPUFLAG_HLE, /**< Hardware Lock elision */ + RTE_CPUFLAG_AVX2, /**< AVX2 */ + RTE_CPUFLAG_SMEP, /**< SMEP */ + RTE_CPUFLAG_BMI2, /**< BMI2 */ + RTE_CPUFLAG_ERMS, /**< ERMS */ + RTE_CPUFLAG_INVPCID, /**< INVPCID */ + RTE_CPUFLAG_RTM, /**< Transactional memory */ + RTE_CPUFLAG_AVX512F, /**< AVX512F */ + + /* (EAX 80000001h) ECX features */ + RTE_CPUFLAG_LAHF_SAHF, /**< LAHF_SAHF */ + RTE_CPUFLAG_LZCNT, /**< LZCNT */ + + /* (EAX 80000001h) EDX features */ + RTE_CPUFLAG_SYSCALL, /**< SYSCALL */ + RTE_CPUFLAG_XD, /**< XD */ + RTE_CPUFLAG_1GB_PG, /**< 1GB_PG */ + RTE_CPUFLAG_RDTSCP, /**< RDTSCP */ + RTE_CPUFLAG_EM64T, /**< EM64T */ + + /* (EAX 80000007h) EDX features */ + RTE_CPUFLAG_INVTSC, /**< INVTSC */ + + /* The last item */ + RTE_CPUFLAG_NUMFLAGS, /**< This should always be the last! */ +}; + +enum cpu_register_t { + RTE_REG_EAX = 0, + RTE_REG_EBX, + RTE_REG_ECX, + RTE_REG_EDX, +}; + +typedef uint32_t cpuid_registers_t[4]; + +/** + * Struct to hold a processor feature entry + */ +struct feature_entry { + uint32_t leaf; /**< cpuid leaf */ + uint32_t subleaf; /**< cpuid subleaf */ + uint32_t reg; /**< cpuid register */ + uint32_t bit; /**< cpuid register bit */ +#define CPU_FLAG_NAME_MAX_LEN 64 + char name[CPU_FLAG_NAME_MAX_LEN]; /**< String for printing */ +}; + +#define FEAT_DEF(name, leaf, subleaf, reg, bit) \ + [RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name }, + +static const struct feature_entry cpu_feature_table[] = { + FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX, 0) + FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX, 1) + FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX, 2) + FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX, 3) + FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX, 4) + FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX, 5) + FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX, 6) + FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX, 7) + FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX, 8) + FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX, 9) + FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10) + FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12) + FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13) + FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14) + FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15) + FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17) + FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18) + FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19) + FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20) + FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21) + FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22) + FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23) + FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24) + FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25) + FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26) + FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27) + FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28) + FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29) + FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30) + + FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX, 0) + FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX, 1) + FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX, 2) + FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX, 3) + FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX, 4) + FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX, 5) + FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX, 6) + FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX, 7) + FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX, 8) + FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX, 9) + FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11) + FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12) + FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13) + FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14) + FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15) + FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16) + FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17) + FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18) + FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19) + FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21) + FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22) + FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23) + FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24) + FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25) + FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26) + FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27) + FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28) + FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29) + FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31) + + FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX, 0) + FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX, 1) + FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX, 2) + FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX, 4) + FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX, 5) + FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX, 6) + + FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX, 0) + FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX, 1) + FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX, 3) + + FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX, 0) + FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX, 2) + FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX, 4) + FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX, 5) + FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX, 6) + FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX, 7) + FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX, 8) + FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10) + FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11) + FEAT_DEF(AVX512F, 0x00000007, 0, RTE_REG_EBX, 16) + + FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX, 0) + FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX, 4) + + FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11) + FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20) + FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26) + FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27) + FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29) + + FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX, 8) +}; + +/* + * Execute CPUID instruction and get contents of a specific register + * + * This function, when compiled with GCC, will generate architecture-neutral + * code, as per GCC manual. + */ +static void cpu_get_features(uint32_t leaf, uint32_t subleaf, + cpuid_registers_t out) +{ +#if defined(__i386__) && defined(__PIC__) + /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */ + __asm__ __volatile__("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0" + : "=r" (out[RTE_REG_EBX]), + "=a" (out[RTE_REG_EAX]), + "=c" (out[RTE_REG_ECX]), + "=d" (out[RTE_REG_EDX]) + : "a" (leaf), "c" (subleaf)); +#else + __asm__ __volatile__("cpuid" + : "=a" (out[RTE_REG_EAX]), + "=b" (out[RTE_REG_EBX]), + "=c" (out[RTE_REG_ECX]), + "=d" (out[RTE_REG_EDX]) + : "a" (leaf), "c" (subleaf)); +#endif +} + +static int cpu_get_flag_enabled(enum rte_cpu_flag_t feature) +{ + const struct feature_entry *feat; + cpuid_registers_t regs; + + if (feature >= RTE_CPUFLAG_NUMFLAGS) + /* Flag does not match anything in the feature tables */ + return -1; + + feat = &cpu_feature_table[feature]; + + if (!feat->leaf) + /* This entry in the table wasn't filled out! */ + return -1; + + cpu_get_features(feat->leaf & 0xffff0000, 0, regs); + if (((regs[RTE_REG_EAX] ^ feat->leaf) & 0xffff0000) || + regs[RTE_REG_EAX] < feat->leaf) + return 0; + + /* get the cpuid leaf containing the desired feature */ + cpu_get_features(feat->leaf, feat->subleaf, regs); + + /* check if the feature is enabled */ + return (regs[feat->reg] >> feat->bit) & 1; +} + +static const char *cpu_get_flag_name(enum rte_cpu_flag_t feature) +{ + if (feature >= RTE_CPUFLAG_NUMFLAGS) + return NULL; + return cpu_feature_table[feature].name; +} + +void cpu_flags_print_all(void) +{ + int len, i; + int max_str = 1024; + int max_len = max_str - 1; + char str[max_str]; + + len = snprintf(str, max_len, "\nCPU features supported:\n"); + + for (i = 0; i < RTE_CPUFLAG_NUMFLAGS; i++) { + if (cpu_get_flag_enabled(i) > 0) + len += snprintf(&str[len], max_len - len, "%s ", + cpu_get_flag_name(i)); + } + + len += snprintf(&str[len], max_len - len, + "\n\nCPU features NOT supported:\n"); + + for (i = 0; i < RTE_CPUFLAG_NUMFLAGS; i++) { + if (cpu_get_flag_enabled(i) <= 0) + len += snprintf(&str[len], max_len - len, "%s ", + cpu_get_flag_name(i)); + } + + len += snprintf(&str[len], max_len - len, "\n\n"); + + str[len] = '\0'; + ODP_PRINT("%s", str); +} diff --git a/platform/linux-generic/arch/x86/cpu_flags.h b/platform/linux-generic/arch/x86/cpu_flags.h new file mode 100644 index 00000000..f709ca08 --- /dev/null +++ b/platform/linux-generic/arch/x86/cpu_flags.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PLAT_CPU_FLAGS_H_ +#define ODP_PLAT_CPU_FLAGS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void cpu_flags_print_all(void); + +#ifdef __cplusplus +} +#endif + +#endif
commit b8c3fffa30ff5c07fe28bab562510157050ebeff Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Apr 28 15:09:49 2017 +0300
api: system: added system info print
This information specifies the system where ODP application is running for debugging purposes.
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
diff --git a/include/odp/api/spec/system_info.h b/include/odp/api/spec/system_info.h index 0bb4f1f1..ca4dcdc7 100644 --- a/include/odp/api/spec/system_info.h +++ b/include/odp/api/spec/system_info.h @@ -45,6 +45,15 @@ uint64_t odp_sys_page_size(void); int odp_sys_cache_line_size(void);
/** + * Print system info + * + * Print out implementation defined information about the system. This + * information is intended for debugging purposes and may contain e.g. + * information about CPUs, memory and other HW configuration. + */ +void odp_sys_info_print(void); + +/** * @} */
-----------------------------------------------------------------------
Summary of changes: configure.ac | 1 + include/odp/api/spec/system_info.h | 9 + platform/Makefile.inc | 4 +- platform/linux-generic/Makefile.am | 5 + platform/linux-generic/arch/arm/odp_cpu_arch.c | 16 + .../linux-generic/arch/arm/odp_sysinfo_parse.c | 4 + platform/linux-generic/arch/default/odp_cpu_arch.c | 16 + .../linux-generic/arch/default/odp_sysinfo_parse.c | 4 + platform/linux-generic/arch/mips64/odp_cpu_arch.c | 16 + .../linux-generic/arch/mips64/odp_sysinfo_parse.c | 4 + platform/linux-generic/arch/powerpc/odp_cpu_arch.c | 16 + .../linux-generic/arch/powerpc/odp_sysinfo_parse.c | 4 + platform/linux-generic/arch/x86/cpu_flags.c | 368 +++++++++++++++++++++ .../odp_errno_define.h => arch/x86/cpu_flags.h} | 12 +- platform/linux-generic/arch/x86/odp_cpu_arch.c | 68 ++++ .../linux-generic/arch/x86/odp_sysinfo_parse.c | 6 + .../include/odp/api/plat/time_types.h | 19 +- platform/linux-generic/include/odp_internal.h | 1 + .../{odp_errno_define.h => odp_time_internal.h} | 16 +- platform/linux-generic/odp_system_info.c | 30 ++ platform/linux-generic/odp_time.c | 247 ++++++++++---- test/common_plat/performance/odp_sched_latency.c | 18 +- test/common_plat/validation/api/system/system.c | 8 + test/common_plat/validation/api/system/system.h | 1 + test/common_plat/validation/api/time/Makefile.am | 2 +- test/common_plat/validation/api/time/time.c | 68 +++- test/common_plat/validation/api/time/time_main.c | 2 +- .../validation/api/time/{time.h => time_test.h} | 0 28 files changed, 846 insertions(+), 119 deletions(-) create mode 100644 platform/linux-generic/arch/x86/cpu_flags.c copy platform/linux-generic/{include/odp_errno_define.h => arch/x86/cpu_flags.h} (58%) copy platform/linux-generic/include/{odp_errno_define.h => odp_time_internal.h} (52%) rename test/common_plat/validation/api/time/{time.h => time_test.h} (100%)
hooks/post-receive