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]

Reply via email to