casaroli opened a new pull request, #21458:
URL: https://github.com/apache/nuttx/pull/21458

   ## Summary
   
   With PERF_OVERFLOW_CORRECTION, perf_gettime() compares the counter with one 
global "last" value. On SMP each CPU has its own counter (PMCCNTR on ARMv7-A), 
and the counters do not hold the same value. A read on a CPU with a lower 
counter than the last read on another CPU counts as an overflow, and adds 2^32 
cycles to all later values. On qemu-armv7a:smp a thread that runs for 500 ms 
shows 4795 ms of CPU time.
   
   This PR keeps the overflow state for each CPU. The state belongs to one CPU, 
so perf_gettime() disables the local interrupts and needs no spinlock. The 
watchdog that reads the counter before it can wrap twice runs on one CPU only, 
so each CPU's watchdog now sends a SMP call to the CPU of its state.
   
   ## Impact
   
   SMP builds with PERF_OVERFLOW_CORRECTION only. A value from perf_gettime() 
compares only with a value from the same CPU, as in an SMP build without the 
option. With SMP off the object has the same size (304 bytes of text, 48 of bss 
on qemu-armv7a:nsh, before and after). The option is off by default. No API 
change, no documentation change (Documentation/ does not name the option).
   
   ## Testing
   
   Test program perfover.c: a thread pinned to each CPU in turn runs a busy 
loop (CLOCK_MONOTONIC) and reads CLOCK_THREAD_CPUTIME_ID, while a second thread 
on the next CPU sleeps 1 ms in a loop. qemu-armv7a:smp, 4 CPUs, QEMU TCG, 
SCHED_CRITMONITOR, ARCH_PERF_EVENTS, PERF_OVERFLOW_CORRECTION. CPU time in ms, 
CPU 0 to 3:
   
   | Busy time | master | this PR |
   |---|---|---|
   | 500 ms (no second thread) | 500, 500, 4795, 500 | 500, 500, 500, 500 |
   | 1000 ms | 5297, 9590, 5295, 5296 | 1000, 1000, 1000, 1000 |
   | 10000 ms (2 wraps at 1 GHz) | 35769, 27188, 35770, 14295 | 10000, 10000, 
10000, 10000 |
   
   To check the SMP call, the same 10000 ms test with `perf_gettime()` in the 
watchdog in place of the SMP call gives 10000, 1410, 1410, 1410: the CPUs that 
do not run the watchdog miss the wraps. The same test with 2 CPUs on this PR 
gives 10000, 10000. ostest exits with status 0 on master and with this PR.
   
   No SMP (qemu-armv7a:nsh, same options): 10000 ms before and after.
   
   Builds with -Werror and the option on: qemu-armv7a:smp, :nsh, :knsh_smp 
(kernel, SMP), :knsh (kernel), mps2-an500:knsh (protected), 
raspberrypi-pico-2:smp (ARMv8-M, SMP), rv-virt:smp (RISC-V, SMP). 
arty_a7:knsh-tickless (the defconfig in the tree that sets the option) also 
builds. The code applies only when unsigned long is not 64 bits, as before. The 
RISC-V and RP2350 configurations were built only, not run.
   
   The runs and builds are on 39a1f27900c. After the rebase on 3d57048f1e1, the 
4-CPU run gives 500 ms on each CPU for the 500 ms test and 10000 ms on each CPU 
for the 10000 ms test.
   
   The branch is now rebased on f19dbe6f6d3 (no change in the touched files).
   


-- 
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