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
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
+8 -5
View File
@@ -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;
}