Skip to content

Commit 95b410c

Browse files
committed
posix + tests: correct timing functions to use CLOCK_REALTIME
Use `CLOCK_REALTIME` by default as per the POSIX specification for the following functions: * `mq_timedreceive()` * `mq_timedsend()` * `pthread_cond_timedwait()` * `pthread_mutex_timedlock()` * `pthread_rwlock_timedrdlock()` * `pthread_rwlock_timedwrlock()` * `sem_timedwait()` and additionally for the following non-portable functions: * `pthread_timedjoin_np()` Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
1 parent 91ca07b commit 95b410c

File tree

15 files changed

+232
-136
lines changed

15 files changed

+232
-136
lines changed

include/zephyr/posix/time.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,6 @@ extern "C" {
8585
#define TIMER_ABSTIME 4
8686
#endif
8787

88-
static inline int32_t _ts_to_ms(const struct timespec *to)
89-
{
90-
return (int32_t)(to->tv_sec * MSEC_PER_SEC) + (int32_t)(to->tv_nsec / NSEC_PER_MSEC);
91-
}
92-
9388
int clock_gettime(clockid_t clock_id, struct timespec *ts);
9489
int clock_getres(clockid_t clock_id, struct timespec *ts);
9590
int clock_settime(clockid_t clock_id, const struct timespec *ts);

lib/posix/options/cond.c

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "posix_internal.h"
99

10+
#include <stdbool.h>
11+
1012
#include <zephyr/init.h>
1113
#include <zephyr/kernel.h>
1214
#include <zephyr/logging/log.h>
@@ -15,10 +17,7 @@
1517

1618
LOG_MODULE_REGISTER(pthread_cond, CONFIG_PTHREAD_COND_LOG_LEVEL);
1719

18-
int64_t timespec_to_timeoutms(const struct timespec *abstime);
19-
20-
__pinned_bss
21-
static struct k_condvar posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT];
20+
__pinned_bss static struct posix_cond posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT];
2221

2322
SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT);
2423

@@ -30,7 +29,7 @@ SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT);
3029
BUILD_ASSERT(CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT,
3130
"CONFIG_MAX_PTHREAD_COND_COUNT is too high");
3231

33-
static inline size_t posix_cond_to_offset(struct k_condvar *cv)
32+
static inline size_t posix_cond_to_offset(struct posix_cond *cv)
3433
{
3534
return cv - posix_cond_pool;
3635
}
@@ -40,7 +39,7 @@ static inline size_t to_posix_cond_idx(pthread_cond_t cond)
4039
return mark_pthread_obj_uninitialized(cond);
4140
}
4241

43-
static struct k_condvar *get_posix_cond(pthread_cond_t cond)
42+
static struct posix_cond *get_posix_cond(pthread_cond_t cond)
4443
{
4544
int actually_initialized;
4645
size_t bit = to_posix_cond_idx(cond);
@@ -66,10 +65,30 @@ static struct k_condvar *get_posix_cond(pthread_cond_t cond)
6665
return &posix_cond_pool[bit];
6766
}
6867

