[PATCH] newlib: import TLS initialization and helpers from picolibc

Torbjörn SVENSSON <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
Hi,

With the decision from Arm to build a GCC toolchain without --disable-tls,
newlib needs to have support in the start code to initialize the TLS block
and implement __aeabi_read_tp to allow GCC to know what thread is current.

The change in the build rules were done in:
https://gitlab.arm.com/tooling/gnu-devtools-for-arm/-/commit/f6a8633309c850d62817859986a165c94f11babf

Below patch imports the implementation from picolibc and leaves the header
filenames as-is, thus, the main header file to include in an application
is picotls.h

Note: This implementation primarily targets TLS mode local-exec. Other
modes might require additional functions to be added.
Also, I've only ported the parts that I've seen as required for
arm-none-eabi, other targets might benefit from TLS support, but I do not
have access to other hardware to validate the implementation on.

For TLS to be properly supported on arm-none-eabi, the following fix is
also required in ld:
https://sourceware.org/pipermail/binutils/2026-August/150870.html


Ok for master?

Kind regards,
Torbjörn

--

This patch introduces, optional, TLS (thread local storage) initialization to
the startup code. It also brings in the same interface that is exposed to the
application from picolibc so that an application can initialize additional
blocks as needed and switch to them when switching tasks.

The picolibc sources are kept as-is except for:

- _BEGIN_STD_C -> __BEGIN_DECLS
- _END_STD_C -> __END_DECLS
- #include <picolibc.h> -> #include <newlib.h>

Origin of the code is picolibc-1.8.12.

This new feature is activated by --enable-newlib-thread-local-storage.

Signed-off-by: Torbjörn SVENSSON <[email protected]>
---
 libgloss/arm/crt0.S                  | 13 ++++
 newlib/configure                     | 21 ++++++
 newlib/configure.ac                  | 13 ++++
 newlib/libc/include/picotls.h        | 76 +++++++++++++++++++++
 newlib/libc/machine/arm/Makefile.inc |  1 +
 newlib/libc/machine/arm/arm_tls.h    | 60 +++++++++++++++++
 newlib/libc/machine/arm/read_tp.S    | 98 ++++++++++++++++++++++++++++
 newlib/libc/machine/arm/set_tls.c    | 79 ++++++++++++++++++++++
 newlib/libc/machine/arm/tls.c        | 52 +++++++++++++++
 newlib/libc/misc/Makefile.inc        |  1 +
 newlib/libc/misc/inittls.c           | 77 ++++++++++++++++++++++
 newlib/libc/sys/arm/crt0.S           | 13 ++++
 newlib/newlib.hin                    |  6 ++
 13 files changed, 510 insertions(+)
 create mode 100644 newlib/libc/include/picotls.h
 create mode 100644 newlib/libc/machine/arm/arm_tls.h
 create mode 100644 newlib/libc/machine/arm/read_tp.S
 create mode 100644 newlib/libc/machine/arm/set_tls.c
 create mode 100644 newlib/libc/machine/arm/tls.c
 create mode 100644 newlib/libc/misc/inittls.c

diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
index b9e768007..81033a3b2 100644
--- a/libgloss/arm/crt0.S
+++ b/libgloss/arm/crt0.S
@@ -388,6 +388,15 @@ __change_mode:
 #endif
 	
 	bl	FUNCTION (memset)
