Hello,

I want to discuss a breaking change before I open the pull request, as
CONTRIBUTING.md 1.13 asks.

The problem

In NuttX, CLOCKS_PER_SEC is the system tick rate (1000000 /
CONFIG_USEC_PER_TICK, 100 by default), and clock() returns system
ticks. POSIX requires CLOCKS_PER_SEC to be 1000000 on XSI systems:

https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html
https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock.html

Issue #3516 (2021) reported this:
https://github.com/apache/nuttx/issues/3516. A comment there says that
ISO C allows any value. That is correct, but programs written for
POSIX systems expect 1000000, and the Open POSIX Test Suite checks it
(conformance/interfaces/clock/2-1.c). Also, the same macro has two
meanings in NuttX today: 22 files in arch/, drivers/, fs/ and sched/
use CLOCKS_PER_SEC as the tick rate, where CLK_TCK or TICK_PER_SEC is
the correct name.

The proposal, in three steps

1. nuttx-apps: netutils/ftpc and system/cpuload use CLK_TCK for the
tick rate. CLK_TCK has the same value as CLOCKS_PER_SEC today, so
nothing changes.
2. nuttx: the 22 files use CLK_TCK for the tick rate. The generated
code does not change.
3. nuttx, the breaking change: CLOCKS_PER_SEC is 1000000 and clock()
returns microseconds. times() and sysconf(_SC_CLK_TCK) stay in ticks
(CLK_TCK). clock_t is int64_t, so the value does not overflow.

Steps 1 and 2 do not change behaviour. I can send them as normal pull
requests now. Only step 3 needs the vote.

What breaks with step 3

- Code that uses CLOCKS_PER_SEC as the number of ticks per second, for
example to convert seconds into a timeout for wd_start() or
nxsig_usleep(). Quick fix: use CLK_TCK or TICK_PER_SEC.
- Code that divides clock() by CLOCKS_PER_SEC needs no change.
- In protected and kernel builds, clock() is a system call. Programs
built with the old header must be built again.

The resolution of clock() does not change: it still advances once per
tick. Only the unit changes. clock() also still returns the time since
boot, not the processor time of the process (the other point of
#3516); this proposal does not change that.

A non-breaking alternative

A Kconfig option selects CLOCKS_PER_SEC = 1000000, and it is off by
default. Steps 1 and 2 stay the same. The problem: the value of a
standard macro then depends on the configuration, so code that uses
CLOCKS_PER_SEC as the tick rate breaks only in some configurations,
and later.

Tests so far

QEMU (qemu-armv8a:knsh): a test program checks CLOCKS_PER_SEC, and
that clock() and times() both measure 0.5 s of processor time
correctly. ostest passes on qemu-armv8a:nsh. Seven configurations
build (flat, protected and kernel; arm64, armv7-m, rv64, x86_64).
Before a vote, I will add build and ostest logs from real hardware of
more than one architecture, as CONTRIBUTING.md 1.14 requires.

Questions

1. Do you agree with the change, or do you prefer the Kconfig option?
2. Is it OK to send steps 1 and 2 now as normal pull requests?

Thank you,
Marco Casaroli

Reply via email to