From 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 27 Sep 2022 07:43:37 +0200 Subject: score: Add CPU_THREAD_LOCAL_STORAGE_VARIANT Update #3835. --- cpukit/include/rtems/score/tls.h | 204 ++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 119 deletions(-) (limited to 'cpukit/include/rtems') diff --git a/cpukit/include/rtems/score/tls.h b/cpukit/include/rtems/score/tls.h index ee4fb9a22e..9c90b6362b 100644 --- a/cpukit/include/rtems/score/tls.h +++ b/cpukit/include/rtems/score/tls.h @@ -10,7 +10,7 @@ */ /* - * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * Copyright (C) 2014, 2022 embedded brains GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,7 @@ #ifndef _RTEMS_SCORE_TLS_H #define _RTEMS_SCORE_TLS_H -#include +#include #include @@ -116,9 +116,9 @@ typedef struct { } TLS_Index; /** - * @brief Gets the TLS size. + * @brief Gets the size of the thread-local storage data in bytes. * - * @return The TLS size. + * @return Returns the size of the thread-local storage data in bytes. */ static inline uintptr_t _TLS_Get_size( void ) { @@ -135,82 +135,64 @@ static inline uintptr_t _TLS_Get_size( void ) } /** - * @brief Returns the value aligned up to the stack alignment. + * @brief Gets the size of the thread control block area in bytes. * - * @param val The value to align. - * - * @return The value aligned to the stack alignment. + * @return Returns the size of the thread control block area in bytes. */ -static inline uintptr_t _TLS_Align_up( uintptr_t val ) +static inline uintptr_t _TLS_Get_thread_control_block_area_size( void ) { - uintptr_t alignment = CPU_STACK_ALIGNMENT; +#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11 + uintptr_t alignment; - return RTEMS_ALIGN_UP( val, alignment ); -} + alignment = (uintptr_t) _TLS_Alignment; -/** - * @brief Returns the size of the thread control block area size for this - * alignment, or the minimum size if alignment is too small. - * - * @param alignment The alignment for the operation. - * - * @return The size of the thread control block area. - */ -static inline uintptr_t _TLS_Get_thread_control_block_area_size( - uintptr_t alignment -) -{ - return alignment <= sizeof(TLS_Thread_control_block) ? - sizeof(TLS_Thread_control_block) : alignment; + return RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), alignment ); +#else + return sizeof( TLS_Thread_control_block ); +#endif } /** - * @brief Return the TLS area allocation size. + * @brief Gets the allocation size of the thread-local storage area in bytes. * - * @return The TLS area allocation size. + * @return Returns the allocation size of the thread-local storage area in + * bytes. */ uintptr_t _TLS_Get_allocation_size( void ); /** - * @brief Copies TLS size bytes from the address tls_area and returns a pointer - * to the start of the area after clearing it. - * - * @param tls_area The starting address of the area to clear. + * @brief Initializes the thread-local storage data. * - * @return The pointer to the beginning of the cleared section. + * @param[out] tls_data is the thread-local storage data to initialize. */ -static inline void *_TLS_Copy_and_clear( void *tls_area ) +static inline void _TLS_Copy_and_clear( void *tls_data ) { - tls_area = memcpy( - tls_area, + tls_data = memcpy( + tls_data, _TLS_Data_begin, (size_t) ((uintptr_t)_TLS_Data_size) ); - memset( - (char *) tls_area + (size_t)((intptr_t) _TLS_BSS_begin) - + (char *) tls_data + (size_t)((intptr_t) _TLS_BSS_begin) - (size_t)((intptr_t) _TLS_Data_begin), 0, ((size_t) (intptr_t)_TLS_BSS_size) ); - - return tls_area; } /** - * @brief Initializes the dynamic thread vector. + * @brief Initializes the thread control block and the dynamic thread vector. + * + * @param tls_data is the thread-local storage data address. * - * @param tls_block The tls block for @a dtv. - * @param tcb The thread control block for @a dtv. - * @param[out] dtv The dynamic thread vector to initialize. + * @param[out] tcb is the thread control block to initialize. * - * @return Pointer to an area that was copied and cleared from tls_block - * onwards (@see _TLS_Copy_and_clear). + * @param[out] dtv is the dynamic thread vector to initialize. */ -static inline void *_TLS_Initialize( - void *tls_block, - TLS_Thread_control_block *tcb, +static inline void _TLS_Initialize_TCB_and_DTV( + void *tls_data, + TLS_Thread_control_block *tcb, TLS_Dynamic_thread_vector *dtv ) { @@ -220,86 +202,70 @@ static inline void *_TLS_Initialize( #else tcb->dtv = dtv; dtv->generation_number = 1; - dtv->tls_blocks[0] = tls_block; + dtv->tls_blocks[0] = tls_data; #endif - - return _TLS_Copy_and_clear( tls_block ); } /** - * @brief Initializes a dynamic thread vector beginning at the given starting - * address. - * - * Use Variant I, TLS offsets emitted by linker takes the TCB into account. + * @brief Initializes the thread-local storage area. * - * @param tls_area The tls area for the initialization. + * @param tls_area[out] is the thread-local storage area to initialize. * - * @return Pointer to an area that was copied and cleared from tls_block - * onwards (@see _TLS_Copy_and_clear). + * @return Where the architectures uses Variant I and the TLS offsets emitted + * by the linker neglect the TCB, returns the address of the thread-local + * storage data. Otherwise, returns the address of the thread control block. */ -static inline void *_TLS_TCB_at_area_begin_initialize( void *tls_area ) +static inline void *_TLS_Initialize_area( void *tls_area ) { - void *tls_block = (char *) tls_area - + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment ); - TLS_Thread_control_block *tcb = (TLS_Thread_control_block *) tls_area; - uintptr_t aligned_size = _TLS_Align_up( (uintptr_t) _TLS_Size ); - TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *) - ((char *) tls_block + aligned_size); - - return _TLS_Initialize( tls_block, tcb, dtv ); -} + uintptr_t alignment; + void *tls_data; + TLS_Thread_control_block *tcb; + TLS_Dynamic_thread_vector *dtv; + void *return_value; +#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11 + uintptr_t tcb_size; +#endif +#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20 + uintptr_t size; + uintptr_t alignment_2; +#endif -/** - * @brief Initializes a dynamic thread vector with the area before a given - * starting address as thread control block. - * - * Use Variant I, TLS offsets emitted by linker neglects the TCB. - * - * @param tls_area The tls area for the initialization. - * - * @return Pointer to an area that was copied and cleared from tls_block - * onwards (@see _TLS_Copy_and_clear). - */ -static inline void *_TLS_TCB_before_TLS_block_initialize( void *tls_area ) -{ - void *tls_block = (char *) tls_area - + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment ); - TLS_Thread_control_block *tcb = (TLS_Thread_control_block *) - ((char *) tls_block - sizeof(*tcb)); - uintptr_t aligned_size = _TLS_Align_up( (uintptr_t) _TLS_Size ); - TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *) - ((char *) tls_block + aligned_size); - - return _TLS_Initialize( tls_block, tcb, dtv ); -} + alignment = (uintptr_t) _TLS_Alignment; -/** - * @brief Initializes a dynamic thread vector with the area after a given - * starting address as thread control block. - * - * Use Variant II - * - * @param tls_area The tls area for the initialization. - * - * @return Pointer to an area that was copied and cleared from tls_block - * onwards (@see _TLS_Copy_and_clear). - */ -static inline void *_TLS_TCB_after_TLS_block_initialize( void *tls_area ) -{ - uintptr_t size = (uintptr_t) _TLS_Size; - uintptr_t tls_align = (uintptr_t) _TLS_Alignment; - uintptr_t tls_mask = tls_align - 1; - uintptr_t heap_align = _TLS_Align_up( tls_align ); - uintptr_t heap_mask = heap_align - 1; - TLS_Thread_control_block *tcb = (TLS_Thread_control_block *) - ((char *) tls_area + ((size + heap_mask) & ~heap_mask)); - void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask); - TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *) - ((char *) tcb + sizeof(*tcb)); - - _TLS_Initialize( tls_block, tcb, dtv ); - - return tcb; +#ifdef __i386__ + dtv = NULL; +#else + dtv = (TLS_Dynamic_thread_vector *) tls_area; + tls_area = (char *) tls_area + sizeof( *dtv ); +#endif + +#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 10 + tls_data = (void *) + RTEMS_ALIGN_UP( (uintptr_t) tls_area + sizeof( *tcb ), alignment ); + tcb = (TLS_Thread_control_block *) ((char *) tls_data - sizeof( *tcb )); + return_value = tls_data; +#elif CPU_THREAD_LOCAL_STORAGE_VARIANT == 11 + tcb_size = RTEMS_ALIGN_UP( sizeof( *tcb ), alignment ); + tls_data = (void *) + RTEMS_ALIGN_UP( (uintptr_t) tls_area + tcb_size, alignment ); + tcb = (TLS_Thread_control_block *) ((char *) tls_data - tcb_size); + return_value = tcb; +#elif CPU_THREAD_LOCAL_STORAGE_VARIANT == 20 + alignment_2 = RTEMS_ALIGN_UP( alignment, CPU_SIZEOF_POINTER ); + tls_area = (void *) RTEMS_ALIGN_UP( (uintptr_t) tls_area, alignment_2 ); + size = _TLS_Get_size(); + tcb = (TLS_Thread_control_block *) + ((char *) tls_area + RTEMS_ALIGN_UP( size, alignment_2 )); + tls_data = (char *) tcb - RTEMS_ALIGN_UP( size, alignment ); + return_value = tcb; +#else +#error "unexpected CPU_THREAD_LOCAL_STORAGE_VARIANT value" +#endif + + _TLS_Initialize_TCB_and_DTV( tls_data, tcb, dtv ); + _TLS_Copy_and_clear( tls_data ); + + return return_value; } /** @} */ -- cgit v1.2.3