Skip to content

Commit 9bd13da

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 9fa1019 commit 9bd13da

File tree

17 files changed

+302
-138
lines changed

17 files changed

+302
-138
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/clock_selection.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2023 Meta
3+
* Copyright (c) 2025 Tenstorrent AI ULC
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include "posix_clock.h"
9+
10+
#include <time.h>
11+
12+
extern int z_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
13+
struct timespec *rmtp);
14+
15+
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
16+
struct timespec *rmtp)
17+
{
18+
return z_clock_nanosleep(clock_id, flags, rqtp, rmtp);
19+
}
20+
21+
int pthread_condattr_getclock(const pthread_condattr_t *ZRESTRICT att,
22+
clockid_t *ZRESTRICT clock_id)
23+
{
24+
struct posix_condattr *const attr = (struct posix_condattr *)att;
25+
26+
if ((attr == NULL) || !attr->initialized) {
27+
return EINVAL;
28+
}
29+
30+
*clock_id = attr->clock;
31+
32+
return 0;
33+
}
34+
35+
int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id)
36+
{
37+
struct posix_condattr *const attr = (struct posix_condattr *)att;
38+
39+
if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC) {
40+
return -EINVAL;
41+
}
42+
43+
if ((attr == NULL) || !attr->initialized) {
44+
return EINVAL;
45+
}
46+
47+
attr->clock = clock_id;
48+
49+
return 0;
50+
}

lib/posix/options/cond.c

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8+
#include "posix_clock.h"
89
#include "posix_internal.h"
910

11+
#include <stdbool.h>
12+
1013
#include <zephyr/init.h>
1114
#include <zephyr/kernel.h>
1215
#include <zephyr/logging/log.h>
@@ -15,10 +18,7 @@
1518

1619
LOG_MODULE_REGISTER(pthread_cond, CONFIG_PTHREAD_COND_LOG_LEVEL);
1720

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];
21+
__pinned_bss static struct posix_cond posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT];
2222

2323
SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT);
2424

@@ -30,7 +30,7 @@ SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT);
3030
BUILD_ASSERT(CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT,
3131
"CONFIG_MAX_PTHREAD_COND_COUNT is too high");
3232

33-
static inline size_t posix_cond_to_offset(struct k_condvar *cv)
33+
static inline size_t posix_cond_to_offset(struct posix_cond *cv)
3434
{
3535
return cv - posix_cond_pool;
3636
}
@@ -40,7 +40,7 @@ static inline size_t to_posix_cond_idx(pthread_cond_t cond)
4040
return mark_pthread_obj_uninitialized(cond);
4141
}
4242

43-
static struct k_condvar *get_posix_cond(pthread_cond_t cond)
43+
static struct posix_cond *get_posix_cond(pthread_cond_t cond)
4444
{
4545
int actually_initialized;
4646
size_t bit = to_posix_cond_idx(cond);
@@ -66,10 +66,30 @@ static struct k_condvar *get_posix_cond(pthread_cond_t cond)
6666
return &posix_cond_pool[bit];
6767
}
6868

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

7494
if (*cvar != PTHREAD_COND_INITIALIZER) {
7595
return get_posix_cond(*cvar);
@@ -85,24 +105,35 @@ static struct k_condvar *to_posix_cond(pthread_cond_t *cvar)
85105
/* Record the associated posix_cond in mu and mark as initialized */
86106
*cvar = mark_pthread_obj_initialized(bit);
87107
cv = &posix_cond_pool[bit];
108+
(void)pthread_condattr_init((pthread_condattr_t *)&cv->attr);
88109

89110
return cv;
90111
}
91112

92-
static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t timeout)
113+
static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, const struct timespec *abstime)
93114
{
94115
int ret;
95116
struct k_mutex *m;
96-
struct k_condvar *cv;
117+
struct posix_cond *cv;
118+
k_timeout_t timeout = K_FOREVER;
97119

98120
m = to_posix_mutex(mu);
99121
cv = to_posix_cond(cond);
100122
if (cv == NULL || m == NULL) {
101123
return EINVAL;
102124
}
103125

126+
if (abstime != NULL) {
127+
if (!is_timespec_valid(abstime)) {
128+
LOG_DBG("%s is invalid", "abstime");
129+
return EINVAL;
130+
}
131+
132+
timeout = K_MSEC((int32_t)timespec_to_timeoutms(cv->attr.clock, abstime));
133+
}
134+
104135
LOG_DBG("Waiting on cond %p with timeout %llx", cv, timeout.ticks);
105-
ret = k_condvar_wait(cv, m, timeout);
136+
ret = k_condvar_wait(&cv->condvar, m, timeout);
106137
if (ret == -EAGAIN) {
107138
LOG_DBG("Timeout waiting on cond %p", cv);
108139
ret = ETIMEDOUT;
@@ -120,15 +151,15 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time
120151
int pthread_cond_signal(pthread_cond_t *cvar)
121152
{
122153
int ret;
123-
struct k_condvar *cv;
154+
struct posix_cond *cv;
124155

125156
cv = to_posix_cond(cvar);
126157
if (cv == NULL) {
127158
return EINVAL;
128159
}
129160

130161
LOG_DBG("Signaling cond %p", cv);
131-
ret = k_condvar_signal(cv);
162+
ret = k_condvar_signal(&cv->condvar);
132163
if (ret < 0) {
133164
LOG_DBG("k_condvar_signal() failed: %d", ret);
134165
return -ret;
@@ -142,15 +173,15 @@ int pthread_cond_signal(pthread_cond_t *cvar)
142173
int pthread_cond_broadcast(pthread_cond_t *cvar)
143174
{
144175
int ret;
145-
struct k_condvar *cv;
176+
struct posix_cond *cv;
146177

147178
cv = get_posix_cond(*cvar);
148179
if (cv == NULL) {
149180
return EINVAL;
150181
}
151182

152183
LOG_DBG("Broadcasting on cond %p", cv);
153-
ret = k_condvar_broadcast(cv);
184+
ret = k_condvar_broadcast(&cv->condvar);
154185
if (ret < 0) {
155186
LOG_DBG("k_condvar_broadcast() failed: %d", ret);
156187
return -ret;
@@ -163,27 +194,33 @@ int pthread_cond_broadcast(pthread_cond_t *cvar)
163194

164195
int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut)
165196
{
166-
return cond_wait(cv, mut, K_FOREVER);
197+
return cond_wait(cv, mut, NULL);
167198
}
168199

169200
int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime)
170201
{
171-
return cond_wait(cv, mut, K_MSEC((int32_t)timespec_to_timeoutms(abstime)));
202+
return cond_wait(cv, mut, abstime);
172203
}
173204

174205
int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att)
175206
{
176-
struct k_condvar *cv;
207+
struct posix_cond *cv;
177208

178-
ARG_UNUSED(att);
179209
*cvar = PTHREAD_COND_INITIALIZER;
180-
181-
/* calls k_condvar_init() */
182210
cv = to_posix_cond(cvar);
183211
if (cv == NULL) {
184212
return ENOMEM;
185213
}
186214

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

189226
return 0;
@@ -193,7 +230,7 @@ int pthread_cond_destroy(pthread_cond_t *cvar)
193230
{
194231
int err;
195232
size_t bit;
196-
struct k_condvar *cv;
233+
struct posix_cond *cv;
197234

198235
cv = get_posix_cond(*cvar);
199236
if (cv == NULL) {
@@ -218,7 +255,7 @@ static int pthread_cond_pool_init(void)
218255
size_t i;
219256

220257
for (i = 0; i < CONFIG_MAX_PTHREAD_COND_COUNT; ++i) {
221-
err = k_condvar_init(&posix_cond_pool[i]);
258+
err = k_condvar_init(&posix_cond_pool[i].condvar);
222259
__ASSERT_NO_MSG(err == 0);
223260
}
224261

@@ -229,33 +266,56 @@ int pthread_condattr_init(pthread_condattr_t *att)
229266
{
230267
__ASSERT_NO_MSG(att != NULL);
231268

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

234274
return 0;
235275
}
236276

237277
int pthread_condattr_destroy(pthread_condattr_t *att)
238278
{
239-
ARG_UNUSED(att);
279+
struct posix_condattr *const attr = (struct posix_condattr *)att;
280+
281+
if (attr == NULL) {
282+
return EINVAL;
283+
}
284+
285+
*attr = (struct posix_condattr){0};
240286

241287
return 0;
242288
}
243289

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

249302
return 0;
250303
}
251304

252305
int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id)
253306
{
307+
struct posix_condattr *const attr = (struct posix_condattr *)att;
308+
254309
if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC) {
255310
return -EINVAL;
256311
}
257312

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

260320
return 0;
261321
}

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_clock.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
/**

0 commit comments

Comments
 (0)