From 0544f1c26b37089ea87971dca8b5b5bff76c5644 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 17 Jun 2024 15:24:51 -0400 Subject: [PATCH 1/4] posix: procN: add missing alias for getpid() Newlib requires an alias for the getpid() function. There was a Kconfig already present for doing so, but the actual alias was missing. So this is technically a bugfix. Signed-off-by: Chris Friedt --- lib/posix/options/multi_process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/posix/options/multi_process.c b/lib/posix/options/multi_process.c index 221dc04ae1ad9..ab697a66c0c72 100644 --- a/lib/posix/options/multi_process.c +++ b/lib/posix/options/multi_process.c @@ -21,3 +21,6 @@ pid_t getpid(void) return 42; } +#ifdef CONFIG_POSIX_MULTI_PROCESS_ALIAS_GETPID +FUNC_ALIAS(getpid, _getpid, pid_t); +#endif /* CONFIG_POSIX_MULTI_PROCESS_ALIAS_GETPID */ From 884b0483d7b7e149bed1b8102639261f211d80ee Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 17 Jun 2024 13:01:06 -0400 Subject: [PATCH 2/4] posix: add stubs for signal.h functions that need process support Since Zephyr itself does not currently support processes, but conformant applications should still be able to link, add stubs for the remaining POSIX functions in the POSIX_SIGNALS Option Group. The POSIX_SIGNALS Option Group is required for PSE51, PSE52, PSE53, PSE54, and likely many other POSIX Subprofiles. Signed-off-by: Chris Friedt --- include/zephyr/posix/signal.h | 34 ++++++++++++++++++ lib/libc/Kconfig | 1 + lib/posix/options/Kconfig.signal | 7 ++++ lib/posix/options/signal.c | 59 ++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index 165050f2ded92..11cbe726dadb2 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -77,6 +77,16 @@ typedef struct { #define SIG_UNBLOCK 2 #endif +#define SIG_DFL ((void *)0) +#define SIG_IGN ((void *)1) +#define SIG_ERR ((void *)-1) + +#define SI_USER 1 +#define SI_QUEUE 2 +#define SI_TIMER 3 +#define SI_ASYNCIO 4 +#define SI_MESGQ 5 + typedef int sig_atomic_t; /* Atomic entity type (ANSI) */ union sigval { @@ -92,12 +102,36 @@ struct sigevent { int sigev_signo; }; +typedef struct { + int si_signo; + int si_code; + union sigval si_value; +} siginfo_t; + +struct sigaction { + void (*sa_handler)(int signno); + sigset_t sa_mask; + int sa_flags; + void (*sa_sigaction)(int signo, siginfo_t *info, void *context); +}; + +typedef void (*sighandler_t)(int signo); + +unsigned int alarm(unsigned int seconds); +int kill(pid_t pid, int sig); +int pause(void); +int raise(int signo); +int sigaction(int sig, const struct sigaction *ZRESTRICT act, struct sigaction *ZRESTRICT oact); +int sigpending(sigset_t *set); +int sigsuspend(const sigset_t *sigmask); +int sigwait(const sigset_t *ZRESTRICT set, int *ZRESTRICT signo); char *strsignal(int signum); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); int sigismember(const sigset_t *set, int signo); +sighandler_t signal(int signo, sighandler_t handler); int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 4b42e0a150c91..7d793848f99ba 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -105,6 +105,7 @@ config NEWLIB_LIBC imply POSIX_FD_MGMT_ALIAS_LSEEK imply POSIX_FILE_SYSTEM_ALIAS_FSTAT imply POSIX_MULTI_PROCESS_ALIAS_GETPID + imply POSIX_SIGNALS_ALIAS_KILL help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index 4507302e3f32d..1e84a55de598d 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -24,6 +24,7 @@ endif # POSIX_REALTIME_SIGNALS config POSIX_SIGNALS bool "POSIX signals [EXPERIMENTAL]" select EXPERIMENTAL + select POSIX_MULTI_PROCESS help Enable support for POSIX signals. @@ -36,6 +37,12 @@ config POSIX_SIGNAL_STRING_DESC Use full description for the strsignal API. Will use 256 bytes of ROM. +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_SIGNALS_ALIAS_KILL + bool + endif endmenu # "Signal support" diff --git a/lib/posix/options/signal.c b/lib/posix/options/signal.c index cb282f69bdc86..84171fde0f07e 100644 --- a/lib/posix/options/signal.c +++ b/lib/posix/options/signal.c @@ -118,3 +118,62 @@ int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset errno = ENOSYS; return -1; } + +/* + * The functions below are provided so that conformant POSIX applications and libraries can still + * link. + */ + +unsigned int alarm(unsigned int seconds) +{ + ARG_UNUSED(seconds); + return 0; +} + +int kill(pid_t pid, int sig) +{ + ARG_UNUSED(pid); + ARG_UNUSED(sig); + errno = ENOSYS; + return -1; +} +#ifdef CONFIG_POSIX_SIGNALS_ALIAS_KILL +FUNC_ALIAS(kill, _kill, int); +#endif /* CONFIG_POSIX_SIGNALS_ALIAS_KILL */ + +int pause(void) +{ + errno = ENOSYS; + return -1; +} + +int sigaction(int sig, const struct sigaction *ZRESTRICT act, struct sigaction *ZRESTRICT oact) +{ + ARG_UNUSED(sig); + ARG_UNUSED(act); + ARG_UNUSED(oact); + errno = ENOSYS; + return -1; +} + +int sigpending(sigset_t *set) +{ + ARG_UNUSED(set); + errno = ENOSYS; + return -1; +} + +int sigsuspend(const sigset_t *sigmask) +{ + ARG_UNUSED(sigmask); + errno = ENOSYS; + return -1; +} + +int sigwait(const sigset_t *ZRESTRICT set, int *ZRESTRICT sig) +{ + ARG_UNUSED(set); + ARG_UNUSED(sig); + errno = ENOSYS; + return -1; +} From 6c9fbec0f2ee9a386db072e51baaf5f22d5e576a Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 17 Jun 2024 13:27:23 -0400 Subject: [PATCH 3/4] tests: posix: headers: add checks for posix signals option group Add tests for the presence of items in the POSIX SIGNALS Option Group. Signed-off-by: Chris Friedt --- tests/posix/headers/src/signal_h.c | 65 +++++++++++++++++------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/tests/posix/headers/src/signal_h.c b/tests/posix/headers/src/signal_h.c index 35616e4a29e54..76cde3e592d91 100644 --- a/tests/posix/headers/src/signal_h.c +++ b/tests/posix/headers/src/signal_h.c @@ -6,6 +6,8 @@ #include "_common.h" +#include + #ifdef CONFIG_POSIX_API #include #else @@ -19,13 +21,17 @@ */ ZTEST(posix_headers, test_signal_h) { - /* zassert_not_equal(-1, SIG_DFL); */ /* not implemented */ - /* zassert_not_equal(-1, SIG_ERR); */ /* not implemented */ + typedef void *(*my_sig_handler_t)(int signo); + + my_sig_handler_t handler; + + handler = SIG_DFL; + handler = SIG_ERR; + handler = SIG_IGN; /* zassert_not_equal(-1, SIG_HOLD); */ /* not implemented */ - /* zassert_not_equal(-1, SIG_IGN); */ /* not implemented */ zassert_not_equal((sig_atomic_t)-1, (sig_atomic_t)0); - /* zassert_not_equal((pid_t)-1, (pid_t)0); */ /* not implemented */ + zassert_not_equal((pid_t)-1, (pid_t)0); zassert_not_equal(-1, offsetof(struct sigevent, sigev_notify)); zassert_not_equal(-1, offsetof(struct sigevent, sigev_signo)); @@ -47,6 +53,15 @@ ZTEST(posix_headers, test_signal_h) zassert_not_equal(-1, SIG_UNBLOCK); zassert_not_equal(-1, SIG_SETMASK); + zassert_not_equal(-1, offsetof(struct sigaction, sa_handler)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_mask)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_flags)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_sigaction)); + + zassert_not_equal(-1, offsetof(siginfo_t, si_signo)); + zassert_not_equal(-1, offsetof(siginfo_t, si_code)); + zassert_not_equal(-1, offsetof(siginfo_t, si_value)); + /* zassert_not_equal(-1, SA_NOCLDSTOP); */ /* not implemented */ /* zassert_not_equal(-1, SA_ONSTACK); */ /* not implemented */ /* zassert_not_equal(-1, SA_RESETHAND); */ /* not implemented */ @@ -117,18 +132,11 @@ ZTEST(posix_headers, test_signal_h) /* zassert_not_equal(-1, CLD_STOPPED); */ /* not implemented */ /* zassert_not_equal(-1, CLD_CONTINUED); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_IN); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_OUT); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_MSG); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_ERR); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_PRI); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_HUP); */ /* not implemented */ - - /* zassert_not_equal(-1, SI_USER); */ /* not implemented */ - /* zassert_not_equal(-1, SI_QUEUE); */ /* not implemented */ - /* zassert_not_equal(-1, SI_TIMER); */ /* not implemented */ - /* zassert_not_equal(-1, SI_ASYNCIO); */ /* not implemented */ - /* zassert_not_equal(-1, SI_MESGQ); */ /* not implemented */ + zassert_not_equal(-1, SI_USER); + zassert_not_equal(-1, SI_QUEUE); + zassert_not_equal(-1, SI_TIMER); + zassert_not_equal(-1, SI_ASYNCIO); + zassert_not_equal(-1, SI_MESGQ); #ifdef CONFIG_POSIX_SIGNALS zassert_true(SIGRTMIN >= 0); @@ -158,37 +166,40 @@ ZTEST(posix_headers, test_signal_h) zassert_not_equal(-1, SIGXCPU); zassert_not_equal(-1, SIGXFSZ); zassert_not_equal(((sigset_t){.sig[0] = 0}).sig[0], ((sigset_t){.sig[0] = -1}).sig[0]); - zassert_not_null(sigemptyset); - zassert_not_null(sigfillset); + zassert_not_null(abort); + zassert_not_null(alarm); + zassert_not_null(kill); + zassert_not_null(pause); + zassert_not_null(pthread_sigmask); + zassert_not_null(raise); + zassert_not_null(sigaction); zassert_not_null(sigaddset); zassert_not_null(sigdelset); + zassert_not_null(sigemptyset); + zassert_not_null(sigfillset); zassert_not_null(sigismember); - zassert_not_null(strsignal); + zassert_not_null(signal); + zassert_not_null(sigpending); zassert_not_null(sigprocmask); - zassert_not_null(pthread_sigmask); + zassert_not_null(sigsuspend); + zassert_not_null(sigwait); + zassert_not_null(strsignal); #endif /* CONFIG_POSIX_SIGNALS */ if (IS_ENABLED(CONFIG_POSIX_API)) { - /* zassert_not_null(kill); */ /* not implemented */ /* zassert_not_null(killpg); */ /* not implemented */ /* zassert_not_null(psiginfo); */ /* not implemented */ /* zassert_not_null(psignal); */ /* not implemented */ /* zassert_not_null(pthread_kill); */ /* not implemented */ - /* zassert_not_null(raise); */ /* not implemented */ - /* zassert_not_null(sigaction); */ /* not implemented */ /* zassert_not_null(sigaltstack); */ /* not implemented */ /* zassert_not_null(sighold); */ /* not implemented */ /* zassert_not_null(sigignore); */ /* not implemented */ /* zassert_not_null(siginterrupt); */ /* not implemented */ - /* zassert_not_null(signal); */ /* not implemented */ /* zassert_not_null(sigpause); */ /* not implemented */ - /* zassert_not_null(sigpending); */ /* not implemented */ /* zassert_not_null(sigqueue); */ /* not implemented */ /* zassert_not_null(sigrelse); */ /* not implemented */ /* zassert_not_null(sigset); */ /* not implemented */ - /* zassert_not_null(sigsuspend); */ /* not implemented */ /* zassert_not_null(sigtimedwait); */ /* not implemented */ - /* zassert_not_null(sigwait); */ /* not implemented */ /* zassert_not_null(sigwaitinfo); */ /* not implemented */ } } From 3136e426b8aaa1772ad277a846326a92d2828060 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 17 Jun 2024 13:04:20 -0400 Subject: [PATCH 4/4] doc: posix: mark posix signals supported with undefined behaviour Mark the POSIX_SIGNALS Option Group as supported to the extent possible under Zephyr, as Zephyr does not yet support processes. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- .../portability/posix/option_groups/index.rst | 31 +++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 8c7cf8c0b99a3..0e7f71cdf7215 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -51,7 +51,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_JUMP `, yes, :ref:`POSIX_C_LANG_SUPPORT `, yes, :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` - :ref:`POSIX_SIGNALS `,, :kconfig:option:`CONFIG_POSIX_SIGNALS` + :ref:`POSIX_SIGNALS `, yes, :kconfig:option:`CONFIG_POSIX_SIGNALS` :ref:`†` :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` :ref:`XSI_THREADS_EXT `, yes, :kconfig:option:`CONFIG_XSI_THREADS_EXT` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 5526b7b1a1a85..d227c9c2233d2 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -450,31 +450,36 @@ POSIX_SIGNAL_JUMP POSIX_SIGNALS +++++++++++++ -Signal services are a basic mechanism within POSIX-based systems and are -required for error and event handling. - Enable this option group with :kconfig:option:`CONFIG_POSIX_SIGNALS`. +.. note:: + As processes are not yet supported in Zephyr, the ISO C functions ``abort()``, ``signal()``, + and ``raise()``, as well as the other POSIX functions listed below, may exhibit undefined + behaviour. The POSIX functions ``kill()``, ``pause()``, ``sigaction()``, ``sigpending()``, + ``sigsuspend()``, and ``sigwait()`` are implemented to ensure that conformant applications can + link, but they are expected to fail, setting errno to ``ENOSYS`` + :ref:`†`. + .. csv-table:: POSIX_SIGNALS :header: API, Supported :widths: 50,10 - abort(),yes - alarm(), - kill(), - pause(), - raise(), - sigaction(), + abort(),yes :ref:`†` + alarm(),yes :ref:`†` + kill(),yes :ref:`†` + pause(),yes :ref:`†` + raise(),yes :ref:`†` + sigaction(),yes :ref:`†` sigaddset(),yes sigdelset(),yes sigemptyset(),yes sigfillset(),yes sigismember(),yes - signal(), - sigpending(), + signal(),yes :ref:`†` + sigpending(),yes :ref:`†` sigprocmask(),yes - sigsuspend(), - sigwait(), + sigsuspend(),yes :ref:`†` + sigwait(),yes :ref:`†` strsignal(),yes .. _posix_option_group_single_process: