mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user