[PATCH v2 1/3] score: Enforce stack and TLS alignment

Kinsey Moore kinsey.moore at oarcorp.com
Tue Mar 2 19:47:45 UTC 2021


Enforce alignment of the stack begin and end by allocating enough stack
area that the desired size can be aligned to CPU_STACK_ALIGNMENT. This
also ensures that the space reserved for TLS data falls on stack
alignment boundaries which satisfies TLS alignment requirements.
---
 cpukit/rtems/src/taskcreate.c       |  5 ++++-
 cpukit/score/src/threadinitialize.c |  8 +++++---
 cpukit/score/src/tlsallocsize.c     | 22 ++++++++++++++--------
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c
index c065a159c6..bad13cb532 100644
--- a/cpukit/rtems/src/taskcreate.c
+++ b/cpukit/rtems/src/taskcreate.c
@@ -53,8 +53,11 @@ static rtems_status_code _RTEMS_tasks_Allocate_and_prepare_stack(
   thread_config->stack_free = _Stack_Free;
   size = _Stack_Ensure_minimum( config->storage_size );
   size = _Stack_Extend_size( size, thread_config->is_fp );
+  size = RTEMS_ALIGN_UP( size, CPU_STACK_ALIGNMENT );
   thread_config->stack_size = size;
-  thread_config->stack_area = _Stack_Allocate( size );
+
+  /* Allocate enough stack space to enforce alignment on use */
+  thread_config->stack_area = _Stack_Allocate( size + CPU_STACK_ALIGNMENT - 1 );
 
   if ( thread_config->stack_area == NULL ) {
     return RTEMS_UNSATISFIED;
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 05c30c3d43..04f62df4de 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -84,7 +84,9 @@ bool _Thread_Initialize(
   }
 #endif
 
-  stack_begin = config->stack_area;
+  /* There is guaranteed to be enough space allocated to enforce alignment */
+  stack_begin = (void * const) RTEMS_ALIGN_UP( (uintptr_t) config->stack_area,
+    CPU_STACK_ALIGNMENT );
   stack_end = stack_begin + config->stack_size;
 
   /* Allocate floating-point context in stack area */
@@ -104,8 +106,8 @@ bool _Thread_Initialize(
 
     stack_end -= tls_size;
     tls_align = (uintptr_t) _TLS_Alignment;
-    the_thread->Start.tls_area = (void *)
-      ( ( (uintptr_t) stack_end + tls_align - 1 ) & ~( tls_align - 1 ) );
+    the_thread->Start.tls_area =
+      (void *)RTEMS_ALIGN_UP( (uintptr_t)stack_end, tls_align );
   }
 
   _Stack_Initialize(
diff --git a/cpukit/score/src/tlsallocsize.c b/cpukit/score/src/tlsallocsize.c
index e7854c677a..0a7ff7d27a 100644
--- a/cpukit/score/src/tlsallocsize.c
+++ b/cpukit/score/src/tlsallocsize.c
@@ -62,23 +62,29 @@ uintptr_t _TLS_Get_allocation_size( void )
     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
 
+    /*
+     * Increase the TLS allocation size to the stack alignment requirements
+     * since it is pulled from the top of the stack allocation. This preserves
+     * the alignment of the top of the stack.
+     */
+    allocation_size = RTEMS_ALIGN_UP( allocation_size, CPU_STACK_ALIGNMENT );
+
     if ( _Thread_Maximum_TLS_size != 0 ) {
       if ( allocation_size <= _Thread_Maximum_TLS_size ) {
         allocation_size = _Thread_Maximum_TLS_size;
+
+        /*
+         * Decrease the TLS allocation size to the stack alignment requirements
+         * since the TLS area has reached maximum size.
+         */
+        allocation_size =
+          RTEMS_ALIGN_DOWN( allocation_size, CPU_STACK_ALIGNMENT );
       } else {
         _Internal_error( INTERNAL_ERROR_TOO_LARGE_TLS_SIZE );
       }
-- 
2.20.1



More information about the devel mailing list