score: Add CPU_THREAD_LOCAL_STORAGE_VARIANT

Update #3835.
This commit is contained in:
Sebastian Huber
2022-09-27 07:43:37 +02:00
parent 15bba4aecf
commit 4c89fbcd31
40 changed files with 213 additions and 188 deletions

View File

@@ -130,7 +130,7 @@ void _CPU_Context_Initialize(
#endif #endif
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
void *tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area ); void *tls_block = _TLS_Initialize_area( tls_area );
the_ppc_context->tp = (uintptr_t) tls_block + 0x7000; the_ppc_context->tp = (uintptr_t) tls_block + 0x7000;
} }

View File

@@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -37,7 +37,7 @@
#ifndef _RTEMS_SCORE_TLS_H #ifndef _RTEMS_SCORE_TLS_H
#define _RTEMS_SCORE_TLS_H #define _RTEMS_SCORE_TLS_H
#include <rtems/score/cpu.h> #include <rtems/score/cpuimpl.h>
#include <string.h> #include <string.h>
@@ -116,9 +116,9 @@ typedef struct {
} TLS_Index; } 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 ) 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 Returns the size of the thread control block area in bytes.
*
* @return The value aligned to the stack alignment.
*/ */
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;
return RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), alignment );
#else
return sizeof( TLS_Thread_control_block );
#endif
} }
/** /**
* @brief Returns the size of the thread control block area size for this * @brief Gets the allocation size of the thread-local storage area in bytes.
* alignment, or the minimum size if alignment is too small.
* *
* @param alignment The alignment for the operation. * @return Returns the allocation size of the thread-local storage area in
* * bytes.
* @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;
}
/**
* @brief Return the TLS area allocation size.
*
* @return The TLS area allocation size.
*/ */
uintptr_t _TLS_Get_allocation_size( void ); uintptr_t _TLS_Get_allocation_size( void );
/** /**
* @brief Copies TLS size bytes from the address tls_area and returns a pointer * @brief Initializes the thread-local storage data.
* to the start of the area after clearing it.
* *
* @param tls_area The starting address of the area to clear. * @param[out] tls_data is the thread-local storage data to initialize.
*
* @return The pointer to the beginning of the cleared section.
*/ */
static inline void *_TLS_Copy_and_clear( void *tls_area ) static inline void _TLS_Copy_and_clear( void *tls_data )
{ {
tls_area = memcpy( tls_data = memcpy(
tls_area, tls_data,
_TLS_Data_begin, _TLS_Data_begin,
(size_t) ((uintptr_t)_TLS_Data_size) (size_t) ((uintptr_t)_TLS_Data_size)
); );
memset( 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), (size_t)((intptr_t) _TLS_Data_begin),
0, 0,
((size_t) (intptr_t)_TLS_BSS_size) ((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_block The tls block for @a dtv. * @param tls_data is the thread-local storage data address.
* @param tcb The thread control block for @a dtv.
* @param[out] dtv The dynamic thread vector to initialize.
* *
* @return Pointer to an area that was copied and cleared from tls_block * @param[out] tcb is the thread control block to initialize.
* onwards (@see _TLS_Copy_and_clear). *
* @param[out] dtv is the dynamic thread vector to initialize.
*/ */
static inline void *_TLS_Initialize( static inline void _TLS_Initialize_TCB_and_DTV(
void *tls_block, void *tls_data,
TLS_Thread_control_block *tcb, TLS_Thread_control_block *tcb,
TLS_Dynamic_thread_vector *dtv TLS_Dynamic_thread_vector *dtv
) )
{ {
@@ -220,86 +202,70 @@ static inline void *_TLS_Initialize(
#else #else
tcb->dtv = dtv; tcb->dtv = dtv;
dtv->generation_number = 1; dtv->generation_number = 1;
dtv->tls_blocks[0] = tls_block; dtv->tls_blocks[0] = tls_data;
#endif
}
/**
* @brief Initializes the thread-local storage area.
*
* @param tls_area[out] is the thread-local storage area to initialize.
*
* @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_Initialize_area( void *tls_area )
{
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 #endif
return _TLS_Copy_and_clear( tls_block ); alignment = (uintptr_t) _TLS_Alignment;
}
/** #ifdef __i386__
* @brief Initializes a dynamic thread vector beginning at the given starting dtv = NULL;
* address. #else
* dtv = (TLS_Dynamic_thread_vector *) tls_area;
* Use Variant I, TLS offsets emitted by linker takes the TCB into account. tls_area = (char *) tls_area + sizeof( *dtv );
* #endif
* @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_at_area_begin_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 *) 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 ); #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 );
* @brief Initializes a dynamic thread vector with the area before a given _TLS_Copy_and_clear( tls_data );
* 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 ); return return_value;
}
/**
* @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;
} }
/** @} */ /** @} */

View File

@@ -142,7 +142,7 @@ void _CPU_Context_Initialize(
the_context->thread_id = (uintptr_t) tls_area; the_context->thread_id = (uintptr_t) tls_area;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
_TLS_TCB_at_area_begin_initialize( tls_area ); the_context->thread_id = (uintptr_t) _TLS_Initialize_area( tls_area );
} }
} }

View File

@@ -50,8 +50,11 @@
*/ */
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_INTERRUPT_FRAME_SIZE 0x2E0 #define CPU_INTERRUPT_FRAME_SIZE 0x2E0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 11
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -42,15 +42,15 @@ void __attribute__((naked)) __aeabi_read_tp(void)
"ldr r0, =_Per_CPU_Information\n" "ldr r0, =_Per_CPU_Information\n"
"ldr r0, [r0, %[executingoff]]\n" "ldr r0, [r0, %[executingoff]]\n"
#if defined(__thumb__) && !defined(__thumb2__) #if defined(__thumb__) && !defined(__thumb2__)
"add r0, %[tlsareaoff]\n" "add r0, %[threadidoff]\n"
"ldr r0, [r0]\n" "ldr r0, [r0]\n"
#else #else
"ldr r0, [r0, %[tlsareaoff]]\n" "ldr r0, [r0, %[threadidoff]]\n"
#endif #endif
"bx lr\n" "bx lr\n"
: :
: [executingoff] "I" (offsetof(Per_CPU_Control, executing)), : [executingoff] "I" (offsetof(Per_CPU_Control, executing)),
[tlsareaoff] "I" (offsetof(Thread_Control, Start.tls_area)) [threadidoff] "I" (offsetof(Thread_Control, Registers.thread_id))
); );
} }

