Skip to content

include/unistd.h: Make the POSIX option macros follow the configuration. - #21146

Merged
xiaoxiang781216 merged 6 commits into
apache:masterfrom
casaroli:g12-options-up
Nov 1, 2026
Merged

xiaoxiang781216 merged 6 commits into
apache:masterfrom
casaroli:g12-options-up

Conversation

@casaroli

@casaroli casaroli commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR makes the POSIX option macros of <unistd.h> and some limits of <limits.h> tell the truth about the configuration, and makes key destructors repeat as POSIX requires.

  • include/unistd.h: Make the POSIX option macros follow the configuration. <unistd.h> defined _POSIX_SEMAPHORES, _POSIX_SHARED_MEMORY_OBJECTS, _POSIX_MAPPED_FILES, _POSIX_MESSAGE_PASSING, _POSIX_THREADS, _POSIX_THREAD_PROCESS_SHARED, _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME in every configuration. A program that tests them then used functions that the build does not have: sem_open() needs CONFIG_FS_NAMED_SEMAPHORES, shm_open() needs CONFIG_FS_SHMFS, mmap() of a regular file needs CONFIG_FS_RAMMAP, and the CPU-time clocks need the run-time accounting of CONFIG_SCHED_CRITMONITOR. It did not define _POSIX_BARRIERS, _POSIX_READER_WRITER_LOCKS, _POSIX_SPIN_LOCKS and _POSIX_THREAD_ATTR_STACKADDR, although the functions exist. Now each option is _POSIX_VERSION when the configuration has it, and -1 when it does not. A kernel build has process-shared mutexes only with memory that two processes can share (CONFIG_FS_SHMFS or CONFIG_MM_SHM). The empty _POSIX_THREADS and _POSIX_THREAD_ATTR_STACKSIZE fallbacks in <pthread.h> go (<pthread.h> includes <unistd.h> first, so they never took effect).
  • Documentation/standards: Name the options that POSIX option macros need. posix.rst gives the Kconfig option of each of these macros.
  • include/limits.h: Define _POSIX_THREAD_KEYS_MAX as the POSIX constant. _POSIX_THREAD_KEYS_MAX is the smallest PTHREAD_KEYS_MAX that POSIX allows, always 128. <limits.h> defined it from CONFIG_TLS_NELEM (0 by default). Now it is 128; PTHREAD_KEYS_MAX still follows CONFIG_TLS_NELEM, and the Kconfig help says that POSIX requires at least 128 keys and what each key costs.
  • libs/libc/tls: Repeat the key destructors as POSIX requires. tls_destruct() called each key destructor once and cleared the value after the call, so a value that a destructor set again was lost. Now the value is cleared before the call, and the pass repeats while a destructor ran, up to PTHREAD_DESTRUCTOR_ITERATIONS (4, the POSIX minimum, new in <limits.h>) times.
  • include/limits.h: Define LOGIN_NAME_MAX. POSIX requires it. It is NAME_MAX + 1 (getlogin() returns at most NAME_MAX bytes), and the getlogin() buffer uses it.
  • Documentation: Describe the destructors of pthread keys. 08_pthread.rst said that the destructor argument of pthread_key_create() is ignored.

Impact

Possible breaking change (source level, every build mode, flat too): the values of these option macros change. An option that the configuration does not have is now -1:

Macro -1 when
_POSIX_SEMAPHORES no CONFIG_FS_NAMED_SEMAPHORES
_POSIX_SHARED_MEMORY_OBJECTS no CONFIG_FS_SHMFS
_POSIX_MAPPED_FILES no CONFIG_FS_RAMMAP
_POSIX_CPUTIME, _POSIX_THREAD_CPUTIME no CONFIG_SCHED_CRITMONITOR
_POSIX_MESSAGE_PASSING CONFIG_DISABLE_MQUEUE
_POSIX_SPIN_LOCKS (new) no CONFIG_PTHREAD_SPINLOCKS
_POSIX_THREAD_PROCESS_SHARED kernel build without CONFIG_FS_SHMFS and CONFIG_MM_SHM
_POSIX_THREADS, _POSIX_THREAD_PRIORITY_SCHEDULING, _POSIX_THREAD_ATTR_STACKADDR (new), _POSIX_THREAD_ATTR_STACKSIZE, _POSIX_BARRIERS (new), _POSIX_READER_WRITER_LOCKS (new) CONFIG_DISABLE_PTHREAD

