From d2588efa504fa78a7670f2848e34c57abfebab93 Mon Sep 17 00:00:00 2001 From: Petri Savolainen Date: Wed, 22 Nov 2023 15:45:43 +0200 Subject: linux-gen: time: change to non-zero startup time Time does not have to start from zero anymore. Optimize time stamp performance by returning the counter value directly. Implemented the new startup time function. Signed-off-by: Petri Savolainen Reviewed-by: Janne Peltonen --- .../arch/common/odp/api/abi/time_cpu_inlines.h | 13 +++++-- platform/linux-generic/arch/common/odp_time_cpu.c | 28 ++++++++++++++- .../arch/default/odp/api/abi/time_inlines.h | 1 + platform/linux-generic/arch/default/odp_time.c | 40 ++++++++++++++-------- .../include/odp/api/plat/time_inlines.h | 6 ++++ 5 files changed, 69 insertions(+), 19 deletions(-) (limited to 'platform/linux-generic') diff --git a/platform/linux-generic/arch/common/odp/api/abi/time_cpu_inlines.h b/platform/linux-generic/arch/common/odp/api/abi/time_cpu_inlines.h index c154c5f1a..553114666 100644 --- a/platform/linux-generic/arch/common/odp/api/abi/time_cpu_inlines.h +++ b/platform/linux-generic/arch/common/odp/api/abi/time_cpu_inlines.h @@ -21,8 +21,9 @@ extern "C" { #define _ODP_TIME_GIGA_HZ 1000000000ULL typedef struct _odp_time_global_t { - uint64_t start_time; uint64_t freq_hz; + uint64_t start_time; + uint64_t start_time_ns; } _odp_time_global_t; @@ -32,7 +33,7 @@ static inline odp_time_t _odp_time_cur(void) { odp_time_t time; - time.count = _odp_time_cpu_global() - _odp_time_glob.start_time; + time.count = _odp_time_cpu_global(); return time; } @@ -40,7 +41,7 @@ static inline odp_time_t _odp_time_cur_strict(void) { odp_time_t time; - time.count = _odp_time_cpu_global_strict() - _odp_time_glob.start_time; + time.count = _odp_time_cpu_global_strict(); return time; } @@ -86,6 +87,12 @@ static inline uint64_t _odp_time_res(void) return _odp_time_glob.freq_hz; } +static inline void _odp_time_startup(odp_time_startup_t *startup) +{ + startup->global.count = _odp_time_glob.start_time; + startup->global_ns = _odp_time_glob.start_time_ns; +} + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/arch/common/odp_time_cpu.c b/platform/linux-generic/arch/common/odp_time_cpu.c index bbfe82e21..3c392de0c 100644 --- a/platform/linux-generic/arch/common/odp_time_cpu.c +++ b/platform/linux-generic/arch/common/odp_time_cpu.c @@ -17,6 +17,8 @@ #include #include +#define YEAR_IN_SEC (365 * 24 * 3600) + #include _odp_time_global_t _odp_time_glob; @@ -25,6 +27,8 @@ _odp_time_global_t _odp_time_glob; int _odp_time_init_global(void) { + uint64_t count, diff, years; + odp_time_t time; _odp_time_global_t *global = &_odp_time_glob; memset(global, 0, sizeof(_odp_time_global_t)); @@ -38,7 +42,29 @@ int _odp_time_init_global(void) _ODP_PRINT("HW time counter freq: %" PRIu64 " hz\n\n", global->freq_hz); - global->start_time = _odp_time_cpu_global(); + count = _odp_time_cpu_global(); + time.count = count; + global->start_time = count; + global->start_time_ns = _odp_time_to_ns(time); + + /* Make sure that counters will not wrap */ + diff = UINT64_MAX - count; + years = (diff / global->freq_hz) / YEAR_IN_SEC; + + if (years < 10) { + _ODP_ERR("Time counter would wrap in 10 years: %" PRIu64 "\n", count); + return -1; + } + + diff = UINT64_MAX - global->start_time_ns; + years = (diff / ODP_TIME_SEC_IN_NS) / YEAR_IN_SEC; + + if (years < 10) { + _ODP_ERR("Time in nsec would wrap in 10 years: %" PRIu64 "\n", + global->start_time_ns); + return -1; + } + return 0; } diff --git a/platform/linux-generic/arch/default/odp/api/abi/time_inlines.h b/platform/linux-generic/arch/default/odp/api/abi/time_inlines.h index b38e52dac..ed0ffdb3f 100644 --- a/platform/linux-generic/arch/default/odp/api/abi/time_inlines.h +++ b/platform/linux-generic/arch/default/odp/api/abi/time_inlines.h @@ -18,6 +18,7 @@ extern "C" { odp_time_t _odp_time_cur(void); uint64_t _odp_time_res(void); +void _odp_time_startup(odp_time_startup_t *startup); static inline odp_time_t _odp_time_cur_strict(void) { diff --git a/platform/linux-generic/arch/default/odp_time.c b/platform/linux-generic/arch/default/odp_time.c index 919a3ba68..664a5deae 100644 --- a/platform/linux-generic/arch/default/odp_time.c +++ b/platform/linux-generic/arch/default/odp_time.c @@ -16,31 +16,24 @@ #include #include +#include #include #include #include +#define YEAR_IN_SEC (365 * 24 * 3600) + typedef struct _odp_time_global_t { struct timespec start_time; + uint64_t start_time_ns; } _odp_time_global_t; _odp_time_global_t _odp_time_glob; -static inline uint64_t time_diff_nsec(struct timespec *t2, struct timespec *t1) +static inline uint64_t time_nsec(struct timespec *t) { - struct timespec diff; - uint64_t nsec; - - diff.tv_sec = t2->tv_sec - t1->tv_sec; - diff.tv_nsec = t2->tv_nsec - t1->tv_nsec; - - if (diff.tv_nsec < 0) { - diff.tv_nsec += ODP_TIME_SEC_IN_NS; - diff.tv_sec -= 1; - } - - nsec = (diff.tv_sec * ODP_TIME_SEC_IN_NS) + diff.tv_nsec; + uint64_t nsec = (t->tv_sec * ODP_TIME_SEC_IN_NS) + t->tv_nsec; return nsec; } @@ -52,13 +45,12 @@ odp_time_t _odp_time_cur(void) int ret; odp_time_t time; struct timespec sys_time; - struct timespec *start_time = &_odp_time_glob.start_time; ret = clock_gettime(CLOCK_MONOTONIC_RAW, &sys_time); if (odp_unlikely(ret != 0)) _ODP_ABORT("clock_gettime() failed\n"); - time.nsec = time_diff_nsec(&sys_time, start_time); + time.nsec = time_nsec(&sys_time); return time; } @@ -75,11 +67,18 @@ uint64_t _odp_time_res(void) return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; } +void _odp_time_startup(odp_time_startup_t *startup) +{ + startup->global.nsec = _odp_time_glob.start_time_ns; + startup->global_ns = _odp_time_glob.start_time_ns; +} + #include int _odp_time_init_global(void) { struct timespec *start_time; + uint64_t diff, years; int ret = 0; _odp_time_global_t *global = &_odp_time_glob; @@ -93,6 +92,17 @@ int _odp_time_init_global(void) if (ret) _ODP_ERR("clock_gettime() failed: %d\n", ret); + global->start_time_ns = time_nsec(start_time); + + diff = UINT64_MAX - global->start_time_ns; + years = (diff / ODP_TIME_SEC_IN_NS) / YEAR_IN_SEC; + + if (years < 10) { + _ODP_ERR("Time in nsec would wrap in 10 years: %" PRIu64 "\n", + global->start_time_ns); + return -1; + } + return ret; } diff --git a/platform/linux-generic/include/odp/api/plat/time_inlines.h b/platform/linux-generic/include/odp/api/plat/time_inlines.h index 76c9276d3..8ead06f7b 100644 --- a/platform/linux-generic/include/odp/api/plat/time_inlines.h +++ b/platform/linux-generic/include/odp/api/plat/time_inlines.h @@ -46,6 +46,7 @@ #define odp_time_wait_ns __odp_time_wait_ns #define odp_time_wait_until __odp_time_wait_until + #define odp_time_startup __odp_time_startup #else #define _ODP_INLINE #endif @@ -180,6 +181,11 @@ _ODP_INLINE void odp_time_wait_ns(uint64_t ns) odp_time_wait_until(end_time); } +_ODP_INLINE void odp_time_startup(odp_time_startup_t *startup) +{ + _odp_time_startup(startup); +} + /** @endcond */ #endif -- cgit v1.2.3