View File

@@ -39,10 +39,10 @@ void *__tls_get_addr(const TLS_Index *ti);
void *__tls_get_addr(const TLS_Index *ti) void *__tls_get_addr(const TLS_Index *ti)
{ {
const Thread_Control *executing = _Thread_Get_executing(); const Thread_Control *executing = _Thread_Get_executing();
void *tls_block = (char *) executing->Start.tls_area void *tls_data = (char *) executing->Registers.thread_id
+ _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment ); + _TLS_Get_thread_control_block_area_size();
assert(ti->module == 1); assert(ti->module == 1);
return (char *) tls_block + ti->offset; return (char *) tls_data + ti->offset;
} }

View File

@@ -61,7 +61,7 @@ void _CPU_Context_Initialize(
context->register_sp = stack_area_end; context->register_sp = stack_area_end;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
_TLS_TCB_at_area_begin_initialize( tls_area ); _TLS_Initialize_area( tls_area );
} }
} }

View File

@@ -56,13 +56,11 @@
); );
#endif #endif
#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER RTEMS_STATIC_ASSERT(
RTEMS_STATIC_ASSERT( offsetof( Context_Control, thread_id )
offsetof( Context_Control, thread_id ) == ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET,
== ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET, ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET
ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET );
);
#endif
#ifdef ARM_MULTILIB_ARCH_V4 #ifdef ARM_MULTILIB_ARCH_V4
RTEMS_STATIC_ASSERT( RTEMS_STATIC_ASSERT(
@@ -118,13 +116,10 @@ void _CPU_Context_Initialize(
the_context->register_sp = (uint32_t) stack_area_begin + stack_area_size; the_context->register_sp = (uint32_t) stack_area_begin + stack_area_size;
the_context->register_lr = (uint32_t) entry_point; the_context->register_lr = (uint32_t) entry_point;
the_context->isr_dispatch_disable = 0; the_context->isr_dispatch_disable = 0;
#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
the_context->thread_id = (uint32_t) tls_area; the_context->thread_id = (uint32_t) tls_area;
#endif
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
_TLS_TCB_at_area_begin_initialize( tls_area ); the_context->thread_id = (uint32_t) _TLS_Initialize_area( tls_area );
} }
} }