+
+#ifdef __THREAD_LOCAL_STORAGE
+    /* Initialize TLS in local-exec mode.  */
+	ldr	a1, .LCtls_base	/* First arg: TLS block.  */
+	bl	FUNCTION (_init_tls)
+	ldr	a1, .LCtls_base	/* First arg: TLS block.  */
+	bl	FUNCTION (_set_tls)
+#endif
+
 #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
 /* Changes by toralf: Taken from libgloss/m68k/crt0.S
    initialize target specific stuff. Only execute these
@@ -607,6 +616,10 @@ change_back:
 	.word	__bss_start__
 .LC2:
 	.word	__bss_end__
+#ifdef __THREAD_LOCAL_STORAGE
+.LCtls_base:
+	.word	__tls_base
+#endif
 #ifdef __USES_INITFINI__
 #ifdef _LITE_EXIT
 .Latexit:
diff --git a/newlib/configure b/newlib/configure
index ab31510aa..0ff110a7c 100755
--- a/newlib/configure
+++ b/newlib/configure
@@ -988,6 +988,7 @@ enable_newlib_global_atexit
 enable_newlib_reent_small
 enable_newlib_reent_binary_compat
 enable_newlib_reent_thread_local
+enable_newlib_thread_local_storage
 enable_newlib_global_stdio_streams
 enable_newlib_fvwrite_in_streamio
 enable_newlib_fseek_optimization
@@ -1659,6 +1660,7 @@ Optional Features:
   --enable-newlib-reent-small   enable small reentrant struct support
   --enable-newlib-reent-binary-compat   enable backward binary compatibility for struct _reent
   --enable-newlib-reent-thread-local   enable thread-local storage objects as a replacment for struct _reent members
+  --enable-newlib-thread-local-storage enable the TLS runtime API
   --enable-newlib-global-stdio-streams   enable global stdio streams
   --disable-newlib-fvwrite-in-streamio    disable iov in streamio
   --disable-newlib-fseek-optimization    disable fseek optimization
@@ -2437,6 +2439,17 @@ else
   newlib_reent_thread_local=no
 fi
 
+# Check whether --enable-newlib-thread-local-storage was given.
+if test "${enable_newlib_thread_local_storage+set}" = set; then :
+  enableval=$enable_newlib_thread_local_storage; case "${enableval}" in
+  yes) newlib_thread_local_storage=yes ;;
+  no)  newlib_thread_local_storage=no ;;
+  *) as_fn_error $? "bad value ${enableval} for newlib-thread-local-storage option" "$LINENO" 5 ;;
+ esac
+else
+  newlib_thread_local_storage=no
+fi
+
 # Check whether --enable-newlib-global-stdio-streams was given.
 if test "${enable_newlib_global_stdio_streams+set}" = set; then :
   enableval=$enable_newlib_global_stdio_streams; case "${enableval}" in
@@ -6603,6 +6616,14 @@ $as_echo "#define _WANT_REENT_THREAD_LOCAL 1" >>confdefs.h
 
 fi
 
+if test "${newlib_thread_local_storage}" = "yes"; then
+
+$as_echo "#define __THREAD_LOCAL_STORAGE 1" >>confdefs.h
+
+$as_echo "#define __THREAD_LOCAL_STORAGE_API 1" >>confdefs.h
+
+fi
+
 _mb_len_max=1
 if test "${newlib_mb}" = "yes"; then
 
diff --git a/newlib/configure.ac b/newlib/configure.ac
index a4807830e..0ade683a8 100644
--- a/newlib/configure.ac
+++ b/newlib/configure.ac
@@ -187,6 +187,14 @@ AC_ARG_ENABLE(newlib-reent-thread-local,
   esac
  fi], [newlib_reent_thread_local=no])dnl
 
+AC_ARG_ENABLE(newlib-thread-local-storage,
+[  --enable-newlib-thread-local-storage enable the TLS runtime API],
+[case "${enableval}" in
+  yes) newlib_thread_local_storage=yes ;;
+  no)  newlib_thread_local_storage=no ;;
+  *)   AC_MSG_ERROR(bad value ${enableval} for newlib-thread-local-storage option) ;;
+ esac], [newlib_thread_local_storage=no])dnl
+
 dnl Support --enable-newlib-global-stdio-streams
 dnl This is no longer optional.  It is enabled in all Newlib configurations.
 AC_ARG_ENABLE(newlib-global-stdio-streams,
@@ -478,6 +486,11 @@ if test "${newlib_reent_thread_local}" = "yes"; then
   AC_DEFINE(_WANT_REENT_THREAD_LOCAL, 1, [Define to enable thread-local storage objects as a replacment for struct _reent members.])
 fi
 
+if test "${newlib_thread_local_storage}" = "yes"; then
+  AC_DEFINE(__THREAD_LOCAL_STORAGE, 1, [Define to enable the TLS runtime API.])
+  AC_DEFINE(__THREAD_LOCAL_STORAGE_API, 1, [Define to enable the TLS runtime API.])
+fi
+
 _mb_len_max=1
 if test "${newlib_mb}" = "yes"; then
   AC_DEFINE(_MB_CAPABLE, 1, [Multibyte supported.])
diff --git a/newlib/libc/include/picotls.h b/newlib/libc/include/picotls.h
new file mode 100644
index 000000000..e87f0b58a
--- /dev/null
+++ b/newlib/libc/include/picotls.h
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2019 Keith Packard
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PICOTLS_H_
+#define _PICOTLS_H_
+
+#include <sys/cdefs.h>
+
+#ifdef __THREAD_LOCAL_STORAGE
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+extern char __tls_size[];
+
+static inline size_t
+_tls_size(void)
+{
+    return (size_t)(uintptr_t)__tls_size;
+}
+
+extern char __tls_align[];
+
+static inline size_t
+_tls_align(void)
+{
+    return (size_t)(uintptr_t)__tls_align;
+}
+
+/*
+ * Initialize a TLS block, copying the data segment from flash and
+ * zeroing the BSS segment.
+ */
+void _init_tls(void *tls);
+
+/* Set the TLS pointer to the specific block */
+void _set_tls(void *tls);
+
+__END_DECLS
+
+#endif
+
+#endif /* _PICOTLS_H_ */
diff --git a/newlib/libc/machine/arm/Makefile.inc b/newlib/libc/machine/arm/Makefile.inc
index 2d6c08d71..253e54620 100644
--- a/newlib/libc/machine/arm/Makefile.inc
+++ b/newlib/libc/machine/arm/Makefile.inc
@@ -3,6 +3,7 @@ libc_a_SOURCES += \
 	%D%/aeabi_memcpy.c %D%/aeabi_memcpy-armv7a.S \
 	%D%/aeabi_memmove.c %D%/aeabi_memmove-soft.S \
 	%D%/aeabi_memset.c %D%/aeabi_memset-soft.S %D%/aeabi_memclr.c \
