casaroli opened a new pull request, #21428:
URL: https://github.com/apache/nuttx/pull/21428
## Summary
This PR fixes two cases where perf_gettime() reads a hardware counter that
does not run, so every critmon time (and the CPU-time clocks of
SCHED_CRITMONITOR) is 0.
1. sched/clock: since #16487, an arch with ARCH_HAVE_PERF_EVENTS always
provides up_perf_*(), and drivers/timers/arch_alarm.c and arch_timer.c do not.
But clock_perf.c still uses up_perf_*() with ALARM_ARCH or TIMER_ARCH, also
when ARCH_PERF_EVENTS is off. The boards call up_perf_init() only with
ARCH_PERF_EVENTS, so the counter does not run: perf_gettime() returns a
constant and perf_convert() divides by ULONG_MAX. On arm64 (always ALARM_ARCH)
this happens when SCHED_CRITMONITOR is enabled in an existing .config: the
"default y if SCHED_CRITMONITOR" of ARCH_PERF_EVENTS does not change a value
that the .config already has. The first commit makes perf_*() use up_perf_*()
only when they count: with ARCH_PERF_EVENTS, or when arch_alarm.c /
arch_timer.c provide them. Else perf_*() use the system ticks, as the help of
ARCH_PERF_EVENTS says ("If disabled, perf events will use software events
only").
2. arch/arm64: the boards call up_perf_init() once, on the boot CPU, but the
cycle counter (PMCCNTR_EL0) belongs to each CPU. With SMP the counter of CPU 1
to N does not run, and the threads on those CPUs get no CPU time. The second
commit starts the cycle counter of each secondary CPU in
arm64_boot_secondary_c_routine(), with the same condition (ARCH_PERF_EVENTS).
The cluster PMU (ARCH_CLUSTER_PMU) is common to the CPUs and is not started
again.
## Impact
Commit 1: only configurations with ARCH_HAVE_PERF_EVENTS, ALARM_ARCH or
TIMER_ARCH, and ARCH_PERF_EVENTS off. Their perf times change from a stopped
hardware counter to the system ticks. On mpfs and litex the counter needs no
up_perf_init(), so there perf_*() lose the counter resolution unless
ARCH_PERF_EVENTS is on (the default with SCHED_CRITMONITOR, SCHED_IRQMONITOR,
RPMSG_PING and SEGGER_SYSVIEW). No defconfig in the tree has this case.
ARCH_PERF_EVENTS_USER_ACCESS keeps up_perf_*(), because libc reads the counter
directly.
Commit 2: arm64 SMP with ARCH_PERF_EVENTS. The secondary CPUs now run their
cycle counter.
No API change. No documentation change: the help of ARCH_PERF_EVENTS already
describes the behavior of commit 1.
## Testing
perfclk.c runs a busy loop of 200 ms (CLOCK_MONOTONIC) and prints the change
of the run time in /proc/self/critmon (perf_convert()) and of
CLOCK_THREAD_CPUTIME_ID. perfsmp.c starts one thread for each CPU, pinned with
pthread_attr_setaffinity_np(), and reads CLOCK_THREAD_CPUTIME_ID over a busy
loop of 500 ms. All with SCHED_CRITMONITOR.
| config | test | master | this PR |
|---|---|---|---|
| qemu-armv8a:nsh, HVF, no ARCH_PERF_EVENTS | perfclk, critmon run time | 0
ms | 200 ms |
| qemu-armv8a:nsh, TCG, no ARCH_PERF_EVENTS | perfclk, critmon run time | 0
ms | 220 ms (busy 205 ms) |
| qemu-armv8a:knsh, HVF, no ARCH_PERF_EVENTS | perfclk, critmon run time | 0
ms | 200 ms |
| qemu-armv8a:nsh_smp (2 CPUs), HVF, ARCH_PERF_EVENTS | perfsmp, CPU 0 / CPU
1 | 8020 / 0 ms | 8000 / 8002 ms |
The CPU times with ARCH_PERF_EVENTS are 16 times too large on master and
with this PR. #21425 (the QEMU PMU rate) fixes that. With #21425 and #21424,
perfsmp gives 525 / 502 ms (HVF) and 500 / 500 ms (TCG) (CPU 0 / CPU 1), the
same as the busy time.
CLOCK_THREAD_CPUTIME_ID stays 0 with this PR alone when ARCH_PERF_EVENTS is
off, because nxclock_gettime() calls up_perf_convert() directly. #21424 changes
it to perf_convert(). With both PRs, perfclk gives 200 ms on qemu-armv8a:nsh
and 204 ms on qemu-armv8a:knsh (HVF, no ARCH_PERF_EVENTS).
ostest exits with status 0 on qemu-armv8a:knsh, qemu-armv8a:nsh and
qemu-armv8a:nsh_smp (2 CPUs, ARCH_PERF_EVENTS), all with HVF.
Builds with -Werror and SCHED_CRITMONITOR: qemu-armv8a:nsh, :knsh (kernel),
:nsh_smp (with ARCH_PERF_EVENTS, and with PERF_OVERFLOW_CORRECTION),
fvp-armv8r:nsh_smp (also with ARCH_CLUSTER_PMU) and :pnsh_smp (protected,
ARCH_PERF_EVENTS_USER_ACCESS), nucleo-l432kc:nsh (Cortex-M, no ALARM_ARCH),
mps2-an500:knsh (protected), rv-virt:nsh64 and :pnsh64 (no
ARCH_HAVE_PERF_EVENTS), qemu-armv7r:pnsh (ARCH_PERF_EVENTS_USER_ACCESS, with
and without ARCH_PERF_EVENTS).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]