picolibc: Enable TLS support [v4]
Allocate and initialize a thread-local block for each thread at the top of the stack. Set the tls base when switching to a new thread. Add tdata/tbss linker instructions to cortex_m and risc-v scripts. Signed-off-by: Keith Packard <keithp@keithp.com> --- v2: Squash fixes v3: Replace tabs with spaces v4: Add tbss to fe310 linker script
This commit is contained in:
parent
a0d3436486
commit
531050ada2
@ -176,6 +176,10 @@ struct _thread {
|
|||||||
const char *name; /**< thread's name */
|
const char *name; /**< thread's name */
|
||||||
int stack_size; /**< thread's stack size */
|
int stack_size; /**< thread's stack size */
|
||||||
#endif
|
#endif
|
||||||
|
/* enable TLS only when Picolibc is compiled with TLS enabled */
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
void *tls; /**< thread local storage ptr */
|
||||||
|
#endif
|
||||||
#ifdef HAVE_THREAD_ARCH_T
|
#ifdef HAVE_THREAD_ARCH_T
|
||||||
thread_arch_t arch; /**< architecture dependent part */
|
thread_arch_t arch; /**< architecture dependent part */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -40,6 +40,10 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
#include <picotls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Needed by OpenOCD to read sched_threads */
|
/* Needed by OpenOCD to read sched_threads */
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
#define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \
|
#define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \
|
||||||
@ -148,6 +152,9 @@ int __attribute__((used)) sched_run(void)
|
|||||||
next_thread->status = STATUS_RUNNING;
|
next_thread->status = STATUS_RUNNING;
|
||||||
sched_active_pid = next_thread->pid;
|
sched_active_pid = next_thread->pid;
|
||||||
sched_active_thread = next_thread;
|
sched_active_thread = next_thread;
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
_set_tls(next_thread->tls);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_MPU_STACK_GUARD
|
#ifdef MODULE_MPU_STACK_GUARD
|
||||||
mpu_configure(
|
mpu_configure(
|
||||||
|
|||||||
@ -20,6 +20,9 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
#include <picotls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -215,6 +218,13 @@ kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority,
|
|||||||
/* allocate our thread control block at the top of our stackspace */
|
/* allocate our thread control block at the top of our stackspace */
|
||||||
thread_t *thread = (thread_t *)(stack + stacksize);
|
thread_t *thread = (thread_t *)(stack + stacksize);
|
||||||
|
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
stacksize -= _tls_size();
|
||||||
|
|
||||||
|
thread->tls = stack + stacksize;
|
||||||
|
_init_tls(thread->tls);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DEVELHELP) || defined(SCHED_TEST_STACK)
|
#if defined(DEVELHELP) || defined(SCHED_TEST_STACK)
|
||||||
if (flags & THREAD_CREATE_STACKTEST) {
|
if (flags & THREAD_CREATE_STACKTEST) {
|
||||||
/* assign each int of the stack the value of it's address */
|
/* assign each int of the stack the value of it's address */
|
||||||
|
|||||||
@ -96,6 +96,42 @@ SECTIONS
|
|||||||
_efixed = .; /* End of text section */
|
_efixed = .; /* End of text section */
|
||||||
} > rom
|
} > rom
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS relocations are offsets relative to the address
|
||||||
|
* of the first TLS symbol. That means we just need to
|
||||||
|
* allocate them all together so that the TLS region
|
||||||
|
* is compact when allocated for each thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS initialization data is loaded into ROM so that
|
||||||
|
* each thread can get its values initialized from there
|
||||||
|
* at startup
|
||||||
|
*/
|
||||||
|
.tdata :
|
||||||
|
{
|
||||||
|
__tdata_start = .;
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
__tdata_end = .;
|
||||||
|
} > rom
|
||||||
|
__tdata_source = LOADADDR(.tdata);
|
||||||
|
__tdata_size = SIZEOF(.tdata);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS zeroed data is relocated as if it immediately followed
|
||||||
|
* the tdata values. However, the linker 'magically' erases the
|
||||||
|
* memory allocation so that no ROM is consumed by this
|
||||||
|
* section
|
||||||
|
*/
|
||||||
|
.tbss :
|
||||||
|
{
|
||||||
|
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||||
|
*(.tcommon)
|
||||||
|
__tbss_end = .;
|
||||||
|
} > rom
|
||||||
|
__tls_size = __tbss_end - __tdata_start;
|
||||||
|
__tbss_size = __tls_size - __tdata_size;
|
||||||
|
|
||||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||||
PROVIDE_HIDDEN (__exidx_start = .);
|
PROVIDE_HIDDEN (__exidx_start = .);
|
||||||
.ARM.exidx :
|
.ARM.exidx :
|
||||||
|
|||||||
@ -27,6 +27,7 @@ PHDRS
|
|||||||
flash PT_LOAD;
|
flash PT_LOAD;
|
||||||
ram_init PT_LOAD;
|
ram_init PT_LOAD;
|
||||||
ram PT_NULL;
|
ram PT_NULL;
|
||||||
|
tls PT_TLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
@ -118,6 +119,42 @@ SECTIONS
|
|||||||
KEEP (*(.dtors))
|
KEEP (*(.dtors))
|
||||||
} >flash AT>flash :flash
|
} >flash AT>flash :flash
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS relocations are offsets relative to the address
|
||||||
|
* of the first TLS symbol. That means we just need to
|
||||||
|
* allocate them all together so that the TLS region
|
||||||
|
* is compact when allocated for each thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS initialization data is loaded into ROM so that
|
||||||
|
* each thread can get its values initialized from there
|
||||||
|
* at startup
|
||||||
|
*/
|
||||||
|
.tdata :
|
||||||
|
{
|
||||||
|
__tdata_start = .;
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
__tdata_end = .;
|
||||||
|
} >flash AT>flash :tls
|
||||||
|
__tdata_source = LOADADDR(.tdata);
|
||||||
|
__tdata_size = SIZEOF(.tdata);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS zeroed data is relocated as if it immediately followed
|
||||||
|
* the tdata values. However, the linker 'magically' erases the
|
||||||
|
* memory allocation so that no ROM is consumed by this
|
||||||
|
* section
|
||||||
|
*/
|
||||||
|
.tbss :
|
||||||
|
{
|
||||||
|
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||||
|
*(.tcommon)
|
||||||
|
__tbss_end = .;
|
||||||
|
} >flash : tls
|
||||||
|
__tls_size = __tbss_end - __tdata_start;
|
||||||
|
__tbss_size = __tls_size - __tdata_size;
|
||||||
|
|
||||||
.lalign :
|
.lalign :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user