mirror of
https://github.com/apache/nuttx.git
synced 2025-01-12 22:08:35 +08:00
arch/xtensa: Support __thread
and thread_local
keywords
Enable architecture-specific support for those keywords. This is a "gcc-based" thread local storage implementation.
This commit is contained in:
parent
02828921db
commit
7548db1980
15 changed files with 291 additions and 2 deletions
|
@ -158,6 +158,7 @@ config ARCH_XTENSA
|
|||
select ARCH_HAVE_INTERRUPTSTACK
|
||||
select ARCH_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_CUSTOMOPT
|
||||
select ARCH_HAVE_THREAD_LOCAL
|
||||
select ARCH_HAVE_TCBINFO
|
||||
select ARCH_HAVE_STDARG_H
|
||||
select ARCH_HAVE_SETJMP if ARCH_TOOLCHAIN_GNU
|
||||
|
|
|
@ -94,8 +94,9 @@
|
|||
#define REG_SAR (18)
|
||||
#define REG_EXCCAUSE (19)
|
||||
#define REG_EXCVADDR (20)
|
||||
#define REG_THREADPTR (21)
|
||||
|
||||
#define _REG_EXTRA_START (21)
|
||||
#define _REG_EXTRA_START (22)
|
||||
|
||||
#if XCHAL_HAVE_S32C1I != 0
|
||||
# define REG_SCOMPARE1 (_REG_EXTRA_START + 0)
|
||||
|
|
|
@ -128,13 +128,14 @@
|
|||
|
||||
/* Tensilica-defined user registers: */
|
||||
|
||||
#define THREADPTR 231 /* threadptr option */
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
#define ... 21..24 /* (545CK) */
|
||||
#define ... 140..143 /* (545CK) */
|
||||
#endif
|
||||
#define EXPSTATE 230 /* Diamond */
|
||||
#define THREADPTR 231 /* threadptr option */
|
||||
#define FCR 232 /* FPU */
|
||||
#define FSR 233 /* FPU */
|
||||
#define AE_OVF_SAR 240 /* HiFi2 */
|
||||
|
|
|
@ -54,6 +54,10 @@ ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
|||
CMN_CSRCS += xtensa_backtrace.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_THREAD_LOCAL),y)
|
||||
CMN_CSRCS += xtensa_tls.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CMN_CSRCS += xtensa_smpcall.c
|
||||
endif
|
||||
|
|
|
@ -144,6 +144,18 @@
|
|||
#define INTSTACK_COLOR 0xdeadbeef
|
||||
#define HEAP_COLOR 'h'
|
||||
|
||||
#define _START_TEXT _stext
|
||||
#define _END_TEXT _etext
|
||||
#define _START_BSS _sbss
|
||||
#define _END_BSS _ebss
|
||||
#define _DATA_INIT _eronly
|
||||
#define _START_DATA _sdata
|
||||
#define _END_DATA _edata
|
||||
#define _START_TDATA _stdata
|
||||
#define _END_TDATA _etdata
|
||||
#define _START_TBSS _stbss
|
||||
#define _END_TBSS _etbss
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
@ -177,6 +189,10 @@ extern uint8_t _sbss[]; /* Start of .bss */
|
|||
extern uint8_t _ebss[]; /* End+1 of .bss */
|
||||
extern uint8_t _sheap[]; /* Start of heap */
|
||||
extern uint8_t _eheap[]; /* End+1 of heap */
|
||||
extern uint8_t _stdata[]; /* Start of .tdata */
|
||||
extern uint8_t _etdata[]; /* End+1 of .tdata */
|
||||
extern uint8_t _stbss[]; /* Start of .tbss */
|
||||
extern uint8_t _etbss[]; /* End+1 of .tbss */
|
||||
extern uint8_t _sbss_extmem[]; /* start of external memory bss */
|
||||
extern uint8_t _ebss_extmem[]; /* End+1 of external memory bss */
|
||||
|
||||
|
|
|
@ -131,6 +131,9 @@ _xtensa_context_save:
|
|||
s32i a15, sp, (4 * REG_A15)
|
||||
#endif
|
||||
|
||||
rur a3, THREADPTR
|
||||
s32i a3, sp, (4 * REG_THREADPTR)
|
||||
|
||||
rsr a3, SAR
|
||||
s32i a3, sp, (4 * REG_SAR)
|
||||
|
||||
|
@ -276,6 +279,9 @@ _xtensa_context_restore:
|
|||
wsr a3, SCOMPARE1
|
||||
#endif
|
||||
|
||||
l32i a3, a2, (4 * REG_THREADPTR)
|
||||
wur a3, THREADPTR
|
||||
|
||||
l32i a3, a2, (4 * REG_SAR)
|
||||
wsr a3, SAR
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/xtensa/core.h>
|
||||
#include <arch/chip/core-isa.h>
|
||||
|
@ -39,6 +40,23 @@
|
|||
|
||||
#include "xtensa.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_THREAD_LOCAL
|
||||
# define TCB_SIZE 8
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern int _thread_local_start;
|
||||
extern int _thread_local_end;
|
||||
extern int _rodata_reserved_start;
|
||||
extern int _rodata_reserved_align;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -59,6 +77,10 @@
|
|||
void up_initial_state(struct tcb_s *tcb)
|
||||
{
|
||||
struct xcptcontext *xcp = &tcb->xcp;
|
||||
#ifdef CONFIG_SCHED_THREAD_LOCAL
|
||||
const uint32_t base = ALIGN_UP((uint32_t)&_rodata_reserved_align,
|
||||
TCB_SIZE);
|
||||
#endif
|
||||
|
||||
/* Initialize the initial exception register context structure */
|
||||
|
||||
|
@ -100,6 +122,116 @@ void up_initial_state(struct tcb_s *tcb)
|
|||
xcp->regs[REG_A1] = (uint32_t)tcb->stack_base_ptr + /* Physical top of stack frame */
|
||||
tcb->adj_stack_size;
|
||||
|
||||
/* Each task access the TLS variables using the THREADPTR register plus an
|
||||
* offset to obtain the address of the variable.
|
||||
*
|
||||
* TLS layout at link-time (on flash), where 0xNNN is the offset that the
|
||||
* linker calculates to a particular TLS variable:
|
||||
*
|
||||
* LOW ADDRESS
|
||||
* |---------------------------| Linker Symbols
|
||||
* | Section | --------------
|
||||
* | .flash.rodata |
|
||||
* 0x0|---------------------------| <- _rodata_reserved_start
|
||||
* ^ | Other Data |
|
||||
* | |---------------------------| <- _thread_local_start
|
||||
* | | .tdata | ^ ^
|
||||
* | | | | |
|
||||
* | | | | Offset from |
|
||||
* | | | | TLS start |
|
||||
* | | | | | tls_area_size
|
||||
* V | | V |
|
||||
* 0xNNN | int example; | |
|
||||
* | | |
|
||||
* | | |
|
||||
* | .tbss | V
|
||||
* |---------------------------| <- _thread_local_end
|
||||
* | Other data |
|
||||
* | ... |
|
||||
* |---------------------------|
|
||||
* HIGH ADDRESS
|
||||
*
|
||||
* Consider the TLS variable `example`. Its location is calculated as:
|
||||
*
|
||||
* &example = &_rodata_reserved_start + 0xNNN
|
||||
*
|
||||
* And the offset 0xNNN can be calculated as:
|
||||
*
|
||||
* 0xNNN = (&_thread_local_start - &_rodata_reserved_start) +
|
||||
* Offset from TLS start
|
||||
*
|
||||
* Consider the following diagram for the stack layout:
|
||||
*
|
||||
* Note: the following diagram shows the stack layout for a particular task
|
||||
* and the memory grows towards the stack base (lower memory addresses).
|
||||
*
|
||||
* HIGH ADDRESS
|
||||
* |---------------------------| <- Top of the stack
|
||||
* | |
|
||||
* | |
|
||||
* |---------------------------| <- Base of the stack
|
||||
* | .tbss (*) |
|
||||
* | |
|
||||
* | |
|
||||
* | int example; |
|
||||
* ^ | | ^
|
||||
* | | | | Offset from TLS start
|
||||
* | | .tdata (*) | V
|
||||
* | |---------------------------| <- Start of the TLS area
|
||||
* 0xNNN | | | ^
|
||||
* | | | |
|
||||
* | | ... | | (_thread_local_start -
|
||||
* | | | | _rodata_reserved_start)
|
||||
* | | | | + align_up(TCB_SIZE,
|
||||
* | | | | tls_section_align)
|
||||
* | | | |
|
||||
* | | | V
|
||||
* V | | <- threadptr register's value
|
||||
*
|
||||
* LOW ADDRESS
|
||||
*
|
||||
* At run-time, each task accesses the TLS variables using the THREADPTR
|
||||
* register plus an offset to obtain the address of the variable.
|
||||
*
|
||||
* &example = THREADPTR + 0xNNN (calculated at link-time)
|
||||
*
|
||||
* Similarly, example can be accessed as:
|
||||
*
|
||||
* &example = Start of the TLS area + Offset from TLS start
|
||||
*
|
||||
* The start of the TLS area is given by (check xtensa_tls.c):
|
||||
*
|
||||
* Start of the TLS area = tcb->stack_alloc_ptr +
|
||||
* sizeof(struct tls_info_s)
|
||||
*
|
||||
* Calculate the THREADPTR register's initialization value based on the
|
||||
* link-time offset and the TLS area allocated on the stack.
|
||||
*
|
||||
* THREADPTR = &example - 0xNNN
|
||||
* THREADPTR = (tcb->stack_alloc_ptr + sizeof(struct tls_info_s)) +
|
||||
* Offset from TLS start - 0xNNN
|
||||
*
|
||||
* And, finally, based on 0xNNN calculated at link-time:
|
||||
*
|
||||
* THREADPTR = (tcb->stack_alloc_ptr + sizeof(struct tls_info_s)) -
|
||||
* (&_thread_local_start - &_rodata_reserved_start) - base
|
||||
*
|
||||
* Note: Xtensa is slightly different compared to the RISC-V port as there
|
||||
* is an implicit aligned TCB_SIZE added to the offset.
|
||||
* - "offset = address - tls_section_vma +
|
||||
* align_up(TCB_SIZE, tls_section_align)"
|
||||
* - TCB_SIZE is hardcoded to 8
|
||||
* Refer to https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=bfd/
|
||||
* elf32-xtensa.c;h=f078cbde7146675fd2ed82eb5102ae2596c20775;hb=HEAD#l1830
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SCHED_THREAD_LOCAL
|
||||
xcp->regs[REG_THREADPTR] = (uintptr_t)tcb->stack_alloc_ptr +
|
||||
sizeof(struct tls_info_s) -
|
||||
((uint32_t)&_thread_local_start -
|
||||
(uint32_t)&_rodata_reserved_start) - base;
|
||||
#endif
|
||||
|
||||
/* Set initial PS to int level 0, user mode. */
|
||||
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
|
|
|
@ -79,6 +79,8 @@ int up_saveusercontext(void *saveregs)
|
|||
" s32i a14, %0, (4 * " STRINGIFY(REG_A14) ")\n"
|
||||
" s32i a15, %0, (4 * " STRINGIFY(REG_A15) ")\n"
|
||||
#endif
|
||||
" rur a2, THREADPTR\n"
|
||||
" s32i a2, %0, (4 * " STRINGIFY(THREADPTR) ")\n"
|
||||
" rsr a2, SAR\n"
|
||||
" s32i a2, %0, (4 * " STRINGIFY(REG_SAR) ")\n"
|
||||
#if XCHAL_HAVE_S32C1I != 0
|
||||
|
|
74
arch/xtensa/src/common/xtensa_tls.c
Normal file
74
arch/xtensa/src/common/xtensa_tls.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/****************************************************************************
|
||||
* arch/xtensa/src/common/xtensa_tls.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/tls.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tls_size
|
||||
*
|
||||
* Description:
|
||||
* Get TLS (sizeof(struct tls_info_s) + tdata + tbss) section size.
|
||||
*
|
||||
* Returned Value:
|
||||
* Size of (sizeof(struct tls_info_s) + tdata + tbss).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_tls_size(void)
|
||||
{
|
||||
size_t size_tls_info_s = sizeof(struct tls_info_s);
|
||||
size_t size_tsec = (_END_TBSS - _START_TDATA);
|
||||
|
||||
return size_tls_info_s + size_tsec;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tls_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize thread local region.
|
||||
*
|
||||
* Input Parameters:
|
||||
* info - The TLS structure to initialize.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_tls_initialize(struct tls_info_s *info)
|
||||
{
|
||||
uint8_t *tls_data = (uint8_t *)(info + 1);
|
||||
|
||||
uint32_t tdata_len = (_END_TDATA - _START_TDATA);
|
||||
uint32_t tbss_len = (_END_TBSS - _START_TBSS);
|
||||
|
||||
memcpy(tls_data, _START_TDATA, tdata_len);
|
||||
memset(tls_data + tdata_len, 0, tbss_len);
|
||||
}
|
|
@ -403,6 +403,7 @@ SECTIONS
|
|||
|
||||
.flash.rodata :
|
||||
{
|
||||
_rodata_reserved_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_srodata = ABSOLUTE(.);
|
||||
*(EXCLUDE_FILE (*libarch.a:esp32_spiflash.* *libarch.a:esp32_spicache.*
|
||||
|
@ -469,8 +470,24 @@ SECTIONS
|
|||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
|
||||
/* TLS data. */
|
||||
|
||||
. = ALIGN(4);
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
|
||||
_stdata = ABSOLUTE(.);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*);
|
||||
_etdata = ABSOLUTE(.);
|
||||
_stbss = ABSOLUTE(.);
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
|
||||
_etbss = ABSOLUTE(.);
|
||||
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
} >default_rodata_seg AT>ROM
|
||||
_rodata_reserved_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
_image_irom_vma = ADDR(.flash.text);
|
||||
_image_irom_lma = LOADADDR(.flash.text);
|
||||
|
|
|
@ -38,6 +38,7 @@ CONFIG_PREALLOC_TIMERS=4
|
|||
CONFIG_RAM_SIZE=114688
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_THREAD_LOCAL=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_START_DAY=6
|
||||
|
|
|
@ -315,6 +315,8 @@ SECTIONS
|
|||
|
||||
.flash.rodata :
|
||||
{
|
||||
_rodata_reserved_start = ABSOLUTE(.);
|
||||
|
||||
_srodata = ABSOLUTE(.);
|
||||
*(EXCLUDE_FILE (esp32s2_start.*) .rodata)
|
||||
*(EXCLUDE_FILE (esp32s2_start.*) .rodata.*)
|
||||
|
@ -374,8 +376,23 @@ SECTIONS
|
|||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
/* TLS data. */
|
||||
|
||||
. = ALIGN(4);
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
|
||||
_stdata = ABSOLUTE(.);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*);
|
||||
_etdata = ABSOLUTE(.);
|
||||
_stbss = ABSOLUTE(.);
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
|
||||
_etbss = ABSOLUTE(.);
|
||||
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
} >default_rodata_seg AT>ROM
|
||||
_rodata_reserved_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
_image_irom_vma = ADDR(.flash.text);
|
||||
_image_irom_lma = LOADADDR(.flash.text);
|
||||
|
|
|
@ -37,6 +37,7 @@ CONFIG_PREALLOC_TIMERS=4
|
|||
CONFIG_RAM_SIZE=114688
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_THREAD_LOCAL=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_START_DAY=6
|
||||
CONFIG_START_MONTH=12
|
||||
|
|
|
@ -523,9 +523,24 @@ SECTIONS
|
|||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
|
||||
/* TLS data. */
|
||||
|
||||
. = ALIGN(4);
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
|
||||
_stdata = ABSOLUTE(.);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*);
|
||||
_etdata = ABSOLUTE(.);
|
||||
_stbss = ABSOLUTE(.);
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
|
||||
_etbss = ABSOLUTE(.);
|
||||
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
} >drom0_0_seg AT>ROM
|
||||
_rodata_reserved_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
_image_irom_vma = ADDR(.flash.text);
|
||||
_image_irom_lma = LOADADDR(.flash.text);
|
||||
|
|
|
@ -40,6 +40,7 @@ CONFIG_PREALLOC_TIMERS=4
|
|||
CONFIG_RAM_SIZE=114688
|
||||
CONFIG_RAM_START=0x20000000
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_THREAD_LOCAL=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_SMP_NCPUS=2
|
||||
|
|
Loading…
Reference in a new issue