View File

@@ -176,9 +176,7 @@
#define CPU_MAXIMUM_PROCESSORS 32 #define CPU_MAXIMUM_PROCESSORS 32
#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER #define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
#define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
#endif
#ifdef ARM_MULTILIB_VFP #ifdef ARM_MULTILIB_VFP
#define ARM_CONTEXT_CONTROL_D8_OFFSET 48 #define ARM_CONTEXT_CONTROL_D8_OFFSET 48
@@ -191,10 +189,8 @@
#ifdef RTEMS_SMP #ifdef RTEMS_SMP
#if defined(ARM_MULTILIB_VFP) #if defined(ARM_MULTILIB_VFP)
#define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 112 #define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 112
#elif defined(ARM_MULTILIB_HAS_THREAD_ID_REGISTER)
#define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 48
#else #else
#define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 44 #define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 48
#endif #endif
#endif #endif
@@ -240,9 +236,7 @@ typedef struct {
#else #else
void *register_sp; void *register_sp;
#endif #endif
#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
uint32_t thread_id; uint32_t thread_id;
#endif
#ifdef ARM_MULTILIB_VFP #ifdef ARM_MULTILIB_VFP
uint64_t register_d8; uint64_t register_d8;
uint64_t register_d9; uint64_t register_d9;

View File

@@ -60,6 +60,8 @@
#endif /* ARM_MULTILIB_ARCH_V4 */ #endif /* ARM_MULTILIB_ARCH_V4 */
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 11
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -29,6 +29,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -193,7 +193,7 @@ void _CPU_Context_Initialize(
the_context->esp = (void *) _stack; the_context->esp = (void *) _stack;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
tcb = (uint32_t) _TLS_TCB_after_TLS_block_initialize( tls_area ); tcb = (uint32_t) _TLS_Initialize_area( tls_area );
} else { } else {
tcb = 0; tcb = 0;
} }

View File

@@ -50,6 +50,8 @@
#define CPU_INTERRUPT_FRAME_SIZE 52 #define CPU_INTERRUPT_FRAME_SIZE 52
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -28,6 +28,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -37,9 +37,7 @@ void __m68k_read_tp(void);
void __m68k_read_tp(void) void __m68k_read_tp(void)
{ {
const Thread_Control *executing = _Thread_Get_executing(); const Thread_Control *executing = _Thread_Get_executing();
void *tp = (char *) executing->Start.tls_area + void *tp = executing->Registers.thread_pointer;
_TLS_Get_thread_control_block_area_size((uintptr_t) _TLS_Alignment)
+ 0x7000;
__asm__ volatile ( __asm__ volatile (
"move.l %0, %%a0" "move.l %0, %%a0"

View File

@@ -279,6 +279,9 @@ void _CPU_Context_Initialize(
#endif #endif
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
_TLS_TCB_before_TLS_block_initialize( tls_area ); the_context->thread_pointer =
(char *) _TLS_Initialize_area( tls_area ) + 0x7000;
} else {
the_context->thread_pointer = NULL;
} }
} }

View File

@@ -145,6 +145,7 @@ typedef struct {
#if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 ) #if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
uint8_t fpu_dis; uint8_t fpu_dis;
#endif #endif
void *thread_pointer;
} Context_Control; } Context_Control;
#define _CPU_Context_Get_SP( _context ) \ #define _CPU_Context_Get_SP( _context ) \

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -46,9 +46,11 @@ void *__tls_get_addr( const TLS_Index *ti );
void *__tls_get_addr( const TLS_Index *ti ) void *__tls_get_addr( const TLS_Index *ti )
{ {
const Thread_Control *executing = _Thread_Get_executing(); const Thread_Control *executing;
void *tls_block = (char *) executing->Start.tls_area
+ _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
return (char *) tls_block + ti->offset; (void) ti;
executing = _Thread_Get_executing();
return executing->Registers.thread_pointer;
} }

