diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index 51542f304fa9a..7f944b7db97ae 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -85,11 +85,6 @@ extern "C" { #define TIMER_ABSTIME 4 #endif -static inline int32_t _ts_to_ms(const struct timespec *to) -{ - return (int32_t)(to->tv_sec * MSEC_PER_SEC) + (int32_t)(to->tv_nsec / NSEC_PER_MSEC); -} - 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); diff --git a/lib/posix/options/cond.c b/lib/posix/options/cond.c index 8155b993fcc22..d1fc231c94c0f 100644 --- a/lib/posix/options/cond.c +++ b/lib/posix/options/cond.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_clock.h" #include "posix_internal.h" #include @@ -15,13 +16,13 @@ LOG_MODULE_REGISTER(pthread_cond, CONFIG_PTHREAD_COND_LOG_LEVEL); -int64_t timespec_to_timeoutms(const struct timespec *abstime); - -__pinned_bss -static struct k_condvar posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT]; +static __pinned_bss struct posix_cond posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT]; SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT); +BUILD_ASSERT(sizeof(struct posix_condattr) <= sizeof(pthread_condattr_t), + "posix_condattr is too large"); + /* * We reserve the MSB to mark a pthread_cond_t as initialized (from the * perspective of the application). With a linear space, this means that @@ -30,7 +31,7 @@ SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT); BUILD_ASSERT(CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT, "CONFIG_MAX_PTHREAD_COND_COUNT is too high"); -static inline size_t posix_cond_to_offset(struct k_condvar *cv) +static inline size_t posix_cond_to_offset(struct posix_cond *cv) { return cv - posix_cond_pool; } @@ -40,7 +41,7 @@ static inline size_t to_posix_cond_idx(pthread_cond_t cond) return mark_pthread_obj_uninitialized(cond); } -static struct k_condvar *get_posix_cond(pthread_cond_t cond) +static struct posix_cond *get_posix_cond(pthread_cond_t cond) { int actually_initialized; size_t bit = to_posix_cond_idx(cond); @@ -66,10 +67,10 @@ static struct k_condvar *get_posix_cond(pthread_cond_t cond) return &posix_cond_pool[bit]; } -static struct k_condvar *to_posix_cond(pthread_cond_t *cvar) +static struct posix_cond *to_posix_cond(pthread_cond_t *cvar) { size_t bit; - struct k_condvar *cv; + struct posix_cond *cv; if (*cvar != PTHREAD_COND_INITIALIZER) { return get_posix_cond(*cvar); @@ -85,15 +86,17 @@ static struct k_condvar *to_posix_cond(pthread_cond_t *cvar) /* Record the associated posix_cond in mu and mark as initialized */ *cvar = mark_pthread_obj_initialized(bit); cv = &posix_cond_pool[bit]; + (void)pthread_condattr_init((pthread_condattr_t *)&cv->attr); return cv; } -static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t timeout) +static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, const struct timespec *abstime) { int ret; struct k_mutex *m; - struct k_condvar *cv; + struct posix_cond *cv; + k_timeout_t timeout = K_FOREVER; m = to_posix_mutex(mu); cv = to_posix_cond(cond); @@ -101,8 +104,12 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time return EINVAL; } + if (abstime != NULL) { + timeout = K_MSEC(timespec_to_timeoutms(cv->attr.clock, abstime)); + } + LOG_DBG("Waiting on cond %p with timeout %llx", cv, timeout.ticks); - ret = k_condvar_wait(cv, m, timeout); + ret = k_condvar_wait(&cv->condvar, m, timeout); if (ret == -EAGAIN) { LOG_DBG("Timeout waiting on cond %p", cv); ret = ETIMEDOUT; @@ -120,7 +127,7 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time int pthread_cond_signal(pthread_cond_t *cvar) { int ret; - struct k_condvar *cv; + struct posix_cond *cv; cv = to_posix_cond(cvar); if (cv == NULL) { @@ -128,7 +135,7 @@ int pthread_cond_signal(pthread_cond_t *cvar) } LOG_DBG("Signaling cond %p", cv); - ret = k_condvar_signal(cv); + ret = k_condvar_signal(&cv->condvar); if (ret < 0) { LOG_DBG("k_condvar_signal() failed: %d", ret); return -ret; @@ -142,7 +149,7 @@ int pthread_cond_signal(pthread_cond_t *cvar) int pthread_cond_broadcast(pthread_cond_t *cvar) { int ret; - struct k_condvar *cv; + struct posix_cond *cv; cv = get_posix_cond(*cvar); if (cv == NULL) { @@ -150,7 +157,7 @@ int pthread_cond_broadcast(pthread_cond_t *cvar) } LOG_DBG("Broadcasting on cond %p", cv); - ret = k_condvar_broadcast(cv); + ret = k_condvar_broadcast(&cv->condvar); if (ret < 0) { LOG_DBG("k_condvar_broadcast() failed: %d", ret); return -ret; @@ -163,27 +170,39 @@ int pthread_cond_broadcast(pthread_cond_t *cvar) int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut) { - return cond_wait(cv, mut, K_FOREVER); + return cond_wait(cv, mut, NULL); } int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime) { - return cond_wait(cv, mut, K_MSEC((int32_t)timespec_to_timeoutms(abstime))); + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + LOG_DBG("%s is invalid", "abstime"); + return EINVAL; + } + + return cond_wait(cv, mut, abstime); } int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att) { - struct k_condvar *cv; + struct posix_cond *cv; + struct posix_condattr *attr = (struct posix_condattr *)attr; - ARG_UNUSED(att); *cvar = PTHREAD_COND_INITIALIZER; - - /* calls k_condvar_init() */ cv = to_posix_cond(cvar); if (cv == NULL) { return ENOMEM; } + if (attr != NULL) { + if (!attr->initialized) { + return EINVAL; + } + + (void)pthread_condattr_destroy((pthread_condattr_t *)&cv->attr); + cv->attr = *attr; + } + LOG_DBG("Initialized cond %p", cv); return 0; @@ -193,7 +212,7 @@ int pthread_cond_destroy(pthread_cond_t *cvar) { int err; size_t bit; - struct k_condvar *cv; + struct posix_cond *cv; cv = get_posix_cond(*cvar); if (cv == NULL) { @@ -218,7 +237,7 @@ static int pthread_cond_pool_init(void) size_t i; for (i = 0; i < CONFIG_MAX_PTHREAD_COND_COUNT; ++i) { - err = k_condvar_init(&posix_cond_pool[i]); + err = k_condvar_init(&posix_cond_pool[i].condvar); __ASSERT_NO_MSG(err == 0); } @@ -227,16 +246,32 @@ static int pthread_cond_pool_init(void) int pthread_condattr_init(pthread_condattr_t *att) { - __ASSERT_NO_MSG(att != NULL); + struct posix_condattr *const attr = (struct posix_condattr *)att; + + if (att == NULL) { + return EINVAL; + } + if (attr->initialized) { + LOG_DBG("%s %s initialized", "attribute", "already"); + return EINVAL; + } - att->clock = CLOCK_MONOTONIC; + attr->clock = CLOCK_REALTIME; + attr->initialized = true; return 0; } int pthread_condattr_destroy(pthread_condattr_t *att) { - ARG_UNUSED(att); + struct posix_condattr *const attr = (struct posix_condattr *)att; + + if ((attr == NULL) || !attr->initialized) { + LOG_DBG("%s %s initialized", "attribute", "not"); + return EINVAL; + } + + *attr = (struct posix_condattr){0}; return 0; } @@ -244,18 +279,32 @@ int pthread_condattr_destroy(pthread_condattr_t *att) int pthread_condattr_getclock(const pthread_condattr_t *ZRESTRICT att, clockid_t *ZRESTRICT clock_id) { - *clock_id = att->clock; + struct posix_condattr *const attr = (struct posix_condattr *)att; + + if ((attr == NULL) || !attr->initialized) { + LOG_DBG("%s %s initialized", "attribute", "not"); + return EINVAL; + } + + *clock_id = attr->clock; return 0; } int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id) { + struct posix_condattr *const attr = (struct posix_condattr *)att; + if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC) { return -EINVAL; } - att->clock = clock_id; + if ((attr == NULL) || !attr->initialized) { + LOG_DBG("%s %s initialized", "attribute", "not"); + return EINVAL; + } + + attr->clock = clock_id; return 0; } diff --git a/lib/posix/options/mqueue.c b/lib/posix/options/mqueue.c index 12bbf30d0ab5e..0eef3f81ccf35 100644 --- a/lib/posix/options/mqueue.c +++ b/lib/posix/options/mqueue.c @@ -4,6 +4,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#include "posix_clock.h" + #include #include #include @@ -34,7 +37,6 @@ K_SEM_DEFINE(mq_sem, 1, 1); /* Initialize the list */ sys_slist_t mq_list = SYS_SLIST_STATIC_INIT(&mq_list); -int64_t timespec_to_timeoutms(const struct timespec *abstime); static mqueue_object *find_in_list(const char *name); static int32_t send_message(mqueue_desc *mqd, const char *msg_ptr, size_t msg_len, k_timeout_t timeout); @@ -255,9 +257,14 @@ int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abstime) { mqueue_desc *mqd = (mqueue_desc *)mqdes; - int32_t timeout = (int32_t) timespec_to_timeoutms(abstime); - return send_message(mqd, msg_ptr, msg_len, K_MSEC(timeout)); + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + errno = EINVAL; + return -1; + } + + return send_message(mqd, msg_ptr, msg_len, + K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime))); } /** @@ -286,9 +293,14 @@ int mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abstime) { mqueue_desc *mqd = (mqueue_desc *)mqdes; - int32_t timeout = (int32_t) timespec_to_timeoutms(abstime); - return receive_message(mqd, msg_ptr, msg_len, K_MSEC(timeout)); + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + errno = EINVAL; + return -1; + } + + return receive_message(mqd, msg_ptr, msg_len, + K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime))); } /** diff --git a/lib/posix/options/mutex.c b/lib/posix/options/mutex.c index d6a54fd36d561..52dec35d24911 100644 --- a/lib/posix/options/mutex.c +++ b/lib/posix/options/mutex.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_clock.h" #include "posix_internal.h" #include @@ -18,8 +19,6 @@ LOG_MODULE_REGISTER(pthread_mutex, CONFIG_PTHREAD_MUTEX_LOG_LEVEL); static SYS_SEM_DEFINE(lock, 1, 1); -int64_t timespec_to_timeoutms(const struct timespec *abstime); - #define MUTEX_MAX_REC_LOCK 32767 /* @@ -212,8 +211,12 @@ int pthread_mutex_trylock(pthread_mutex_t *m) int pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *abstime) { - int32_t timeout = (int32_t)timespec_to_timeoutms(abstime); - return acquire_mutex(m, K_MSEC(timeout)); + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + LOG_DBG("%s is invalid", "abstime"); + return EINVAL; + } + + return acquire_mutex(m, K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime))); } /** diff --git a/lib/posix/options/posix_clock.h b/lib/posix/options/posix_clock.h index f505dbc175271..12de6f9fe8c9f 100644 --- a/lib/posix/options/posix_clock.h +++ b/lib/posix/options/posix_clock.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Meta + * Copyright (c) 2025 Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,13 +8,65 @@ #ifndef ZEPHYR_LIB_POSIX_POSIX_CLOCK_H_ #define ZEPHYR_LIB_POSIX_POSIX_CLOCK_H_ +#include +#include +#include #include -#include -#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +static inline bool timespec_is_valid(const struct timespec *ts) +{ + __ASSERT_NO_MSG(ts != NULL); + return (ts->tv_nsec >= 0) && (ts->tv_nsec < NSEC_PER_SEC); +} + +static inline int64_t ts_to_ns(const struct timespec *ts) +{ + return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec; +} + +static inline int64_t ts_to_ms(const struct timespec *ts) +{ + return ts->tv_sec * MSEC_PER_SEC + ts->tv_nsec / NSEC_PER_MSEC; +} + +static inline bool tp_ge(const struct timespec *a, const struct timespec *b) +{ + return ts_to_ns(a) >= ts_to_ns(b); +} + +static inline int64_t tp_diff(const struct timespec *a, const struct timespec *b) +{ + return ts_to_ns(a) - ts_to_ns(b); +} + +/* lo <= (a - b) < hi */ +static inline bool tp_diff_in_range_ns(const struct timespec *a, const struct timespec *b, + int64_t lo, int64_t hi) +{ + int64_t diff = tp_diff(a, b); + + return diff >= lo && diff < hi; +} + +uint32_t timespec_to_timeoutms(clockid_t clock_id, const struct timespec *abstime); __syscall int __posix_clock_get_base(clockid_t clock_id, struct timespec *ts); +/** INTERNAL_HIDDEN @endcond */ + #include +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/posix/options/posix_internal.h b/lib/posix/options/posix_internal.h index 24bfb83e14b7e..3a4804d0ee4f3 100644 --- a/lib/posix/options/posix_internal.h +++ b/lib/posix/options/posix_internal.h @@ -66,6 +66,20 @@ struct posix_thread { uint8_t qid; }; +struct posix_condattr { + /* leaves room for CLOCK_REALTIME (1, default) and CLOCK_MONOTONIC (4) */ + unsigned int clock: 3; + bool initialized: 1; +#ifdef _POSIX_THREAD_PROCESS_SHARED + unsigned int pshared: 1; +#endif +}; + +struct posix_cond { + struct k_condvar condvar; + struct posix_condattr attr; +}; + typedef struct pthread_key_obj { /* List of pthread_key_data objects that contain thread * specific data for the key diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c index 398951307aa7e..c505b8564bb30 100644 --- a/lib/posix/options/pthread.c +++ b/lib/posix/options/pthread.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_clock.h" #include "posix_internal.h" #include "pthread_sched.h" @@ -81,7 +82,6 @@ BUILD_ASSERT((PTHREAD_CANCEL_ENABLE == 0 || PTHREAD_CANCEL_DISABLE == 0) && BUILD_ASSERT(CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS + CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS <= 32); -int64_t timespec_to_timeoutms(const struct timespec *abstime); static void posix_thread_recycle(void); __pinned_data @@ -1149,15 +1149,13 @@ static int pthread_timedjoin_internal(pthread_t pthread, void **status, k_timeou */ int pthread_timedjoin_np(pthread_t pthread, void **status, const struct timespec *abstime) { - if (abstime == NULL) { + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + LOG_DBG("%s is invalid", "abstime"); return EINVAL; } - if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= NSEC_PER_SEC) { - return EINVAL; - } - - return pthread_timedjoin_internal(pthread, status, K_MSEC(timespec_to_timeoutms(abstime))); + return pthread_timedjoin_internal(pthread, status, + K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime))); } /** diff --git a/lib/posix/options/rwlock.c b/lib/posix/options/rwlock.c index fab35ec84a233..b7eb21bd6be2e 100644 --- a/lib/posix/options/rwlock.c +++ b/lib/posix/options/rwlock.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_clock.h" #include "posix_internal.h" #include @@ -27,9 +28,8 @@ struct posix_rwlockattr { bool pshared: 1; }; -int64_t timespec_to_timeoutms(const struct timespec *abstime); -static uint32_t read_lock_acquire(struct posix_rwlock *rwl, int32_t timeout); -static uint32_t write_lock_acquire(struct posix_rwlock *rwl, int32_t timeout); +static uint32_t read_lock_acquire(struct posix_rwlock *rwl, uint32_t timeout); +static uint32_t write_lock_acquire(struct posix_rwlock *rwl, uint32_t timeout); LOG_MODULE_REGISTER(pthread_rwlock, CONFIG_PTHREAD_RWLOCK_LOG_LEVEL); @@ -198,22 +198,20 @@ int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abstime) { - int32_t timeout; uint32_t ret = 0U; struct posix_rwlock *rwl; - if (abstime->tv_nsec < 0 || abstime->tv_nsec > NSEC_PER_SEC) { + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + LOG_DBG("%s is invalid", "abstime"); return EINVAL; } - timeout = (int32_t) timespec_to_timeoutms(abstime); - rwl = get_posix_rwlock(*rwlock); if (rwl == NULL) { return EINVAL; } - if (read_lock_acquire(rwl, timeout) != 0U) { + if (read_lock_acquire(rwl, timespec_to_timeoutms(CLOCK_REALTIME, abstime)) != 0U) { ret = ETIMEDOUT; } @@ -271,22 +269,20 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abstime) { - int32_t timeout; uint32_t ret = 0U; struct posix_rwlock *rwl; - if (abstime->tv_nsec < 0 || abstime->tv_nsec > NSEC_PER_SEC) { + if ((abstime == NULL) || !timespec_is_valid(abstime)) { + LOG_DBG("%s is invalid", "abstime"); return EINVAL; } - timeout = (int32_t) timespec_to_timeoutms(abstime); - rwl = get_posix_rwlock(*rwlock); if (rwl == NULL) { return EINVAL; } - if (write_lock_acquire(rwl, timeout) != 0U) { + if (write_lock_acquire(rwl, timespec_to_timeoutms(CLOCK_REALTIME, abstime)) != 0U) { ret = ETIMEDOUT; } @@ -345,7 +341,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) return 0; } -static uint32_t read_lock_acquire(struct posix_rwlock *rwl, int32_t timeout) +static uint32_t read_lock_acquire(struct posix_rwlock *rwl, uint32_t timeout) { uint32_t ret = 0U; @@ -360,7 +356,7 @@ static uint32_t read_lock_acquire(struct posix_rwlock *rwl, int32_t timeout) return ret; } -static uint32_t write_lock_acquire(struct posix_rwlock *rwl, int32_t timeout) +static uint32_t write_lock_acquire(struct posix_rwlock *rwl, uint32_t timeout) { uint32_t ret = 0U; int64_t elapsed_time, st_time = k_uptime_get(); diff --git a/lib/posix/options/semaphore.c b/lib/posix/options/semaphore.c index 537b618ff6f7c..55ac57c5cfd3f 100644 --- a/lib/posix/options/semaphore.c +++ b/lib/posix/options/semaphore.c @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_clock.h" + #include #include #include @@ -159,31 +161,12 @@ int sem_post(sem_t *semaphore) */ int sem_timedwait(sem_t *semaphore, struct timespec *abstime) { - int32_t timeout; - struct timespec current; - int64_t current_ms, abstime_ms; - - __ASSERT(abstime, "abstime pointer NULL"); - - if ((abstime->tv_sec < 0) || (abstime->tv_nsec >= NSEC_PER_SEC)) { + if ((abstime == NULL) || !timespec_is_valid(abstime)) { errno = EINVAL; return -1; } - if (clock_gettime(CLOCK_REALTIME, ¤t) < 0) { - return -1; - } - - abstime_ms = (int64_t)_ts_to_ms(abstime); - current_ms = (int64_t)_ts_to_ms(¤t); - - if (abstime_ms <= current_ms) { - timeout = 0; - } else { - timeout = (int32_t)(abstime_ms - current_ms); - } - - if (k_sem_take(semaphore, K_MSEC(timeout))) { + if (k_sem_take(semaphore, K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime)))) { errno = ETIMEDOUT; return -1; } diff --git a/lib/posix/options/timer.c b/lib/posix/options/timer.c index e810b4576f7c9..257fdce59ef36 100644 --- a/lib/posix/options/timer.c +++ b/lib/posix/options/timer.c @@ -4,8 +4,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ + #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L + +#include "posix_clock.h" + #include #include @@ -241,11 +245,8 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct timer_obj *timer = (struct timer_obj *) timerid; uint32_t duration, current; - if (timer == NULL || - value->it_interval.tv_nsec < 0 || - value->it_interval.tv_nsec >= NSEC_PER_SEC || - value->it_value.tv_nsec < 0 || - value->it_value.tv_nsec >= NSEC_PER_SEC) { + if ((timer == NULL) || !timespec_is_valid(&value->it_interval) || + !timespec_is_valid(&value->it_value)) { errno = EINVAL; return -1; } @@ -266,12 +267,12 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, } /* Calculate timer period */ - timer->reload = _ts_to_ms(&value->it_interval); + timer->reload = ts_to_ms(&value->it_interval); timer->interval.tv_sec = value->it_interval.tv_sec; timer->interval.tv_nsec = value->it_interval.tv_nsec; /* Calculate timer duration */ - duration = _ts_to_ms(&(value->it_value)); + duration = ts_to_ms(&(value->it_value)); if ((flags & TIMER_ABSTIME) != 0) { current = k_timer_remaining_get(&timer->ztimer); diff --git a/lib/posix/options/timespec_to_timeout.c b/lib/posix/options/timespec_to_timeout.c index e72956e6e3e93..068646c2064d4 100644 --- a/lib/posix/options/timespec_to_timeout.c +++ b/lib/posix/options/timespec_to_timeout.c @@ -4,28 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include "posix_clock.h" + +#include +#include + #include +#include -int64_t timespec_to_timeoutms(const struct timespec *abstime) +uint32_t timespec_to_timeoutms(clockid_t clock_id, const struct timespec *abstime) { - int64_t milli_secs, secs, nsecs; struct timespec curtime; - /* FIXME: Zephyr does have CLOCK_REALTIME to get time. - * As per POSIX standard time should be calculated wrt CLOCK_REALTIME. - * Zephyr deviates from POSIX 1003.1 standard on this aspect. - */ - clock_gettime(CLOCK_MONOTONIC, &curtime); - secs = abstime->tv_sec - curtime.tv_sec; - nsecs = abstime->tv_nsec - curtime.tv_nsec; - - if (secs < 0 || (secs == 0 && nsecs < NSEC_PER_MSEC)) { - milli_secs = 0; - } else { - milli_secs = secs * MSEC_PER_SEC + nsecs / NSEC_PER_MSEC; + if (clock_gettime(clock_id, &curtime) < 0) { + return 0; } - return milli_secs; + return CLAMP(tp_diff(abstime, &curtime) / NSEC_PER_MSEC, 0, UINT32_MAX); } diff --git a/tests/lib/c_lib/thrd/src/cnd.c b/tests/lib/c_lib/thrd/src/cnd.c index aaf00f9cb7b97..82741e352bbcf 100644 --- a/tests/lib/c_lib/thrd/src/cnd.c +++ b/tests/lib/c_lib/thrd/src/cnd.c @@ -71,7 +71,7 @@ static int test_cnd_thread_fn(void *arg) struct libc_cnd_fixture *const fixture = arg; if (fixture->do_timedwait) { - zassume_ok(clock_gettime(CLOCK_MONOTONIC, &time_point)); + zassume_ok(clock_gettime(CLOCK_REALTIME, &time_point)); timespec_add_ms(&time_point, WAIT_TIME_MS); res = cnd_timedwait(&fixture->cond, &fixture->mutex, &time_point); } else { diff --git a/tests/posix/common/src/cond.c b/tests/posix/common/src/cond.c index b648ac0abd0f3..94de124c3758a 100644 --- a/tests/posix/common/src/cond.c +++ b/tests/posix/common/src/cond.c @@ -55,7 +55,7 @@ ZTEST(cond, test_pthread_condattr) zassert_ok(pthread_condattr_init(&att)); zassert_ok(pthread_condattr_getclock(&att, &clock_id), "pthread_condattr_getclock failed"); - zassert_equal(clock_id, CLOCK_MONOTONIC, "clock attribute not set correctly"); + zassert_equal(clock_id, CLOCK_REALTIME, "clock attribute not set correctly"); zassert_ok(pthread_condattr_setclock(&att, CLOCK_REALTIME), "pthread_condattr_setclock failed"); diff --git a/tests/posix/common/src/pthread.c b/tests/posix/common/src/pthread.c index 3801d3b41862c..035730ee4dc73 100644 --- a/tests/posix/common/src/pthread.c +++ b/tests/posix/common/src/pthread.c @@ -404,9 +404,8 @@ ZTEST(pthread, test_pthread_timedjoin) struct timespec not_done; struct timespec done; struct timespec invalid[] = { - [0] = {.tv_sec = -1}, - [1] = {.tv_nsec = -1}, - [2] = {.tv_nsec = NSEC_PER_SEC}, + {.tv_nsec = -1}, + {.tv_nsec = NSEC_PER_SEC}, }; /* setup timespecs when the thread is still running and when it is done */ @@ -426,7 +425,7 @@ ZTEST(pthread, test_pthread_timedjoin) /* Creating a thread that exits after 200ms*/ zassert_ok(pthread_create(&th, NULL, timedjoin_thread, INT_TO_POINTER(sleep_duration_ms))); - /* pthread_timedjoin-np must return -EINVAL for invalid struct timespecs */ + /* pthread_timedjoin-np must return EINVAL for invalid struct timespecs */ zassert_equal(pthread_timedjoin_np(th, &ret, NULL), EINVAL); for (size_t i = 0; i < ARRAY_SIZE(invalid); ++i) { zassert_equal(pthread_timedjoin_np(th, &ret, &invalid[i]), EINVAL); diff --git a/tests/posix/rwlocks/src/main.c b/tests/posix/rwlocks/src/main.c index 7e0fd101f028a..aaf859663bfbd 100644 --- a/tests/posix/rwlocks/src/main.c +++ b/tests/posix/rwlocks/src/main.c @@ -86,8 +86,9 @@ ZTEST(posix_rw_locks, test_rw_lock) usleep(USEC_PER_MSEC); LOG_DBG("Parent thread acquiring WR lock again"); - time.tv_sec = 2; - time.tv_nsec = 0; + zassert_ok(clock_gettime(CLOCK_REALTIME, &time)); + time.tv_sec += 2; + ret = pthread_rwlock_timedwrlock(&rwlock, &time); if (ret) { zassert_ok(pthread_rwlock_wrlock(&rwlock), "Failed to acquire write lock"); diff --git a/tests/posix/timers/CMakeLists.txt b/tests/posix/timers/CMakeLists.txt index 7c689da26a445..9eab9f09c6fc2 100644 --- a/tests/posix/timers/CMakeLists.txt +++ b/tests/posix/timers/CMakeLists.txt @@ -9,3 +9,4 @@ FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) target_compile_options(app PRIVATE -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/lib/posix/options) diff --git a/tests/posix/timers/src/clock.c b/tests/posix/timers/src/clock.c index 0b34e87db06f4..7e6b39137b962 100644 --- a/tests/posix/timers/src/clock.c +++ b/tests/posix/timers/src/clock.c @@ -4,6 +4,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +/* for tp_ge(), tp_diff() */ +#include "posix_clock.h" + #include #include #include @@ -29,35 +33,6 @@ static const bool settable[] = { true, }; -static inline int64_t ts_to_ns(const struct timespec *ts) -{ - return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec; -} - -#define _tp_op(_a, _b, _op) (ts_to_ns(_a) _op ts_to_ns(_b)) - -#define _decl_op(_type, _name, _op) \ - __used static inline _type _name(const struct timespec *_a, const struct timespec *_b) \ - { \ - return _tp_op(_a, _b, _op); \ - } - -_decl_op(bool, tp_eq, ==); /* a == b */ -_decl_op(bool, tp_lt, <); /* a < b */ -_decl_op(bool, tp_gt, >); /* a > b */ -_decl_op(bool, tp_le, <=); /* a <= b */ -_decl_op(bool, tp_ge, >=); /* a >= b */ -_decl_op(int64_t, tp_diff, -); /* a - b */ - -/* lo <= (a - b) < hi */ -__used static inline bool tp_diff_in_range_ns(const struct timespec *a, const struct timespec *b, - int64_t lo, int64_t hi) -{ - int64_t diff = tp_diff(a, b); - - return diff >= lo && diff < hi; -} - ZTEST(posix_timers, test_clock_gettime) { struct timespec ts;