Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:27

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreTLS
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _TLS_Get_allocation_size().
0010  */
0011 
0012 /*
0013  * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040 
0041 #include <rtems/score/tls.h>
0042 #include <rtems/score/interr.h>
0043 #include <rtems/score/thread.h>
0044 
0045 extern char _TLS_Data_begin[];
0046 
0047 extern char _TLS_Data_size[];
0048 
0049 extern char _TLS_BSS_begin[];
0050 
0051 extern char _TLS_BSS_size[];
0052 
0053 extern char _TLS_Size[];
0054 
0055 /**
0056  * @brief The TLS section alignment.
0057  *
0058  * This symbol is provided by the linker command file as the maximum alignment
0059  * of the .tdata and .tbss sections.  The linker ensures that the first TLS
0060  * output section is aligned to the maximum alignment of all TLS output
0061  * sections, see function _bfd_elf_tls_setup() in bfd/elflink.c of the GNU
0062  * Binutils sources.  The linker command file must take into account the case
0063  * that the .tdata section is empty and the .tbss section is non-empty.
0064  */
0065 extern char _TLS_Alignment[];
0066 
0067 const volatile TLS_Configuration _TLS_Configuration = {
0068   .data_begin = _TLS_Data_begin,
0069   .data_size = _TLS_Data_size,
0070   .bss_begin = _TLS_BSS_begin,
0071   .bss_size = _TLS_BSS_size,
0072   .size = _TLS_Size,
0073   .alignment = _TLS_Alignment
0074 };
0075 
0076 static uintptr_t _TLS_Allocation_size;
0077 
0078 uintptr_t _TLS_Get_allocation_size( void )
0079 {
0080   const volatile TLS_Configuration *config;
0081   uintptr_t                         size;
0082   uintptr_t                         allocation_size;
0083 
0084   config = &_TLS_Configuration;
0085   size = (uintptr_t) config->size;
0086 
0087   if ( size == 0 ) {
0088     return 0;
0089   }
0090 
0091   allocation_size = _TLS_Allocation_size;
0092 
0093   if ( allocation_size == 0 ) {
0094     uintptr_t tls_align;
0095     uintptr_t stack_align;
0096 
0097     /*
0098      * The TLS area is allocated in the thread storage area.  Each allocation
0099      * shall meet the stack alignment requirement.
0100      */
0101     stack_align = CPU_STACK_ALIGNMENT;
0102     tls_align = RTEMS_ALIGN_UP( (uintptr_t) config->alignment, stack_align );
0103 
0104 #if !defined(__i386__) && !defined(__x86_64__)
0105     /* Reserve space for the dynamic thread vector */
0106     allocation_size +=
0107       RTEMS_ALIGN_UP( sizeof( TLS_Dynamic_thread_vector ), stack_align );
0108 #endif
0109 
0110     /* Reserve space for the thread control block */
0111     allocation_size +=
0112 #if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
0113       RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), tls_align );
0114 #else
0115       RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), stack_align );
0116 #endif
0117 
0118     /* Reserve space for the thread-local storage data */
0119     allocation_size +=
0120 #if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20
0121       RTEMS_ALIGN_UP( size, tls_align );
0122 #else
0123       RTEMS_ALIGN_UP( size, stack_align );
0124 #endif
0125 
0126     /*
0127      * The stack allocator does not support aligned allocations.  Allocate
0128      * enough to do the alignment manually.
0129      */
0130     if ( tls_align > stack_align ) {
0131       _Assert( tls_align % stack_align == 0 );
0132       allocation_size += tls_align - stack_align;
0133     }
0134 
0135     if ( _Thread_Maximum_TLS_size != 0 ) {
0136       if ( allocation_size <= _Thread_Maximum_TLS_size ) {
0137         _Assert( _Thread_Maximum_TLS_size % CPU_STACK_ALIGNMENT == 0 );
0138         allocation_size = _Thread_Maximum_TLS_size;
0139       } else {
0140         _Internal_error( INTERNAL_ERROR_TOO_LARGE_TLS_SIZE );
0141       }
0142     }
0143 
0144     _TLS_Allocation_size = allocation_size;
0145   }
0146 
0147   return allocation_size;
0148 }