casaroli opened a new pull request, #20947: URL: https://github.com/apache/nuttx/pull/20947
## Summary `CLOCKS_PER_SEC` is the system tick rate in NuttX (`1000000 / CONFIG_USEC_PER_TICK`, 100 by default), and `clock()` returns system ticks. XSI requires `CLOCKS_PER_SEC` to be 1000000, so `clock()` counts microseconds: - https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html - https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock.html Issue #3516 reported this. The tick rate is `CLK_TCK`, the unit of `times()` and of `sysconf(_SC_CLK_TCK)`. This PR defines `CLOCKS_PER_SEC` as 1000000. `clock()` returns microseconds (from `clock_systime_timespec()`), `times()` still returns ticks, and `sysconf(_SC_CLK_TCK)` returns `CLK_TCK`. The resolution of `clock()` does not change: it still advances once per tick. The two earlier steps are merged: #20923 (the kernel and libc use `CLK_TCK` for the tick rate and the tick counter for tick values, with `CLOCK2TICK()`, `CLOCK2MSEC()` and `CLOCK2USEC()` for `clock()` values) and apache/nuttx-apps#3904 (the same for the apps). apache/nuttx-apps#3906 does it for the `TIME` function of bas. After them, no code in nuttx or nuttx-apps uses `CLOCKS_PER_SEC` as the tick rate or a `clock()` value as ticks. The dev@ thread "[DISCUSS] Breaking change: make CLOCKS_PER_SEC 1000000" (https://lists.apache.org/thread/bqxry570g9t63j63zmk4c5l82lybtx4s) discusses the change; this PR stays a draft until the vote. ## BREAKING CHANGE `CLOCKS_PER_SEC` is 1000000 and `clock()` counts microseconds, in all configurations. - Code that uses `CLOCKS_PER_SEC` as the number of system ticks per second (for example, to convert seconds into a timeout for `wd_start()` or `nxsig_usleep()`) must use `CLK_TCK` or `TICK_PER_SEC`. - Code that uses the value of `clock()` as ticks (for example `TICK2MSEC(clock() - start)`) must use `clock_systime_ticks()` in the kernel, `CLOCK2TICK(clock())` in user space, or convert a difference of `clock()` values with `CLOCK2MSEC()`/`CLOCK2USEC()` or `CLOCKS_PER_SEC`. - Code that divides `clock()` by `CLOCKS_PER_SEC` needs no change. - In protected and kernel builds `clock()` is a system call: build programs again with the new header. Quick fix: replace `CLOCKS_PER_SEC` by `CLK_TCK` where it means "ticks per second", and `clock()` by `clock_systime_ticks()` where kernel code wants ticks. ## Impact All configurations. `clock_t` is 64 bits (`int64_t`), so microseconds do not overflow. `times()` and `sysconf(_SC_CLK_TCK)` keep their values. ## Testing Test program `clockunits.c` on qemu-armv8a:knsh (QEMU with HVF): | Case | master | this PR | |---|---|---| | 1 `CLOCKS_PER_SEC` == 1000000 | FAIL (1000) | PASS | | 2 `sysconf(_SC_CLK_TCK)` == `CLK_TCK` | PASS | PASS | | 3 `clock()` / `CLOCKS_PER_SEC` measures 0.5 s of CPU time | PASS | PASS | | 4 `times()` / `sysconf(_SC_CLK_TCK)` measures the same time | PASS | PASS | Test program `clktick.c` (the test of step 2) with `CONFIG_LIBC_USRWORK`, on this PR: `sysconf(_SC_CLK_TCK)` is 1000, `times()` and `clock()` measure a 0.5 s sleep (501 ms and 500 ms), and a user-space work item queued with 500 ticks has `work_timeleft()` 501 and runs after 501 ms: PASS, as on master. ostest exits with status 0 on qemu-armv8a:knsh (with `CONFIG_LIBC_USRWORK`) and qemu-armv8a:nsh. Build, each OK: qemu-armv8a:nsh (flat, arm64), qemu-armv8a:knsh (kernel, arm64), rv-virt:nsh64 (flat, rv64), rv-virt:pnsh64 (protected, rv64), rv-virt:knsh64 (kernel, rv64), lm3s6965-ek:qemu-protected (protected, armv7-m). Real hardware (CONTRIBUTING.md 1.14), flat nsh with `clockunits.c` and ostest, `CONFIG_USEC_PER_TICK=10000`: | Board | Arch | master `clockunits` | this PR `clockunits` | this PR ostest | |---|---|---|---|---| | Pimoroni Pico Plus 2 (RP2350), `pimoroni-pico-2-plus:nsh` | Armv8-M (Cortex-M33) | case 1 FAIL (`CLOCKS_PER_SEC`=100) | 4/4 PASS | status 0 | | ESP32-S3-DevKitC (WROOM-2 N32R8V), `esp32s3-devkit:nsh` | Xtensa LX7 | case 1 FAIL (`CLOCKS_PER_SEC`=100) | 4/4 PASS | status 0 | On both boards `clock()` and `times()` measure 0.510 s for the 0.5 s busy loop. The ESP32-S3 ostest run uses `CONFIG_ESP32S3_DONT_USE_ROM_LIBC=y`: with the ROM `strtoul()` ostest fails in `libc_strto.c` on master too. The board runs used `07cd8b341fa`: the same commit on #20923 before #20923 merged (`git range-diff` shows no change). <details><summary>RP2350 console (this PR)</summary> ``` NuttX 13.0.1-RC0 07cd8b341fa Oct 24 2026 01:52:33 arm pimoroni-pico-2-plus clockunits: CLOCKS_PER_SEC=1000000 CLK_TCK=100 _SC_CLK_TCK=100 clockunits: 1 CLOCKS_PER_SEC == 1000000 PASS clockunits: 2 _SC_CLK_TCK == CLK_TCK PASS clockunits: clock() 0.510 s, times() 0.510 s clockunits: 3 clock() / CLOCKS_PER_SEC is seconds PASS clockunits: 4 times() / _SC_CLK_TCK is seconds PASS clockunits: PASS ostest_main: Exiting with status 0 NuttX 13.0.1-RC0 07cd8b341fa Oct 24 2026 01:52:33 arm pimoroni-pico-2-plus ``` </details> <details><summary>ESP32-S3 console (this PR)</summary> ``` NuttX 13.0.1-RC0 07cd8b341fa Oct 24 2026 02:06:23 xtensa esp32s3-devkit clockunits: CLOCKS_PER_SEC=1000000 CLK_TCK=100 _SC_CLK_TCK=100 clockunits: 1 CLOCKS_PER_SEC == 1000000 PASS clockunits: 2 _SC_CLK_TCK == CLK_TCK PASS clockunits: clock() 0.510 s, times() 0.510 s clockunits: 3 clock() / CLOCKS_PER_SEC is seconds PASS clockunits: 4 times() / _SC_CLK_TCK is seconds PASS clockunits: PASS ostest_main: Exiting with status 0 NuttX 13.0.1-RC0 07cd8b341fa Oct 24 2026 02:06:23 xtensa esp32s3-devkit ``` </details> `tools/checkpatch.sh -c -u -m -g` passes. -- 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]
