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]
