This is an automated email from the ASF dual-hosted git repository. jiuzhudong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 197ed9fc94cca42fc552d8ef32f0a6d3686adf34 Author: zhangyuan29 <[email protected]> AuthorDate: Tue Mar 18 09:48:37 2025 +0800 sched/clock: add perf overflow offset for clock perf dd ARCH_PERF_COUNT_BITWIDTH configuration to support architectures with different perf counter bit widths (TriCore 31-bit, others 32-bit), enabling proper overflow correction across diverse platforms. Signed-off-by: zhangyuan29 <[email protected]> --- arch/Kconfig | 9 +++++++++ sched/clock/clock_perf.c | 13 ++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index a1235dc623f..4a44cf7d335 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -614,6 +614,15 @@ config ARCH_PERF_EVENTS Enable hardware performance counter support for perf events. If disabled, perf events will use software events only. +config ARCH_PERF_COUNT_BITWIDTH + int "Bit width of the perf count" + default 31 if ARCH_TRICORE + default 32 if !ARCH_TRICORE + depends on PERF_OVERFLOW_CORRECTION + ---help--- + Bit width of the perf count. When arch is tricore, the value is 31. + When arch is not tricore, the value is 32. + config ARCH_HAVE_BOOTLOADER bool default n diff --git a/sched/clock/clock_perf.c b/sched/clock/clock_perf.c index 50ab97d25ad..646e84fcb2a 100644 --- a/sched/clock/clock_perf.c +++ b/sched/clock/clock_perf.c @@ -43,6 +43,7 @@ struct perf_s spinlock_t lock; unsigned long last; unsigned long overflow; + clock_t timeout; }; /**************************************************************************** @@ -61,10 +62,10 @@ static struct perf_s g_perf; static void perf_update(wdparm_t arg) { - clock_t tick = (clock_t)LONG_MAX * TICK_PER_SEC / up_perf_getfreq(); + FAR struct perf_s *perf = &g_perf; perf_gettime(); - wd_start_next((FAR struct wdog_s *)arg, tick, perf_update, arg); + wd_start_next((FAR struct wdog_s *)arg, perf->timeout, perf_update, arg); } /**************************************************************************** @@ -78,13 +79,14 @@ static void perf_update(wdparm_t arg) void perf_init(void) { FAR struct perf_s *perf = &g_perf; - clock_t tick = (clock_t)LONG_MAX * TICK_PER_SEC / up_perf_getfreq(); + perf->timeout = (((clock_t)1 << (CONFIG_ARCH_PERF_COUNT_BITWIDTH - 1)) - 1) + * TICK_PER_SEC / up_perf_getfreq(); perf->last = up_perf_gettime(); /* Periodic check for overflow */ - wd_start(&perf->wdog, tick, perf_update, (wdparm_t)perf); + wd_start(&perf->wdog, perf->timeout, perf_update, (wdparm_t)perf); } /**************************************************************************** @@ -106,7 +108,8 @@ clock_t perf_gettime(void) } perf->last = now; - result = (clock_t)now | (clock_t)perf->overflow << 32; + result = (clock_t)now | \ + (clock_t)perf->overflow << CONFIG_ARCH_PERF_COUNT_BITWIDTH; spin_unlock_irqrestore(&perf->lock, flags); return result; }