+	%D%/tls.c %D%/set_tls.c %D%/read_tp.S \
 	%D%/memchr-stub.c \
 	%D%/memchr.S \
 	%D%/memcpy-stub.c \
diff --git a/newlib/libc/machine/arm/arm_tls.h b/newlib/libc/machine/arm/arm_tls.h
new file mode 100644
index 000000000..0a7421d68
--- /dev/null
+++ b/newlib/libc/machine/arm/arm_tls.h
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2020 Keith Packard
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if ((__ARM_FEATURE_COPROC & 1) || __ARM_ARCH >= 8) && __ARM_ARCH_PROFILE != 'M' && __ARM_ARCH >= 6
+#define ARM_TLS_CP15
+#endif
+
+/* Switch cortex-m0 to use RP2040 CPUID register if requested */
+#ifdef __THREAD_LOCAL_STORAGE_RP2040
+#define ARM_RP2040
+#endif
+
+#ifdef ARM_RP2040
+#define RP2040_SIO_BASE 0xd0000000
+#define RP2040_CPUID    (RP2040_SIO_BASE + 0)
+#define ARM_TLS_COUNT   2
+#else
+#define ARM_TLS_COUNT 1
+#endif
+
+#ifndef _IN_ASM
+/* This needs to be global so that __aeabi_read_tp can
+ * refer to it in an asm statement
+ */
+#ifndef ARM_TLS_CP15
+extern void *__tls[ARM_TLS_COUNT];
+#endif
+#endif
diff --git a/newlib/libc/machine/arm/read_tp.S b/newlib/libc/machine/arm/read_tp.S
new file mode 100644
index 000000000..811e073f8
--- /dev/null
+++ b/newlib/libc/machine/arm/read_tp.S
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2020 Keith Packard
+ * Copyright © 2024 Stephen Street
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <newlib.h>
+
+#ifdef __THREAD_LOCAL_STORAGE
+
+#define _IN_ASM
+#include "arm_tls.h"
+/*
+ * This cannot be a C ABI function as the compiler assumes that it
+ * does not modify anything other than r0 and lr.
+ */
+	.syntax unified
+	.section .text.__aeabi_read_tp
+	.align 4
+	.p2align 4,,15
+	.global __aeabi_read_tp
+	.type __aeabi_read_tp,%function
+#ifdef __thumb__
+	.thumb
+#endif
+
+__aeabi_read_tp:
+	.cfi_sections .debug_frame
+	.cfi_startproc
+
+#ifdef ARM_TLS_CP15
+	mrc p15, 0, r0, c13, c0, 3
+	bx lr
+#else
+
+#ifdef ARM_RP2040
+
+	/*
+	 * Code for RP2040 processor. This is a dual-core cortex-m0
+	 * design. We use the CPUID register, stored at offset zero of
+	 * the Single-cycle IO block at 0xd0000000
+	 */
+
+#define TLS_SIZE	(4 * RP2040_NCORE)
+
+	push {r1,lr}		/* Save R1 (and LR) */
+	ldr r1,=0xd0000000	/* Address of SIO->CPUID */
+	ldr r1,[r1]	   	/* Fetch active core */
+	lsls r1,r1,#2	   	/* Multiply by 4 */
+	ldr r0,=__tls		/* Address of __tls array */
+	ldr r0,[r0,r1]		/* Fetch __tls[CPUID] */
+	pop {r1,pc}		/* Restore R1 and return  */
+
+#else
+
+#define TLS_SIZE	4
+
+	ldr r0,=__tls		/* Load the address of __tls */
+	ldr r0,[r0]		/* Dereference to get the value of __tls */
+	bx lr			/* All done, return to caller */
+
+#endif
+
+#endif
+
+	.cfi_endproc
+
+#endif
+
diff --git a/newlib/libc/machine/arm/set_tls.c b/newlib/libc/machine/arm/set_tls.c
new file mode 100644
index 000000000..fd3e940f6
--- /dev/null
+++ b/newlib/libc/machine/arm/set_tls.c
@@ -0,0 +1,79 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2019 Keith Packard
+ * Copyright © 2024 Stephen Street
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <picotls.h>
+#include <string.h>
+#include <stdint.h>
+
+#ifdef __THREAD_LOCAL_STORAGE_API
+
+#include "arm_tls.h"
+
+/* This needs to be global so that __aeabi_read_tp can
+ * refer to it in an asm statement
+ */
+#ifndef ARM_TLS_CP15
+extern void *__tls[];
+#endif
+
+/* The size of the thread control block.
+ * TLS relocations are generated relative to
+ * a location this far *before* the first thread
+ * variable (!)
+ * NB: The actual size before tp also includes padding
+ * to align up to the alignment of .tdata/.tbss.
+ */
+#define TCB_SIZE 8
+extern char __arm32_tls_tcb_offset;
+#define TP_OFFSET ((size_t)&__arm32_tls_tcb_offset)
+
+void
+_set_tls(void *tls)
+{
+    tls = (uint8_t *)tls - TP_OFFSET;
+#ifdef ARM_TLS_CP15
+    __asm__("mcr p15, 0, %0, cr13, cr0, 3" : : "r"(tls));
+#else
+#ifdef ARM_RP2040
+    uint32_t cpuid = *(uint32_t *)0xd0000000;
+    __tls[cpuid] = tls;
+#else
+    __tls[0] = tls;
+#endif
+#endif
+}
+
+#endif
diff --git a/newlib/libc/machine/arm/tls.c b/newlib/libc/machine/arm/tls.c
new file mode 100644
index 000000000..156b9d72a
--- /dev/null
+++ b/newlib/libc/machine/arm/tls.c
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2019 Keith Packard
+ * Copyright © 2024 Stephen Street
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <picotls.h>
+#include <string.h>
+#include <stdint.h>
+
+#ifdef __THREAD_LOCAL_STORAGE
+
+#include "arm_tls.h"
+
+/* This needs to be global so that __aeabi_read_tp can
+ * refer to it in an asm statement
+ */
+#ifndef ARM_TLS_CP15
+void *__tls[ARM_TLS_COUNT];
+#endif
+
+#endif
diff --git a/newlib/libc/misc/Makefile.inc b/newlib/libc/misc/Makefile.inc
index 78bb022dd..1abd05295 100644
--- a/newlib/libc/misc/Makefile.inc
+++ b/newlib/libc/misc/Makefile.inc
@@ -2,6 +2,7 @@ libc_a_SOURCES += \
 	%D%/__dprintf.c \
 	%D%/unctrl.c \
 	%D%/ffs.c \
