casaroli opened a new pull request, #20840:
URL: https://github.com/apache/nuttx/pull/20840

   ## Summary
   
   Four small POSIX fixes in headers and libc, one commit each.
   
   **`<pthread.h>` makes the `<sched.h>` symbols visible.** POSIX says: 
"Inclusion of the `<pthread.h>` header shall make symbols defined in the 
headers `<sched.h>` and `<time.h>` visible." NuttX's `<pthread.h>` included 
`<time.h>` but not `<sched.h>`. A program that includes only `<pthread.h>` and 
calls `sched_yield()`, uses `SCHED_FIFO` or `struct sched_param` did not 
compile. `<pthread.h>` now includes `<sched.h>`.
   
   **`<unistd.h>` defines `_POSIX_MONOTONIC_CLOCK` and 
`_POSIX_CLOCK_SELECTION`.** NuttX supports `CLOCK_MONOTONIC`, 
`clock_nanosleep()` and `pthread_condattr_setclock()`, 
`sysconf(_SC_MONOTONIC_CLOCK)` returns 1, and 
`Documentation/standards/posix.rst` marks both options as supported. But 
`<unistd.h>` did not define the two macros, so a program that checks them at 
compile time did not use the monotonic clock, and 
`sysconf(_SC_CLOCK_SELECTION)` failed with `ENOSYS`. Both macros are now 
`_POSIX_VERSION`, as the other supported options in `<unistd.h>`, and 
`sysconf()` returns them for `_SC_MONOTONIC_CLOCK` and `_SC_CLOCK_SELECTION`.
   
   **`<sys/stat.h>` defines `UTIME_OMIT` for C++ too.** Commit 545a93301ba 
("fs: Don't define UTIME_OMIT if __cplusplus is defined") removed `UTIME_OMIT` 
from C++, because libc++ uses `utimensat()` when `UTIME_OMIT` is defined, and 
NuttX did not have `utimensat()` at that time. Its commit message says to 
revert it when `utimensat()` is available. `utimensat()` is in libc now 
(`libs/libc/misc/lib_utimensat.c`), and the VFS handles `UTIME_OMIT` and 
`UTIME_NOW` (`fs_chstat.c`, `fs_fchstat.c`).
   
   **`remove()` removes a directory after `unlink()` fails with `EPERM`.** 
POSIX says that `remove()` of a directory is equivalent to `rmdir()`. NuttX's 
`remove()` called `rmdir()` only when `unlink()` failed with `EISDIR`, but 
POSIX also lets `unlink()` of a directory fail with `EPERM`, and V9FS on a 
macOS host does that. Then `remove()` of an empty directory failed with 
`EPERM`. `remove()` now also calls `rmdir()` after `EPERM`; if `rmdir()` then 
fails with `ENOTDIR`, the path is not a directory, and `remove()` keeps the 
`errno` of `unlink()`.
   
   ## Impact
   
   - `<pthread.h>` also declares the `<sched.h>` symbols. No code changes.
   - The two `<unistd.h>` macros are new, and `sysconf(_SC_CLOCK_SELECTION)` no 
longer fails. `sysconf(_SC_MONOTONIC_CLOCK)` returns `_POSIX_VERSION` instead 
of 1; both values are greater than zero, which is what a program checks.
   - C++ code sees `UTIME_OMIT`. libc++ (`CONFIG_LIBCXX`) then uses 
`utimensat()` in `std::filesystem::last_write_time()` instead of `utimes()`.
   - `remove()` of a directory now works on file systems where `unlink()` of a 
directory fails with `EPERM`. Other results do not change.
   - No documentation change: `Documentation/` does not describe the contents 
of these headers, and `posix.rst` already marks both clock options as supported.
   
   ## Testing
   
   Each commit was tested on its own, on `qemu-armv8a:knsh` (QEMU 11 with HVF 
on an Apple M4), with test programs built with the `qemu-armv8a:knsh` export:
   
   | Commit | Check | master | this PR |
   |---|---|---|---|
   | `<pthread.h>` | C program that includes only `<pthread.h>` and uses 
`sched_yield()`, `sched_get_priority_max(SCHED_FIFO)`, `sched_getparam()`, 
`struct sched_param` | does not compile | compiles, PASS |
   | `<pthread.h>` | the same as a C++ translation unit (aarch64 g++) | 
`'sched_yield' was not declared in this scope` | compiles |
   | `<unistd.h>` | `_POSIX_MONOTONIC_CLOCK > 0`, `_POSIX_CLOCK_SELECTION > 0` 
| FAIL | ok |
   | `<unistd.h>` | `sysconf(_SC_CLOCK_SELECTION)` | -1, `ENOSYS` | 201712 |
   | `<unistd.h>` | `sysconf(_SC_MONOTONIC_CLOCK)` | 1 | 201712 |
   | `<unistd.h>` | `clock_gettime(CLOCK_MONOTONIC)`, 
`clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME)` 100 ms, 
`pthread_cond_timedwait()` with `pthread_condattr_setclock(CLOCK_MONOTONIC)` 
100 ms | ok | ok |
   | `<sys/stat.h>` | C++ translation unit that uses `UTIME_OMIT` and 
`UTIME_NOW` with `utimensat()` | `'UTIME_OMIT' was not declared in this scope` 
| compiles |
   | `remove()` | `remove(file)` on V9FS (a macOS directory over virtio 9p) | 
ok | ok |
   | `remove()` | `remove(non-empty directory)` | -1, `EPERM` | -1, `ENOTEMPTY` 
|
   | `remove()` | `remove(empty directory)` | -1, `EPERM` | 0, directory 
removed |
   | `remove()` | `remove(missing path)` | -1, `ENOENT` | -1, `ENOENT` |
   
   For each commit, `ostest` on `qemu-armv8a:knsh` and `qemu-armv8a:nsh` ends 
with `ostest_main: Exiting with status 0`, and `qemu-armv7a:nsh` (gcc 15.3) 
builds with no new warnings. `qemu-armv7a:full` (libc++ 17.0.6, gcc 13.2) 
builds with the `UTIME_OMIT` commit, with `src/filesystem/operations.cpp`, and 
has the same warnings as master. The four commits together: `qemu-armv8a:nsh` 
and `qemu-armv8a:knsh` build with `-Werror`. `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]

Reply via email to