diff --git a/core/include/thread.h b/core/include/thread.h index a2d2a1486d..78131c24c6 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -176,6 +176,10 @@ struct _thread { const char *name; /**< thread's name */ int stack_size; /**< thread's stack size */ #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 thread_arch_t arch; /**< architecture dependent part */ #endif diff --git a/core/sched.c b/core/sched.c index f099c5f15b..907ddb5a23 100644 --- a/core/sched.c +++ b/core/sched.c @@ -40,6 +40,10 @@ #include #endif +#ifdef PICOLIBC_TLS +#include +#endif + /* Needed by OpenOCD to read sched_threads */ #if defined(__APPLE__) && defined(__MACH__) #define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \ @@ -148,6 +152,9 @@ int __attribute__((used)) sched_run(void) next_thread->status = STATUS_RUNNING; sched_active_pid = next_thread->pid; sched_active_thread = next_thread; +#ifdef PICOLIBC_TLS + _set_tls(next_thread->tls); +#endif #ifdef MODULE_MPU_STACK_GUARD mpu_configure( diff --git a/core/thread.c b/core/thread.c index b723bbfde1..3de9dfb23c 100644 --- a/core/thread.c +++ b/core/thread.c @@ -20,6 +20,9 @@ #include #include +#ifdef PICOLIBC_TLS +#include +#endif #include "assert.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 */ 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 (flags & THREAD_CREATE_STACKTEST) { /* assign each int of the stack the value of it's address */ diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index 2ed641a0f5..de0dc81fd1 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -96,6 +96,42 @@ SECTIONS _efixed = .; /* End of text section */ } > 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. */ PROVIDE_HIDDEN (__exidx_start = .); .ARM.exidx : diff --git a/cpu/fe310/ldscripts/fe310_base.ld b/cpu/fe310/ldscripts/fe310_base.ld index 845b6d1d45..3a344dd5ec 100644 --- a/cpu/fe310/ldscripts/fe310_base.ld +++ b/cpu/fe310/ldscripts/fe310_base.ld @@ -27,6 +27,7 @@ PHDRS flash PT_LOAD; ram_init PT_LOAD; ram PT_NULL; + tls PT_TLS; } SECTIONS @@ -118,6 +119,42 @@ SECTIONS KEEP (*(.dtors)) } >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 : { . = ALIGN(4);