[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