Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:37

0001 /*
0002  * Copyright (c) 2017 embedded brains GmbH & Co. KG
0003  *
0004  * The license and distribution terms for this file may be
0005  * found in the file LICENSE in this distribution or at
0006  * http://www.rtems.com/license/LICENSE.
0007  */
0008 
0009 /*
0010  * This test program runs also on GNU/Linux.  Use
0011  *
0012  * cc init.c -pthread -Wall -Wextra -lrt && sudo ./a.out
0013  *
0014  * to run it.  It must run probably as root for the clock_settime().
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 /* __rtems__ */
0040 
0041 #include <assert.h>
0042 
0043 #define rtems_test_assert(x) assert(x)
0044 
0045 #endif /* __rtems__ */
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 /* __rtems__ */
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 /* __rtems__ */
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 /* __rtems__ */
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   /* Do nothing */
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 /* __rtems__ */
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 /* __rtems__ */
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 /* __rtems__ */
0540   rtems_test_assert(eno == 0 || eno == EBUSY);
0541 #endif /* __rtems__ */
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 /* __rtems__ */
0591 
0592 int main(void)
0593 {
0594   test(&test_instance);
0595   return 0;
0596 }
0597 
0598 #endif /* __rtems__ */