mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-10-06 10:59:48 +08:00
cpukit/score/cpu/mips: Add thread-local storage
The port declared CPU_THREAD_LOCAL_STORAGE_VARIANT but implemented none of it. _CPU_Context_Initialize() ignored its thread-local storage area, _CPU_Get_TLS_thread_pointer() returned NULL, and there was nothing to give the compiler the thread pointer, so every access to a thread-local object read the wrong memory. Keep the thread pointer in the context. It follows the registers saved by _CPU_Context_switch(), which addresses the members before it through the offsets defined in cpu_asm.S, so nothing in the assembly changes. The ABI places the thread pointer 0x7000 bytes above the thread-local storage data, so that the signed 16-bit offsets emitted by the linker reach a larger part of the area. The compiler reads the thread pointer with rdhwr, which this processor does not have. Supplying it is the task of the exception handler. Update #5689. Assisted-by: Claude:claude-opus-5 claude-code Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
@@ -73,6 +73,7 @@
|
||||
|
||||
#include <rtems/score/cpuimpl.h>
|
||||
#include <rtems/score/isr.h>
|
||||
#include <rtems/score/tls.h>
|
||||
|
||||
#if CPU_HARDWARE_FP
|
||||
Context_Control_fp _CPU_Null_fp_context;
|
||||
@@ -150,7 +151,6 @@ void _CPU_Context_Initialize(
|
||||
)
|
||||
{
|
||||
(void) is_fp;
|
||||
(void) tls_area;
|
||||
|
||||
uintptr_t stack_tmp;
|
||||
__MIPS_REGISTER_TYPE intlvl = new_level & 0xff;
|
||||
@@ -181,6 +181,13 @@ void _CPU_Context_Initialize(
|
||||
}
|
||||
#endif
|
||||
the_context->c0_sr = c0_sr;
|
||||
|
||||
if ( tls_area != NULL ) {
|
||||
the_context->thread_pointer = (char *) _TLS_Initialize_area( tls_area ) +
|
||||
MIPS_TLS_THREAD_POINTER_OFFSET;
|
||||
} else {
|
||||
the_context->thread_pointer = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* _CPU_Internal_threads_Idle_thread_body
|
||||
|
||||
@@ -295,6 +295,12 @@ typedef struct {
|
||||
__MIPS_REGISTER_TYPE ra;
|
||||
__MIPS_REGISTER_TYPE c0_sr;
|
||||
__MIPS_REGISTER_TYPE c0_epc;
|
||||
/*
|
||||
* The thread pointer of the thread-local storage area. It follows the
|
||||
* registers saved by _CPU_Context_switch(), which addresses the members
|
||||
* above through the offsets defined in cpu_asm.S.
|
||||
*/
|
||||
void *thread_pointer;
|
||||
} Context_Control;
|
||||
|
||||
#define _CPU_Context_Get_SP( _context ) \
|
||||
|
||||
@@ -53,6 +53,13 @@
|
||||
|
||||
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
|
||||
|
||||
/*
|
||||
* The ABI places the thread pointer this many bytes above the thread-local
|
||||
* storage data, so that the signed 16-bit offsets emitted by the linker reach
|
||||
* a larger part of the area.
|
||||
*/
|
||||
#define MIPS_TLS_THREAD_POINTER_OFFSET 0x7000
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -77,6 +84,11 @@ static inline void _CPU_Use_thread_local_storage(
|
||||
const Context_Control *context
|
||||
)
|
||||
{
|
||||
/*
|
||||
* There is no register which holds the thread pointer. The compiler reads
|
||||
* it with rdhwr, which the exception handler emulates for processors which
|
||||
* lack the instruction.
|
||||
*/
|
||||
(void) context;
|
||||
}
|
||||
|
||||
@@ -84,8 +96,7 @@ static inline void *_CPU_Get_TLS_thread_pointer(
|
||||
const Context_Control *context
|
||||
)
|
||||
{
|
||||
(void) context;
|
||||
return NULL;
|
||||
return context->thread_pointer;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user