casaroli opened a new pull request, #21057:
URL: https://github.com/apache/nuttx/pull/21057
## Summary
A program can define `NUTTX_NO_EXTENSIONS` before its first `#include` to
keep the non-standard names of the NuttX headers free for its own use. Today
the headers still define many such names with that macro, and a program that
uses one of them for itself does not compile. This PR hides nine groups of
them, one commit each:
- `include/nuttx/compiler.h` reaches every program through `<sys/types.h>`.
It defines generic helper macros such as `memory_barrier()`, `UNUSED()`,
`return_address`, `predict_true()` and `atomic_load_4()`; `NUTTX_NO_EXTENSIONS`
hid only four of them. Now it undefines every helper macro that the headers a
program includes do not use, directly or through another macro of the file,
under any condition. `FAR` and the other storage class macros, `offsetof`, the
attribute macros of the public prototypes (`noreturn_function`, `printf_like`,
...) and the macros that they expand to stay. With GCC and clang, a definition
that the program made before its first `#include` is saved with `#pragma
push_macro` and restored at the end of the file.
- `<stdio.h>` and `<pthread.h>` include `nuttx/mutex.h`, then
`nuttx/semaphore.h`, then `nuttx/clock.h` and `nuttx/lib/math32.h`: about 130
macros such as `TM_YEAR_BASE`, `SEC_PER_MIN`, `NSEC_PER_SEC` and
`div_round_up()`. `nuttx/semaphore.h` needs only `clockid_t` and `uint32_t`
from them, so it now includes `<stdint.h>` and `<time.h>` and includes
`nuttx/clock.h` only without `NUTTX_NO_EXTENSIONS`. `nuttx/mm/mm.h` now
includes `<string.h>` for `memset()`, which it got through `nuttx/clock.h`.
- `<fcntl.h>` hid `O_TEXT` but not `O_BINARY`. A program that tests
`O_BINARY` and then uses `O_TEXT` did not compile. Both are hidden now.
- `<sys/stat.h>` declares `utimens()` and `lutimens()`, which are not in
POSIX (POSIX has `utimensat()` and `futimens()`). Other code uses these names
for its own functions. They are hidden now; libc and the system calls still
have them.
- `<assert.h>` defines `PANIC()`, `PANIC_WITH_REGS()`, `ASSERT()`,
`VERIFY()`, `COMPILE_TIME_ASSERT()` and `BUILD_BUG_ON_ZERO()`, and removes the
program's own definition of `PANIC`, `ASSERT` or `VERIFY`. With
`NUTTX_NO_EXTENSIONS` it now does neither. `assert()`, `static_assert` and the
`DEBUG*` macros stay (the NuttX port of libmetal uses `DEBUGASSERT` in its
headers).
- `<sys/statfs.h>` (and so `<sys/vfs.h>`) defines about 60 file system types
`*_MAGIC` (`TMPFS_MAGIC`, ...). POSIX does not define them (Linux has them in
`<linux/magic.h>`), and programs define constants with these names for their
own `f_type` checks: `uint32_t const TMPFS_MAGIC = 0x01021994;` did not
compile. They are hidden now; NuttX code keeps them.
- `<unistd.h>` declares the NuttX `crypt_r(key, salt, char *output)`. glibc
and libxcrypt have `crypt_r(key, salt, struct crypt_data *)` in `<crypt.h>`, so
a program that uses libxcrypt and includes `<unistd.h>` did not compile
(conflicting types). The NuttX declaration is hidden now; `crypt()` does not
change.
- `<sys/types.h>` defines the types `unchar` and `s_char`, which no other C
library has. Programs use the names for their own things (gdbm's tools have a
function `s_char()`). They are hidden now. The BSD and System V types that
other C libraries also have (`u_char`, `ushort`, `uint`, `ulong`, `caddr_t`,
...) stay.
- With optimisation, `nuttx/compiler.h` defines `builtin_function(fn)` and
`builtin_original(fn)` for the inline versions of `memcpy()` and the other
functions of `<string.h>`. A program that uses these names for its own code did
not compile (vim has a function `builtin_function()`). With
`NUTTX_NO_EXTENSIONS` they are not defined, and `<string.h>` declares the plain
functions. The compiler can still use its own built-in functions.
Each commit updates the list in the comment of `nuttx/compiler.h`. The last
commit updates the paragraph about `NUTTX_NO_EXTENSIONS` in
`Documentation/os/libs/libc/index.rst`.
## Impact
Only programs that define `NUTTX_NO_EXTENSIONS`. NuttX and nuttx-apps do not
define it, so the OS, the libraries and the applications do not change. A
program that defines `NUTTX_NO_EXTENSIONS` and still uses one of the hidden
names must stop defining the macro, or use the standard name (`assert()`,
`utimensat()`, ...).
## Testing
Ten test programs, each with `#define NUTTX_NO_EXTENSIONS 1`, built with the
export of qemu-armv8a:knsh and run on qemu-armv8a:knsh (QEMU with HVF):
| Test | master | this PR |
|---|---|---|
| `noextmb.c` (`-Werror`): own `UNUSED()`, `memory_barrier()`,
`return_address`, `predict_true()`, `atomic_load_4()` after the headers | does
not compile (`"UNUSED" redefined`, `macro "memory_barrier" passed 1 arguments`)
| PASS |
| `noextclk.c` (`-Werror`): own `TM_YEAR_BASE`, `SEC_PER_MIN`,
`NSEC_PER_SEC` after `<stdio.h>` and `<pthread.h>` | does not compile | PASS |
| `fcntlbin.c`: `#ifdef O_BINARY` ... `O_TEXT` | does not compile (`O_TEXT`
undeclared) | PASS |
| `utimenstest.c`: own `utimens()` with three parameters | does not compile
(conflicting types) | PASS |
| `asserttest.c` (`-Werror`): own `ASSERT`, and `VERIFY`, `PANIC`,
`COMPILE_TIME_ASSERT`, `BUILD_BUG_ON_ZERO` as enum constants | does not compile
(`"ASSERT" redefined`) | PASS |
| `statfsmagic.c`: own `TMPFS_MAGIC` and `RAMFS_MAGIC` constants, then
`statfs("/")` | does not compile | PASS (`f_type` 0x9fa0) |
| `cryptrdecl.c` (with `CONFIG_CRYPTO` and `/dev/crypto`): the libxcrypt
prototype of `crypt_r()` after `<unistd.h>`, then `crypt()` | does not compile
(conflicting types for `crypt_r`) | PASS (`crypt()` gives the MD5 hash of
glibc) |
| `systypes.c`: own `s_char()` function and `unchar` variable; `u_char`,
`ushort`, `uint`, `ulong`, `caddr_t`, `u_int32_t` still defined | does not
compile (`unchar` and `s_char` redeclared as different kind of symbol) | PASS |
| `builtinname.c` (`-O2`): own `builtin_function()` and `builtin_original()`
functions, then `memcpy()`, `memset()`, `strlen()`, `strcmp()` | does not
compile (`macro "builtin_function" passed 3 arguments, but takes just 1`) |
PASS |
| `noext2.c`: own `UNUSED` and `memory_barrier()` defined before the first
`#include` | PASS | PASS (the definitions stay) |
Header sweep with the same export: each of the 233 public headers (not
`nuttx/`, `arch/`, C++) alone, after `#define NUTTX_NO_EXTENSIONS 1`, with
`-Werror` at `-O0`, `-O2` and `-Os`. The results are the same on master and
with this PR: 216 headers compile, and the same 17 headers fail at all levels
for other reasons (for example `sys/syscall_lookup.h` and the
`metal/system/nuttx/` headers, which are not for direct inclusion). So no
header uses a macro that this PR hides.
The tests ran with `CONFIG_CRYPTO` and the software `/dev/crypto`
(`CONFIG_ALLOW_BSD_COMPONENTS`, `CONFIG_CRYPTO_SW_AES`,
`CONFIG_CRYPTO_CRYPTODEV`, `CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO`). ostest
exits with status 0 on qemu-armv8a:knsh and qemu-armv8a:nsh with these options.
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),
and rv-virt:nsh64 with CMake.
`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]