View File

@@ -73,7 +73,7 @@ void _CPU_Context_Initialize(
context->rmsr = msr; context->rmsr = msr;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
_TLS_TCB_at_area_begin_initialize( tls_area ); context->thread_pointer = _TLS_Initialize_area( tls_area );
} }
} }

View File

@@ -137,6 +137,7 @@ typedef struct {
uint32_t r30; uint32_t r30;
uint32_t r31; uint32_t r31;
uint32_t rmsr; uint32_t rmsr;
void *thread_pointer;
} Context_Control; } Context_Control;
/** /**

View File

@@ -49,8 +49,11 @@
*/ */
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_INTERRUPT_FRAME_SIZE 56 #define CPU_INTERRUPT_FRAME_SIZE 56
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#define MICROBLAZE_INTERRUPT_FRAME_R3 0 #define MICROBLAZE_INTERRUPT_FRAME_R3 0
#define MICROBLAZE_INTERRUPT_FRAME_R4 4 #define MICROBLAZE_INTERRUPT_FRAME_R4 4
#define MICROBLAZE_INTERRUPT_FRAME_R5 8 #define MICROBLAZE_INTERRUPT_FRAME_R5 8

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -90,9 +90,6 @@ void _CPU_Context_Initialize(
} }
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
context->r23 = (uintptr_t) tls_area + context->r23 = (uintptr_t) _TLS_Initialize_area( tls_area ) + 0x7000;
_TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment ) +
0x7000;
_TLS_TCB_before_TLS_block_initialize( tls_area );
} }
} }

View File

@@ -54,6 +54,24 @@
*/ */
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
/**
* @brief Defines the thread-local storage (TLS) variant.
*
* Use one of the following values:
*
* 10: The architecture uses Variant I and the TLS offsets emitted by the
* linker neglect the TCB (examples: nios2, m68k, microblaze, powerpc,
* riscv). The thread pointer directly references the thread-local data
* area.
*
* 11: The architecture uses Variant I and the TLS offsets emitted by the
* linker take the TCB into account (examples: arm, aarch64).
* The thread pointer references the TCB.
*
* 20: The architecture uses Variant II (examples: i386, sparc).
*/
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -151,6 +151,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifdef RTEMS_SMP #ifdef RTEMS_SMP
/* Use SPRG0 for the per-CPU control of the current processor */ /* Use SPRG0 for the per-CPU control of the current processor */

View File

@@ -54,6 +54,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 16 #define CPU_PER_CPU_CONTROL_SIZE 16
#endif #endif
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifdef RTEMS_SMP #ifdef RTEMS_SMP
#define RISCV_CONTEXT_IS_EXECUTING 0 #define RISCV_CONTEXT_IS_EXECUTING 0
#endif #endif

View File

@@ -68,7 +68,7 @@ void _CPU_Context_Initialize(
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
void *tls_block; void *tls_block;
tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area ); tls_block = _TLS_Initialize_area( tls_area );
context->tp = (uintptr_t) tls_block; context->tp = (uintptr_t) tls_block;
} }
} }

View File

@@ -29,6 +29,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -319,7 +319,7 @@ void _CPU_Context_Initialize(
the_context->isr_dispatch_disable = 0; the_context->isr_dispatch_disable = 0;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area ); void *tcb = _TLS_Initialize_area( tls_area );
the_context->g7 = (uintptr_t) tcb; the_context->g7 = (uintptr_t) tcb;
} }

View File

