From cfae0418347a9e6a49c0735e83c0a52613ccb26c Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 13 Apr 2025 11:14:57 -0400 Subject: [PATCH] posix: implement the XSI_SINGLE_PROCESS Option Group gettimeofday() was already implemented, but incorrectly lumped into POSIX_TIMERS. putenv() is really just a wrapper around setenv(). The only one left to implement was gethostid() which was relatively trivial. Signed-off-by: Chris Friedt --- include/zephyr/posix/unistd.h | 4 + lib/posix/options/CMakeLists.txt | 9 ++ lib/posix/options/Kconfig.proc1 | 6 +- lib/posix/options/Kconfig.profile | 1 + lib/posix/options/Kconfig.xsi_single_process | 7 +- lib/posix/options/clock.c | 21 ----- lib/posix/options/xsi_single_process.c | 92 ++++++++++++++++++++ tests/lib/time/prj.conf | 1 + tests/posix/headers/src/sys_time_h.c | 2 +- 9 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 lib/posix/options/xsi_single_process.c diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index b7ac069bdc5..10d44bfd4a8 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -77,6 +77,10 @@ size_t confstr(int name, char *buf, size_t len); long sysconf(int opt); #endif /* CONFIG_POSIX_SYSCONF_IMPL_FULL */ +#if _XOPEN_SOURCE >= 500 +long gethostid(void); +#endif + #ifdef __cplusplus } #endif diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index a5200f6f62e..0ef4e52b6e9 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -3,6 +3,7 @@ set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) zephyr_syscall_header_ifdef(CONFIG_POSIX_TIMERS posix_clock.h) +zephyr_syscall_header_ifdef(CONFIG_XSI_SINGLE_PROCESS posix_clock.h) if(CONFIG_POSIX_API) zephyr_include_directories(${ZEPHYR_BASE}/include/zephyr/posix) @@ -155,6 +156,14 @@ endif() zephyr_library_sources_ifdef(CONFIG_XOPEN_STREAMS stropts.c) +if (NOT CONFIG_TC_PROVIDES_XSI_SINGLE_PROCESS) + zephyr_library_sources_ifdef(CONFIG_XSI_SINGLE_PROCESS + clock_common.c + env_common.c + xsi_single_process.c + ) +endif() + if (NOT CONFIG_TC_PROVIDES_XSI_SYSTEM_LOGGING) zephyr_library_sources_ifdef(CONFIG_XSI_SYSTEM_LOGGING syslog.c) endif() diff --git a/lib/posix/options/Kconfig.proc1 b/lib/posix/options/Kconfig.proc1 index 9ab29048ca2..30f9c8fe601 100644 --- a/lib/posix/options/Kconfig.proc1 +++ b/lib/posix/options/Kconfig.proc1 @@ -49,8 +49,12 @@ config POSIX_UNAME_NODENAME_LEN help Defines the maximum string length of nodename version. +endif # POSIX_SINGLE_PROCESS + +if POSIX_SINGLE_PROCESS || XSI_SINGLE_PROCESS + module = POSIX_ENV module-str = POSIX env logging source "subsys/logging/Kconfig.template.log_config" -endif # POSIX_SINGLE_PROCESS +endif # POSIX_SINGLE_PROCESS || XSI_SINGLE_PROCESS diff --git a/lib/posix/options/Kconfig.profile b/lib/posix/options/Kconfig.profile index 2eb0c9a11ce..9fdbe71de74 100644 --- a/lib/posix/options/Kconfig.profile +++ b/lib/posix/options/Kconfig.profile @@ -12,6 +12,7 @@ config POSIX_API imply EVENTFD # eventfd(), eventfd_read(), eventfd_write() imply POSIX_FD_MGMT # open(), close(), read(), write() imply POSIX_MULTI_PROCESS # sleep(), getpid(), etc + imply XSI_SINGLE_PROCESS # gettimeofday() help This option enables the required POSIX System Interfaces (base definitions), all of PSE51, and some features found in PSE52. diff --git a/lib/posix/options/Kconfig.xsi_single_process b/lib/posix/options/Kconfig.xsi_single_process index ac5a8316455..9ef3d3a6dac 100644 --- a/lib/posix/options/Kconfig.xsi_single_process +++ b/lib/posix/options/Kconfig.xsi_single_process @@ -4,11 +4,14 @@ config XSI_SINGLE_PROCESS bool "X/Open single process" - depends on POSIX_SINGLE_PROCESS - depends on POSIX_TIMERS + select HWINFO help Select 'y' here and Zephyr will provide implementations of gethostid(), gettimeofday(), and putenv(). For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +module = XSI_SINGLE_PROCESS +module-str = XSI Single Process +source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index a76e5d28769..1f453346731 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -91,27 +91,6 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) return z_clock_nanosleep(CLOCK_MONOTONIC, 0, rqtp, rmtp); } -/** - * @brief Get current real time. - * - * See IEEE 1003.1 - */ -int gettimeofday(struct timeval *tv, void *tz) -{ - struct timespec ts; - int res; - - /* As per POSIX, "if tzp is not a null pointer, the behavior - * is unspecified." "tzp" is the "tz" parameter above. */ - ARG_UNUSED(tz); - - res = clock_gettime(CLOCK_REALTIME, &ts); - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; - - return res; -} - int clock_getcpuclockid(pid_t pid, clockid_t *clock_id) { /* We don't allow any process ID but our own. */ diff --git a/lib/posix/options/xsi_single_process.c b/lib/posix/options/xsi_single_process.c new file mode 100644 index 00000000000..cc5e82cb99a --- /dev/null +++ b/lib/posix/options/xsi_single_process.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Meta + * Copyright (c) 2025 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(xsi_single_process, CONFIG_XSI_SINGLE_PROCESS_LOG_LEVEL); + +extern int z_setenv(const char *name, const char *val, int overwrite); +extern int z_clock_gettime(clockid_t clockid, struct timespec *tp); + +long gethostid(void) +{ + int rc; + uint32_t buf = 0; + + rc = hwinfo_get_device_id((uint8_t *)&buf, sizeof(buf)); + if ((rc < 0) || (rc != sizeof(buf)) || (buf == 0)) { + LOG_DBG("%s() failed: %d", "hwinfo_get_device_id", rc); + return (long)rc; + } + + return (long)buf; +} + +int gettimeofday(struct timeval *tv, void *tz) +{ + struct timespec ts; + int res; + + /* + * As per POSIX, "if tzp is not a null pointer, the behavior is unspecified." "tzp" is the + * "tz" parameter above. + */ + ARG_UNUSED(tz); + + res = z_clock_gettime(CLOCK_REALTIME, &ts); + if (res < 0) { + LOG_DBG("%s() failed: %d", "clock_gettime", res); + return res; + } + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; + + return 0; +} + +int putenv(char *string) +{ + if (string == NULL) { + errno = EINVAL; + return -1; + } + + char *const name = string; + + for (char *val = name; *val != '\0'; ++val) { + if (*val == '=') { + int rc; + + *val = '\0'; + ++val; + rc = z_setenv(name, val, 1); + --val; + *val = '='; + + if (rc < 0) { + LOG_DBG("%s() failed: %d", "setenv", rc); + return rc; + } + + return 0; + } + } + + /* was unable to find '=' in string */ + errno = EINVAL; + return -1; +} diff --git a/tests/lib/time/prj.conf b/tests/lib/time/prj.conf index ce932c79220..dd87f5a1338 100644 --- a/tests/lib/time/prj.conf +++ b/tests/lib/time/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_POSIX_TIMERS=y +CONFIG_XSI_SINGLE_PROCESS=y CONFIG_PICOLIBC=y diff --git a/tests/posix/headers/src/sys_time_h.c b/tests/posix/headers/src/sys_time_h.c index aa766943961..4de47eaf785 100644 --- a/tests/posix/headers/src/sys_time_h.c +++ b/tests/posix/headers/src/sys_time_h.c @@ -29,7 +29,7 @@ ZTEST(posix_headers, test_sys_time_h) /* zassert_not_equal(-1, ITIMER_VIRTUAL); */ /* not implemented */ /* zassert_not_equal(-1, ITIMER_PROF); */ /* not implemented */ - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_XSI_SINGLE_PROCESS)) { /* zassert_not_null(getitimer); */ /* not implemented */ zassert_not_null(gettimeofday); /* zassert_not_null(setitimer); */ /* not implemented */