[PATCH 06/21] score: Simplify TLS area allocation
Sebastian Huber
sebastian.huber at embedded-brains.de
Mon Dec 16 14:28:11 UTC 2019
Use the stack area to allocate the TLS area.
Update #3835.
---
cpukit/Makefile.am | 2 +
cpukit/include/rtems/confdefs.h | 3 +-
cpukit/include/rtems/config.h | 8 +---
cpukit/include/rtems/score/stack.h | 11 ++++-
cpukit/include/rtems/score/stackimpl.h | 4 +-
cpukit/include/rtems/score/tls.h | 25 ++----------
cpukit/score/src/configstackspacesize.c | 54 +++++++++++++++++++++++++
cpukit/score/src/threadinitialize.c | 30 +++++++-------
cpukit/score/src/threadrestart.c | 2 -
cpukit/score/src/tlsallocsize.c | 72 +++++++++++++++++++++++++++++++++
cpukit/score/src/wkspace.c | 38 -----------------
11 files changed, 161 insertions(+), 88 deletions(-)
create mode 100644 cpukit/score/src/configstackspacesize.c
create mode 100644 cpukit/score/src/tlsallocsize.c
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 62c34c9c00..3ced5bdd4d 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1006,6 +1006,7 @@ librtemscpu_a_SOURCES += score/src/ioprintf.c
librtemscpu_a_SOURCES += score/src/iovprintf.c
librtemscpu_a_SOURCES += score/src/isrisinprogress.c
librtemscpu_a_SOURCES += score/src/condition.c
+librtemscpu_a_SOURCES += score/src/configstackspacesize.c
librtemscpu_a_SOURCES += score/src/futex.c
librtemscpu_a_SOURCES += score/src/profilingisrentryexit.c
librtemscpu_a_SOURCES += score/src/mutex.c
@@ -1016,6 +1017,7 @@ librtemscpu_a_SOURCES += score/src/smpbarrierwait.c
librtemscpu_a_SOURCES += score/src/kern_tc.c
librtemscpu_a_SOURCES += score/src/libatomic.c
librtemscpu_a_SOURCES += score/src/processormaskcopy.c
+librtemscpu_a_SOURCES += score/src/tlsallocsize.c
librtemscpu_a_SOURCES += sapi/src/chainappendnotify.c
librtemscpu_a_SOURCES += sapi/src/chaingetnotify.c
librtemscpu_a_SOURCES += sapi/src/chaingetwait.c
diff --git a/cpukit/include/rtems/confdefs.h b/cpukit/include/rtems/confdefs.h
index 186ab0f39e..069666abda 100644
--- a/cpukit/include/rtems/confdefs.h
+++ b/cpukit/include/rtems/confdefs.h
@@ -2791,12 +2791,13 @@ struct _reent *__getreent(void)
uint32_t rtems_minimum_stack_size =
CONFIGURE_MINIMUM_TASK_STACK_SIZE;
+ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
+
/**
* This is the primary Configuration Table for this application.
*/
const rtems_configuration_table Configuration = {
CONFIGURE_EXECUTIVE_RAM_SIZE, /* required RTEMS workspace */
- _CONFIGURE_STACK_SPACE_SIZE, /* required stack space */
CONFIGURE_MAXIMUM_USER_EXTENSIONS, /* maximum dynamic extensions */
CONFIGURE_MICROSECONDS_PER_TICK, /* microseconds per clock tick */
CONFIGURE_TICKS_PER_TIMESLICE, /* ticks per timeslice quantum */
diff --git a/cpukit/include/rtems/config.h b/cpukit/include/rtems/config.h
index 15e944dd2f..6e3fa39a5f 100644
--- a/cpukit/include/rtems/config.h
+++ b/cpukit/include/rtems/config.h
@@ -94,11 +94,6 @@ typedef struct {
*/
uintptr_t work_space_size;
- /**
- * This field specifies the size in bytes of the RTEMS thread stack space.
- */
- uintptr_t stack_space_size;
-
/**
* This field contains the maximum number of POSIX API
* key value pairs which are configured for this application.
@@ -198,8 +193,7 @@ extern const rtems_configuration_table Configuration;
#define rtems_configuration_get_stack_allocator_avoids_work_space() \
(Configuration.stack_allocator_avoids_work_space)
-#define rtems_configuration_get_stack_space_size() \
- (Configuration.stack_space_size)
+uintptr_t rtems_configuration_get_stack_space_size( void );
#define rtems_configuration_get_work_space_size() \
(Configuration.work_space_size + \
diff --git a/cpukit/include/rtems/score/stack.h b/cpukit/include/rtems/score/stack.h
index 1158f3472e..2ad362abd2 100644
--- a/cpukit/include/rtems/score/stack.h
+++ b/cpukit/include/rtems/score/stack.h
@@ -58,12 +58,19 @@ typedef struct {
} Stack_Control;
/**
- * This variable contains the the minimum stack size;
+ * @brief The minimum stack size.
*
- * @note It is instantiated and set by User Configuration via confdefs.h.
+ * Application provided via <rtems/confdefs.h>.
*/
extern uint32_t rtems_minimum_stack_size;
+/**
+ * @brief The configured stack space size.
+ *
+ * Application provided via <rtems/confdefs.h>.
+ */
+extern const uintptr_t _Stack_Space_size;
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/include/rtems/score/stackimpl.h b/cpukit/include/rtems/score/stackimpl.h
index 60704534c7..aafde5d1a0 100644
--- a/cpukit/include/rtems/score/stackimpl.h
+++ b/cpukit/include/rtems/score/stackimpl.h
@@ -23,6 +23,7 @@
#include <rtems/score/stack.h>
#include <rtems/score/context.h>
+#include <rtems/score/tls.h>
#ifdef __cplusplus
extern "C" {
@@ -87,7 +88,8 @@ RTEMS_INLINE_ROUTINE bool _Stack_Is_enough(
{
size_t minimum;
- minimum = _Stack_Minimum();
+ minimum = _TLS_Get_allocation_size();
+ minimum += _Stack_Minimum();
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
if ( is_fp ) {
diff --git a/cpukit/include/rtems/score/tls.h b/cpukit/include/rtems/score/tls.h
index dadcb770ad..1b9dae11b1 100644
--- a/cpukit/include/rtems/score/tls.h
+++ b/cpukit/include/rtems/score/tls.h
@@ -134,30 +134,11 @@ static inline uintptr_t _TLS_Get_thread_control_block_area_size(
}
/**
- * @brief Returns the actual size that has to be allocated for this size and
- * alignment.
+ * @brief Return the TLS area allocation size.
*
- * @param size The size for the operation.
- * @param alignment The alignment for the operation.
- *
- * @return The actual allocation size.
+ * @return The TLS area allocation size.
*/
-static inline uintptr_t _TLS_Get_allocation_size(
- uintptr_t size,
- uintptr_t alignment
-)
-{
- uintptr_t allocation_size = 0;
-
- allocation_size += _TLS_Heap_align_up( size );
- allocation_size += _TLS_Get_thread_control_block_area_size( alignment );
-
-#ifndef __i386__
- allocation_size += sizeof(TLS_Dynamic_thread_vector);
-#endif
-
- return allocation_size;
-}
+uintptr_t _TLS_Get_allocation_size( void );
/**
* @brief Copies TLS size bytes from the address tls_area and returns a pointer
diff --git a/cpukit/score/src/configstackspacesize.c b/cpukit/score/src/configstackspacesize.c
new file mode 100644
index 0000000000..4f0c24cee6
--- /dev/null
+++ b/cpukit/score/src/configstackspacesize.c
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2014, 2019 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/config.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/tls.h>
+#include <rtems/score/thread.h>
+
+uintptr_t rtems_configuration_get_stack_space_size( void )
+{
+ uintptr_t space_size;
+
+ space_size = _Stack_Space_size;
+
+ /*
+ * In case we have a non-zero TLS size, then we need a TLS area for each
+ * thread. These areas are allocated within the stack area from the stack
+ * space. Ensure that the stack space is large enough to fulfill all requests
+ * known at configuration time (so excluding the unlimited option). It is not
+ * possible to estimate the TLS size in the configuration at compile-time.
+ * The TLS size is determined at application link-time.
+ */
+ space_size += _Thread_Initial_thread_count * _TLS_Get_allocation_size();
+
+ return space_size;
+}
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 48444824b2..a1bc3b2939 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -42,7 +42,7 @@ bool _Thread_Initialize(
Objects_Name name
)
{
- uintptr_t tls_size = _TLS_Get_size();
+ uintptr_t tls_size;
bool extension_status;
size_t i;
Scheduler_Node *scheduler_node;
@@ -83,6 +83,8 @@ bool _Thread_Initialize(
(char *) the_thread + add_on->source_offset;
}
+ tls_size = _TLS_Get_allocation_size();
+
/* Allocate the stack for this thread */
#if defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
if ( stack_area == NULL ) {
@@ -95,6 +97,7 @@ bool _Thread_Initialize(
}
#endif
+ stack_size += tls_size;
stack_area = _Stack_Allocate( stack_size );
if ( stack_area == NULL ) {
@@ -116,6 +119,17 @@ bool _Thread_Initialize(
}
#endif
+ /* Allocate thread-local storage (TLS) area in stack area */
+ if ( tls_size > 0 ) {
+ uintptr_t tls_align;
+
+ tls_align = (uintptr_t) _TLS_Alignment;
+ the_thread->Start.tls_area = (void *)
+ ( ( (uintptr_t) stack_area + tls_align - 1 ) & ~( tls_align - 1 ) );
+ stack_size -= tls_size;
+ stack_area = (char *) stack_area + tls_size;
+ }
+
_Stack_Initialize(
&the_thread->Start.Initial_stack,
stack_area,
@@ -124,19 +138,6 @@ bool _Thread_Initialize(
scheduler_index = 0;
- /* Thread-local storage (TLS) area allocation */
- if ( tls_size > 0 ) {
- uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
- uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
-
- the_thread->Start.tls_area =
- _Workspace_Allocate_aligned( tls_alloc, tls_align );
-
- if ( the_thread->Start.tls_area == NULL ) {
- goto failed;
- }
- }
-
/*
* Get thread queue heads
*/
@@ -301,7 +302,6 @@ failed:
}
#endif
- _Workspace_Free( the_thread->Start.tls_area );
_Freechain_Put(
&information->Thread_queue_heads.Free,
the_thread->Wait.spare_heads
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index aa47fefd1f..0c6890324c 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -185,8 +185,6 @@ static void _Thread_Free( Thread_Control *the_thread )
*/
_Stack_Free( the_thread->Start.allocated_stack );
- _Workspace_Free( the_thread->Start.tls_area );
-
#if defined(RTEMS_SMP)
_ISR_lock_Destroy( &the_thread->Scheduler.Lock );
_ISR_lock_Destroy( &the_thread->Wait.Lock.Default );
diff --git a/cpukit/score/src/tlsallocsize.c b/cpukit/score/src/tlsallocsize.c
new file mode 100644
index 0000000000..046579814a
--- /dev/null
+++ b/cpukit/score/src/tlsallocsize.c
@@ -0,0 +1,72 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2014, 2019 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/tls.h>
+
+static uintptr_t _TLS_Allocation_size;
+
+uintptr_t _TLS_Get_allocation_size( void )
+{
+ uintptr_t size;
+ uintptr_t allocation_size;
+ uintptr_t alignment;
+
+ size = _TLS_Get_size();
+
+ if ( size == 0 ) {
+ return 0;
+ }
+
+ allocation_size = _TLS_Allocation_size;
+
+ if ( allocation_size == 0 ) {
+ allocation_size = _TLS_Heap_align_up( size );
+ alignment = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
+
+ /*
+ * The stack allocator does not support aligned allocations. Allocate
+ * enough to do the alignment manually.
+ */
+ if ( alignment > CPU_HEAP_ALIGNMENT ) {
+ allocation_size += alignment;
+ }
+
+ allocation_size += _TLS_Get_thread_control_block_area_size( alignment );
+
+#ifndef __i386__
+ allocation_size += sizeof(TLS_Dynamic_thread_vector);
+#endif
+
+ _TLS_Allocation_size = allocation_size;
+ }
+
+ return allocation_size;
+}
diff --git a/cpukit/score/src/wkspace.c b/cpukit/score/src/wkspace.c
index 41c6cd3059..37445ff843 100644
--- a/cpukit/score/src/wkspace.c
+++ b/cpukit/score/src/wkspace.c
@@ -23,7 +23,6 @@
#include <rtems/score/heapimpl.h>
#include <rtems/score/interr.h>
#include <rtems/score/threadimpl.h>
-#include <rtems/score/tls.h>
#include <rtems/posix/pthread.h>
#include <rtems/config.h>
#include <rtems/sysinit.h>
@@ -37,41 +36,6 @@
Heap_Control _Workspace_Area;
-static uintptr_t _Workspace_Space_for_TLS( uintptr_t page_size )
-{
- uintptr_t tls_size;
- uintptr_t space;
-
- tls_size = _TLS_Get_size();
-
- /*
- * In case we have a non-zero TLS size, then we need a TLS area for each
- * thread. These areas are allocated from the workspace. Ensure that the
- * workspace is large enough to fulfill all requests known at configuration
- * time (so excluding the unlimited option). It is not possible to estimate
- * the TLS size in the configuration at compile-time. The TLS size is
- * determined at application link-time.
- */
- if ( tls_size > 0 ) {
- uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
- uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
-
- /*
- * Memory allocated with an alignment constraint is allocated from the end
- * of a free block. The last allocation may need one free block of minimum
- * size.
- */
- space = _Heap_Min_block_size( page_size );
-
- space += _Thread_Initial_thread_count
- * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
- } else {
- space = 0;
- }
-
- return space;
-}
-
static void _Workspace_Initialize( void )
{
_Workspace_Handler_initialization( _Memory_Get(), _Heap_Extend );
@@ -98,8 +62,6 @@ void _Workspace_Handler_initialization(
page_size = CPU_HEAP_ALIGNMENT;
remaining = rtems_configuration_get_work_space_size();
- remaining += _Workspace_Space_for_TLS( page_size );
-
init_or_extend = _Heap_Initialize;
do_zero = rtems_configuration_get_do_zero_of_workspace();
unified = rtems_configuration_get_unified_work_area();
--
2.16.4
More information about the devel
mailing list