A program that only tests #ifdef sees no difference. A program that tests the value (#if _POSIX_SEMAPHORES > 0) now takes its fallback when the function is missing; before, it did not link or failed at run time. sysconf(_SC_CPUTIME) and sysconf(_SC_THREAD_CPUTIME) return -1 without CONFIG_SCHED_CRITMONITOR (before: 201712L, while clock_gettime() of these clocks failed with EINVAL).

In-tree users: no C code in nuttx or nuttx-apps tests these macros. lib_sysconf.c returns _POSIX_CPUTIME/_POSIX_THREAD_CPUTIME (see above). The lely-canopen patch in nuttx-apps already excludes NuttX from its _POSIX_MAPPED_FILES paths. getlogin() keeps its buffer size.

<limits.h>: _POSIX_THREAD_KEYS_MAX is 128 in every configuration (was CONFIG_TLS_NELEM); LOGIN_NAME_MAX and PTHREAD_DESTRUCTOR_ITERATIONS are new.

Key destructors: a destructor that sets a value again is called again (at most 4 passes), and a destructor sees its key with the value NULL. In-tree users of pthread_key_create() (ostest, the sim SMP code) give no destructor. Task-local storage (task_tls_alloc()) is not changed.

No size change of a structure. No new Kconfig option.

Testing

Test programs posixopts.c (each option macro must match what the build can do) and limitsposix.c, on qemu-armv8a:knsh (kernel build) and qemu-armv8a:nsh (flat build, the tests as builtin apps), QEMU with HVF, CONFIG_TLS_NELEM=8:

Case master this PR
_POSIX_BARRIERS, _POSIX_READER_WRITER_LOCKS, _POSIX_SPIN_LOCKS defined; barriers and rwlocks work not defined: FAIL 201712L, 201712L, -1: PASS
_POSIX_THREAD_ATTR_STACKSIZE/STACKADDR have a value empty / not defined: FAIL 201712L: PASS
_POSIX_MAPPED_FILES matches mmap() of a file 201712L, mmap() fails: FAIL -1: PASS
_POSIX_SEMAPHORES matches sem_open() (default) 201712L, no sem_open(): FAIL -1: PASS
the same with CONFIG_FS_NAMED_SEMAPHORES (knsh) PASS 201712L: PASS
_POSIX_THREAD_PROCESS_SHARED: a process-shared mutex and condition variable work across two tasks in shm_open() memory (knsh; flat with CONFIG_FS_SHMFS) PASS PASS
_POSIX_THREAD_KEYS_MAX == 128 8: FAIL 128: PASS
LOGIN_NAME_MAX defined, >= 9 not defined: FAIL 33: PASS
PTHREAD_DESTRUCTOR_ITERATIONS defined, >= 4 not defined: FAIL 4: PASS
a destructor that sets the value again is called again, and sees NULL 1 call: FAIL 3 calls, NULL each time: PASS

The results are the same on knsh and on flat nsh. ostest exits with status 0 on qemu-armv8a:knsh and qemu-armv8a:nsh (also in the flat runs with the test apps), on master and with this PR.

Build, each OK: qemu-armv8a:nsh (flat, arm64), also with CONFIG_FS_RAMMAP and CONFIG_SCHED_CRITMONITOR; qemu-armv8a:knsh (kernel, arm64), also with CONFIG_FS_NAMED_SEMAPHORES, CONFIG_PTHREAD_SPINLOCKS and CONFIG_MM_SHM; rv-virt:knsh64 (kernel, rv64); mps2-an500:nsh (flat, Cortex-M7), also with CONFIG_DISABLE_PTHREAD (without the ostest and getprime apps, which need pthreads, as on master); mps2-an500:knsh (protected, Cortex-M7).

tools/checkpatch.sh -c -u -m -g passes.

<unistd.h> defined _POSIX_SEMAPHORES, _POSIX_SHARED_MEMORY_OBJECTS,
_POSIX_MAPPED_FILES, _POSIX_MESSAGE_PASSING, _POSIX_THREADS,
_POSIX_THREAD_PROCESS_SHARED, _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME
in every configuration.  A program that tests them then used functions
that the build does not have: sem_open() needs
CONFIG_FS_NAMED_SEMAPHORES, shm_open() needs CONFIG_FS_SHMFS, mmap() of
a regular file needs CONFIG_FS_RAMMAP, and the CPU-time clocks need the
run-time accounting of CONFIG_SCHED_CRITMONITOR.

