From 022851aba54d32831feaff13deb3d9943e130eee Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 28 Jan 2014 12:10:08 +0100 Subject: Add thread-local storage (TLS) support Tested and implemented on ARM, m68k, PowerPC and SPARC. Other architectures need more work. --- testsuites/sptests/Makefile.am | 4 + testsuites/sptests/configure.ac | 7 + testsuites/sptests/sptls01/Makefile.am | 19 +++ testsuites/sptests/sptls01/init.c | 98 +++++++++++++ testsuites/sptests/sptls01/sptls01.doc | 11 ++ testsuites/sptests/sptls01/sptls01.scn | 5 + testsuites/sptests/sptls02/Makefile.am | 20 +++ testsuites/sptests/sptls02/init.cc | 256 +++++++++++++++++++++++++++++++++ testsuites/sptests/sptls02/sptls02.doc | 12 ++ testsuites/sptests/sptls02/sptls02.scn | 4 + 10 files changed, 436 insertions(+) create mode 100644 testsuites/sptests/sptls01/Makefile.am create mode 100644 testsuites/sptests/sptls01/init.c create mode 100644 testsuites/sptests/sptls01/sptls01.doc create mode 100644 testsuites/sptests/sptls01/sptls01.scn create mode 100644 testsuites/sptests/sptls02/Makefile.am create mode 100644 testsuites/sptests/sptls02/init.cc create mode 100644 testsuites/sptests/sptls02/sptls02.doc create mode 100644 testsuites/sptests/sptls02/sptls02.scn (limited to 'testsuites/sptests') diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 7eab621dc5..1eacf5ceb3 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -30,6 +30,10 @@ SUBDIRS = \ spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \ spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \ spregion_err01 sppartition_err01 +if HAS_CPLUSPLUS +SUBDIRS += sptls02 +endif +SUBDIRS += sptls01 SUBDIRS += spintrcritical20 SUBDIRS += spintrcritical19 SUBDIRS += spcontext01 diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index 6b14543e9e..623e784fd5 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -11,16 +11,21 @@ RTEMS_CANONICAL_TARGET_CPU AM_INIT_AUTOMAKE([no-define foreign 1.12.2]) AM_MAINTAINER_MODE +RTEMS_ENABLE_CXX RTEMS_ENV_RTEMSBSP RTEMS_CHECK_RTEMS_TEST_NO_PAUSE RTEMS_PROJECT_ROOT RTEMS_PROG_CC_FOR_TARGET +RTEMS_PROG_CXX_FOR_TARGET RTEMS_CANONICALIZE_TOOLS RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP) +RTEMS_CHECK_CXX(RTEMS_BSP) + +AM_CONDITIONAL([HAS_CPLUSPLUS],[test $HAS_CPLUSPLUS = "yes"]) # FIXME: We should get rid of this. It's a cludge. AC_CHECK_SIZEOF([time_t]) @@ -31,6 +36,8 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +sptls02/Makefile +sptls01/Makefile spintrcritical20/Makefile spintrcritical19/Makefile spcontext01/Makefile diff --git a/testsuites/sptests/sptls01/Makefile.am b/testsuites/sptests/sptls01/Makefile.am new file mode 100644 index 0000000000..5512b8aa3d --- /dev/null +++ b/testsuites/sptests/sptls01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = sptls01 +sptls01_SOURCES = init.c + +dist_rtems_tests_DATA = sptls01.scn sptls01.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 = $(sptls01_OBJECTS) +LINK_LIBS = $(sptls01_LDLIBS) + +sptls01$(EXEEXT): $(sptls01_OBJECTS) $(sptls01_DEPENDENCIES) + @rm -f sptls01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/sptls01/init.c b/testsuites/sptests/sptls01/init.c new file mode 100644 index 0000000000..76bd671dff --- /dev/null +++ b/testsuites/sptests/sptls01/init.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 + +#include "tmacros.h" + +static rtems_id master_task; + +static __thread volatile char tls_item = 123; + +static void check_tls_item(int expected) +{ + printf("TLS item = %i\n", tls_item); + rtems_test_assert(tls_item == expected); +} + +static void task(rtems_task_argument arg) +{ + rtems_status_code sc; + + check_tls_item(123); + + sc = rtems_event_transient_send(master_task); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_suspend(RTEMS_SELF); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void test(void) +{ + rtems_id id; + rtems_status_code sc; + + master_task = rtems_task_self(); + + check_tls_item(123); + tls_item = 5; + + sc = rtems_task_create( + rtems_build_name('T', 'A', 'S', 'K'), + RTEMS_MINIMUM_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, task, 0); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_delete(id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + check_tls_item(5); +} + +static void Init(rtems_task_argument arg) +{ + puts("\n\n*** TEST SPTLS 1 ***"); + + test(); + + puts("*** END OF TEST SPTLS 1 ***"); + + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 2 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/sptests/sptls01/sptls01.doc b/testsuites/sptests/sptls01/sptls01.doc new file mode 100644 index 0000000000..a6cc38b81c --- /dev/null +++ b/testsuites/sptests/sptls01/sptls01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: sptls01 + +directives: + + - None + +concepts: + + - Ensure that thread-local storage (TLS) works minimum alignment requirements. diff --git a/testsuites/sptests/sptls01/sptls01.scn b/testsuites/sptests/sptls01/sptls01.scn new file mode 100644 index 0000000000..eaeb11e21f --- /dev/null +++ b/testsuites/sptests/sptls01/sptls01.scn @@ -0,0 +1,5 @@ +*** TEST SPTLS 1 *** +TLS item = 123 +TLS item = 123 +TLS item = 5 +*** END OF TEST SPTLS 1 *** diff --git a/testsuites/sptests/sptls02/Makefile.am b/testsuites/sptests/sptls02/Makefile.am new file mode 100644 index 0000000000..d577b5b2c8 --- /dev/null +++ b/testsuites/sptests/sptls02/Makefile.am @@ -0,0 +1,20 @@ +rtems_tests_PROGRAMS = sptls02 +sptls02_SOURCES = init.cc + +dist_rtems_tests_DATA = sptls02.scn sptls02.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 +AM_CXXFLAGS += -std=c++11 -ftls-model=local-exec + +LINK_OBJS = $(sptls02_OBJECTS) +LINK_LIBS = $(sptls02_LDLIBS) + +sptls02$(EXEEXT): $(sptls02_OBJECTS) $(sptls02_DEPENDENCIES) + @rm -f sptls02$(EXEEXT) + $(make-cxx-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/sptls02/init.cc b/testsuites/sptests/sptls02/init.cc new file mode 100644 index 0000000000..d70419009a --- /dev/null +++ b/testsuites/sptests/sptls02/init.cc @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 +#include + +#include +#include + +#include "tmacros.h" + +static thread_local long i123 = 123; + +alignas(256) static thread_local long a256 = 256; + +static thread_local long i0; + +alignas(512) static thread_local long a512; + +static void clobber() +{ + i123 = 0xdead0001; + a256 = 0xdead0002; + i0 = 0xdead0003; + a512 = 0xdead0004; +} + +static long f456(bool clobber) +{ + static thread_local long fi456 = 456; + + if (clobber) { + fi456 = 0xdead0003; + } + + return fi456; +} + +static long f0(bool clobber) +{ + static thread_local long fi0; + + if (clobber) { + fi0 = 0xdead0004; + } + + return fi0; +} + +class C { + public: + static long c789() + { + return ci789; + } + + static long c0() + { + return ci0; + } + + static void clobber() + { + ci789 = 0xdead0005; + ci0 = 0xdead0006; + } + + private: + static thread_local long ci789; + + static thread_local long ci0; +}; + +thread_local long C::ci789 = 789; + +thread_local long C::ci0; + +class A { + public: + A(long i) + : ii(i), c(gc) + { + ++gc; + } + + ~A() + { + --gc; + } + + long i() const + { + return ii; + } + + void clobber() + { + ii = ~ii; + c = ~c; + } + + long counter() const + { + return c; + } + + static long globalCounter() + { + return gc; + } + + private: + static long gc; + + long ii; + + long c; +}; + +long A::gc; + +static volatile long mc; + +static thread_local A a1(mc + 1); +static thread_local A a2(mc + 2); +static thread_local A a3(mc + 3); + +static void checkTLSValues() +{ + rtems_test_assert(i123 == 123); + rtems_test_assert(a256 == 256); + rtems_test_assert((a256 & 255) == 0); + rtems_test_assert(i0 == 0); + rtems_test_assert(a512 == 0); + rtems_test_assert((a512 & 511) == 0); + rtems_test_assert(f456(false) == 456); + rtems_test_assert(f0(false) == 0); + rtems_test_assert(C::c789() == 789); + rtems_test_assert(C::c0() == 0); + rtems_test_assert(a1.i() == 1); + rtems_test_assert(a2.i() == 2); + rtems_test_assert(a3.i() == 3); +} + +static rtems_id masterTask; + +static void task(rtems_task_argument arg) +{ + checkTLSValues(); + + const long gc = static_cast(arg); + + rtems_test_assert(A::globalCounter() == gc + 3); + + rtems_test_assert(a1.counter() == gc + 0); + rtems_test_assert(a2.counter() == gc + 1); + rtems_test_assert(a3.counter() == gc + 2); + + clobber(); + f456(true); + f0(true); + C::clobber(); + a1.clobber(); + a2.clobber(); + a3.clobber(); + + rtems_status_code sc = rtems_event_transient_send(masterTask); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_suspend(RTEMS_SELF); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void testTask() +{ + checkTLSValues(); + + rtems_id id; + rtems_status_code sc = rtems_task_create( + rtems_build_name('T', 'A', 'S', 'K'), + RTEMS_MINIMUM_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + const long gc = A::globalCounter(); + + sc = rtems_task_start(id, task, gc); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_delete(id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(A::globalCounter() == gc); + + checkTLSValues(); +} + +extern "C" void Init(rtems_task_argument arg) +{ + puts("\n\n*** TEST SPTLS 2 ***"); + + printf("A::globalCounter() = %li\n", A::globalCounter()); + + checkTLSValues(); + + printf("A::globalCounter() = %li\n", A::globalCounter()); + + masterTask = rtems_task_self(); + + testTask(); + + rtems_resource_snapshot snapshot; + rtems_resource_snapshot_take(&snapshot); + + testTask(); + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); + + puts("*** END OF TEST SPTLS 2 ***"); + + exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 2 +#define CONFIGURE_MAXIMUM_SEMAPHORES 3 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/sptests/sptls02/sptls02.doc b/testsuites/sptests/sptls02/sptls02.doc new file mode 100644 index 0000000000..7c19462166 --- /dev/null +++ b/testsuites/sptests/sptls02/sptls02.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: sptls02 + +directives: + + - None + +concepts: + + - Ensure thread-local storage (TLS) alignment requirements. + - Ensure thread-local storage (TLS) object construction and destruction. diff --git a/testsuites/sptests/sptls02/sptls02.scn b/testsuites/sptests/sptls02/sptls02.scn new file mode 100644 index 0000000000..e4c92f5f36 --- /dev/null +++ b/testsuites/sptests/sptls02/sptls02.scn @@ -0,0 +1,4 @@ +*** TEST SPTLS 2 *** +A::globalCounter() = 0 +A::globalCounter() = 3 +*** END OF TEST SPTLS 2 *** -- cgit v1.2.3