Skip to content

Commit f3c0a2e

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 <[email protected]>
1 parent 90cd350 commit f3c0a2e

File tree

12 files changed

+137
-80
lines changed

12 files changed

+137
-80
lines changed

include/zephyr/posix/time.h

-5
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

+79-26
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,6 +104,7 @@ 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
}
@@ -93,7 +113,7 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time
93113
{
94114
int ret;
95115
struct k_mutex *m;
96-
struct k_condvar *cv;
116+
struct posix_cond *cv;
97117

98118
m = to_posix_mutex(mu);
99119
cv = to_posix_cond(cond);
@@ -102,7 +122,7 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time
102122
}
103123

104124
LOG_DBG("Waiting on cond %p with timeout %llx", cv, timeout.ticks);
105-
ret = k_condvar_wait(cv, m, timeout);
125+
ret = k_condvar_wait(&cv->condvar, m, timeout);
106126
if (ret == -EAGAIN) {
107127
LOG_DBG("Timeout waiting on cond %p", cv);
108128
ret = ETIMEDOUT;
@@ -120,15 +140,15 @@ static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t time
120140
int pthread_cond_signal(pthread_cond_t *cvar)
121141
{
122142
int ret;
123-
struct k_condvar *cv;
143+
struct posix_cond *cv;
124144

125145
cv = to_posix_cond(cvar);
126146
if (cv == NULL) {
127147
return EINVAL;
128148
}
129149

130150
LOG_DBG("Signaling cond %p", cv);
131-
ret = k_condvar_signal(cv);
151+
ret = k_condvar_signal(&cv->condvar);
132152
if (ret < 0) {
133153
LOG_DBG("k_condvar_signal() failed: %d", ret);
134154
return -ret;
@@ -142,15 +162,15 @@ int pthread_cond_signal(pthread_cond_t *cvar)
142162
int pthread_cond_broadcast(pthread_cond_t *cvar)
143163
{
144164
int ret;
145-
struct k_condvar *cv;
165+
struct posix_cond *cv;
146166

147167
cv = get_posix_cond(*cvar);
148168
if (cv == NULL) {
149169
return EINVAL;
150170
}
151171

152172
LOG_DBG("Broadcasting on cond %p", cv);
153-
ret = k_condvar_broadcast(cv);
173+
ret = k_condvar_broadcast(&cv->condvar);
154174
if (ret < 0) {
155175
LOG_DBG("k_condvar_broadcast() failed: %d", ret);
156176
return -ret;
@@ -168,22 +188,30 @@ int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut)
168188

169189
int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime)
170190
{
171-
return cond_wait(cv, mut, K_MSEC((int32_t)timespec_to_timeoutms(abstime)));
191+
return cond_wait(cv, mut,
192+
K_MSEC((int32_t)timespec_to_timeoutms(
193+
((struct posix_cond *)cv)->attr.clock, abstime)));
172194
}
173195

174196
int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att)
175197
{
176-
struct k_condvar *cv;
198+
struct posix_cond *cv;
177199

178-
ARG_UNUSED(att);
179200
*cvar = PTHREAD_COND_INITIALIZER;
180-
181-
/* calls k_condvar_init() */
182201
cv = to_posix_cond(cvar);
183202
if (cv == NULL) {
184203
return ENOMEM;
185204
}
186205

206+
if (att != NULL) {
207+
if (!is_posix_condattr_valid((struct posix_condattr *)att)) {
208+
LOG_ERR("%s invalid", "pthread_condattr_t");
209+
return EINVAL;
210+
}
211+
212+
cv->attr = *((const struct posix_condattr *)att);
213+
}
214+
187215
LOG_DBG("Initialized cond %p", cv);
188216

189217
return 0;
@@ -193,7 +221,7 @@ int pthread_cond_destroy(pthread_cond_t *cvar)
193221
{
194222
int err;
195223
size_t bit;
196-
struct k_condvar *cv;
224+
struct posix_cond *cv;
197225

198226
cv = get_posix_cond(*cvar);
199227
if (cv == NULL) {
@@ -218,7 +246,7 @@ static int pthread_cond_pool_init(void)
218246
size_t i;
219247

220248
for (i = 0; i < CONFIG_MAX_PTHREAD_COND_COUNT; ++i) {
221-
err = k_condvar_init(&posix_cond_pool[i]);
249+
err = k_condvar_init(&posix_cond_pool[i].condvar);
222250
__ASSERT_NO_MSG(err == 0);
223251
}
224252

@@ -227,35 +255,60 @@ static int pthread_cond_pool_init(void)
227255

228256
int pthread_condattr_init(pthread_condattr_t *att)
229257
{
230-
__ASSERT_NO_MSG(att != NULL);
258+
struct posix_condattr *const attr = (struct posix_condattr *)att;
231259

232-
att->clock = CLOCK_MONOTONIC;
260+
if (attr == NULL) {
261+
return EINVAL;
262+
}
263+
264+
attr->clock = CLOCK_MONOTONIC;
265+
attr->initialized = true;
233266

234267
return 0;
235268
}
236269

237270
int pthread_condattr_destroy(pthread_condattr_t *att)
238271
{
239-
ARG_UNUSED(att);
272+
struct posix_condattr *const attr = (struct posix_condattr *)att;
273+
274+
if (attr == NULL) {
275+
return EINVAL;
276+
}
277+
278+
*attr = (struct posix_condattr){0};
240279

241280
return 0;
242281
}
243282

244283
int pthread_condattr_getclock(const pthread_condattr_t *ZRESTRICT att,
245284
clockid_t *ZRESTRICT clock_id)
246285
{
247-
*clock_id = att->clock;
286+
struct posix_condattr *const attr = (struct posix_condattr *)att;
287+
288+
if ((attr == NULL) || !attr->initialized) {
289+
LOG_DBG("condattr is not initialized");
290+
return EINVAL;
291+
}
292+
293+
*clock_id = attr->clock;
248294

249295
return 0;
250296
}
251297

252298
int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id)
253299
{
300+
struct posix_condattr *const attr = (struct posix_condattr *)att;
301+
254302
if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC) {
255303
return -EINVAL;
256304
}
257305

258-
att->clock = clock_id;
306+
if ((attr == NULL) || !attr->initialized) {
307+
LOG_DBG("condattr is not initialized");
308+
return EINVAL;
309+
}
310+
311+
attr->clock = clock_id;
259312

260313
return 0;
261314
}

lib/posix/options/mqueue.c

+6-4
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);
@@ -255,9 +257,9 @@ int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
255257
unsigned int msg_prio, const struct timespec *abstime)
256258
{
257259
mqueue_desc *mqd = (mqueue_desc *)mqdes;
258-
int32_t timeout = (int32_t) timespec_to_timeoutms(abstime);
259260

260-
return send_message(mqd, msg_ptr, msg_len, K_MSEC(timeout));
261+
return send_message(mqd, msg_ptr, msg_len,
262+
K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
261263
}
262264

263265
/**
@@ -286,7 +288,7 @@ int mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
286288
unsigned int *msg_prio, const struct timespec *abstime)
287289
{
288290
mqueue_desc *mqd = (mqueue_desc *)mqdes;
289-
int32_t timeout = (int32_t) timespec_to_timeoutms(abstime);
291+
int32_t timeout = (int32_t)timespec_to_timeoutms(CLOCK_REALTIME, abstime);
290292

291293
return receive_message(mqd, msg_ptr, msg_len, K_MSEC(timeout));
292294
}

lib/posix/options/mutex.c

+3-6
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 */
@@ -170,7 +168,7 @@ static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout)
170168

171169
if (ret == 0) {
172170
ret = k_mutex_lock(m, timeout);
173-
if (ret == -EAGAIN) {
171+
if ((ret == -EAGAIN) || (ret == -EBUSY) || (ret == -ETIMEDOUT)) {
174172
LOG_DBG("Timeout locking mutex %p", m);
175173
/*
176174
* special quirk - k_mutex_lock() returns EAGAIN if a timeout occurs, but
@@ -212,8 +210,7 @@ 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+
return acquire_mutex(m, K_MSEC(timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
217214
}
218215

219216
/**

lib/posix/options/posix_internal.h

+21
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ struct posix_thread {
6666
uint8_t qid;
6767
};
6868

69+
struct posix_condattr {
70+
bool initialized: 1;
71+
/* leaves room for CLOCK_REALTIME (1, default) and CLOCK_MONOTONIC (4) */
72+
unsigned int clock: 3;
73+
#ifdef _POSIX_THREAD_PROCESS_SHARED
74+
unsigned int pshared: 1;
75+
#endif
76+
};
77+
78+
struct posix_cond {
79+
struct k_condvar condvar;
80+
struct posix_condattr attr;
81+
};
82+
6983
typedef struct pthread_key_obj {
7084
/* List of pthread_key_data objects that contain thread
7185
* specific data for the key
@@ -104,6 +118,11 @@ static inline uint32_t mark_pthread_obj_uninitialized(uint32_t obj)
104118
return obj & ~PTHREAD_OBJ_MASK_INIT;
105119
}
106120

121+
static inline bool is_timespec_valid(const struct timespec *ts)
122+
{
123+
return (ts != NULL) && (ts->tv_nsec >= 0) && (ts->tv_nsec < NSEC_PER_SEC);
124+
}
125+
107126
struct posix_thread *to_posix_thread(pthread_t pth);
108127

109128
/* get and possibly initialize a posix_mutex */
@@ -112,4 +131,6 @@ struct k_mutex *to_posix_mutex(pthread_mutex_t *mu);
112131
int posix_to_zephyr_priority(int priority, int policy);
113132
int zephyr_to_posix_priority(int priority, int *policy);
114133

134+
int64_t timespec_to_timeoutms(clockid_t clock, const struct timespec *abstime);
135+
115136
#endif

lib/posix/options/pthread.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ BUILD_ASSERT((PTHREAD_CANCEL_ENABLE == 0 || PTHREAD_CANCEL_DISABLE == 0) &&
8181
BUILD_ASSERT(CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS + CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS <=
8282
32);
8383

84-
int64_t timespec_to_timeoutms(const struct timespec *abstime);
8584
static void posix_thread_recycle(void);
8685

8786
__pinned_data
@@ -1157,7 +1156,8 @@ int pthread_timedjoin_np(pthread_t pthread, void **status, const struct timespec
11571156
return EINVAL;
11581157
}
11591158

1160-
return pthread_timedjoin_internal(pthread, status, K_MSEC(timespec_to_timeoutms(abstime)));
1159+
return pthread_timedjoin_internal(
1160+
pthread, status, K_MSEC((int32_t)timespec_to_timeoutms(CLOCK_REALTIME, abstime)));
11611161
}
11621162

11631163
/**

0 commit comments

Comments
 (0)