From 83f21da1c9757a4528871463467db3927890b6d5 Mon Sep 17 00:00:00 2001 From: Al Date: Sat, 10 Sep 2022 14:13:49 -0700 Subject: [PATCH 1/8] pico_tls module --- src/rp2_common/CMakeLists.txt | 1 + src/rp2_common/pico_runtime/CMakeLists.txt | 3 + .../pico_standard_link/memmap_blocked_ram.ld | 6 ++ .../pico_standard_link/memmap_copy_to_ram.ld | 6 ++ .../pico_standard_link/memmap_default.ld | 6 ++ .../pico_standard_link/memmap_no_flash.ld | 9 ++ src/rp2_common/pico_tls/CMakeLists.txt | 38 ++++++++ src/rp2_common/pico_tls/tls.S | 4 + src/rp2_common/pico_tls/tls.c | 97 +++++++++++++++++++ test/kitchen_sink/CMakeLists.txt | 1 + test/kitchen_sink/kitchen_sink.c | 9 ++ 11 files changed, 180 insertions(+) create mode 100644 src/rp2_common/pico_tls/CMakeLists.txt create mode 100644 src/rp2_common/pico_tls/tls.S create mode 100644 src/rp2_common/pico_tls/tls.c diff --git a/src/rp2_common/CMakeLists.txt b/src/rp2_common/CMakeLists.txt index 0d0f9b93d..a3de4f86b 100644 --- a/src/rp2_common/CMakeLists.txt +++ b/src/rp2_common/CMakeLists.txt @@ -49,6 +49,7 @@ if (NOT PICO_BARE_METAL) pico_add_subdirectory(pico_mem_ops) pico_add_subdirectory(pico_malloc) pico_add_subdirectory(pico_printf) + pico_add_subdirectory(pico_tls) pico_add_subdirectory(pico_stdio) pico_add_subdirectory(pico_stdio_semihosting) diff --git a/src/rp2_common/pico_runtime/CMakeLists.txt b/src/rp2_common/pico_runtime/CMakeLists.txt index 3b6cc1817..b46ff60c9 100644 --- a/src/rp2_common/pico_runtime/CMakeLists.txt +++ b/src/rp2_common/pico_runtime/CMakeLists.txt @@ -38,6 +38,9 @@ endif() if (TARGET pico_standard_link) target_link_libraries(pico_runtime INTERFACE pico_standard_link) endif() +if (TARGET pico_tls) + target_link_libraries(pico_runtime INTERFACE pico_tls) +endif() # todo is this correct/needed? target_link_options(pico_runtime INTERFACE "--specs=nosys.specs") diff --git a/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld b/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld index 5b0afe65b..101dcb67e 100644 --- a/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld @@ -134,8 +134,14 @@ SECTIONS *(.text*) . = ALIGN(4); *(.rodata*) + . = ALIGN(4); + /* emutls objects */ + PROVIDE_HIDDEN (__emutls_array_start = .); + KEEP(*(.data.__emutls_v.*)) + PROVIDE_HIDDEN (__emutls_array_end = .); + . = ALIGN(4); *(.data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld index 90975b593..eeced1283 100644 --- a/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld @@ -133,8 +133,14 @@ SECTIONS . = ALIGN(4); *(.rodata*) + . = ALIGN(4); + /* emutls objects */ + PROVIDE_HIDDEN (__emutls_array_start = .); + KEEP(*(.data.__emutls_v.*)) + PROVIDE_HIDDEN (__emutls_array_end = .); + . = ALIGN(4); *(.data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_default.ld b/src/rp2_common/pico_standard_link/memmap_default.ld index 07d5812db..c3dd1a76c 100644 --- a/src/rp2_common/pico_standard_link/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/memmap_default.ld @@ -134,8 +134,14 @@ SECTIONS *(.text*) . = ALIGN(4); *(.rodata*) + . = ALIGN(4); + /* emutls objects */ + PROVIDE_HIDDEN (__emutls_array_start = .); + KEEP(*(.data.__emutls_v.*)) + PROVIDE_HIDDEN (__emutls_array_end = .); + . = ALIGN(4); *(.data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/memmap_no_flash.ld index 7a5977fa5..184461775 100644 --- a/src/rp2_common/pico_standard_link/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/memmap_no_flash.ld @@ -104,6 +104,15 @@ SECTIONS __etext = .; __data_start__ = .; *(vtable) + + + . = ALIGN(4); + /* emutls objects */ + PROVIDE_HIDDEN (__emutls_array_start = .); + KEEP(*(.data.__emutls_v.*)) + PROVIDE_HIDDEN (__emutls_array_end = .); + + . = ALIGN(4); *(.data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_tls/CMakeLists.txt b/src/rp2_common/pico_tls/CMakeLists.txt new file mode 100644 index 000000000..30537466c --- /dev/null +++ b/src/rp2_common/pico_tls/CMakeLists.txt @@ -0,0 +1,38 @@ +if (NOT TARGET pico_tls) + # library to be depended on - we make this depend on particular implementations using per target generator expressions + pico_add_impl_library(pico_tls) + + # no custom implementation; falls thru to compiler + pico_add_impl_library(pico_tls_compiler) + + # add alias "default" which is just core_thread. + add_library(pico_tls_default INTERFACE) + target_link_libraries(pico_tls_default INTERFACE pico_tls_core_thread) + + set(PICO_DEFAULT_TLS_IMPL pico_tls_default) + + target_link_libraries(pico_tls INTERFACE + $>,$,${PICO_DEFAULT_TLS_IMPL}>) + + add_library(pico_tls_core_thread_explicit INTERFACE) + target_sources(pico_tls_core_thread_explicit INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/tls.c + ${CMAKE_CURRENT_LIST_DIR}/tls.S + ) + + pico_add_impl_library(pico_tls_core_thread) + + target_link_libraries(pico_tls_core_thread INTERFACE pico_tls_core_thread_explicit) + + pico_wrap_function(pico_tls_core_thread __emutls_get_address) + + # Call this to substitute an alternate implementation, e.g. if using an RTOS. + macro(pico_set_tls_implementation TARGET IMPL) + get_target_property(target_type ${TARGET} TYPE) + if ("EXECUTABLE" STREQUAL "${target_type}") + set_target_properties(${TARGET} PROPERTIES PICO_TARGET_TLS_IMPL "pico_tls_${IMPL}") + else() + message(FATAL_ERROR "tls implementation must be set on executable not library") + endif() + endmacro() +endif() diff --git a/src/rp2_common/pico_tls/tls.S b/src/rp2_common/pico_tls/tls.S new file mode 100644 index 000000000..bfe2caaa6 --- /dev/null +++ b/src/rp2_common/pico_tls/tls.S @@ -0,0 +1,4 @@ +#include "pico/asm_helper.S" + +// This has to happen after memcpy() and memset() are available. +__pre_init tls_init, 10000 diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c new file mode 100644 index 000000000..ebb78fe73 --- /dev/null +++ b/src/rp2_common/pico_tls/tls.c @@ -0,0 +1,97 @@ +#include "pico.h" + +#include +#include + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 201112) +#include +#define aligned_alloc memalign +#endif + +// From emutls.c: +// 'For every TLS variable xyz, there is one __emutls_control variable named __emutls_v.xyz. If xyz has +// non-zero initial value, __emutls_v.xyz's "value" will point to __emutls_t.xyz, which has the initial value.' +// +// The linker script groups all the __emutls_v.xyz variables into a single array and provides symbols +// __emutls_array_start and __emutls_array_end, which can be used to iterate over the array. This allows +// the storage for each core's thread local variables to be pre-allocated and pre-initialized, which leaves +// minimal work for __wrap___emutls_get_address. +// +// This array is available to other TLS implementations too, such a TLS implementation for an RTOS. + +// Same layout as libgcc __emutls_object. Unfortunately, __emutls_object doesn't appear in any header files. +typedef struct { + uint size; + uint align; + union { + struct { + uint offset; + void *template; + } s; + void* lookup[NUM_CORES]; + } u; +} tls_object; + +extern tls_object __emutls_array_start; +extern tls_object __emutls_array_end; + +static char* tls_storage[NUM_CORES]; + +void tls_init(void); +void* __wrap___emutls_get_address(tls_object*); + +// Must be called after it is safe to call memcpy. +void tls_init(void) { + // Three passes: + // 1) Calculate the offset of each thread local variable and the total storage to be allocated for each thread. + uint offset = 0; + uint max_align = 1; + for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { + assert((object->align & (object->align - 1)) == 0); + + if (object->align > max_align) { + max_align = object->align; + } + + offset = (offset + object->align - 1) & ~(object->align - 1); + object->u.s.offset = offset; + offset += object->size; + } + + if (offset == 0) { + return; + } + + // 2) Allocate storage for each thread and initialize the thread local variables to their initial value. + for (uint i = 0; i < NUM_CORES; ++i) { + // TODO: tls_init is invoked before pico_malloc's auto-initialized mutex has been initialized. + // However, aligned_alloc and memalign are not wrapped by pico_malloc so don't acquire or release + // the mutex so this works, though not for a satisfying reason. + // + // What I would like to do here, since malloc and friends ought not to be called at this point in + // initialization, is decrement the heap limit buy the TLS storage size. At time of writing, the + // heap limit is &__StackLimit, i.e. static. It could be dynamic though. + char* storage = tls_storage[i] = (char*) aligned_alloc(max_align, offset); + + for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { + if (object->u.s.template) { + memcpy(storage + object->u.s.offset, object->u.s.template, object->size); + } else { + memset(storage + object->u.s.offset, 0, object->size); + } + } + } + + // 3) Repurpose the tls_objects so each contains a lookup table mapping from core index to pointer to + // thread local variable. + for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { + uint offset = object->u.s.offset; + for (uint i = 0; i < NUM_CORES; ++i) { + object->u.lookup[i] = tls_storage[i] + offset; + } + } +} + +void* __wrap___emutls_get_address(tls_object* object) { + return object->u.lookup[get_core_num()]; +} diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index a2019919c..fb25a264d 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -37,6 +37,7 @@ target_link_libraries(kitchen_sink_libs INTERFACE pico_platform pico_stdlib pico_sync + pico_tls pico_time pico_unique_id pico_util diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index a49654d1b..77280608f 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -116,6 +116,9 @@ __force_inline int something_inlined(int x) { auto_init_mutex(mutex); auto_init_recursive_mutex(recursive_mutex); +__thread int initialized_tls_var = 7; +__thread int uninitialized_tls_var; + int main(void) { spiggle(); @@ -129,6 +132,12 @@ int main(void) { hard_assert(!mutex_try_enter(&mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); + + hard_assert(initialized_tls_var == 7); + hard_assert(uninitialized_tls_var == 0); + initialized_tls_var = 8; + hard_assert(initialized_tls_var == 8); + // this should compile as we are Cortex M0+ __asm volatile("SVC #3"); From 36ba3bd6e7fc9800f6ee563617cc1c0e5261cbb1 Mon Sep 17 00:00:00 2001 From: Al Date: Sat, 10 Sep 2022 15:08:59 -0700 Subject: [PATCH 2/8] assert if emutls_get_address called from exception --- src/rp2_common/pico_tls/tls.c | 2 ++ test/kitchen_sink/kitchen_sink.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c index ebb78fe73..5736c12d7 100644 --- a/src/rp2_common/pico_tls/tls.c +++ b/src/rp2_common/pico_tls/tls.c @@ -93,5 +93,7 @@ void tls_init(void) { } void* __wrap___emutls_get_address(tls_object* object) { + // TLS storage is not allocated for exceptions. + assert(!__get_current_exception()); return object->u.lookup[get_core_num()]; } diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 77280608f..30583bc5a 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -116,8 +116,12 @@ __force_inline int something_inlined(int x) { auto_init_mutex(mutex); auto_init_recursive_mutex(recursive_mutex); -__thread int initialized_tls_var = 7; -__thread int uninitialized_tls_var; +#ifndef __cplusplus +#define thread_local __thread +#endif + +thread_local int initialized_tls_var = 7; +thread_local int uninitialized_tls_var; int main(void) { spiggle(); From af970625aca70c3f6576fbd6d769ab72e0c0a4a6 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 11 Sep 2022 07:44:23 -0700 Subject: [PATCH 3/8] comment & white space fixes --- src/rp2_common/pico_tls/tls.S | 6 ++++++ src/rp2_common/pico_tls/tls.c | 28 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/rp2_common/pico_tls/tls.S b/src/rp2_common/pico_tls/tls.S index bfe2caaa6..85a689aa0 100644 --- a/src/rp2_common/pico_tls/tls.S +++ b/src/rp2_common/pico_tls/tls.S @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include "pico/asm_helper.S" // This has to happen after memcpy() and memset() are available. diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c index 5736c12d7..4509edf5d 100644 --- a/src/rp2_common/pico_tls/tls.c +++ b/src/rp2_common/pico_tls/tls.c @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include "pico.h" #include @@ -21,15 +27,15 @@ // Same layout as libgcc __emutls_object. Unfortunately, __emutls_object doesn't appear in any header files. typedef struct { - uint size; - uint align; - union { - struct { - uint offset; - void *template; - } s; - void* lookup[NUM_CORES]; - } u; + uint size; + uint align; + union { + struct { + uint offset; + void *template; + } s; + void* lookup[NUM_CORES]; + } u; } tls_object; extern tls_object __emutls_array_start; @@ -40,7 +46,7 @@ static char* tls_storage[NUM_CORES]; void tls_init(void); void* __wrap___emutls_get_address(tls_object*); -// Must be called after it is safe to call memcpy. +// Must be called after it is safe to call memcpy & memset. void tls_init(void) { // Three passes: // 1) Calculate the offset of each thread local variable and the total storage to be allocated for each thread. @@ -69,7 +75,7 @@ void tls_init(void) { // the mutex so this works, though not for a satisfying reason. // // What I would like to do here, since malloc and friends ought not to be called at this point in - // initialization, is decrement the heap limit buy the TLS storage size. At time of writing, the + // initialization, is decrement the heap limit by the TLS storage size. At time of writing, the // heap limit is &__StackLimit, i.e. static. It could be dynamic though. char* storage = tls_storage[i] = (char*) aligned_alloc(max_align, offset); From 92d1eac9838affe33bb7d18cc25077ffffa65ebf Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 11 Sep 2022 08:35:35 -0700 Subject: [PATCH 4/8] pico_runtime no longer depends on pico_tls --- src/rp2_common/pico_runtime/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/rp2_common/pico_runtime/CMakeLists.txt b/src/rp2_common/pico_runtime/CMakeLists.txt index b46ff60c9..3b6cc1817 100644 --- a/src/rp2_common/pico_runtime/CMakeLists.txt +++ b/src/rp2_common/pico_runtime/CMakeLists.txt @@ -38,9 +38,6 @@ endif() if (TARGET pico_standard_link) target_link_libraries(pico_runtime INTERFACE pico_standard_link) endif() -if (TARGET pico_tls) - target_link_libraries(pico_runtime INTERFACE pico_tls) -endif() # todo is this correct/needed? target_link_options(pico_runtime INTERFACE "--specs=nosys.specs") From f1b296942fe63213ecfb2cbf8ef31a0c1a8993c8 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 11 Sep 2022 09:36:51 -0700 Subject: [PATCH 5/8] Allow TLS objects to be garbage collected --- src/rp2_common/pico_standard_link/memmap_blocked_ram.ld | 2 +- src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld | 2 +- src/rp2_common/pico_standard_link/memmap_default.ld | 2 +- src/rp2_common/pico_standard_link/memmap_no_flash.ld | 2 +- test/kitchen_sink/kitchen_sink.c | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld b/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld index 101dcb67e..e35255195 100644 --- a/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_standard_link/memmap_blocked_ram.ld @@ -138,7 +138,7 @@ SECTIONS . = ALIGN(4); /* emutls objects */ PROVIDE_HIDDEN (__emutls_array_start = .); - KEEP(*(.data.__emutls_v.*)) + *(.*.__emutls_v.*) PROVIDE_HIDDEN (__emutls_array_end = .); . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld index eeced1283..e565f8199 100644 --- a/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld @@ -137,7 +137,7 @@ SECTIONS . = ALIGN(4); /* emutls objects */ PROVIDE_HIDDEN (__emutls_array_start = .); - KEEP(*(.data.__emutls_v.*)) + *(.*.__emutls_v.*) PROVIDE_HIDDEN (__emutls_array_end = .); . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_default.ld b/src/rp2_common/pico_standard_link/memmap_default.ld index c3dd1a76c..dc8582770 100644 --- a/src/rp2_common/pico_standard_link/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/memmap_default.ld @@ -138,7 +138,7 @@ SECTIONS . = ALIGN(4); /* emutls objects */ PROVIDE_HIDDEN (__emutls_array_start = .); - KEEP(*(.data.__emutls_v.*)) + *(.*.__emutls_v.*) PROVIDE_HIDDEN (__emutls_array_end = .); . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/memmap_no_flash.ld index 184461775..6f34c1ac4 100644 --- a/src/rp2_common/pico_standard_link/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/memmap_no_flash.ld @@ -109,7 +109,7 @@ SECTIONS . = ALIGN(4); /* emutls objects */ PROVIDE_HIDDEN (__emutls_array_start = .); - KEEP(*(.data.__emutls_v.*)) + *(.*.__emutls_v.*) PROVIDE_HIDDEN (__emutls_array_end = .); . = ALIGN(4); diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 30583bc5a..16fc5c26c 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -121,7 +121,9 @@ auto_init_recursive_mutex(recursive_mutex); #endif thread_local int initialized_tls_var = 7; +thread_local int __attribute__((section("other_section"))) other_section_tls_var = 7; thread_local int uninitialized_tls_var; +thread_local int garbage_collected_tls_var; int main(void) { spiggle(); @@ -138,6 +140,7 @@ int main(void) { hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(initialized_tls_var == 7); + hard_assert(other_section_tls_var == 7); hard_assert(uninitialized_tls_var == 0); initialized_tls_var = 8; hard_assert(initialized_tls_var == 8); From 9ef746afc5056f5c7b9628c2e6b34fa28d0331c6 Mon Sep 17 00:00:00 2001 From: Al Date: Tue, 13 Sep 2022 20:37:42 -0700 Subject: [PATCH 6/8] Give tls_storage auto storage class. Rename it to stores. --- src/rp2_common/pico_tls/tls.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c index 4509edf5d..825e64c08 100644 --- a/src/rp2_common/pico_tls/tls.c +++ b/src/rp2_common/pico_tls/tls.c @@ -41,8 +41,6 @@ typedef struct { extern tls_object __emutls_array_start; extern tls_object __emutls_array_end; -static char* tls_storage[NUM_CORES]; - void tls_init(void); void* __wrap___emutls_get_address(tls_object*); @@ -69,6 +67,7 @@ void tls_init(void) { } // 2) Allocate storage for each thread and initialize the thread local variables to their initial value. + char* stores[NUM_CORES]; for (uint i = 0; i < NUM_CORES; ++i) { // TODO: tls_init is invoked before pico_malloc's auto-initialized mutex has been initialized. // However, aligned_alloc and memalign are not wrapped by pico_malloc so don't acquire or release @@ -77,7 +76,7 @@ void tls_init(void) { // What I would like to do here, since malloc and friends ought not to be called at this point in // initialization, is decrement the heap limit by the TLS storage size. At time of writing, the // heap limit is &__StackLimit, i.e. static. It could be dynamic though. - char* storage = tls_storage[i] = (char*) aligned_alloc(max_align, offset); + char* storage = stores[i] = (char*) aligned_alloc(max_align, offset); for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { if (object->u.s.template) { @@ -93,7 +92,7 @@ void tls_init(void) { for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { uint offset = object->u.s.offset; for (uint i = 0; i < NUM_CORES; ++i) { - object->u.lookup[i] = tls_storage[i] + offset; + object->u.lookup[i] = stores[i] + offset; } } } From 88b81e7a820e1bc70577e3da34de8856d8e4b5fc Mon Sep 17 00:00:00 2001 From: Al Date: Tue, 13 Sep 2022 21:20:18 -0700 Subject: [PATCH 7/8] #include --- src/rp2_common/pico_tls/tls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c index 825e64c08..a44f4f42d 100644 --- a/src/rp2_common/pico_tls/tls.c +++ b/src/rp2_common/pico_tls/tls.c @@ -6,6 +6,7 @@ #include "pico.h" +#include #include #include From 365f81860f8705d4bb6e22f78ba036370a32b92c Mon Sep 17 00:00:00 2001 From: Al Date: Tue, 13 Sep 2022 21:33:11 -0700 Subject: [PATCH 8/8] Try to fix aligned_alloc build action error: newlib/libc/stdlib/aligned_alloc.c:35: undefined reference to `posix_memalign' Maybe memalign() works. --- src/rp2_common/pico_tls/tls.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/rp2_common/pico_tls/tls.c b/src/rp2_common/pico_tls/tls.c index a44f4f42d..3ac7d9cff 100644 --- a/src/rp2_common/pico_tls/tls.c +++ b/src/rp2_common/pico_tls/tls.c @@ -7,14 +7,10 @@ #include "pico.h" #include +#include #include #include -#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 201112) -#include -#define aligned_alloc memalign -#endif - // From emutls.c: // 'For every TLS variable xyz, there is one __emutls_control variable named __emutls_v.xyz. If xyz has // non-zero initial value, __emutls_v.xyz's "value" will point to __emutls_t.xyz, which has the initial value.' @@ -77,7 +73,7 @@ void tls_init(void) { // What I would like to do here, since malloc and friends ought not to be called at this point in // initialization, is decrement the heap limit by the TLS storage size. At time of writing, the // heap limit is &__StackLimit, i.e. static. It could be dynamic though. - char* storage = stores[i] = (char*) aligned_alloc(max_align, offset); + char* storage = stores[i] = (char*) memalign(max_align, offset); for (tls_object* object = &__emutls_array_start; object < &__emutls_array_end; ++object) { if (object->u.s.template) {