source: rtems/testsuites/psxtests/psxclockrealtime01/init.c @ d85c94c0

5
Last change on this file since d85c94c0 was d85c94c0, checked in by Sebastian Huber <sebastian.huber@…>, on 10/13/17 at 06:00:46

psxclockrealtime01: New test

Update #3182.

  • Property mode set to 100644
File size: 12.8 KB
Line 
1/*
2 * Copyright (c) 2017 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15/*
16 * This test program runs also on GNU/Linux.  Use
17 *
18 * cc init.c -pthread -Wall -Wextra -lrt && sudo ./a.out
19 *
20 * to run it.  It must run probably as root for the clock_settime().
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <sys/stat.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <inttypes.h>
31#include <limits.h>
32#include <mqueue.h>
33#include <pthread.h>
34#include <semaphore.h>
35#include <stdbool.h>
36#include <stdio.h>
37#include <string.h>
38#include <time.h>
39#include <unistd.h>
40
41#ifdef __rtems__
42
43#include "tmacros.h"
44
45#else /* __rtems__ */
46
47#include <assert.h>
48
49#define rtems_test_assert(x) assert(x)
50
51#endif /* __rtems__ */
52
53static void assert_eno(const char *hint, int eno, int expected_eno)
54{
55  const char *warn;
56
57  if (eno != expected_eno) {
58    warn = "WARNING: ";
59  } else {
60    warn = "";
61  }
62
63  printf(
64    "%s%s: actual '%s', expected '%s'\n",
65    warn,
66    hint,
67    strerror(eno),
68    strerror(expected_eno)
69  );
70#ifdef __rtems__
71  rtems_test_assert(eno == expected_eno);
72#endif /* __rtems__ */
73}
74
75static void assert_rv(const char *hint, int rv, int expected_eno)
76{
77  int eno;
78
79  if (rv != 0) {
80    eno = errno;
81  } else {
82    eno = 0;
83  }
84
85  assert_eno(hint, eno, expected_eno);
86}
87
88typedef struct {
89  char data;
90} test_msg;
91
92#define MSG_COUNT 1
93
94#define MSG_SIZE sizeof(test_msg)
95
96typedef struct {
97  int value;
98  pthread_mutex_t mtx;
99  pthread_cond_t cnd;
100} event;
101
102typedef enum {
103  ACTION_NONE,
104  ACTION_MTX_LOCK,
105  ACTION_CND_WAIT,
106  ACTION_RW_RDLOCK,
107  ACTION_RW_WRLOCK,
108  ACTION_SEM_WAIT,
109  ACTION_MQ_SEND,
110  ACTION_MQ_RECV,
111  ACTION_CLOCK_NANOSLEEP,
112  ACTION_TERMINATE
113} test_action;
114
115typedef enum {
116  MODE_TIMEOUT_FINITE,
117  MODE_TIMEOUT_NEGATIVE_SEC,
118  MODE_TIMEOUT_NEGATIVE_NSEC,
119  MODE_TIMEOUT_NEGATIVE_SEC_NSEC,
120  MODE_TIMEOUT_HUGE_NSEC,
121#ifdef __rtems__
122  MODE_TIMEOUT_NULL,
123#endif /* __rtems__ */
124  MODE_TIMEOUT_PRACTICALLY_INFINITE,
125  MODE_COUNT
126} test_mode;
127
128typedef struct {
129  test_mode mode;
130  pthread_t worker;
131  event action;
132  event done;
133  pthread_mutex_t mtx;
134  pthread_mutex_t mtx2;
135  pthread_cond_t cnd;
136  pthread_rwlock_t rw;
137  sem_t sem;
138  mqd_t mq;
139  int counter[ACTION_TERMINATE + 1];
140} test_context;
141
142static test_context test_instance;
143
144static void event_init(event *e)
145{
146  int eno;
147
148  eno = pthread_mutex_init(&e->mtx, NULL);
149  rtems_test_assert(eno == 0);
150
151  eno = pthread_cond_init(&e->cnd, NULL);
152  rtems_test_assert(eno == 0);
153}
154
155static void event_destroy(event *e)
156{
157  int eno;
158
159  eno = pthread_mutex_destroy(&e->mtx);
160  rtems_test_assert(eno == 0);
161
162  eno = pthread_cond_destroy(&e->cnd);
163  rtems_test_assert(eno == 0);
164}
165
166static void event_post(event *e, int value)
167{
168  int eno;
169
170  eno = pthread_mutex_lock(&e->mtx);
171  rtems_test_assert(eno == 0);
172
173  e->value = value;
174
175  eno = pthread_cond_signal(&e->cnd);
176  rtems_test_assert(eno == 0);
177
178  eno = pthread_mutex_unlock(&e->mtx);
179  rtems_test_assert(eno == 0);
180}
181
182static int event_get(event *e)
183{
184  int eno;
185  int value;
186
187  eno = pthread_mutex_lock(&e->mtx);
188  rtems_test_assert(eno == 0);
189
190  while (true) {
191    value = e->value;
192
193    if (value != 0) {
194      e->value = 0;
195      break;
196    }
197
198    eno = pthread_cond_wait(&e->cnd, &e->mtx);
199    rtems_test_assert(eno == 0);
200  }
201
202  eno = pthread_mutex_unlock(&e->mtx);
203  rtems_test_assert(eno == 0);
204
205  return value;
206}
207
208static void *worker(void *arg)
209{
210  test_context *ctx;
211  test_action action;
212  test_mode mode;
213  int eno;
214  int unused;
215
216  ctx = arg;
217  mode = ctx->mode;
218
219  eno = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &unused);
220  rtems_test_assert(eno == 0);
221
222  eno = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &unused);
223  rtems_test_assert(eno == 0);
224
225  while ((action = event_get(&ctx->action)) != ACTION_TERMINATE) {
226    int rv;
227    struct timespec to_storage;
228    const struct timespec *to;
229    int expected_eno;
230    test_msg msg;
231    unsigned prio;
232
233    switch (mode) {
234      case MODE_TIMEOUT_FINITE:
235        rv = clock_gettime(CLOCK_REALTIME, &to_storage);
236        rtems_test_assert(rv == 0);
237
238        to_storage.tv_sec += 3600;
239        to = &to_storage;
240        expected_eno = ETIMEDOUT;
241        break;
242      case MODE_TIMEOUT_NEGATIVE_SEC:
243        to_storage.tv_sec = -1;
244        to_storage.tv_nsec = 1;
245        to = &to_storage;
246        expected_eno = ETIMEDOUT;
247        break;
248      case MODE_TIMEOUT_NEGATIVE_NSEC:
249        to_storage.tv_sec = 1;
250        to_storage.tv_nsec = -1;
251        to = &to_storage;
252        expected_eno = EINVAL;
253        break;
254      case MODE_TIMEOUT_NEGATIVE_SEC_NSEC:
255        to_storage.tv_sec = -1;
256        to_storage.tv_nsec = -1;
257        to = &to_storage;
258        expected_eno = EINVAL;
259        break;
260      case MODE_TIMEOUT_HUGE_NSEC:
261        to_storage.tv_sec = 1;
262        to_storage.tv_nsec = LONG_MAX;
263        to = &to_storage;
264        expected_eno = EINVAL;
265        break;
266#ifdef __rtems__
267      case MODE_TIMEOUT_NULL:
268        to = NULL;
269        expected_eno = EINVAL;
270        break;
271#endif /* __rtems__ */
272      case MODE_TIMEOUT_PRACTICALLY_INFINITE:
273        to_storage.tv_sec = INT64_MAX;
274        to_storage.tv_nsec = 999999999;
275        to = &to_storage;
276        expected_eno = -1;
277        break;
278      default:
279        rtems_test_assert(0);
280        break;
281    }
282
283    switch (action) {
284      case ACTION_MTX_LOCK:
285        eno = pthread_mutex_timedlock(&ctx->mtx, to);
286        assert_eno("pthread_mutex_timedlock", eno, expected_eno);
287        break;
288      case ACTION_CND_WAIT:
289        eno = pthread_mutex_lock(&ctx->mtx2);
290        rtems_test_assert(eno == 0);
291
292        eno = pthread_cond_timedwait(&ctx->cnd, &ctx->mtx2, to);
293        assert_eno("pthread_cond_timedwait", eno, expected_eno);
294
295        eno = pthread_mutex_unlock(&ctx->mtx2);
296        rtems_test_assert(eno == 0);
297        break;
298      case ACTION_RW_RDLOCK:
299        eno = pthread_rwlock_timedrdlock(&ctx->rw, to);
300        assert_eno("pthread_rwlock_timedrdlock", eno, expected_eno);
301        break;
302      case ACTION_RW_WRLOCK:
303        eno = pthread_rwlock_timedwrlock(&ctx->rw, to);
304        assert_eno("pthread_rwlock_timedwrlock", eno, expected_eno);
305        break;
306      case ACTION_SEM_WAIT:
307        errno = 0;
308        rv = sem_timedwait(&ctx->sem, to);
309        assert_rv("sem_timedwait", rv, expected_eno);
310        break;
311      case ACTION_MQ_SEND:
312        msg.data = 13;
313        rv = mq_send(ctx->mq, &msg.data, sizeof(msg), 7);
314        rtems_test_assert(rv == 0);
315        msg.data = 31;
316        errno = 0;
317        rv = mq_timedsend(ctx->mq, &msg.data, sizeof(msg), 5, to);
318        assert_rv("mq_timedsend", rv, expected_eno);
319        break;
320      case ACTION_MQ_RECV:
321        msg.data = 0;
322        prio = 0;
323        rv = mq_receive(ctx->mq, &msg.data, sizeof(msg), &prio);
324        rtems_test_assert(rv == 1);
325        rtems_test_assert(msg.data == 13);
326        rtems_test_assert(prio == 7);
327        msg.data = 0;
328        prio = 0;
329        errno = 0;
330        rv = mq_timedreceive(ctx->mq, &msg.data, sizeof(msg), &prio, to);
331        assert_rv("mq_timedreceive", rv, expected_eno);
332        rtems_test_assert(msg.data == 0);
333        rtems_test_assert(prio == 0);
334        break;
335      case ACTION_CLOCK_NANOSLEEP:
336        rv = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, to, NULL);
337
338        if (expected_eno == ETIMEDOUT) {
339          assert_rv("clock_nanosleep", rv, 0);
340        } else {
341          assert_rv("clock_nanosleep", rv, expected_eno);
342        }
343        break;
344      default:
345        rtems_test_assert(0);
346        break;
347    }
348
349    ++ctx->counter[action];
350
351    event_post(&ctx->done, 1);
352  }
353
354  return ctx;
355}
356
357static void delay(void)
358{
359  int rv;
360
361  rv = usleep(100000);
362  rtems_test_assert(rv == 0);
363}
364
365static void run(
366  test_context *ctx,
367  const char *test,
368  test_mode mode,
369  void (*f)(void)
370)
371{
372  test_action action;
373  int eno;
374  void *status;
375
376  printf("*** %s ***\n", test);
377  ctx->mode = mode;
378
379  eno = pthread_create(&ctx->worker, NULL, worker, ctx);
380  rtems_test_assert(eno == 0);
381
382  for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
383    event_post(&ctx->action, action);
384    delay();
385
386    (*f)();
387
388    event_get(&ctx->done);
389  }
390
391  event_post(&ctx->action, ACTION_TERMINATE);
392
393  status = NULL;
394  eno = pthread_join(ctx->worker, &status);
395  rtems_test_assert(eno == 0);
396  rtems_test_assert(status == ctx);
397}
398
399static void timeout_finite(void)
400{
401  struct timespec now;
402  int rv;
403
404  rv = clock_gettime(CLOCK_REALTIME, &now);
405  rtems_test_assert(rv == 0);
406
407  now.tv_sec += 7200;
408
409  rv = clock_settime(CLOCK_REALTIME, &now);
410  rtems_test_assert(rv == 0);
411}
412
413static void test_timeout_finite(test_context *ctx)
414{
415  run(ctx, "timeout finite", MODE_TIMEOUT_FINITE, timeout_finite);
416}
417
418static void do_nothing(void)
419{
420  /* Do nothing */
421}
422
423static void test_timeout_negative_sec(test_context *ctx)
424{
425  run(ctx, "timeout negative sec", MODE_TIMEOUT_NEGATIVE_SEC, do_nothing);
426}
427
428static void test_timeout_negative_nsec(test_context *ctx)
429{
430  run(ctx, "timout negative nsec", MODE_TIMEOUT_NEGATIVE_NSEC, do_nothing);
431}
432
433static void test_timeout_negative_sec_nsec(test_context *ctx)
434{
435  run(
436    ctx,
437    "timout negative sec and nsec",
438    MODE_TIMEOUT_NEGATIVE_SEC_NSEC,
439    do_nothing
440  );
441}
442
443static void test_timeout_huge_nsec(test_context *ctx)
444{
445  run(ctx, "timout huge nsec", MODE_TIMEOUT_HUGE_NSEC, do_nothing);
446}
447
448#ifdef __rtems__
449static void test_timeout_null(test_context *ctx)
450{
451  run(ctx, "timeout NULL", MODE_TIMEOUT_NULL, do_nothing);
452}
453#endif /* __rtems__ */
454
455static void test_timeout_practically_infinite(test_context *ctx)
456{
457  test_action action;
458  int eno;
459
460  puts("*** timeout practically infinite ***");
461  ctx->mode = MODE_TIMEOUT_PRACTICALLY_INFINITE;
462
463  for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
464    void *status;
465
466    eno = pthread_create(&ctx->worker, NULL, worker, ctx);
467    rtems_test_assert(eno == 0);
468
469    event_post(&ctx->action, action);
470    delay();
471
472    eno = pthread_cancel(ctx->worker);
473    rtems_test_assert(eno == 0);
474
475    status = NULL;
476    eno = pthread_join(ctx->worker, &status);
477    rtems_test_assert(eno == 0);
478    rtems_test_assert(status == PTHREAD_CANCELED);
479  }
480}
481
482static void test(test_context *ctx)
483{
484  test_action action;
485  int eno;
486  int rv;
487  mode_t mode;
488  struct mq_attr ma;
489
490  event_init(&ctx->action);
491  event_init(&ctx->done);
492
493  eno = pthread_mutex_init(&ctx->mtx, NULL);
494  rtems_test_assert(eno == 0);
495
496  eno = pthread_mutex_lock(&ctx->mtx);
497  rtems_test_assert(eno == 0);
498
499  eno = pthread_mutex_init(&ctx->mtx2, NULL);
500  rtems_test_assert(eno == 0);
501
502  eno = pthread_cond_init(&ctx->cnd, NULL);
503  rtems_test_assert(eno == 0);
504
505  eno = pthread_rwlock_init(&ctx->rw, NULL);
506  rtems_test_assert(eno == 0);
507
508  eno = pthread_rwlock_wrlock(&ctx->rw);
509  rtems_test_assert(eno == 0);
510
511  rv = sem_init(&ctx->sem, 0, 0);
512  rtems_test_assert(rv == 0);
513
514  mode = S_IRWXU | S_IRWXG | S_IRWXO;
515  memset(&ma, 0, sizeof(ma));
516  ma.mq_maxmsg = MSG_COUNT;
517  ma.mq_msgsize = MSG_SIZE;
518  ctx->mq = mq_open("/mq", O_CREAT | O_RDWR, mode, &ma);
519  rtems_test_assert(ctx->mq != (mqd_t) -1);
520
521  test_timeout_finite(ctx);
522  test_timeout_negative_sec(ctx);
523  test_timeout_negative_nsec(ctx);
524  test_timeout_negative_sec_nsec(ctx);
525  test_timeout_huge_nsec(ctx);
526#ifdef __rtems__
527  test_timeout_null(ctx);
528#endif /* __rtems__ */
529  test_timeout_practically_infinite(ctx);
530
531  event_destroy(&ctx->action);
532  event_destroy(&ctx->done);
533
534  eno = pthread_mutex_unlock(&ctx->mtx);
535  rtems_test_assert(eno == 0);
536
537  eno = pthread_mutex_destroy(&ctx->mtx);
538  rtems_test_assert(eno == 0);
539
540  eno = pthread_mutex_destroy(&ctx->mtx2);
541#ifdef __rtems__
542  rtems_test_assert(eno == 0);
543#else /* __rtems__ */
544  rtems_test_assert(eno == 0 || eno == EBUSY);
545#endif /* __rtems__ */
546
547  eno = pthread_cond_destroy(&ctx->cnd);
548  rtems_test_assert(eno == 0);
549
550  eno = pthread_rwlock_unlock(&ctx->rw);
551  rtems_test_assert(eno == 0);
552
553  eno = pthread_rwlock_destroy(&ctx->rw);
554  rtems_test_assert(eno == 0);
555
556  rv = sem_destroy(&ctx->sem);
557  rtems_test_assert(rv == 0);
558
559  rv = mq_close(ctx->mq);
560  rtems_test_assert(rv == 0);
561
562  rv = mq_unlink("/mq");
563  rtems_test_assert(rv == 0);
564
565  for (action = ACTION_MTX_LOCK; action < ACTION_TERMINATE; ++action) {
566    rtems_test_assert(ctx->counter[action] == MODE_COUNT - 1);
567  }
568}
569
570#ifdef __rtems__
571
572const char rtems_test_name[] = "PSXCLOCKREALTIME 1";
573
574static void *POSIX_Init(void *arg)
575{
576  TEST_BEGIN();
577  test(&test_instance);
578  TEST_END();
579  rtems_test_exit(0);
580}
581
582#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
583#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
584
585#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
586#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1
587
588#define CONFIGURE_POSIX_INIT_THREAD_TABLE
589
590#define CONFIGURE_INIT
591
592#include <rtems/confdefs.h>
593
594#else /* __rtems__ */
595
596int main(void)
597{
598  test(&test_instance);
599  return 0;
600}
601
602#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.