Skip to content

Commit f35cc31

Browse files
committed
posix + tests: correct a number of timing functions to use CLOCK_REALTIME
Use CLOCK_REALTIME by default for pthread_cond_timedwait() as per the POSIX specification, and similarly use CLOCK_REALTIME as per the POSIX specification for the following: * mq_timedsend() * mq_timedreceive() * pthread_mutex_timedlock() * pthread_rwlock_timedrdlock() * pthread_rwlock_timedwrlock() Additionally, for the non-POSIX compatibility function pthread_timedjoin_np(), use CLOCK_REALTIME. Signed-off-by: Chris Friedt <[email protected]>
1 parent 8a4bb18 commit f35cc31

File tree

9 files changed

+118
-48
lines changed

9 files changed

+118
-48
lines changed

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

+16
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
@@ -112,4 +126,6 @@ struct k_mutex *to_posix_mutex(pthread_mutex_t *mu);
112126
int posix_to_zephyr_priority(int priority, int policy);
113127
int zephyr_to_posix_priority(int priority, int *policy);
114128

129+
int64_t timespec_to_timeoutms(clockid_t clock, const struct timespec *abstime);
130+
115131
#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)