It also did not define _POSIX_BARRIERS, _POSIX_READER_WRITER_LOCKS,
_POSIX_SPIN_LOCKS and _POSIX_THREAD_ATTR_STACKADDR, although the
functions exist.  <pthread.h> defined _POSIX_THREAD_ATTR_STACKSIZE with
no value, so "#if _POSIX_THREAD_ATTR_STACKSIZE > 0" did not compile.

Define each option as _POSIX_VERSION when the configuration has it, and
as -1 when it does not.  A kernel build has process-shared mutexes only
with memory that two processes can share (CONFIG_FS_SHMFS or
CONFIG_MM_SHM).  Remove the empty fallbacks from <pthread.h>.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
_POSIX_SEMAPHORES, _POSIX_SHARED_MEMORY_OBJECTS, _POSIX_MAPPED_FILES,
_POSIX_THREAD_PROCESS_SHARED and the CPU-time options are now -1 when
the configuration does not have the functions.  Give the Kconfig options
in the remarks.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
_POSIX_THREAD_KEYS_MAX is the smallest PTHREAD_KEYS_MAX that POSIX
allows, and it is always 128.  <limits.h> defined it from
CONFIG_TLS_NELEM (0 by default), so a program could not see that the
configured number of keys is below the POSIX minimum.

Define it as 128.  PTHREAD_KEYS_MAX still follows CONFIG_TLS_NELEM; the
Kconfig help now says that POSIX requires at least 128 keys and what
each key costs.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
<limits.h> did not define PTHREAD_DESTRUCTOR_ITERATIONS, and
tls_destruct() called each key destructor once.  It also cleared the
value after the call, so a value that a destructor set again was lost
without a second call.

Clear the value before the call, and repeat while a destructor ran, up
to PTHREAD_DESTRUCTOR_ITERATIONS (4, the POSIX minimum) passes.
Define PTHREAD_DESTRUCTOR_ITERATIONS in <limits.h>.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
POSIX requires LOGIN_NAME_MAX in <limits.h>, and sysconf() lists
_SC_LOGIN_NAME_MAX.  getlogin() returns at most NAME_MAX bytes, so
define LOGIN_NAME_MAX as NAME_MAX + 1 (the terminating null included)
and size the getlogin() buffer with it.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The pthread_key_create() page said that the destructor argument is
ignored.  The destructors run when a thread exits, and now again while a
destructor sets a value, up to PTHREAD_DESTRUCTOR_ITERATIONS times.  Say
so, and that PTHREAD_KEYS_MAX is CONFIG_TLS_NELEM, with the POSIX
minimum of 128.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Size: M The size of the change in this PR is medium labels Oct 29, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

No memory changes detected for:


Catch memory regressions in CI with MemBrowse. Free for open source.

@casaroli
casaroli marked this pull request as draft October 30, 2026 08:28
acassis pushed a commit to apache/nuttx-apps that referenced this pull request Oct 31, 2026
NuttX has the CPU-time clocks (CLOCK_PROCESS_CPUTIME_ID and
CLOCK_THREAD_CPUTIME_ID) only with the run-time accounting of the
critical section monitor (CONFIG_SCHED_CRITMONITOR_MAXTIME_THREAD >= 0).
Without it, <unistd.h> defines _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME
as -1 (apache/nuttx#21146), and the LTP tests of these options print
"unsupported" or "not supported" instead of a result.  Do not build them then, as for the
other options that a configuration does not have.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@casaroli
casaroli marked this pull request as ready for review October 31, 2026 22:10
@xiaoxiang781216

Copy link
Copy Markdown
Contributor

please fix ci error, @casaroli

@casaroli

casaroli commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

The arm-ti failure is on master: lm3s6965-ek:qemu-flat overflows by 212 bytes and qemu-protected by 280 bytes without this PR. #21219 and #21321 fix them.

@xiaoxiang781216
xiaoxiang781216 merged commit 0f29ca8 into apache:master Nov 1, 2026
91 of 101 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Documentation Improvements or additions to documentation Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants