From f4dbf37dd432623c345f8e19f78a4eb01fcedb8b Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 9 Dec 2019 10:12:14 +0100 Subject: score: Simplify TLS area allocation 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 (limited to 'cpukit') diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 9182919558..303c0afe9a 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -1009,6 +1009,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 @@ -1019,6 +1020,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 a356a94118..7fc1cf97de 100644 --- a/cpukit/include/rtems/confdefs.h +++ b/cpukit/include/rtems/confdefs.h @@ -2726,12 +2726,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 fac5c6e009..725f45d140 100644 --- a/cpukit/include/rtems/config.h +++ b/cpukit/include/rtems/config.h @@ -95,11 +95,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. @@ -191,8 +186,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 . */ extern uint32_t rtems_minimum_stack_size; +/** + * @brief The configured stack space size. + * + * Application provided via . + */ +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 #include +#include #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 +#include +#include +#include + +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 + +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 5a87ee4b83..fbdb0b0ba9 100644 --- a/cpukit/score/src/wkspace.c +++ b/cpukit/score/src/wkspace.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -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 ); @@ -97,8 +61,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; unified = rtems_configuration_get_unified_work_area(); overhead = _Heap_Area_overhead( page_size ); -- cgit v1.2.3