diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 4808cb80ce799..a6094667559ba 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -90,9 +90,9 @@ #define _POSIX_MESSAGE_PASSING _POSIX_VERSION #endif -#ifdef CONFIG_POSIX_MONOTONIC_CLOCK -#define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION -#endif +// #ifdef CONFIG_POSIX_MONOTONIC_CLOCK +// #define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION +// #endif /* #define _POSIX_PRIORITIZED_IO (-1L) */ @@ -177,9 +177,9 @@ #define _POSIX_TIMEOUTS _POSIX_VERSION #endif -#ifdef CONFIG_POSIX_TIMERS -#define _POSIX_TIMERS _POSIX_VERSION -#endif +// #ifdef CONFIG_POSIX_TIMERS +// #define _POSIX_TIMERS _POSIX_VERSION +// #endif /* #define _POSIX_TRACE (-1L) */ /* #define _POSIX_TRACE_EVENT_FILTER (-1L) */ diff --git a/include/zephyr/posix/posix_types.h b/include/zephyr/posix/posix_types.h index e65a398cdcc9c..550af165162e5 100644 --- a/include/zephyr/posix/posix_types.h +++ b/include/zephyr/posix/posix_types.h @@ -76,7 +76,13 @@ typedef unsigned long blkcnt_t; #endif #if !defined(CONFIG_ARCMWDT_LIBC) -typedef int pid_t; + +#if (!defined(_PID_T_DECLARED) && !defined(__pid_t_defined)) || defined(__DOXYGEN__) +typedef long pid_t; +#define _PID_T_DECLARED +#define __pid_t_defined +#endif + #endif #ifndef __useconds_t_defined diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index df2980601722e..be8cc843d03e2 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -3,112 +3,6 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_POSIX_TIME_H_ -#define ZEPHYR_INCLUDE_POSIX_TIME_H_ -/* Read standard header. This may find since they - * refer to the same file when include/posix is in the search path. - */ -#include - -#ifdef CONFIG_NEWLIB_LIBC -/* Kludge to support outdated newlib version as used in SDK 0.10 for Xtensa */ -#include - -#ifdef __NEWLIB__ -/* Newever Newlib 3.x+ */ -#include -#else /* __NEWLIB__ */ -/* Workaround for older Newlib 2.x, as used by Xtensa. It lacks sys/_timeval.h, - * so mimic it here. - */ -#include -#ifndef __timespec_defined - -#ifdef __cplusplus -extern "C" { -#endif - -struct timespec { - time_t tv_sec; - long tv_nsec; -}; - -struct itimerspec { - struct timespec it_interval; /* Timer interval */ - struct timespec it_value; /* Timer expiration */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __timespec_defined */ -#endif /* __NEWLIB__ */ - -#else /* CONFIG_NEWLIB_LIBC */ -/* Not Newlib */ -# if defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC) -# include -# include -# else -# include -# endif -#endif /* CONFIG_NEWLIB_LIBC */ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef CLOCK_REALTIME -#define CLOCK_REALTIME SYS_CLOCK_REALTIME -#endif - -#ifndef CLOCK_PROCESS_CPUTIME_ID -#define CLOCK_PROCESS_CPUTIME_ID 2 -#endif - -#ifndef CLOCK_THREAD_CPUTIME_ID -#define CLOCK_THREAD_CPUTIME_ID 3 -#endif - -#ifndef CLOCK_MONOTONIC -#define CLOCK_MONOTONIC SYS_CLOCK_MONOTONIC -#endif - -#ifndef TIMER_ABSTIME -#define TIMER_ABSTIME SYS_TIMER_ABSTIME -#endif - -int clock_gettime(clockid_t clock_id, struct timespec *ts); -int clock_getres(clockid_t clock_id, struct timespec *ts); -int clock_settime(clockid_t clock_id, const struct timespec *ts); -int clock_getcpuclockid(pid_t pid, clockid_t *clock_id); -/* Timer APIs */ -int timer_create(clockid_t clockId, struct sigevent *evp, timer_t *timerid); -int timer_delete(timer_t timerid); -struct itimerspec; -int timer_gettime(timer_t timerid, struct itimerspec *its); -int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, - struct itimerspec *ovalue); -int timer_getoverrun(timer_t timerid); -int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); -int clock_nanosleep(clockid_t clock_id, int flags, - const struct timespec *rqtp, struct timespec *rmtp); - -#ifdef __cplusplus -} -#endif - -#else /* ZEPHYR_INCLUDE_POSIX_TIME_H_ */ -/* Read the toolchain header when finds itself on the - * first attempt. - */ +/* TODO: Deprecate including this header */ #include_next -#endif /* ZEPHYR_INCLUDE_POSIX_TIME_H_ */ diff --git a/lib/libc/minimal/include/time.h b/lib/libc/minimal/include/time.h index 62ec45b03a171..8762c5612ebd5 100644 --- a/lib/libc/minimal/include/time.h +++ b/lib/libc/minimal/include/time.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 Intel Corporation * Copyright (c) 2019 Peter Bigot Consulting, LLC + * Copyright (c) 2025 Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,19 +9,91 @@ #ifndef ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_TIME_H_ #define ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_TIME_H_ -#include #include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The header shall define the clock_t, size_t, time_t, types as described in + * . */ + +#if (!defined(_CLOCK_T_DECLARED) && !defined(__clock_t_defined)) || defined(__DOXYGEN__) +typedef unsigned long clock_t; +#define _CLOCK_T_DECLARED +#define __clock_t_defined +#endif + +/* size_t */ +#include + +/* _TIME_T_, _SUSECONDS_T_*/ #include -#include -/* Minimal time.h to fulfill the requirements of certain libraries - * like mbedTLS and to support time APIs. +#if (!defined(_TIME_T_DECLARED) && !defined(__time_t_defined)) || defined(__DOXYGEN__) +typedef _TIME_T_ time_t; +#define _TIME_T_DECLARED +#define __time_t_defined +#endif + +#if !defined(__suseconds_t_defined) +#define __suseconds_t_defined +typedef _SUSECONDS_T_ suseconds_t; +#endif + +/* The header shall define the clockid_t and timer_t types as described in . */ -#ifdef __cplusplus -extern "C" { +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#if (!defined(_CLOCKID_T_DECLARED) && !defined(__clockid_t_defined)) || defined(__DOXYGEN__) +typedef unsigned long clockid_t; +#define _CLOCKID_T_DECLARED +#define __clockid_t_defined #endif +#if (!defined(_TIMER_T_DECLARED) && !defined(__timer_t_defined)) || defined(__DOXYGEN__) +typedef unsigned long timer_t; +#define _TIMER_T_DECLARED +#define __timer_t_defined +#endif + +#endif + +/* The header shall define the locale_t type as described in . */ +/* #include */ +#if (!defined(_LOCALE_T_DECLARED) && !defined(__locale_t_defined)) || defined(__DOXYGEN__) + +struct locale_s { + char __unused: 1; +}; + +typedef struct locale_s locale_t; +#define _LOCALE_T_DECLARED +#define __locale_t_defined +#endif + +/* The header shall define the pid_t type as described in . */ + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#if (!defined(_PID_T_DECLARED) && !defined(__pid_t_defined)) || defined(__DOXYGEN__) +typedef long pid_t; +#define _PID_T_DECLARED +#define __pid_t_defined +#endif + +#endif + +/* The tag sigevent shall be declared as naming an incomplete structure type, the contents of which + * are described in the header. */ + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) +struct sigevent; +#endif + +/* The header shall declare the tm structure */ + struct tm { int tm_sec; int tm_min; @@ -33,37 +106,166 @@ struct tm { int tm_isdst; }; -#if !defined(__time_t_defined) -#define __time_t_defined -typedef _TIME_T_ time_t; +/* The header shall declare the timespec structure */ +#include + +/* The header shall also declare the itimerspec structure */ + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +struct itimer_spec { + struct timespec it_interval; /* Timer interval */ + struct timespec it_value; /* Timer expiration */ +}; #endif -#if !defined(__suseconds_t_defined) -#define __suseconds_t_defined -typedef _SUSECONDS_T_ suseconds_t; #endif -/* - * Conversion between civil time and UNIX time. The companion - * mktime() is not provided here since it - * require access to time zone information. - * - * The localtime() & localtime_r() simply - * wraps around the gmtime() & gmtime_r() functions, the - * results are always expressed as UTC. +/* The header shall define the following macros: NULL (stddef.h), CLOCKS_PER_SEC [XSI] */ + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#define CLOCKS_PER_SEC 1000000 + +#endif + +/* The header shall define the following symbolic constants. The values shall have a type + * that is assignment-compatible with clockid_t. CLOCK_MONOTONIC [MON], CLOCK_PROCESS_CPUTIME_ID + * [CPT], CLOCK_REALTIME [CX], CLOCK_THREAD_CPUTIME_ID [TCT] */ -struct tm *gmtime(const time_t *timep); -struct tm *gmtime_r(const time_t *ZRESTRICT timep, - struct tm *ZRESTRICT result); -char *asctime(const struct tm *timeptr); -struct tm *localtime(const time_t *timer); -char *ctime(const time_t *clock); + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#include + +#if defined(_POSIX_MONOTONIC_CLOCK) || defined(__DOXYGEN__) +#define CLOCK_MONOTONIC ((clockid_t)SYS_CLOCK_MONOTONIC) +#endif + +#if defined(_POSIX_CPUTIME) || defined(__DOXYGEN__) +#define CLOCK_PROCESS_CPUTIME_ID ((clockid_t)2) +#endif + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +#define CLOCK_REALTIME ((clockid_t)SYS_CLOCK_REALTIME) +#endif + +#if defined(_POSIX_THREAD_CPUTIME) || defined(__DOXYGEN__) +#define CLOCK_THREAD_CPUTIME_ID ((clockid_t)3) +#endif + +#endif + +/* The header shall define the following symbolic constant */ + +#if defined(_POSIX_C_SOURCE) || defined(__DOXYGEN__) + +#include + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +#define TIMER_ABSTIME SYS_TIMER_ABSTIME +#endif + +#endif + +/* The header shall provide a declaration or definition for getdate_err. */ +#if defined(_XOPEN_SOURCE) || defined(__DOXYGEN__) +extern int getdate_err; +#endif + +/* The following shall be declared as functions and may also be defined as macros. Function + * prototypes shall be provided. */ + +char *asctime(const struct tm *tp); + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || (_POSIX_C_SOURCE >= 200809L) || defined(__DOXYGEN__) +/* moved from thread safe to base in issue 7 (_POSIX_THREAD_SAFE_FUNCTIONS part of base) */ char *asctime_r(const struct tm *ZRESTRICT tp, char *ZRESTRICT buf); -char *ctime_r(const time_t *clock, char *buf); +#endif + +clock_t clock(void); + +#if defined(_POSIX_CPUTIME) || defined(__DOXYGEN__) +int clock_getcpuclockid(pid_t pid, clockid_t *clock_id); +#endif + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +int clock_getres(clockid_t clock_id, struct timespec *); +int clock_gettime(clockid_t clock_id, struct timespec *); +#endif + +#if defined(_POSIX_CLOCK_SELECTION) || defined(__DOXYGEN__) +int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, + struct timespec *rem); +#endif + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +int clock_settime(clockid_t clock_id, const struct timespec *tp); +#endif + +char *ctime(const time_t *timer); + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || (_POSIX_C_SOURCE >= 200809L) || defined(__DOXYGEN__) +/* moved from thread safe to base in issue 7 (_POSIX_THREAD_SAFE_FUNCTIONS part of base) */ +char *ctime_r(const time_t *, char *); +#endif + +double difftime(time_t, time_t); + +#if defined(_XOPEN_SOURCE) || defined(__DOXYGEN__) +struct tm *getdate(const char *string); +#endif + +struct tm *gmtime(const time_t *timer); + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || (_POSIX_C_SOURCE >= 200809L) || defined(__DOXYGEN__) +/* also visible in C23 */ +struct tm *gmtime_r(const time_t *ZRESTRICT timep, struct tm *ZRESTRICT result); +#endif + +struct tm *localtime(const time_t *timer); + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || (_POSIX_C_SOURCE >= 200809L) || defined(__DOXYGEN__) struct tm *localtime_r(const time_t *ZRESTRICT timer, struct tm *ZRESTRICT result); +#endif + +time_t mktime(struct tm *arg); + +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +int nanosleep(const struct timespec *req, struct timespec *rem); +#endif + +size_t strftime(char *ZRESTRICT s, size_t maxsize, const char *ZRESTRICT format, + const struct tm *ZRESTRICT timeptr); + +/* + * FIXME: needs locale.h or locale_t + * size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, + * locale_t); + */ + +#if defined(_XOPEN_SOURCE) || defined(__DOXYGEN__) +char *strptime(const char *ZRESTRICT s, const char *ZRESTRICT format, struct tm *ZRESTRICT tm); +#endif time_t time(time_t *tloc); +#if defined(_POSIX_TIMERS) || defined(__DOXYGEN__) +/* moved from timers to base in issue 7 (_POSIX_TIMERS part of base) */ +int timer_create(clockid_t clock_id, struct sigevent *ZRESTRICT evp, timer_t *ZRESTRICT timer_id); +int timer_delete(timer_t timer_id); +int timer_getoverrun(timer_t timer_id); +int timer_gettime(timer_t timer_id, struct itimerspec *ZRESTRICT value); +int timer_settime(timer_t timer_id, int flags, const struct itimerspec *ZRESTRICT value, + struct itimerspec *ZRESTRICT old_value); +#endif + #ifdef __cplusplus } #endif diff --git a/lib/libc/minimal/source/time/gmtime.c b/lib/libc/minimal/source/time/gmtime.c index 8df80d7c7c8e2..e2e2582f164ca 100644 --- a/lib/libc/minimal/source/time/gmtime.c +++ b/lib/libc/minimal/source/time/gmtime.c @@ -4,7 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L #include + #include #ifdef CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS diff --git a/lib/libc/newlib/CMakeLists.txt b/lib/libc/newlib/CMakeLists.txt index d3dc448eccafc..4ecd453e157c3 100644 --- a/lib/libc/newlib/CMakeLists.txt +++ b/lib/libc/newlib/CMakeLists.txt @@ -49,3 +49,12 @@ if(CONFIG_NEWLIB_LIBC_NANO) -specs=nano.specs ) endif() + +if(CONFIG_POSIX_API) + set(POSIX_VERSION 200809L) + zephyr_compile_options( + -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=${POSIX_VERSION} + -U_POSIX_TIMERS -D_POSIX_TIMERS=${POSIX_VERSION} + -U__POSIX_VISIBLE -D__POSIX_VISIBLE=${POSIX_VERSION} + ) +endif() diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 5ef2032e5a91c..76518b66964a3 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -1,5 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +set(POSIX_VERSION 200809L) +set(XOPEN_VERSION 700) + set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) zephyr_syscall_header_ifdef(CONFIG_POSIX_CLOCK_SELECTION posix_clock.h) @@ -8,6 +11,9 @@ zephyr_syscall_header_ifdef(CONFIG_XSI_SINGLE_PROCESS posix_clock.h) if(CONFIG_POSIX_SYSTEM_HEADERS) zephyr_include_directories(${ZEPHYR_BASE}/include/zephyr/posix) + zephyr_compile_options( + -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=${POSIX_VERSION} + ) endif() if (NOT CONFIG_TC_PROVIDES_POSIX_SIGNALS) @@ -125,6 +131,12 @@ if (NOT CONFIG_TC_PROVIDES_POSIX_TIMERS) timespec_to_timeout.c ) endif() +zephyr_compile_options_ifdef(CONFIG_POSIX_TIMERS + -U_POSIX_TIMERS -D_POSIX_TIMERS=${POSIX_VERSION} + # Technically _POSIX_MONOTONIC_CLOCK should be selected by CONFIG_POSIX_ADVANCED_REALTIME + # See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html + -U_POSIX_MONOTONIC_CLOCK -D_POSIX_MONOTONIC_CLOCK=${POSIX_VERSION} +) if (NOT CONFIG_TC_PROVIDES_POSIX_READER_WRITER_LOCKS) # Note: the Option is _POSIX_READER_WRITER_LOCKS, while the Option Group is POSIX_RW_LOCKS. diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index 466974705ac3a..4b408e48676db 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -33,8 +33,17 @@ int clock_getres(clockid_t clock_id, struct timespec *res) CONFIG_SYS_CLOCK_TICKS_PER_SEC <= NSEC_PER_SEC, "CONFIG_SYS_CLOCK_TICKS_PER_SEC must be > 0 and <= NSEC_PER_SEC"); - if (!(clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_REALTIME || - clock_id == CLOCK_PROCESS_CPUTIME_ID)) { + if (!( +/* FIXME: this should check CONFIG_POSIX_ADVANCED_REALTIME */ +#if defined(_POSIX_MONOTONIC_CLOCK) + clock_id == CLOCK_MONOTONIC || +#endif + clock_id == CLOCK_REALTIME || +/* FIXME: this should check CONFIG_POSIX_ADVANCED_REALTIME */ +#if defined(_POSIX_CPUTIME) + clock_id == CLOCK_PROCESS_CPUTIME_ID || +#endif + false)) { errno = EINVAL; return -1; } @@ -117,6 +126,8 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) return 0; } +/* FIXME: this should check CONFIG_POSIX_ADVANCED_REALTIME */ +#if defined(_POSIX_CPUTIME) int clock_getcpuclockid(pid_t pid, clockid_t *clock_id) { /* We don't allow any process ID but our own. */ @@ -128,3 +139,4 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clock_id) return 0; } +#endif diff --git a/tests/posix/timers/src/clock.c b/tests/posix/timers/src/clock.c index 7e6b39137b962..1f3012b020177 100644 --- a/tests/posix/timers/src/clock.c +++ b/tests/posix/timers/src/clock.c @@ -157,8 +157,10 @@ ZTEST(posix_timers, test_realtime) zassert_between_inclusive(cma, lo, hi); } +/* FIXME: this should be moved to a testsuite called advanced_realtime */ ZTEST(posix_timers, test_clock_getcpuclockid) { +#ifdef _POSIX_CPUTIME int ret = 0; clockid_t clock_id = CLOCK_INVALID; @@ -168,6 +170,7 @@ ZTEST(posix_timers, test_clock_getcpuclockid) ret = clock_getcpuclockid((pid_t)2482, &clock_id); zassert_equal(ret, EPERM, "POSIX clock_getcpuclock id failed"); +#endif } ZTEST(posix_timers, test_clock_getres) @@ -190,13 +193,21 @@ ZTEST(posix_timers, test_clock_getres) {CLOCK_INVALID, NULL, -1}, {CLOCK_INVALID, &res, -1}, {CLOCK_REALTIME, NULL, 0}, +#if defined(_POSIX_MONOTONIC_CLOCK) {CLOCK_MONOTONIC, NULL, 0}, +#endif +#if defined(_POSIX_CPUTIME) {CLOCK_PROCESS_CPUTIME_ID, NULL, 0}, +#endif /* all valid inputs */ {CLOCK_REALTIME, &res, 0}, +#if defined(_POSIX_MONOTONIC_CLOCK) {CLOCK_MONOTONIC, &res, 0}, +#endif +#if defined(_POSIX_CPUTIME) {CLOCK_PROCESS_CPUTIME_ID, &res, 0}, +#endif }; ARRAY_FOR_EACH_PTR(args, arg) { diff --git a/tests/posix/timers/src/timer.c b/tests/posix/timers/src/timer.c index 1d4936d6a4be6..49e896f991e43 100644 --- a/tests/posix/timers/src/timer.c +++ b/tests/posix/timers/src/timer.c @@ -9,6 +9,7 @@ #include #include +#include #define SECS_TO_SLEEP 2 #define DURATION_SECS 1