Hello all,

This is the vote for the breaking change in
https://github.com/apache/nuttx/pull/20947, as CONTRIBUTING.md 1.13
step 5 requires. The discussion is in the [DISCUSS] thread "Breaking
change: make CLOCKS_PER_SEC 1000000":
https://lists.apache.org/thread/bqxry570g9t63j63zmk4c5l82lybtx4s

In that thread, Xiang asked for no Kconfig option ("always conform the
spec or not change it at all"), so the change applies to all
configurations. Alan agreed and suggested the next major release.
Greg asked about the timer interrupt rate: the change does not change
the timer or its interrupt rate (my reply in the thread). Nobody
objected.

The change:
CLOCKS_PER_SEC is 1000000 and clock() returns microseconds (from
clock_systime_timespec()). Today CLOCKS_PER_SEC is the system tick rate
(1000000 / CONFIG_USEC_PER_TICK, 100 by default), and clock() returns
ticks. The tick rate does not change: it is CLK_TCK and TICK_PER_SEC,
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. clock_t is int64_t, so the value does not overflow.

Reference: <time.h> and clock() in POSIX.1-2024 (XSI: CLOCKS_PER_SEC
is one million):
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html
https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock.html
Issue: https://github.com/apache/nuttx/issues/3516

Why it is necessary:
- Programs written for POSIX systems expect 1000000, and the Open
  POSIX Test Suite checks it (conformance/interfaces/clock/2-1.c).
- One macro had two meanings in NuttX: the unit of clock() and the
  tick rate. The 15 in-tree tickless configurations with
  CONFIG_USEC_PER_TICK=1 already have CLOCKS_PER_SEC = 1000000, so code
  that mixes the two meanings works there and fails elsewhere.

Non-breaking alternative: a Kconfig option. Xiang explained in the
thread why it is worse: the meaning of a standard macro would then
depend on the configuration.

The earlier steps are merged and do not change behaviour:
- nuttx #20923: the kernel and libc use CLK_TCK for the tick rate and
  the tick counter for tick values; new CLOCK2TICK(), CLOCK2MSEC() and
  CLOCK2USEC() in <nuttx/clock.h> convert clock() values.
- nuttx-apps #3904 (ftpc, cpuload, dhcpc, ping) and #3906 (bas).
  After them, no code in nuttx or nuttx-apps uses CLOCKS_PER_SEC as the
  tick rate or a clock() value as ticks. resmonitor and testsuites divide
  clock() differences by CLOCKS_PER_SEC and need no change. i8shark puts
  the raw clock() value into the ZEP timestamp field, which changes unit
  (it is not NTP time today either).

Quick fix for out-of-tree code:
- CLOCKS_PER_SEC used as "ticks per second" (for example to convert
  seconds into a timeout for wd_start() or nxsig_usleep()): use CLK_TCK
  or TICK_PER_SEC.
- A clock() value used as ticks: 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.

Tests: build and runtime logs on real hardware (RP2350, Cortex-M33, and
ESP32-S3, Xtensa LX7) are in the PR, with ostest and a test of
CLOCKS_PER_SEC, clock() and times() (fails on master, passes with the
PR). The PR also has QEMU runs and builds of flat, protected and kernel
configurations on arm64, rv64 and armv7-m.

The vote is open for at least 72 hours.

[ ] +1 Accept the change
[ ] 0  No opinion
[ ] -1 Reject the change, because...

NuttX PMC members cast binding votes. The change needs at least 4
binding +1 votes and no binding -1 vote.

My vote: +1 (non-binding)

Regards,
Marco Casaroli

Reply via email to