diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-09-10 17:12:06 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-10-14 07:47:12 +0200 |
commit | cff773f5802d0b5b4d007be3f6f4adbb04ce0d41 (patch) | |
tree | afada47b1eb3d9ebbe755c8cd7eca6e3e9eec632 | |
parent | libstdthreads: Import from FreeBSD (diff) | |
download | rtems-cff773f5802d0b5b4d007be3f6f4adbb04ce0d41.tar.bz2 |
libstdthreads: Add C11 threads
-rw-r--r-- | cpukit/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/configure.ac | 4 | ||||
-rw-r--r-- | cpukit/libstdthreads/Makefile.am | 21 | ||||
-rw-r--r-- | cpukit/libstdthreads/call_once.c | 6 | ||||
-rw-r--r-- | cpukit/libstdthreads/cnd.c | 31 | ||||
-rw-r--r-- | cpukit/libstdthreads/mtx.c | 48 | ||||
-rw-r--r-- | cpukit/libstdthreads/thrd.c | 9 | ||||
-rw-r--r-- | cpukit/libstdthreads/tss.c | 7 | ||||
-rw-r--r-- | cpukit/wrapup/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/sptests/Makefile.am | 3 | ||||
-rw-r--r-- | testsuites/sptests/configure.ac | 4 | ||||
-rw-r--r-- | testsuites/sptests/spstdthreads01/Makefile.am | 19 | ||||
-rw-r--r-- | testsuites/sptests/spstdthreads01/init.c | 438 | ||||
-rw-r--r-- | testsuites/sptests/spstdthreads01/spstdthreads01.doc | 35 | ||||
-rw-r--r-- | testsuites/sptests/spstdthreads01/spstdthreads01.scn | 2 |
15 files changed, 554 insertions, 75 deletions
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index c9a4e0f506..063a795b7f 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -16,6 +16,7 @@ SUBDIRS += libmisc SUBDIRS += libmd SUBDIRS += libgnat SUBDIRS += libdl +SUBDIRS += libstdthreads SUBDIRS += wrapup SUBDIRS += zlib diff --git a/cpukit/configure.ac b/cpukit/configure.ac index 14ce0f1a4c..01da86d3e4 100644 --- a/cpukit/configure.ac +++ b/cpukit/configure.ac @@ -141,6 +141,9 @@ AS_IF([test -n "$rtems_missing_header"], AC_CHECK_HEADERS([semaphore.h]) AM_CONDITIONAL([HAVE_SEMAPHORE_H],[test x"$ac_cv_header_semaphore_h" = x"yes"]) +AC_CHECK_HEADERS([threads.h]) +AM_CONDITIONAL([HAVE_THREADS_H],[test x"$ac_cv_header_threads_h" = x"yes"]) + ## error out if libc doesn't provide stdint.h AS_IF([test x"${ac_cv_header_stdint_h}" != xyes], [AC_MSG_ERROR([Required header stdint.h not found])]) @@ -481,6 +484,7 @@ libmisc/Makefile libi2c/Makefile libmd/Makefile libdl/Makefile +libstdthreads/Makefile zlib/Makefile ftpd/Makefile telnetd/Makefile diff --git a/cpukit/libstdthreads/Makefile.am b/cpukit/libstdthreads/Makefile.am new file mode 100644 index 0000000000..8b4ffaae0f --- /dev/null +++ b/cpukit/libstdthreads/Makefile.am @@ -0,0 +1,21 @@ +include $(top_srcdir)/automake/compile.am + +include_HEADERS = + +noinst_LIBRARIES = libstdthreads.a + +libstdthreads_a_CFLAGS = -std=c11 +libstdthreads_a_CPPFLAGS = $(AM_CPPFLAGS) + +libstdthreads_a_SOURCES = +if HAVE_THREADS_H +libstdthreads_a_SOURCES += call_once.c +libstdthreads_a_SOURCES += cnd.c +libstdthreads_a_SOURCES += mtx.c +if HAS_PTHREADS +libstdthreads_a_SOURCES += thrd.c +endif +libstdthreads_a_SOURCES += tss.c +endif + +include $(top_srcdir)/automake/local.am diff --git a/cpukit/libstdthreads/call_once.c b/cpukit/libstdthreads/call_once.c index 2d7d6ff89e..9a577d68db 100644 --- a/cpukit/libstdthreads/call_once.c +++ b/cpukit/libstdthreads/call_once.c @@ -26,13 +26,9 @@ * $FreeBSD r228904 2011-12-26T21:51:53Z$ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <threads.h> #include <pthread.h> -#include "threads.h" - void call_once(once_flag *flag, void (*func)(void)) { diff --git a/cpukit/libstdthreads/cnd.c b/cpukit/libstdthreads/cnd.c index cccf728c77..7ed750aee4 100644 --- a/cpukit/libstdthreads/cnd.c +++ b/cpukit/libstdthreads/cnd.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org> + * Copyright (c) 2015 embedded brains GmbH <info@embedded-brains.de> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,20 +27,14 @@ * $FreeBSD r228904 2011-12-26T21:51:53Z$ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <threads.h> #include <errno.h> -#include <pthread.h> - -#include "threads.h" int cnd_broadcast(cnd_t *cond) { - if (pthread_cond_broadcast(cond) != 0) - return (thrd_error); + _Condition_Broadcast(cond); return (thrd_success); } @@ -47,29 +42,22 @@ void cnd_destroy(cnd_t *cond) { - (void)pthread_cond_destroy(cond); + _Condition_Destroy(cond); } int cnd_init(cnd_t *cond) { - switch (pthread_cond_init(cond, NULL)) { - case 0: - return (thrd_success); - case ENOMEM: - return (thrd_nomem); - default: - return (thrd_error); - } + _Condition_Initialize(cond); + return (thrd_success); } int cnd_signal(cnd_t *cond) { - if (pthread_cond_signal(cond) != 0) - return (thrd_error); + _Condition_Signal(cond); return (thrd_success); } @@ -78,7 +66,7 @@ cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts) { - switch (pthread_cond_timedwait(cond, mtx, ts)) { + switch (_Condition_Wait_recursive_timed(cond, mtx, ts)) { case 0: return (thrd_success); case ETIMEDOUT: @@ -92,7 +80,6 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx) { - if (pthread_cond_wait(cond, mtx) != 0) - return (thrd_error); + _Condition_Wait_recursive(cond, mtx); return (thrd_success); } diff --git a/cpukit/libstdthreads/mtx.c b/cpukit/libstdthreads/mtx.c index 2d42f8a8db..48369c2ed0 100644 --- a/cpukit/libstdthreads/mtx.c +++ b/cpukit/libstdthreads/mtx.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org> + * Copyright (c) 2015 embedded brains GmbH <info@embedded-brains.de> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,46 +27,23 @@ * $FreeBSD r279326 2015-02-26T16:39:57Z$ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <threads.h> +#include <sys/lock.h> #include <errno.h> -#include <pthread.h> - -#include "threads.h" void mtx_destroy(mtx_t *mtx) { - (void)pthread_mutex_destroy(mtx); + _Mutex_recursive_Destroy(mtx); } int mtx_init(mtx_t *mtx, int type) { - pthread_mutexattr_t attr; - int mt; - switch (type) { - case mtx_plain: - case mtx_timed: - mt = PTHREAD_MUTEX_NORMAL; - break; - case mtx_plain | mtx_recursive: - case mtx_timed | mtx_recursive: - mt = PTHREAD_MUTEX_RECURSIVE; - break; - default: - return (thrd_error); - } - - if (pthread_mutexattr_init(&attr) != 0) - return (thrd_error); - if (pthread_mutexattr_settype(&attr, mt) != 0) - return (thrd_error); - if (pthread_mutex_init(mtx, &attr) != 0) - return (thrd_error); + (void)type; + _Mutex_recursive_Initialize(mtx); return (thrd_success); } @@ -73,8 +51,7 @@ int mtx_lock(mtx_t *mtx) { - if (pthread_mutex_lock(mtx) != 0) - return (thrd_error); + _Mutex_recursive_Acquire(mtx); return (thrd_success); } @@ -82,7 +59,7 @@ int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts) { - switch (pthread_mutex_timedlock(mtx, ts)) { + switch (_Mutex_recursive_Acquire_timed(mtx, ts)) { case 0: return (thrd_success); case ETIMEDOUT: @@ -96,13 +73,11 @@ int mtx_trylock(mtx_t *mtx) { - switch (pthread_mutex_trylock(mtx)) { + switch (_Mutex_recursive_Try_acquire(mtx)) { case 0: return (thrd_success); - case EBUSY: - return (thrd_busy); default: - return (thrd_error); + return (thrd_busy); } } @@ -110,7 +85,6 @@ int mtx_unlock(mtx_t *mtx) { - if (pthread_mutex_unlock(mtx) != 0) - return (thrd_error); + _Mutex_recursive_Release(mtx); return (thrd_success); } diff --git a/cpukit/libstdthreads/thrd.c b/cpukit/libstdthreads/thrd.c index 562e806226..c2e439f45c 100644 --- a/cpukit/libstdthreads/thrd.c +++ b/cpukit/libstdthreads/thrd.c @@ -26,15 +26,12 @@ * $FreeBSD r279318 2015-02-26T09:42:03Z$ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <threads.h> #include <pthread.h> +#include <sched.h> #include <stdint.h> #include <stdlib.h> -#include "threads.h" - struct thrd_param { thrd_start_t func; void *arg; @@ -124,5 +121,5 @@ void thrd_yield(void) { - pthread_yield(); + sched_yield(); } diff --git a/cpukit/libstdthreads/tss.c b/cpukit/libstdthreads/tss.c index 0d4eea7a2e..9ff9d3bd3a 100644 --- a/cpukit/libstdthreads/tss.c +++ b/cpukit/libstdthreads/tss.c @@ -26,13 +26,10 @@ * $FreeBSD r228904 2011-12-26T21:51:53Z$ */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <threads.h> +#include <limits.h> #include <pthread.h> -#include "threads.h" - int tss_create(tss_t *key, tss_dtor_t dtor) { diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am index 5fd6e33004..57ef83275c 100644 --- a/cpukit/wrapup/Makefile.am +++ b/cpukit/wrapup/Makefile.am @@ -20,6 +20,7 @@ TMP_LIBS += ../libgnat/libgnat.a endif TMP_LIBS += ../libcrypt/libcrypt.a +TMP_LIBS += ../libstdthreads/libstdthreads.a TMP_LIBS += ../libcsupport/libcsupport.a TMP_LIBS += ../libcsupport/libcalloc.a TMP_LIBS += ../libblock/libblock.a 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 *** |