@@ -120,6 +120,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#endif #endif
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
#if ( SPARC_HAS_FPU == 1 ) #if ( SPARC_HAS_FPU == 1 )
/** /**
* @brief Offset of the CPU_Per_CPU_control::fsr field relative to the * @brief Offset of the CPU_Per_CPU_control::fsr field relative to the

View File

@@ -132,7 +132,7 @@ void _CPU_Context_Initialize(
the_context->isr_dispatch_disable = 0; the_context->isr_dispatch_disable = 0;
if ( tls_area != NULL ) { if ( tls_area != NULL ) {
void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area ); void *tcb = _TLS_Initialize_area( tls_area );
the_context->g7 = (uintptr_t) tcb; the_context->g7 = (uintptr_t) tcb;
} }

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -48,6 +48,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -32,6 +32,8 @@
#define CPU_PER_CPU_CONTROL_SIZE 0 #define CPU_PER_CPU_CONTROL_SIZE 0
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
#ifndef ASM #ifndef ASM
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -267,12 +267,8 @@ static bool _Thread_Try_initialize(
/* Allocate thread-local storage (TLS) area in stack area */ /* Allocate thread-local storage (TLS) area in stack area */
if ( tls_size > 0 ) { if ( tls_size > 0 ) {
uintptr_t tls_align;
stack_end -= tls_size; stack_end -= tls_size;
tls_align = (uintptr_t) _TLS_Alignment; the_thread->Start.tls_area = stack_end;
the_thread->Start.tls_area = (void *)
( ( (uintptr_t) stack_end + tls_align - 1 ) & ~( tls_align - 1 ) );
} }
_Stack_Initialize( _Stack_Initialize(

View File

@@ -10,7 +10,7 @@
*/ */
/* /*
* Copyright (C) 2014, 2020 embedded brains GmbH (http://www.embedded-brains.de) * Copyright (C) 2014, 2022 embedded brains GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -58,29 +58,45 @@ uintptr_t _TLS_Get_allocation_size( void )
allocation_size = _TLS_Allocation_size; allocation_size = _TLS_Allocation_size;
if ( allocation_size == 0 ) { if ( allocation_size == 0 ) {
uintptr_t alignment; uintptr_t tls_align;
uintptr_t stack_align;
alignment = _TLS_Align_up( (uintptr_t) _TLS_Alignment );
allocation_size = size;
allocation_size += _TLS_Get_thread_control_block_area_size( alignment );
#ifndef __i386__
allocation_size += sizeof( TLS_Dynamic_thread_vector );
#endif
/* /*
* The TLS area is allocated in the thread storage area. Each allocation * The TLS area is allocated in the thread storage area. Each allocation
* shall meet the stack alignment requirement. * shall meet the stack alignment requirement.
*/ */
allocation_size = _TLS_Align_up( allocation_size ); stack_align = CPU_STACK_ALIGNMENT;
tls_align = RTEMS_ALIGN_UP( (uintptr_t) _TLS_Alignment, stack_align );
#ifndef __i386__
/* Reserve space for the dynamic thread vector */
allocation_size +=
RTEMS_ALIGN_UP( sizeof( TLS_Dynamic_thread_vector ), stack_align );
#endif
/* Reserve space for the thread control block */
allocation_size +=
#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), tls_align );
#else
RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), stack_align );
#endif
/* Reserve space for the thread-local storage data */
allocation_size +=
#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20
RTEMS_ALIGN_UP( size, tls_align );
#else
RTEMS_ALIGN_UP( size, stack_align );
#endif
/* /*
* The stack allocator does not support aligned allocations. Allocate * The stack allocator does not support aligned allocations. Allocate
* enough to do the alignment manually. * enough to do the alignment manually.
*/ */
if ( alignment > CPU_STACK_ALIGNMENT ) { if ( tls_align > stack_align ) {
_Assert( alignment % CPU_STACK_ALIGNMENT == 0 ); _Assert( tls_align % stack_align == 0 );
allocation_size += alignment - CPU_STACK_ALIGNMENT; allocation_size += tls_align - stack_align;
} }
if ( _Thread_Maximum_TLS_size != 0 ) { if ( _Thread_Maximum_TLS_size != 0 ) {