69-
static struct k_condvar *to_posix_cond(pthread_cond_t *cvar)
68+
static inline bool is_posix_condattr_valid(struct posix_condattr *attr)
69+
{
70+
if (attr == NULL) {
71+
return false;
72+
}
73+
74+
if (!attr->initialized) {
75+
LOG_DBG("condattr is not initialized");
76+
return false;
77+
}
78+
79+
/* revisit when POSIX_CLOCK_SELECTION is reworked */
80+
if (!((attr->clock == CLOCK_REALTIME) || (attr->clock == CLOCK_MONOTONIC))) {
81+
LOG_DBG("condattr clock %u is invalid", attr->clock);
82+
return false;
83+
}
84+
85+
return true;
86+
}
87+
88+
static struct posix_cond *to_posix_cond(pthread_cond_t *cvar)
7089
{
7190
size_t bit;
72-
struct k_condvar *cv;
91+
struct posix_cond *cv;
7392

7493
if (*cvar != PTHREAD_COND_INITIALIZER) {
7594
return get_posix_cond(*cvar);
@@ -85,24 +104,35 @@ static struct k_condvar *to_posix_cond(pthread_cond_t *cvar)
85104
/* Record the associated posix_cond in mu and mark as initialized */
86105
*cvar = mark_pthread_obj_initialized(bit);
87106
cv = &posix_cond_pool[bit];
107+
(void)pthread_condattr_init((pthread_condattr_t *)&cv->attr);
88108

89109
return cv;
90110
}
91111

92-
static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t timeout)
112+
static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, const struct timespec *abstime)
93113
{
94114
int ret;
95115
struct k_mutex *m;
96-
struct k_condvar *cv;
116+
struct posix_cond *cv;
117+
k_timeout_t timeout = K_FOREVER;
97118

98119
m = to_posix_mutex(mu);
99120
cv = to_posix_cond(cond);
100121
if (cv == NULL || m == NULL) {
101122
return EINVAL;
102123
}
103124

125+
if (abstime != NULL) {
126+
if (!is_timespec_valid(abstime)) {
127+
LOG_DBG("%s is invalid", "abstime");
128+
return EINVAL;
129+
}
130+
131+
timeout = K_MSEC((int32_t)timespec_to_timeoutms(cv->attr.clock, abstime));
132+
}
133+
104134
LOG_DBG("Waiting on cond %p with timeout %llx", cv, timeout.ticks);
105-
ret = k_condvar_wait(cv, m, timeout);
135+
ret = k_condvar_wait(&cv->condvar, m, timeout);
106136
if (ret == -EAGAIN) {
107137
LOG_DBG("Timeout waiting on cond %p", cv);
108138
ret = ETIMEDOUT;
@@ -120,15 +150,15 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time
120150
int pthread_cond_signal(pthread_cond_t *cvar)
121151
{
122152
int ret;
123-
struct k_condvar *cv;
153+
struct posix_cond *cv;
124154

125155
cv = to_posix_cond(cvar);
126156
if (cv == NULL) {
127157
return EINVAL;
128158
}
129159

130160
LOG_DBG("Signaling cond %p", cv);
131-
ret = k_condvar_signal(cv);
161+
ret = k_condvar_signal(&cv->condvar);
132162
if (ret < 0) {
133163
LOG_DBG("k_condvar_signal() failed: %d", ret);
134164
return -ret;
@@ -142,15 +172,15 @@ int pthread_cond_signal(pthread_cond_t *cvar)
142172
int pthread_cond_broadcast(pthread_cond_t *cvar)
143173
{
144174
int ret;
145-
struct k_condvar *cv;
175+
struct posix_cond *cv;
146176

147177
cv = get_posix_cond(*cvar);
148178
if (cv == NULL) {
149179
return EINVAL;
150180
}
151181

152182
LOG_DBG("Broadcasting on cond %p", cv);
153-
ret = k_condvar_broadcast(cv);
183+
ret = k_condvar_broadcast(&cv->condvar);
154184
if (ret < 0) {
155185
LOG_DBG("k_condvar_broadcast() failed: %d", ret);
156186
return -ret;
@@ -163,27 +193,33 @@ int pthread_cond_broadcast(pthread_cond_t *cvar)
163193

164194
int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut)
165195
{
166-
return cond_wait(cv, mut, K_FOREVER);
196+
return cond_wait(cv, mut, NULL);
167197
}
168198

169199
int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime)
170200
{
171-
return cond_wait(cv, mut, K_MSEC((int32_t)timespec_to_timeoutms(abstime)));
201+
return cond_wait(cv, mut, abstime);
172202
}
173203

174204
int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att)
175205
{
176-
struct k_condvar *cv;
206+
struct posix_cond *cv;
177207

178-
ARG_UNUSED(att);
179208
*cvar = PTHREAD_COND_INITIALIZER;
180-
181-
/* calls k_condvar_init() */
182209
cv = to_posix_cond(cvar);
183210
if (cv == NULL) {
184211
return ENOMEM;
185212
}
186213

214+
if (att != NULL) {
215+
if (!is_posix_condattr_valid((struct posix_condattr *)att)) {
216+
LOG_ERR("%s invalid", "pthread_condattr_t");
217+
return EINVAL;
218+
}
219+
220+
cv->attr = *((const struct posix_condattr *)att);
221+
}
222+
187223
LOG_DBG("Initialized cond %p", cv);
188224

189225
return 0;
@@ -193,7 +229,7 @@ int pthread_cond_destroy(pthread_cond_t *cvar)
193229
{
194230
int err;
195231
size_t bit;
196-
struct k_condvar *cv;
232+
struct posix_cond *cv;
197233

198234
cv = get_posix_cond(*cvar);
199235
if (cv == NULL) {
@@ -218,7 +254,7 @@ static int pthread_cond_pool_init(void)
218254
size_t i;
219255

220256
for (i = 0; i < CONFIG_MAX_PTHREAD_COND_COUNT; ++i) {
221-
err = k_condvar_init(&posix_cond_pool[i]);
257+
err = k_condvar_init(&posix_cond_pool[i].condvar);
222258
__ASSERT_NO_MSG(err == 0);
223259
}
224260

@@ -229,33 +265,56 @@ int pthread_condattr_init(pthread_condattr_t *att)
229265
{
230266
__ASSERT_NO_MSG(att != NULL);
231267

232-
att->clock = CLOCK_MONOTONIC;
268+
struct posix_condattr *const attr = (struct posix_condattr *)att;
269+
270+
attr->clock = CLOCK_REALTIME;
271+
attr->initialized = true;
233272

234273
return 0;
235274
}
236275

237276
int pthread_condattr_destroy(pthread_condattr_t *att)
238277
{
239-
ARG_UNUSED(att);
278+
struct posix_condattr *const attr = (struct posix_condattr *)att;
279+
280+
if (attr == NULL) {
281+
return EINVAL;
282+
}
283+
284+
*attr = (struct posix_condattr){0};
240285

241286
return 0;
242287
}
243288

244289
int pthread_condattr_getclock(const pthread_condattr_t *ZRESTRICT att,
245290
clockid_t *ZRESTRICT clock_id)
246291
{
247-
*clock_id = att->clock;
292+
struct posix_condattr *const attr = (struct posix_condattr *)att;
293+
294+
if ((attr == NULL) || !attr->initialized) {
295+
LOG_DBG("condattr is not initialized");
296+
return EINVAL;
297+
}
298+
299+
*clock_id = attr->clock;
248300

249301
return 0;
250302
}
251303

252304
int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id)
253305
{
306+
struct posix_condattr *const attr = (struct posix_condattr *)att;
307+
254308
if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC) {
255309
return -EINVAL;
256310
}
257311

258-
att->clock = clock_id;
312+
if ((attr == NULL) || !attr->initialized) {
313+
LOG_DBG("condattr is not initialized");
314+
return EINVAL;
315+
}
316+
317+
attr->clock = clock_id;
259318

260319
return 0;
261320
}

lib/posix/options/mqueue.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*
55
* SPDX-License-Identifier: Apache-2.0
66
*/
7+
8+
#include "posix_internal.h"
9+
710
#include <zephyr/kernel.h>
811
#include <errno.h>
912
#include <string.h>
@@ -34,7 +37,6 @@ K_SEM_DEFINE(mq_sem, 1, 1);
3437
/* Initialize the list */
3538
sys_slist_t mq_list = SYS_SLIST_STATIC_INIT(&mq_list);
3639

37-
int64_t timespec_to_timeoutms(const struct timespec *abstime);
3840
static mqueue_object *find_in_list(const char *name);
3941
static int32_t send_message(mqueue_desc *mqd, const char *msg_ptr, size_t msg_len,
4042
k_timeout_t timeout);
@@ -254,10 +256,15 @@ int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
254256
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
255257
unsigned int msg_prio, const struct timespec *abstime)
256258
{
257-
mqueue_desc *mqd = (mqueue_desc *)mqdes;
258-
int32_t timeout = (int32_t) timespec_to_timeoutms(abstime);
259+
mqueue_desc *const mqd = (mqueue_desc *)mqdes;
260+
261+
if (!is_timespec_valid(abstime)) {
262+
errno = EINVAL;
263+
return -1;
264+
}
259265

260-
return send_message(mqd, msg_ptr, msg_len, K_MSEC(timeout));
266+
return send_message(mqd, msg_ptr, msg_len,
267+
K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
261268
}
262269

263270
/**
@@ -285,10 +292,15 @@ int mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
285292
int mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
286293
unsigned int *msg_prio, const struct timespec *abstime)
287294
{
288-
mqueue_desc *mqd = (mqueue_desc *)mqdes;
289-
int32_t timeout = (int32_t) timespec_to_timeoutms(abstime);
295+
mqueue_desc *const mqd = (mqueue_desc *)mqdes;
296+
297+
if (!is_timespec_valid(abstime)) {
298+
errno = EINVAL;
299+
return -1;
300+
}
290301

291-
return receive_message(mqd, msg_ptr, msg_len, K_MSEC(timeout));
302+
return receive_message(mqd, msg_ptr, msg_len,
303+
K_MSEC((int32_t)timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
292304
}
293305

294306
/**

lib/posix/options/mutex.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ LOG_MODULE_REGISTER(pthread_mutex, CONFIG_PTHREAD_MUTEX_LOG_LEVEL);
1818

1919
static SYS_SEM_DEFINE(lock, 1, 1);
2020

21-
int64_t timespec_to_timeoutms(const struct timespec *abstime);
22-
2321
#define MUTEX_MAX_REC_LOCK 32767
2422

2523
/*
@@ -141,7 +139,7 @@ static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout)
141139
case PTHREAD_MUTEX_NORMAL:
142140
if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
143141
LOG_DBG("Timeout locking mutex %p", m);
144-
ret = EBUSY;
142+
ret = ETIMEDOUT;
145143
break;
146144
}
147145
/* On most POSIX systems, this usually results in an infinite loop */
@@ -212,8 +210,15 @@ int pthread_mutex_trylock(pthread_mutex_t *m)
212210
int pthread_mutex_timedlock(pthread_mutex_t *m,
213211
const struct timespec *abstime)
214212
{
215-
int32_t timeout = (int32_t)timespec_to_timeoutms(abstime);
216-
return acquire_mutex(m, K_MSEC(timeout));
213+
__ASSERT(m != NULL, "%s is NULL", "mutex");
214+
__ASSERT(abstime != NULL, "%s is NULL", "abstime");
215+
216+
if (!is_timespec_valid(abstime)) {
217+
LOG_DBG("%s is invalid", "abstime");
218+
return EINVAL;
219+
}
220+
221+
return acquire_mutex(m, K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
217222
}
218223

219224
/**

0 commit comments

Comments
 (0)