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/sptls02/Makefile.am | 20 +++ testsuites/sptests/sptls02/init.cc | 256 +++++++++++++++++++++++++++++++++ testsuites/sptests/sptls02/sptls02.doc | 12 ++ testsuites/sptests/sptls02/sptls02.scn | 4 + 4 files changed, 292 insertions(+) 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/sptls02') 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