+	%D%/inittls.c \
 	%D%/init.c \
 	%D%/fini.c
 
diff --git a/newlib/libc/misc/inittls.c b/newlib/libc/misc/inittls.c
new file mode 100644
index 000000000..458013fbb
--- /dev/null
+++ b/newlib/libc/misc/inittls.c
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright © 2019 Keith Packard
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <picotls.h>
+#include <string.h>
+#include <stdint.h>
+
+#ifdef __THREAD_LOCAL_STORAGE_API
+
+/*
+ * The TLS block consists of initialized data immediately followed by
+ * zero filled data
+ *
+ * These addresses must be defined by the loader configuration file
+ */
+
+extern char __tdata_source[]; /* Source of TLS initialization data (in ROM) */
+
+#ifdef __PICOCRT_RUNTIME_SIZE
+extern char __tdata_start[]; /* Start of static tdata area */
+extern char __tdata_end[];   /* End of static tdata area */
+extern char __tbss_start[];  /* Start of static zero-initialized TLS data */
+extern char __tbss_end[];    /* End of static zero-initialized TLS data */
+#define __tdata_size  (__tdata_end - __tdata_start)
+#define __tbss_size   (__tbss_end - __tbss_start)
+#define __tbss_offset (__tbss_start - __tdata_start)
+#else
+extern char __tdata_size[];  /* Size of TLS initized data */
+extern char __tbss_size[];   /* Size of TLS zero-filled data */
+extern char __tbss_offset[]; /* Offset from tdata to tbss */
+#endif
+
+void
+_init_tls(void *__tls)
+{
+    char *tls = __tls;
+
+    /* Copy tls initialized data */
+    memcpy(tls, __tdata_source, (uintptr_t)__tdata_size);
+
+    /* Clear tls zero data */
+    memset(tls + (uintptr_t)__tbss_offset, '\0', (uintptr_t)__tbss_size);
+}
+
+#endif
diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
index 51e86d549..ea2122d93 100644
--- a/newlib/libc/sys/arm/crt0.S
+++ b/newlib/libc/sys/arm/crt0.S
@@ -375,6 +375,15 @@ __change_mode:
 #endif
 	
 	bl	FUNCTION (memset)
