Update #2843. --- cpukit/Makefile.am | 1 + cpukit/include/rtems/thread.h | 280 +++++++++++++++++++++++++++ cpukit/preinstall.am | 4 + cpukit/score/src/semaphore.c | 99 +++++++++- testsuites/sptests/Makefile.am | 1 + testsuites/sptests/configure.ac | 1 + testsuites/sptests/spthread01/Makefile.am | 19 ++ testsuites/sptests/spthread01/init.c | 249 ++++++++++++++++++++++++ testsuites/sptests/spthread01/spthread01.doc | 11 ++ testsuites/sptests/spthread01/spthread01.scn | 0 10 files changed, 662 insertions(+), 3 deletions(-) create mode 100644 cpukit/include/rtems/thread.h create mode 100644 testsuites/sptests/spthread01/Makefile.am create mode 100644 testsuites/sptests/spthread01/init.c create mode 100644 testsuites/sptests/spthread01/spthread01.doc create mode 100644 testsuites/sptests/spthread01/spthread01.scn
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index d317fbba1c..3c149696ed 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -258,6 +258,7 @@ include_rtems_HEADERS += libmisc/untar/untar.h ## fsmount include_rtems_HEADERS += libmisc/fsmount/fsmount.h +include_rtems_HEADERS += include/rtems/thread.h include_rtems_HEADERS += include/rtems/tm27-default.h ## Driver manager diff --git a/cpukit/include/rtems/thread.h b/cpukit/include/rtems/thread.h new file mode 100644 index 0000000000..e1c47c5703 --- /dev/null +++ b/cpukit/include/rtems/thread.h @@ -0,0 +1,280 @@ +/* + * 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.org/license/LICENSE. + */ + +#ifndef _RTEMS_THREAD_H +#define _RTEMS_THREAD_H + +#include <sys/lock.h> +#include <errno.h> +#include <stdint.h> + +__BEGIN_DECLS + +typedef struct _Mutex_Control rtems_mutex; + +#define RTEMS_MUTEX_INITIALIZER( name ) _MUTEX_NAMED_INITIALIZER( name ) + +static __inline void rtems_mutex_init( rtems_mutex *mutex, const char *name ) +{ + _Mutex_Initialize_named( mutex, name ); +} + +static __inline const char *rtems_mutex_get_name( const rtems_mutex *mutex ) +{ + return mutex->_Queue._name; +} + +static __inline void rtems_mutex_set_name( rtems_mutex *mutex, const char *name ) +{ + mutex->_Queue._name = name; +} + +static __inline void rtems_mutex_lock( rtems_mutex *mutex ) +{ + _Mutex_Acquire( mutex ); +} + +static __inline void rtems_mutex_unlock( rtems_mutex *mutex ) +{ + _Mutex_Release( mutex ); +} + +static __inline void rtems_mutex_destroy( rtems_mutex *mutex ) +{ + _Mutex_Destroy( mutex ); +} + +typedef struct _Mutex_recursive_Control rtems_recursive_mutex; + +#define RTEMS_RECURSIVE_MUTEX_INITIALIZER( name ) \ + _MUTEX_RECURSIVE_NAMED_INITIALIZER( name ) + +static __inline void rtems_recursive_mutex_init( + rtems_recursive_mutex *mutex, const char *name +) +{ + _Mutex_recursive_Initialize_named( mutex, name ); +} + +static __inline const char *rtems_recursive_mutex_get_name( + const rtems_recursive_mutex *mutex +) +{ + return mutex->_Mutex._Queue._name; +} + +static __inline void rtems_recursive_mutex_set_name( + rtems_recursive_mutex *mutex, const char *name +) +{ + mutex->_Mutex._Queue._name = name; +} + +static __inline void rtems_recursive_mutex_lock( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Acquire( mutex ); +} + +static __inline void rtems_recursive_mutex_unlock( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Release( mutex ); +} + +static __inline void rtems_recursive_mutex_destroy( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Destroy( mutex ); +} + +typedef struct _Condition_Control rtems_condition_variable; + +#define RTEMS_CONDITION_VARIABLE_INITIALIZER( name ) \ + _CONDITION_NAMED_INITIALIZER( name ) + +static __inline void rtems_condition_variable_init( + rtems_condition_variable *condition_variable, + const char *name +) +{ + _Condition_Initialize_named( condition_variable, name ); +} + +static __inline const char *rtems_condition_variable_get_name( + const rtems_condition_variable *condition_variable +) +{ + return condition_variable->_Queue._name; +} + +static __inline void rtems_condition_variable_set_name( + rtems_condition_variable *condition_variable, + const char *name +) +{ + condition_variable->_Queue._name = name; +} + +static __inline void rtems_condition_variable_wait( + rtems_condition_variable *condition_variable, + rtems_mutex *mutex +) +{ + _Condition_Wait( condition_variable, mutex ); +} + +static __inline void rtems_condition_variable_signal( + rtems_condition_variable *condition_variable +) +{ + _Condition_Broadcast( condition_variable ); +} + +static __inline void rtems_condition_variable_broadcast( + rtems_condition_variable *condition_variable +) +{ + _Condition_Broadcast( condition_variable ); +} + +static __inline void rtems_condition_variable_destroy( + rtems_condition_variable *condition_variable +) +{ + _Condition_Destroy( condition_variable ); +} + +typedef struct _Semaphore_Control rtems_counting_semaphore; + +#define RTEMS_COUNTING_SEMAPHORE_INITIALIZER( name, value ) \ + _SEMAPHORE_NAMED_INITIALIZER( name, value ) + +static __inline void rtems_counting_semaphore_init( + rtems_counting_semaphore *counting_semaphore, + const char *name, + unsigned int value +) +{ + _Semaphore_Initialize_named( counting_semaphore, name, value ); +} + +static __inline const char *rtems_counting_semaphore_get_name( + const rtems_counting_semaphore *counting_semaphore +) +{ + return counting_semaphore->_Queue._name; +} + +static __inline void rtems_counting_semaphore_set_name( + rtems_counting_semaphore *counting_semaphore, + const char *name +) +{ + counting_semaphore->_Queue._name = name; +} + +static __inline void rtems_counting_semaphore_wait( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Wait( counting_semaphore ); +} + +static __inline void rtems_counting_semaphore_post( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Post( counting_semaphore ); +} + +static __inline void rtems_counting_semaphore_destroy( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Destroy( counting_semaphore ); +} + +typedef struct { + struct _Semaphore_Control Semaphore; +} rtems_binary_semaphore; + +#define RTEMS_BINARY_SEMAPHORE_INITIALIZER( name ) \ + { _SEMAPHORE_NAMED_INITIALIZER( name, 0 ) } + +static __inline void rtems_binary_semaphore_init( + rtems_binary_semaphore *binary_semaphore, + const char *name +) +{ + _Semaphore_Initialize_named( &binary_semaphore->Semaphore, name, 0 ); +} + +static __inline const char *rtems_binary_semaphore_get_name( + const rtems_binary_semaphore *binary_semaphore +) +{ + return binary_semaphore->Semaphore._Queue._name; +} + +static __inline void rtems_binary_semaphore_set_name( + rtems_binary_semaphore *binary_semaphore, + const char *name +) +{ + binary_semaphore->Semaphore._Queue._name = name; +} + +static __inline void rtems_binary_semaphore_wait( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Wait( &binary_semaphore->Semaphore ); +} + +static __inline int rtems_binary_semaphore_wait_timed_ticks( + rtems_binary_semaphore *binary_semaphore, + uint32_t ticks +) +{ + return _Semaphore_Wait_timed_ticks( &binary_semaphore->Semaphore, ticks ); +} + +static __inline int rtems_binary_semaphore_try_wait( + rtems_binary_semaphore *binary_semaphore +) +{ + return _Semaphore_Try_wait( &binary_semaphore->Semaphore ); +} + +static __inline void rtems_binary_semaphore_post( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Post_binary( &binary_semaphore->Semaphore ); +} + +static __inline void rtems_binary_semaphore_destroy( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Destroy( &binary_semaphore->Semaphore ); +} + +__END_DECLS + +#endif /* _RTEMS_THREAD_H */ diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am index fd26535031..d347e94593 100644 --- a/cpukit/preinstall.am +++ b/cpukit/preinstall.am @@ -565,6 +565,10 @@ $(PROJECT_INCLUDE)/rtems/fsmount.h: libmisc/fsmount/fsmount.h $(PROJECT_INCLUDE) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fsmount.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fsmount.h +$(PROJECT_INCLUDE)/rtems/thread.h: include/rtems/thread.h $(PROJECT_INCLUDE)/rtems/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/thread.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/thread.h + $(PROJECT_INCLUDE)/rtems/tm27-default.h: include/rtems/tm27-default.h $(PROJECT_INCLUDE)/rtems/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/tm27-default.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/tm27-default.h diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c index 4edd25a387..f76ee332a4 100644 --- a/cpukit/score/src/semaphore.c +++ b/cpukit/score/src/semaphore.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -18,8 +18,9 @@ #include <rtems/score/semaphoreimpl.h> #include <rtems/score/statesimpl.h> +#include <rtems/score/threadimpl.h> -#include <limits.h> +#include <errno.h> RTEMS_STATIC_ASSERT( offsetof( Sem_Control, Queue ) @@ -71,6 +72,66 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem ) } } +int _Semaphore_Wait_timed_ticks( struct _Semaphore_Control *_sem, uint32_t ticks ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + Thread_Control *executing; + unsigned int count; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + executing = _Sem_Queue_acquire_critical( sem, &queue_context ); + + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + _Sem_Queue_release( sem, level, &queue_context ); + return 0; + } else { + _Thread_queue_Context_set_thread_state( + &queue_context, + STATES_WAITING_FOR_SEMAPHORE + ); + _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, ticks ); + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + _Thread_queue_Enqueue( + &sem->Queue.Queue, + SEMAPHORE_TQ_OPERATIONS, + executing, + &queue_context + ); + return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) ); + } +} + +int _Semaphore_Try_wait( struct _Semaphore_Control *_sem ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + unsigned int count; + int eno; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + eno = 0; + } else { + eno = EAGAIN; + } + + _Sem_Queue_release( sem, level, &queue_context ); + return eno; +} + void _Semaphore_Post( struct _Semaphore_Control *_sem ) { Sem_Control *sem; @@ -85,7 +146,6 @@ void _Semaphore_Post( struct _Semaphore_Control *_sem ) heads = sem->Queue.Queue.heads; if ( __predict_true( heads == NULL ) ) { - _Assert( sem->count < UINT_MAX ); ++sem->count; _Sem_Queue_release( sem, level, &queue_context ); } else { @@ -104,3 +164,36 @@ void _Semaphore_Post( struct _Semaphore_Control *_sem ) ); } } + +void _Semaphore_Post_binary( struct _Semaphore_Control *_sem ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + Thread_queue_Heads *heads; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + heads = sem->Queue.Queue.heads; + if ( __predict_true( heads == NULL ) ) { + sem->count = 1; + _Sem_Queue_release( sem, level, &queue_context ); + } else { + const Thread_queue_Operations *operations; + Thread_Control *first; + + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + operations = SEMAPHORE_TQ_OPERATIONS; + first = ( *operations->first )( heads ); + + _Thread_queue_Extract_critical( + &sem->Queue.Queue, + operations, + first, + &queue_context + ); + } +} diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 00f7571902..561d2d73e0 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -33,6 +33,7 @@ _SUBDIRS = \ spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \ spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \ sptask_err04 spclock_err01 +_SUBDIRS += spthread01 _SUBDIRS += spconsole01 _SUBDIRS += spintrcritical24 _SUBDIRS += spfatal29 diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index 6a303b25c5..84619282b9 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -36,6 +36,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +spthread01/Makefile sptls04/Makefile spconsole01/Makefile spintrcritical24/Makefile diff --git a/testsuites/sptests/spthread01/Makefile.am b/testsuites/sptests/spthread01/Makefile.am new file mode 100644 index 0000000000..f9e14cb380 --- /dev/null +++ b/testsuites/sptests/spthread01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = spthread01 +spthread01_SOURCES = init.c + +dist_rtems_tests_DATA = spthread01.scn spthread01.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 = $(spthread01_OBJECTS) +LINK_LIBS = $(spthread01_LDLIBS) + +spthread01$(EXEEXT): $(spthread01_OBJECTS) $(spthread01_DEPENDENCIES) + @rm -f spthread01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spthread01/init.c b/testsuites/sptests/spthread01/init.c new file mode 100644 index 0000000000..4c5bfc12e1 --- /dev/null +++ b/testsuites/sptests/spthread01/init.c @@ -0,0 +1,249 @@ +/* + * 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 <rtems/thread.h> +#include <rtems.h> + +#include <string.h> + +#include <tmacros.h> + +const char rtems_test_name[] = "SPTHREAD 1"; + +static void test_mutex(void) +{ + rtems_mutex a = RTEMS_MUTEX_INITIALIZER("a"); + const char *name; + + name = rtems_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "a") == 0); + + rtems_mutex_set_name(&a, "b"); + + name = rtems_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "b") == 0); + + rtems_mutex_destroy(&a); + + rtems_mutex_init(&a, "c"); + + name = rtems_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "c") == 0); + + rtems_mutex_lock(&a); + + rtems_mutex_unlock(&a); + + rtems_mutex_destroy(&a); +} + +static void test_recursive_mutex(void) +{ + rtems_recursive_mutex a = RTEMS_RECURSIVE_MUTEX_INITIALIZER("a"); + const char *name; + + name = rtems_recursive_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "a") == 0); + + rtems_recursive_mutex_set_name(&a, "b"); + + name = rtems_recursive_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "b") == 0); + + rtems_recursive_mutex_destroy(&a); + + rtems_recursive_mutex_init(&a, "c"); + + name = rtems_recursive_mutex_get_name(&a); + rtems_test_assert(strcmp(name, "c") == 0); + + rtems_recursive_mutex_lock(&a); + + rtems_recursive_mutex_lock(&a); + + rtems_recursive_mutex_unlock(&a); + + rtems_recursive_mutex_unlock(&a); + + rtems_recursive_mutex_destroy(&a); +} + +typedef struct { + rtems_mutex mtx; + rtems_condition_variable cnd; +} signal_context; + +static void signal_task(rtems_task_argument arg) +{ + signal_context *s; + + s = (signal_context *) arg; + rtems_mutex_lock(&s->mtx); + rtems_condition_variable_signal(&s->cnd); + rtems_mutex_unlock(&s->mtx); +} + +static void test_condition_variable(void) +{ + rtems_condition_variable a = RTEMS_CONDITION_VARIABLE_INITIALIZER("a"); + signal_context s; + const char *name; + rtems_status_code sc; + rtems_id id; + + name = rtems_condition_variable_get_name(&a); + rtems_test_assert(strcmp(name, "a") == 0); + + rtems_condition_variable_set_name(&a, "b"); + + name = rtems_condition_variable_get_name(&a); + rtems_test_assert(strcmp(name, "b") == 0); + + rtems_condition_variable_destroy(&a); + + rtems_mutex_init(&s.mtx, "d"); + rtems_condition_variable_init(&s.cnd, "c"); + + name = rtems_condition_variable_get_name(&s.cnd); + rtems_test_assert(strcmp(name, "c") == 0); + + rtems_condition_variable_signal(&s.cnd); + + rtems_condition_variable_broadcast(&s.cnd); + + rtems_mutex_lock(&s.mtx); + + sc = rtems_task_create( + rtems_build_name('C', 'O', 'N', 'D'), + 2, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, signal_task, (rtems_task_argument) &s); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_condition_variable_wait(&s.cnd, &s.mtx); + + sc = rtems_task_delete(id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_mutex_unlock(&s.mtx); + + rtems_condition_variable_destroy(&s.cnd); + rtems_mutex_destroy(&s.mtx); +} + +static void test_counting_semaphore(void) +{ + rtems_counting_semaphore a = RTEMS_COUNTING_SEMAPHORE_INITIALIZER("a", 1); + const char *name; + + name = rtems_counting_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "a") == 0); + + rtems_counting_semaphore_set_name(&a, "b"); + + name = rtems_counting_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "b") == 0); + + rtems_counting_semaphore_destroy(&a); + + rtems_counting_semaphore_init(&a, "c", 0); + + name = rtems_counting_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "c") == 0); + + rtems_counting_semaphore_post(&a); + + rtems_counting_semaphore_wait(&a); + + rtems_counting_semaphore_destroy(&a); +} + +static void test_binary_semaphore(void) +{ + rtems_binary_semaphore a = RTEMS_BINARY_SEMAPHORE_INITIALIZER("a"); + const char *name; + int eno; + + name = rtems_binary_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "a") == 0); + + rtems_binary_semaphore_set_name(&a, "b"); + + name = rtems_binary_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "b") == 0); + + rtems_binary_semaphore_destroy(&a); + + rtems_binary_semaphore_init(&a, "c"); + + name = rtems_binary_semaphore_get_name(&a); + rtems_test_assert(strcmp(name, "c") == 0); + + eno = rtems_binary_semaphore_try_wait(&a); + rtems_test_assert(eno == EAGAIN); + + eno = rtems_binary_semaphore_wait_timed_ticks(&a, 1); + rtems_test_assert(eno == ETIMEDOUT); + + rtems_binary_semaphore_post(&a); + + rtems_binary_semaphore_wait(&a); + + rtems_binary_semaphore_post(&a); + + eno = rtems_binary_semaphore_try_wait(&a); + rtems_test_assert(eno == 0); + + rtems_binary_semaphore_post(&a); + + eno = rtems_binary_semaphore_wait_timed_ticks(&a, 1); + rtems_test_assert(eno == 0); + + rtems_binary_semaphore_destroy(&a); +} + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + test_mutex(); + test_recursive_mutex(); + test_condition_variable(); + test_counting_semaphore(); + test_binary_semaphore(); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 2 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> diff --git a/testsuites/sptests/spthread01/spthread01.doc b/testsuites/sptests/spthread01/spthread01.doc new file mode 100644 index 0000000000..b1cd716cfa --- /dev/null +++ b/testsuites/sptests/spthread01/spthread01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: spthread01 + +directives: + + TBD + +concepts: + + TBD diff --git a/testsuites/sptests/spthread01/spthread01.scn b/testsuites/sptests/spthread01/spthread01.scn new file mode 100644 index 0000000000..e69de29bb2 -- 2.12.3 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel