forked from Imagelibrary/rtems
Add thread-local storage (TLS) support
Tested and implemented on ARM, m68k, PowerPC and SPARC. Other architectures need more work.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
19
testsuites/sptests/sptls01/Makefile.am
Normal file
19
testsuites/sptests/sptls01/Makefile.am
Normal file
@@ -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
|
||||
98
testsuites/sptests/sptls01/init.c
Normal file
98
testsuites/sptests/sptls01/init.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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 <rtems/confdefs.h>
|
||||
11
testsuites/sptests/sptls01/sptls01.doc
Normal file
11
testsuites/sptests/sptls01/sptls01.doc
Normal file
@@ -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.
|
||||
5
testsuites/sptests/sptls01/sptls01.scn
Normal file
5
testsuites/sptests/sptls01/sptls01.scn
Normal file
@@ -0,0 +1,5 @@
|
||||
*** TEST SPTLS 1 ***
|
||||
TLS item = 123
|
||||
TLS item = 123
|
||||
TLS item = 5
|
||||
*** END OF TEST SPTLS 1 ***
|
||||
20
testsuites/sptests/sptls02/Makefile.am
Normal file
20
testsuites/sptests/sptls02/Makefile.am
Normal file
@@ -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
|
||||
256
testsuites/sptests/sptls02/init.cc
Normal file
256
testsuites/sptests/sptls02/init.cc
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libcsupport.h>
|
||||
|
||||
#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<long>(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 <rtems/confdefs.h>
|
||||
12
testsuites/sptests/sptls02/sptls02.doc
Normal file
12
testsuites/sptests/sptls02/sptls02.doc
Normal file
@@ -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.
|
||||
4
testsuites/sptests/sptls02/sptls02.scn
Normal file
4
testsuites/sptests/sptls02/sptls02.scn
Normal file
@@ -0,0 +1,4 @@
|
||||
*** TEST SPTLS 2 ***
|
||||
A::globalCounter() = 0
|
||||
A::globalCounter() = 3
|
||||
*** END OF TEST SPTLS 2 ***
|
||||
Reference in New Issue
Block a user