Update #3182. --- testsuites/psxtests/Makefile.am | 1 + testsuites/psxtests/configure.ac | 1 + testsuites/psxtests/psxclockrealtime01/Makefile.am | 19 ++ testsuites/psxtests/psxclockrealtime01/init.c | 304 +++++++++++++++++++++ .../psxclockrealtime01/psxclockrealtime01.doc | 16 ++ .../psxclockrealtime01/psxclockrealtime01.scn | 2 + 6 files changed, 343 insertions(+) create mode 100644 testsuites/psxtests/psxclockrealtime01/Makefile.am create mode 100644 testsuites/psxtests/psxclockrealtime01/init.c create mode 100644 testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.doc create mode 100644 testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.scn
diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am index cccdb39118..2a74470d60 100644 --- a/testsuites/psxtests/Makefile.am +++ b/testsuites/psxtests/Makefile.am @@ -36,6 +36,7 @@ endif _SUBDIRS += psxclock if HAS_POSIX _SUBDIRS += psxclock01 +_SUBDIRS += psxclockrealtime01 _SUBDIRS += psxconcurrency01 _SUBDIRS += psxcond01 _SUBDIRS += psxcond02 diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac index 96a0149302..7243bfdbb5 100644 --- a/testsuites/psxtests/configure.ac +++ b/testsuites/psxtests/configure.ac @@ -140,6 +140,7 @@ psxcleanup01/Makefile psxcleanup02/Makefile psxclock/Makefile psxclock01/Makefile +psxclockrealtime01/Makefile psxconcurrency01/Makefile psxcond01/Makefile psxcond02/Makefile diff --git a/testsuites/psxtests/psxclockrealtime01/Makefile.am b/testsuites/psxtests/psxclockrealtime01/Makefile.am new file mode 100644 index 0000000000..d0b1a76dbe --- /dev/null +++ b/testsuites/psxtests/psxclockrealtime01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = psxclockrealtime01 +psxclockrealtime01_SOURCES = init.c + +dist_rtems_tests_DATA = psxclockrealtime01.scn psxclockrealtime01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(psxclockrealtime01_OBJECTS) +LINK_LIBS = $(psxclockrealtime01_LDLIBS) + +psxclockrealtime01$(EXEEXT): $(psxclockrealtime01_OBJECTS) $(psxclockrealtime01_DEPENDENCIES) + @rm -f psxclockrealtime01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/psxtests/psxclockrealtime01/init.c b/testsuites/psxtests/psxclockrealtime01/init.c new file mode 100644 index 0000000000..f5a05056a7 --- /dev/null +++ b/testsuites/psxtests/psxclockrealtime01/init.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <semaphore.h> +#include <stdbool.h> +#include <time.h> +#include <unistd.h> + +#ifdef __rtems__ +#include "tmacros.h" +#else /* __rtems__ */ +#include <assert.h> +#define rtems_test_assert(x) assert(x) +#endif /* __rtems__ */ + +const char rtems_test_name[] = "PSXCLOCKREALTIME 1"; + +typedef struct { + int value; + pthread_mutex_t mtx; + pthread_cond_t cnd; +} event; + +typedef enum { + ACTION_NONE, + ACTION_MTX_LOCK, + ACTION_CND_WAIT, + ACTION_RW_RDLOCK, + ACTION_RW_WRLOCK, + ACTION_SEM_WAIT, + ACTION_TERMINATE +} test_action; + +typedef struct { + pthread_t worker; + event action; + event done; + pthread_mutex_t mtx; + pthread_mutex_t mtx2; + pthread_cond_t cnd; + pthread_rwlock_t rw; + sem_t sem; + int counter[ACTION_TERMINATE + 1]; +} test_context; + +static test_context test_instance; + +static void event_init(event *e) +{ + int eno; + + eno = pthread_mutex_init(&e->mtx, NULL); + rtems_test_assert(eno == 0); + + eno = pthread_cond_init(&e->cnd, NULL); + rtems_test_assert(eno == 0); +} + +static void event_destroy(event *e) +{ + int eno; + + eno = pthread_mutex_destroy(&e->mtx); + rtems_test_assert(eno == 0); + + eno = pthread_cond_destroy(&e->cnd); + rtems_test_assert(eno == 0); +} + +static void event_post(event *e, int value) +{ + int eno; + + eno = pthread_mutex_lock(&e->mtx); + rtems_test_assert(eno == 0); + + e->value = value; + + eno = pthread_cond_signal(&e->cnd); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_unlock(&e->mtx); + rtems_test_assert(eno == 0); +} + +static int event_get(event *e) +{ + int eno; + int value; + + eno = pthread_mutex_lock(&e->mtx); + rtems_test_assert(eno == 0); + + while (true) { + value = e->value; + + if (value != 0) { + e->value = 0; + break; + } + + eno = pthread_cond_wait(&e->cnd, &e->mtx); + rtems_test_assert(eno == 0); + } + + eno = pthread_mutex_unlock(&e->mtx); + rtems_test_assert(eno == 0); + + return value; +} + +static void *worker(void *arg) +{ + test_context *ctx; + test_action action; + ctx = arg; + + while ((action = event_get(&ctx->action)) != ACTION_TERMINATE) { + int eno; + int rv; + struct timespec to; + + rv = clock_gettime(CLOCK_REALTIME, &to); + rtems_test_assert(rv == 0); + + to.tv_sec += 3600; + + switch (action) { + case ACTION_MTX_LOCK: + eno = pthread_mutex_timedlock(&ctx->mtx, &to); + rtems_test_assert(eno == ETIMEDOUT); + break; + case ACTION_CND_WAIT: + eno = pthread_mutex_lock(&ctx->mtx2); + rtems_test_assert(eno == 0); + + eno = pthread_cond_timedwait(&ctx->cnd, &ctx->mtx2, &to); + rtems_test_assert(eno == ETIMEDOUT); + + eno = pthread_mutex_unlock(&ctx->mtx2); + rtems_test_assert(eno == 0); + break; + case ACTION_RW_RDLOCK: + eno = pthread_rwlock_timedrdlock(&ctx->rw, &to); + rtems_test_assert(eno == ETIMEDOUT); + break; + case ACTION_RW_WRLOCK: + eno = pthread_rwlock_timedwrlock(&ctx->rw, &to); + rtems_test_assert(eno == ETIMEDOUT); + break; + case ACTION_SEM_WAIT: + errno = 0; + rv = sem_timedwait(&ctx->sem, &to); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == ETIMEDOUT); + break; + default: + rtems_test_assert(0); + break; + } + + ++ctx->counter[action]; + + event_post(&ctx->done, 1); + } + + return ctx; +} + +static void test(test_context *ctx) +{ + test_action action; + int eno; + int rv; + void *status; + + event_init(&ctx->action); + event_init(&ctx->done); + + eno = pthread_mutex_init(&ctx->mtx, NULL); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_lock(&ctx->mtx); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_init(&ctx->mtx2, NULL); + rtems_test_assert(eno == 0); + + eno = pthread_cond_init(&ctx->cnd, NULL); + rtems_test_assert(eno == 0); + + eno = pthread_rwlock_init(&ctx->rw, NULL); + rtems_test_assert(eno == 0); + + eno = pthread_rwlock_wrlock(&ctx->rw); + rtems_test_assert(eno == 0); + + rv = sem_init(&ctx->sem, 0, 0); + rtems_test_assert(rv == 0); + + eno = pthread_create(&ctx->worker, NULL, worker, ctx); + rtems_test_assert(eno == 0); + + for (action = ACTION_MTX_LOCK; action <= ACTION_SEM_WAIT; ++action) { + struct timespec now; + + event_post(&ctx->action, action); + + rv = sleep(1); + rtems_test_assert(rv == 0); + + rv = clock_gettime(CLOCK_REALTIME, &now); + rtems_test_assert(rv == 0); + + now.tv_sec += 7200; + + rv = clock_settime(CLOCK_REALTIME, &now); + rtems_test_assert(rv == 0); + + event_get(&ctx->done); + } + + event_post(&ctx->action, ACTION_TERMINATE); + + eno = pthread_join(ctx->worker, &status); + rtems_test_assert(eno == 0); + rtems_test_assert(status == ctx); + + event_destroy(&ctx->action); + event_destroy(&ctx->done); + + eno = pthread_mutex_unlock(&ctx->mtx); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_destroy(&ctx->mtx); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_destroy(&ctx->mtx2); + rtems_test_assert(eno == 0); + + eno = pthread_cond_destroy(&ctx->cnd); + rtems_test_assert(eno == 0); + + eno = pthread_rwlock_unlock(&ctx->rw); + rtems_test_assert(eno == 0); + + eno = pthread_rwlock_destroy(&ctx->rw); + rtems_test_assert(eno == 0); + + rv = sem_destroy(&ctx->sem); + rtems_test_assert(rv == 0); + + for (action = ACTION_MTX_LOCK; action <= ACTION_SEM_WAIT; ++action) { + rtems_test_assert(ctx->counter[action] == 1); + } +} + +#ifdef __rtems__ + +static void *POSIX_Init(void *arg) +{ + TEST_BEGIN(); + test(&test_instance); + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_POSIX_THREADS 2 + +#define CONFIGURE_POSIX_INIT_THREAD_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> + +#else /* __rtems__ */ + +int main(void) +{ + test(&test_instance); + return 0; +} + +#endif /* __rtems__ */ diff --git a/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.doc b/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.doc new file mode 100644 index 0000000000..5669df84e8 --- /dev/null +++ b/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.doc @@ -0,0 +1,16 @@ +This file describes the directives and concepts tested by this test set. + +test set name: psxclockrealtime01 + +directives: + + - pthread_mutex_timedlock() + - pthread_cond_timedwait() + - pthread_rwlock_timedrdlock() + - pthread_rwlock_timedwrlock() + - sem_timedwait() + +concepts: + + - Ensure that absolute CLOCK_REALTIME timeouts expire due to external clock + changes. diff --git a/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.scn b/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.scn new file mode 100644 index 0000000000..df2801b674 --- /dev/null +++ b/testsuites/psxtests/psxclockrealtime01/psxclockrealtime01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST PSXCLOCKREALTIME 1 *** +*** END OF TEST PSXCLOCKREALTIME 1 *** -- 2.12.3 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel