summaryrefslogtreecommitdiffstats
path: root/testsuites
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-09-10 17:12:06 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-10-14 07:47:12 +0200
commitcff773f5802d0b5b4d007be3f6f4adbb04ce0d41 (patch)
treeafada47b1eb3d9ebbe755c8cd7eca6e3e9eec632 /testsuites
parentlibstdthreads: Import from FreeBSD (diff)
downloadrtems-cff773f5802d0b5b4d007be3f6f4adbb04ce0d41.tar.bz2
libstdthreads: Add C11 threads
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/sptests/Makefile.am3
-rw-r--r--testsuites/sptests/configure.ac4
-rw-r--r--testsuites/sptests/spstdthreads01/Makefile.am19
-rw-r--r--testsuites/sptests/spstdthreads01/init.c438
-rw-r--r--testsuites/sptests/spstdthreads01/spstdthreads01.doc35
-rw-r--r--testsuites/sptests/spstdthreads01/spstdthreads01.scn2
6 files changed, 501 insertions, 0 deletions
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index d01201974f..688c66f97d 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -40,6 +40,9 @@ endif
if HAS__THREAD_QUEUE_QUEUE
_SUBDIRS += spsyslock01
endif
+if HAS_THREADS_H
+_SUBDIRS += spstdthreads01
+endif
_SUBDIRS += sptasknopreempt01
_SUBDIRS += spintrcritical23
_SUBDIRS += sptimecounter01
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index be69f092b2..ea96dbf9da 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -33,6 +33,9 @@ AC_CHECK_SIZEOF([time_t])
AC_CHECK_TYPES([struct _Thread_queue_Queue],[],[],[#include <sys/lock.h>])
AM_CONDITIONAL(HAS__THREAD_QUEUE_QUEUE,test x"${ac_cv_type_struct__Thread_queue_Queue}" = x"yes")
+AC_CHECK_HEADERS([threads.h])
+AM_CONDITIONAL([HAS_THREADS_H],[test x"$ac_cv_header_threads_h" = x"yes"])
+
# Added to newlib pthreads for RTEMS SMP (np), may not be present
AC_CHECK_HEADERS([sys/cpuset.h])
AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes")
@@ -43,6 +46,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
+spstdthreads01/Makefile
spsyslock01/Makefile
sptasknopreempt01/Makefile
spintrcritical23/Makefile
diff --git a/testsuites/sptests/spstdthreads01/Makefile.am b/testsuites/sptests/spstdthreads01/Makefile.am
new file mode 100644
index 0000000000..bef6888042
--- /dev/null
+++ b/testsuites/sptests/spstdthreads01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = spstdthreads01
+spstdthreads01_SOURCES = init.c
+
+dist_rtems_tests_DATA = spstdthreads01.scn spstdthreads01.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 = $(spstdthreads01_OBJECTS)
+LINK_LIBS = $(spstdthreads01_LDLIBS)
+
+spstdthreads01$(EXEEXT): $(spstdthreads01_OBJECTS) $(spstdthreads01_DEPENDENCIES)
+ @rm -f spstdthreads01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spstdthreads01/init.c b/testsuites/sptests/spstdthreads01/init.c
new file mode 100644
index 0000000000..40d44d6c39
--- /dev/null
+++ b/testsuites/sptests/spstdthreads01/init.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@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.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <threads.h>
+
+#include <rtems/malloc.h>
+
+const char rtems_test_name[] = "SPSTDTHREADS 1";
+
+#define US_PER_TICK 10000
+
+#define EVENT_MTX_LOCK RTEMS_EVENT_0
+
+#define EVENT_MTX_UNLOCK RTEMS_EVENT_1
+
+#define EVENT_CND_WAIT RTEMS_EVENT_2
+
+#define EVENT_CND_TIMEDWAIT RTEMS_EVENT_3
+
+#define EVENT_TSS RTEMS_EVENT_4
+
+typedef struct {
+ rtems_id high;
+ rtems_id low;
+ once_flag once_flag;
+ mtx_t mtx;
+ cnd_t cnd;
+ tss_t tss;
+ thrd_t thrd;
+ int generation;
+} test_context;
+
+static test_context test_instance = {
+ .once_flag = ONCE_FLAG_INIT
+};
+
+static void next_generation(test_context *ctx)
+{
+ ++ctx->generation;
+}
+
+static void send_event(test_context *ctx, rtems_event_set events)
+{
+ rtems_status_code sc;
+
+ sc = rtems_event_send(ctx->high, events);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void get_abs_timeout(struct timespec *to)
+{
+ int rv;
+
+ rv = clock_gettime(CLOCK_REALTIME, to);
+ rtems_test_assert(rv == 0);
+
+ to->tv_nsec += 2 * US_PER_TICK * 1000;
+ if (to->tv_nsec >= 1000000000) {
+ ++to->tv_sec;
+ to->tv_nsec -= 1000000000;
+ }
+}
+
+static void test_init(test_context *ctx)
+{
+ int status;
+
+ status = mtx_init(&ctx->mtx, mtx_plain);
+ rtems_test_assert(status == thrd_success);
+
+ status = cnd_init(&ctx->cnd);
+ rtems_test_assert(status == thrd_success);
+}
+
+static void test_destroy(test_context *ctx)
+{
+ mtx_destroy(&ctx->mtx);
+ cnd_destroy(&ctx->cnd);
+}
+
+static void once_func(void)
+{
+ test_context *ctx = &test_instance;
+
+ next_generation(ctx);
+}
+
+static void test_once(test_context *ctx)
+{
+ int gen = ctx->generation;
+
+ call_once(&ctx->once_flag, once_func);
+ rtems_test_assert(ctx->generation == gen + 1);
+
+ call_once(&ctx->once_flag, once_func);
+ rtems_test_assert(ctx->generation == gen + 1);
+}
+
+static void test_mtx(test_context *ctx)
+{
+ mtx_t *mtx = &ctx->mtx;
+ int gen = ctx->generation;
+ struct timespec to;
+ int status;
+
+ status = mtx_trylock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_lock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ get_abs_timeout(&to);
+ status = mtx_timedlock(mtx, &to);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ send_event(ctx, EVENT_MTX_LOCK);
+ rtems_test_assert(ctx->generation == gen + 1);
+
+ status = mtx_trylock(mtx);
+ rtems_test_assert(status == thrd_busy);
+
+ memset(&to, 0xff, sizeof(to));
+ status = mtx_timedlock(mtx, &to);
+ rtems_test_assert(status == thrd_error);
+
+ get_abs_timeout(&to);
+ status = mtx_timedlock(mtx, &to);
+ rtems_test_assert(status == thrd_timedout);
+
+ send_event(ctx, EVENT_MTX_UNLOCK);
+ rtems_test_assert(ctx->generation == gen + 2);
+}
+
+static void test_cnd(test_context *ctx)
+{
+ cnd_t *cnd = &ctx->cnd;
+ mtx_t *mtx = &ctx->mtx;
+ int gen = ctx->generation;
+ struct timespec to;
+ int status;
+
+ send_event(ctx, EVENT_CND_WAIT);
+ rtems_test_assert(ctx->generation == gen + 1);
+
+ status = mtx_lock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = cnd_signal(cnd);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+ rtems_test_assert(ctx->generation == gen + 2);
+
+ send_event(ctx, EVENT_CND_WAIT);
+ rtems_test_assert(ctx->generation == gen + 3);
+
+ status = mtx_lock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = cnd_broadcast(cnd);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+ rtems_test_assert(ctx->generation == gen + 4);
+
+ status = mtx_lock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ memset(&to, 0xff, sizeof(to));
+ status = cnd_timedwait(cnd, mtx, &to);
+ rtems_test_assert(status == thrd_error);
+
+ get_abs_timeout(&to);
+ status = cnd_timedwait(cnd, mtx, &to);
+ rtems_test_assert(status == thrd_timedout);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ send_event(ctx, EVENT_CND_TIMEDWAIT);
+ rtems_test_assert(ctx->generation == gen + 5);
+
+ status = mtx_lock(mtx);
+ rtems_test_assert(status == thrd_success);
+
+ status = cnd_signal(cnd);
+ rtems_test_assert(status == thrd_success);
+
+ status = mtx_unlock(mtx);
+ rtems_test_assert(status == thrd_success);
+ rtems_test_assert(ctx->generation == gen + 6);
+}
+
+static int tss_val = TSS_DTOR_ITERATIONS;
+
+static void tss_dtor(void *val)
+{
+ test_context *ctx = &test_instance;
+
+ rtems_test_assert(val == &tss_val);
+ next_generation(ctx);
+}
+
+static void test_tss(test_context *ctx)
+{
+ tss_dtor_t dtor = tss_dtor;
+ int gen = ctx->generation;
+ int status;
+
+ status = tss_create(&ctx->tss, dtor);
+ rtems_test_assert(status == thrd_success);
+
+ send_event(ctx, EVENT_TSS);
+ rtems_test_assert(ctx->generation == gen + 1);
+
+ tss_delete(ctx->tss);
+}
+
+#if defined(RTEMS_POSIX_API)
+static int thrd(void *arg)
+{
+ thrd_exit(123);
+}
+#endif
+
+static void test_thrd(test_context *ctx)
+{
+#if defined(RTEMS_POSIX_API)
+ thrd_start_t thrd_start = thrd;
+ int status;
+ int exit_status;
+ struct timespec duration;
+ struct timespec remaining;
+ void *greedy;
+
+ rtems_test_assert(thrd_equal(rtems_task_self(), thrd_current()));
+
+ thrd_yield();
+
+ memset(&duration, 0, sizeof(duration));
+ duration.tv_nsec = 1;
+ thrd_sleep(&duration, &remaining);
+ rtems_test_assert(remaining.tv_sec == 0);
+ rtems_test_assert(remaining.tv_nsec == 0);
+
+ greedy = rtems_heap_greedy_allocate(NULL, 0);
+ status = thrd_create(&ctx->thrd, thrd_start, ctx);
+ rtems_test_assert(status == thrd_nomem);
+ rtems_heap_greedy_free(greedy);
+
+ status = thrd_create(&ctx->thrd, thrd_start, ctx);
+ rtems_test_assert(status == thrd_success);
+
+ status = thrd_create(&ctx->thrd, thrd_start, ctx);
+ rtems_test_assert(status == thrd_error);
+
+ exit_status = 0;
+ status = thrd_join(ctx->thrd, &exit_status);
+ rtems_test_assert(status == thrd_success);
+ rtems_test_assert(exit_status == 123);
+
+ status = thrd_detach(thrd_current());
+ rtems_test_assert(status == thrd_success);
+
+ status = thrd_detach(11235);
+ rtems_test_assert(status == thrd_error);
+#endif
+}
+
+static void high_task(rtems_task_argument idx)
+{
+ test_context *ctx = &test_instance;
+
+ while (true) {
+ rtems_event_set events;
+ rtems_status_code sc;
+ int status;
+
+ sc = rtems_event_receive(
+ RTEMS_ALL_EVENTS,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ if ((events & EVENT_MTX_LOCK) != 0) {
+ status = mtx_lock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+ }
+
+ if ((events & EVENT_MTX_UNLOCK) != 0) {
+ status = mtx_unlock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+ }
+
+ if ((events & EVENT_CND_WAIT) != 0) {
+ status = mtx_lock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+
+ status = cnd_wait(&ctx->cnd, &ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+
+ status = mtx_unlock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ }
+
+ if ((events & EVENT_CND_TIMEDWAIT) != 0) {
+ struct timespec to;
+
+ status = mtx_lock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+
+ get_abs_timeout(&to);
+ status = cnd_timedwait(&ctx->cnd, &ctx->mtx, &to);
+ rtems_test_assert(status == thrd_success);
+ next_generation(ctx);
+
+ status = mtx_unlock(&ctx->mtx);
+ rtems_test_assert(status == thrd_success);
+ }
+
+ if ((events & EVENT_TSS) != 0) {
+ void *val;
+
+ status = tss_set(ctx->tss, &tss_val);
+ rtems_test_assert(status == thrd_success);
+
+ val = tss_get(ctx->tss);
+ rtems_test_assert(val == &tss_val);
+
+ rtems_task_delete(RTEMS_SELF);
+ rtems_test_assert(0);
+ }
+ }
+}
+
+static void test(void)
+{
+ test_context *ctx = &test_instance;
+ rtems_status_code sc;
+
+ test_init(ctx);
+
+ ctx->low = rtems_task_self();
+
+ sc = rtems_task_create(
+ rtems_build_name('H', 'I', 'G', 'H'),
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->high
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(ctx->high, high_task, 0);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ test_once(ctx);
+ test_mtx(ctx);
+ test_cnd(ctx);
+ test_tss(ctx);
+ test_thrd(ctx);
+ test_destroy(ctx);
+}
+
+static void Init(rtems_task_argument arg)
+{
+ TEST_BEGIN();
+
+ test();
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_MAXIMUM_TASKS 4
+
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 1
+
+#if defined(RTEMS_POSIX_API)
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
+#endif
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_INIT_TASK_PRIORITY 4
+#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spstdthreads01/spstdthreads01.doc b/testsuites/sptests/spstdthreads01/spstdthreads01.doc
new file mode 100644
index 0000000000..15943745fc
--- /dev/null
+++ b/testsuites/sptests/spstdthreads01/spstdthreads01.doc
@@ -0,0 +1,35 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: spstdthreads01
+
+directives:
+
+ - call_once()
+ - cnd_broadcast()
+ - cnd_destroy()
+ - cnd_init()
+ - cnd_signal()
+ - cnd_timedwait()
+ - cnd_wait()
+ - mtx_destroy()
+ - mtx_init()
+ - mtx_lock()
+ - mtx_timedlock()
+ - mtx_trylock()
+ - mtx_unlock()
+ - thrd_create()
+ - thrd_current()
+ - thrd_detach()
+ - thrd_equal()
+ - thrd_exit()
+ - thrd_join()
+ - thrd_sleep()
+ - thrd_yield()
+ - tss_create()
+ - tss_delete()
+ - tss_get()
+ - tss_set()
+
+concepts:
+
+ - Ensure that the C11 threads API works.
diff --git a/testsuites/sptests/spstdthreads01/spstdthreads01.scn b/testsuites/sptests/spstdthreads01/spstdthreads01.scn
new file mode 100644
index 0000000000..010272d70e
--- /dev/null
+++ b/testsuites/sptests/spstdthreads01/spstdthreads01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPSTDTHREADS 1 ***
+*** END OF TEST SPSTDTHREADS 1 ***