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 <zhangyuan29@xiaomi.com>
This commit is contained in:
zhangyuan29
2025-03-18 09:48:37 +08:00
committed by Donny(董九柱)
parent 633014b6b1
commit 197ed9fc94
2 changed files with 17 additions and 5 deletions
+9
View File
@@ -614,6 +614,15 @@ config ARCH_PERF_EVENTS
Enable hardware performance counter support for perf events. If Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only. 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 config ARCH_HAVE_BOOTLOADER
bool bool
default n default n
+8 -5
View File
@@ -43,6 +43,7 @@ struct perf_s
spinlock_t lock; spinlock_t lock;
unsigned long last; unsigned long last;
unsigned long overflow; unsigned long overflow;
clock_t timeout;
}; };
/**************************************************************************** /****************************************************************************
@@ -61,10 +62,10 @@ static struct perf_s g_perf;
static void perf_update(wdparm_t arg) 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(); 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) void perf_init(void)
{ {
FAR struct perf_s *perf = &g_perf; 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(); perf->last = up_perf_gettime();
/* Periodic check for overflow */ /* 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; 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); spin_unlock_irqrestore(&perf->lock, flags);
return result; return result;
} }