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;
 }

Reply via email to