File indexing completed on 2025-05-11 08:24:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifdef HAVE_CONFIG_H
0018 #include "config.h"
0019 #endif
0020
0021 #include <sys/stat.h>
0022 #include <errno.h>
0023 #include <fcntl.h>
0024 #include <inttypes.h>
0025 #include <limits.h>
0026 #include <mqueue.h>
0027 #include <pthread.h>
0028 #include <semaphore.h>
0029 #include <stdbool.h>
0030 #include <stdio.h>
0031 #include <string.h>
0032 #include <time.h>
0033 #include <unistd.h>
0034
0035 #ifdef __rtems__
0036
0037 #include "tmacros.h"
0038
0039 #else
0040
0041 #include <assert.h>
0042
0043 #define rtems_test_assert(x) assert(x)
0044
0045 #endif
0046
0047 static void assert_eno(const char *hint, int eno, int expected_eno)
0048 {
0049 const char *warn;
0050
0051 if (eno != expected_eno) {
0052 warn = "WARNING: ";
0053 } else {
0054 warn = "";
0055 }
0056
0057 printf(
0058 "%s%s: actual '%s', expected '%s'\n",
0059 warn,
0060 hint,
0061 strerror(eno),
0062 strerror(expected_eno)
0063 );
0064 #ifdef __rtems__
0065 rtems_test_assert(eno == expected_eno);
0066 #endif
0067 }
0068
0069 static void assert_rv(const char *hint, int rv, int expected_eno)
0070 {
0071 int eno;
0072
0073 if (rv != 0) {
0074 eno = errno;
0075 } else {
0076 eno = 0;
0077 }
0078
0079 assert_eno(hint, eno, expected_eno);
0080 }
0081
0082 typedef struct {
0083 char data;
0084 } test_msg;
0085
0086 #define MSG_COUNT 1
0087
0088 #define MSG_SIZE sizeof(test_msg)
0089
0090 typedef struct {
0091 int value;
0092 pthread_mutex_t mtx;
0093 pthread_cond_t cnd;
0094 } event;
0095
0096 typedef enum {
0097 ACTION_NONE,
0098 ACTION_MTX_LOCK,
0099 ACTION_CND_WAIT,
0100 ACTION_RW_RDLOCK,
0101 ACTION_RW_WRLOCK,
0102 ACTION_SEM_WAIT,
0103 ACTION_MQ_SEND,
0104 ACTION_MQ_RECV,
0105 ACTION_CLOCK_NANOSLEEP,
0106 ACTION_TERMINATE
0107 } test_action;
0108
0109 typedef enum {
0110 MODE_TIMEOUT_FINITE,
0111 MODE_TIMEOUT_NEGATIVE_SEC,
0112 MODE_TIMEOUT_NEGATIVE_NSEC,
0113 MODE_TIMEOUT_NEGATIVE_SEC_NSEC,
0114 MODE_TIMEOUT_HUGE_NSEC,
0115 #ifdef __rtems__
0116 MODE_TIMEOUT_NULL,
0117 #endif
0118 MODE_TIMEOUT_PRACTICALLY_INFINITE,
0119 MODE_COUNT
0120 } test_mode;
0121
0122 typedef struct {
0123 test_mode mode;
0124 pthread_t worker;
0125 event action;
0126 event done;
0127 pthread_mutex_t mtx;
0128 pthread_mutex_t mtx2;
0129 pthread_cond_t cnd;
0130 pthread_rwlock_t rw;
0131 sem_t sem;
0132 mqd_t mq;
0133 int counter[ACTION_TERMINATE + 1];
0134 } test_context;
0135
0136 static test_context test_instance;
0137
0138 static void event_init(event *e)
0139 {
0140 int eno;
0141
0142 eno = pthread_mutex_init(&e->mtx, NULL);
0143 rtems_test_assert(eno == 0);
0144
0145 eno = pthread_cond_init(&e->cnd, NULL);
0146 rtems_test_assert(eno == 0);
0147 }
0148
0149 static void event_destroy(event *e)
0150 {
0151 int eno;
0152
0153 eno = pthread_mutex_destroy(&e->mtx);
0154 rtems_test_assert(eno == 0);
0155
0156 eno = pthread_cond_destroy(&e->cnd);
0157 rtems_test_assert(eno == 0);
0158 }
0159
0160 static void event_post(event *e, int value)
0161 {
0162 int eno;
0163
0164 eno = pthread_mutex_lock(&e->mtx);
0165 rtems_test_assert(eno == 0);
0166
0167 e->value = value;
0168
0169 eno = pthread_cond_signal(&e->cnd);
0170 rtems_test_assert(eno == 0);
0171
0172 eno = pthread_mutex_unlock(&e->mtx);
0173 rtems_test_assert(eno == 0);
0174 }
0175
0176 static int event_get(event *e)
0177 {
0178 int eno;
0179 int value;
0180
0181 eno = pthread_mutex_lock(&e->mtx);
0182 rtems_test_assert(eno == 0);
0183
0184 while (true) {
0185 value = e->value;
0186
0187 if (value != 0) {
0188 e->value = 0;
0189 break;
0190 }
0191
0192 eno = pthread_cond_wait(&e->cnd, &e->mtx);
0193 rtems_test_assert(eno == 0);
0194 }
0195
0196 eno = pthread_mutex_unlock(&e->mtx);
0197 rtems_test_assert(eno == 0);
0198
0199 return value;
0200 }
0201
0202 static void *worker(void *arg)
0203 {
0204 test_context *ctx;
0205 test_action action;
0206 test_mode mode;
0207 int eno;
0208 int unused;
0209
0210 ctx = arg;
0211 mode = ctx->mode;
0212
0213 eno = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &unused);
0214 rtems_test_assert(eno == 0);
0215
0216 eno = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &unused);
0217 rtems_test_assert(eno == 0);
0218
0219 while ((action = event_get(&ctx->action)) != ACTION_TERMINATE) {
0220 int rv;
0221 struct timespec to_storage;
0222 const struct timespec *to;
0223 int expected_eno;
0224 test_msg msg;
0225 unsigned prio;
0226
0227 switch (mode) {
0228 case MODE_TIMEOUT_FINITE:
0229 rv = clock_gettime(CLOCK_REALTIME, &to_storage);
0230 rtems_test_assert(rv == 0);
0231
0232 to_storage.tv_sec += 3600;
0233 to = &to_storage;
0234 expected_eno = ETIMEDOUT;
0235 break;
0236 case MODE_TIMEOUT_NEGATIVE_SEC:
0237 to_storage.tv_sec = -1;
0238 to_storage.tv_nsec = 1;
0239 to = &to_storage;
0240 expected_eno = ETIMEDOUT;
0241 break;
0242 case MODE_TIMEOUT_NEGATIVE_NSEC:
0243 to_storage.tv_sec = 1;
0244 to_storage.tv_nsec = -1;
0245 to = &to_storage;
0246 expected_eno = EINVAL;
0247 break;
0248 case MODE_TIMEOUT_NEGATIVE_SEC_NSEC:
0249 to_storage.tv_sec = -1;
0250 to_storage.tv_nsec = -1;
0251 to = &to_storage;
0252 expected_eno = EINVAL;
0253 break;
0254 case MODE_TIMEOUT_HUGE_NSEC:
0255 to_storage.tv_sec = 1;
0256 to_storage.tv_nsec = LONG_MAX;
0257 to = &to_storage;
0258 expected_eno = EINVAL;
0259 break;
0260 #ifdef __rtems__
0261 case MODE_TIMEOUT_NULL:
0262 to = NULL;
0263 expected_eno = EINVAL;
0264 break;
0265 #endif
0266 case MODE_TIMEOUT_PRACTICALLY_INFINITE:
0267 to_storage.tv_sec = INT64_MAX;
0268 to_storage.tv_nsec = 999999999;
0269 to = &to_storage;
0270 expected_eno = -1;
0271 break;
0272 default:
0273 to = NULL;
0274 expected_eno = -1;
0275 rtems_test_assert(0);
0276 break;
0277 }
0278
0279 switch (action) {
0280 case ACTION_MTX_LOCK:
0281 eno = pthread_mutex_timedlock(&ctx->mtx, to);
0282 assert_eno("pthread_mutex_timedlock", eno, expected_eno);
0283 break;
0284 case ACTION_CND_WAIT:
0285 eno = pthread_mutex_lock(&ctx->mtx2);
0286 rtems_test_assert(eno == 0);
0287
0288 eno = pthread_cond_timedwait(&ctx->cnd, &ctx->mtx2, to);
0289 assert_eno("pthread_cond_timedwait", eno, expected_eno);
0290
0291 eno = pthread_mutex_unlock(&ctx->mtx2);
0292 rtems_test_assert(eno == 0);
0293 break;
0294 case ACTION_RW_RDLOCK:
0295 eno = pthread_rwlock_timedrdlock(&ctx->rw, to);
0296 assert_eno("pthread_rwlock_timedrdlock", eno, expected_eno);
0297 break;
0298 case ACTION_RW_WRLOCK:
0299 eno = pthread_rwlock_timedwrlock(&ctx->rw, to);
0300 assert_eno("pthread_rwlock_timedwrlock", eno, expected_eno);
0301 break;
0302 case ACTION_SEM_WAIT:
0303 errno = 0;
0304 rv = sem_timedwait(&ctx->sem, to);
0305 assert_rv("sem_timedwait", rv, expected_eno);
0306 break;
0307 case ACTION_MQ_SEND:
0308 msg.data = 13;
0309 rv = mq_send(ctx->mq, &msg.data, sizeof(msg), 7);
0310 rtems_test_assert(rv == 0);
0311 msg.data = 31;
0312 errno = 0;
0313 rv = mq_timedsend(ctx->mq, &msg.data, sizeof(msg), 5, to);
0314 assert_rv("mq_timedsend", rv, expected_eno);
0315 break;
0316 case ACTION_MQ_RECV:
0317 msg.data = 0;
0318 prio = 0;
0319 rv = mq_receive(ctx->mq, &msg.data, sizeof(msg), &prio);
0320 rtems_test_assert(rv == 1);
0321 rtems_test_assert(msg.data == 13);
0322 rtems_test_assert(prio == 7);
0323 msg.data = 0;
0324 prio = 0;
0325 errno = 0;
0326 rv = mq_timedreceive(ctx->mq, &msg.data, sizeof(msg), &prio, to);
0327 assert_rv("mq_timedreceive", rv, expected_eno);
0328 rtems_test_assert(msg.data == 0);
0329 rtems_test_assert(prio == 0);
0330 break;
0331 case ACTION_CLOCK_NANOSLEEP:
0332 rv = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, to, NULL);
0333
0334 if (expected_eno == ETIMEDOUT) {
0335 assert_rv("clock_nanosleep", rv, 0);
0336 } else {
0337 assert_rv("clock_nanosleep", rv, expected_eno);
0338 }
0339 break;
0340 default:
0341 rtems_test_assert(0);
0342 break;
0343 }
0344
0345 ++ctx->counter[action];
0346
0347 event_post(&ctx->done, 1);
0348 }
0349
0350 return ctx;
0351 }
0352
0353 static void delay(void)
0354 {
0355 int rv;
0356
0357 rv = usleep(100000);
0358 rtems_test_assert(rv == 0);
0359 }
0360
0361 static void run(
0362 test_context *ctx,
0363 const char *test,
0364 test_mode mode,
0365 void (*f)(void)
0366 )
0367 {
0368 test_action action;
0369 int eno;
0370 void *status;
0371
0372 printf("*** %s ***\n", test);
0373 ctx->mode = mode;
0374
0375 eno = pthread_create(&ctx->worker, NULL, worker, ctx);
0376 rtems_test_assert(eno == 0);
0377
0378 for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
0379 event_post(&ctx->action, action);
0380 delay();
0381
0382 (*f)();
0383
0384 event_get(&ctx->done);
0385 }
0386
0387 event_post(&ctx->action, ACTION_TERMINATE);
0388
0389 status = NULL;
0390 eno = pthread_join(ctx->worker, &status);
0391 rtems_test_assert(eno == 0);
0392 rtems_test_assert(status == ctx);
0393 }
0394
0395 static void timeout_finite(void)
0396 {
0397 struct timespec now;
0398 int rv;
0399
0400 rv = clock_gettime(CLOCK_REALTIME, &now);
0401 rtems_test_assert(rv == 0);
0402
0403 now.tv_sec += 7200;
0404
0405 rv = clock_settime(CLOCK_REALTIME, &now);
0406 rtems_test_assert(rv == 0);
0407 }
0408
0409 static void test_timeout_finite(test_context *ctx)
0410 {
0411 run(ctx, "timeout finite", MODE_TIMEOUT_FINITE, timeout_finite);
0412 }
0413
0414 static void do_nothing(void)
0415 {
0416
0417 }
0418
0419 static void test_timeout_negative_sec(test_context *ctx)
0420 {
0421 run(ctx, "timeout negative sec", MODE_TIMEOUT_NEGATIVE_SEC, do_nothing);
0422 }
0423
0424 static void test_timeout_negative_nsec(test_context *ctx)
0425 {
0426 run(ctx, "timout negative nsec", MODE_TIMEOUT_NEGATIVE_NSEC, do_nothing);
0427 }
0428
0429 static void test_timeout_negative_sec_nsec(test_context *ctx)
0430 {
0431 run(
0432 ctx,
0433 "timout negative sec and nsec",
0434 MODE_TIMEOUT_NEGATIVE_SEC_NSEC,
0435 do_nothing
0436 );
0437 }
0438
0439 static void test_timeout_huge_nsec(test_context *ctx)
0440 {
0441 run(ctx, "timout huge nsec", MODE_TIMEOUT_HUGE_NSEC, do_nothing);
0442 }
0443
0444 #ifdef __rtems__
0445 static void test_timeout_null(test_context *ctx)
0446 {
0447 run(ctx, "timeout NULL", MODE_TIMEOUT_NULL, do_nothing);
0448 }
0449 #endif
0450
0451 static void test_timeout_practically_infinite(test_context *ctx)
0452 {
0453 test_action action;
0454 int eno;
0455
0456 puts("*** timeout practically infinite ***");
0457 ctx->mode = MODE_TIMEOUT_PRACTICALLY_INFINITE;
0458
0459 for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
0460 void *status;
0461
0462 eno = pthread_create(&ctx->worker, NULL, worker, ctx);
0463 rtems_test_assert(eno == 0);
0464
0465 event_post(&ctx->action, action);
0466 delay();
0467
0468 eno = pthread_cancel(ctx->worker);
0469 rtems_test_assert(eno == 0);
0470
0471 status = NULL;
0472 eno = pthread_join(ctx->worker, &status);
0473 rtems_test_assert(eno == 0);
0474 rtems_test_assert(status == PTHREAD_CANCELED);
0475 }
0476 }
0477
0478 static void test(test_context *ctx)
0479 {
0480 test_action action;
0481 int eno;
0482 int rv;
0483 mode_t mode;
0484 struct mq_attr ma;
0485
0486 event_init(&ctx->action);
0487 event_init(&ctx->done);
0488
0489 eno = pthread_mutex_init(&ctx->mtx, NULL);
0490 rtems_test_assert(eno == 0);
0491
0492 eno = pthread_mutex_lock(&ctx->mtx);
0493 rtems_test_assert(eno == 0);
0494
0495 eno = pthread_mutex_init(&ctx->mtx2, NULL);
0496 rtems_test_assert(eno == 0);
0497
0498 eno = pthread_cond_init(&ctx->cnd, NULL);
0499 rtems_test_assert(eno == 0);
0500
0501 eno = pthread_rwlock_init(&ctx->rw, NULL);
0502 rtems_test_assert(eno == 0);
0503
0504 eno = pthread_rwlock_wrlock(&ctx->rw);
0505 rtems_test_assert(eno == 0);
0506
0507 rv = sem_init(&ctx->sem, 0, 0);
0508 rtems_test_assert(rv == 0);
0509
0510 mode = S_IRWXU | S_IRWXG | S_IRWXO;
0511 memset(&ma, 0, sizeof(ma));
0512 ma.mq_maxmsg = MSG_COUNT;
0513 ma.mq_msgsize = MSG_SIZE;
0514 ctx->mq = mq_open("/mq", O_CREAT | O_RDWR, mode, &ma);
0515 rtems_test_assert(ctx->mq != (mqd_t) -1);
0516
0517 test_timeout_finite(ctx);
0518 test_timeout_negative_sec(ctx);
0519 test_timeout_negative_nsec(ctx);
0520 test_timeout_negative_sec_nsec(ctx);
0521 test_timeout_huge_nsec(ctx);
0522 #ifdef __rtems__
0523 test_timeout_null(ctx);
0524 #endif
0525 test_timeout_practically_infinite(ctx);
0526
0527 event_destroy(&ctx->action);
0528 event_destroy(&ctx->done);
0529
0530 eno = pthread_mutex_unlock(&ctx->mtx);
0531 rtems_test_assert(eno == 0);
0532
0533 eno = pthread_mutex_destroy(&ctx->mtx);
0534 rtems_test_assert(eno == 0);
0535
0536 eno = pthread_mutex_destroy(&ctx->mtx2);
0537 #ifdef __rtems__
0538 rtems_test_assert(eno == 0);
0539 #else
0540 rtems_test_assert(eno == 0 || eno == EBUSY);
0541 #endif
0542
0543 eno = pthread_cond_destroy(&ctx->cnd);
0544 rtems_test_assert(eno == 0);
0545
0546 eno = pthread_rwlock_unlock(&ctx->rw);
0547 rtems_test_assert(eno == 0);
0548
0549 eno = pthread_rwlock_destroy(&ctx->rw);
0550 rtems_test_assert(eno == 0);
0551
0552 rv = sem_destroy(&ctx->sem);
0553 rtems_test_assert(rv == 0);
0554
0555 rv = mq_close(ctx->mq);
0556 rtems_test_assert(rv == 0);
0557
0558 rv = mq_unlink("/mq");
0559 rtems_test_assert(rv == 0);
0560
0561 for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
0562 rtems_test_assert(ctx->counter[action] == MODE_COUNT - 1);
0563 }
0564 }
0565
0566 #ifdef __rtems__
0567
0568 const char rtems_test_name[] = "PSXCLOCKREALTIME 1";
0569
0570 static void *POSIX_Init(void *arg)
0571 {
0572 TEST_BEGIN();
0573 test(&test_instance);
0574 TEST_END();
0575 rtems_test_exit(0);
0576 }
0577
0578 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0579 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0580
0581 #define CONFIGURE_MAXIMUM_POSIX_THREADS 2
0582 #define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1
0583
0584 #define CONFIGURE_POSIX_INIT_THREAD_TABLE
0585
0586 #define CONFIGURE_INIT
0587
0588 #include <rtems/confdefs.h>
0589
0590 #else
0591
0592 int main(void)
0593 {
0594 test(&test_instance);
0595 return 0;
0596 }
0597
0598 #endif