+
+#ifdef __THREAD_LOCAL_STORAGE
+    /* Initialize TLS in local-exec mode.  */
+	ldr	a1, .LCtls_base	/* First arg: TLS block.  */
+	bl	FUNCTION (_init_tls)
+	ldr	a1, .LCtls_base	/* First arg: TLS block.  */
+	bl	FUNCTION (_set_tls)
+#endif
+
 #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
 /* Changes by toralf: Taken from libgloss/m68k/crt0.S
    initialize target specific stuff. Only execute these
@@ -598,6 +607,10 @@ change_back:
 	.word	__bss_start__
 .LC2:
 	.word	__bss_end__
+#ifdef __THREAD_LOCAL_STORAGE
+.LCtls_base:
+	.word	__tls_base
+#endif
 #ifdef __USES_INITFINI__
 #ifdef _LITE_EXIT
 .Latexit:
diff --git a/newlib/newlib.hin b/newlib/newlib.hin
index 52cd500db..350762f2f 100644
--- a/newlib/newlib.hin
+++ b/newlib/newlib.hin
@@ -420,6 +420,12 @@
    _reent members. */
 #undef _WANT_REENT_THREAD_LOCAL
 
+/* Define to enable the TLS runtime API. */
+#undef __THREAD_LOCAL_STORAGE
+
+/* Define to enable the TLS runtime API. */
+#undef __THREAD_LOCAL_STORAGE_API
+
 /* Register application finalization function using atexit. */
 #undef _WANT_REGISTER_FINI
 
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.