Loading...
Searching...
No Matches
picotls.h
1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2019 Keith Packard
5 * Copyright (c) 2026 Raspberry Pi (Trading) Ltd.
6 */
7#ifndef _PICO_THREAD_LOCAL_PICOTLS_H
8#define _PICO_THREAD_LOCAL_PICOTLS_H
9
10// Note the name of this file is slightly confusing - this is actually overriding <picotls.h> from picolibc (if present)!
11
32
33// PICO_CONFIG: PICO_THREAD_LOCAL_MODE_PER_THREAD, Enable proper thread local support with one value per thread, type=bool, default=1, group=pico_thread_local
34// PICO_CONFIG: PICO_THREAD_LOCAL_MODE_GLOBAL, Support compiling code with thread local variables but only keep one global value, type=bool, default=0, group=pico_thread_local
35// PICO_CONFIG: PICO_THREAD_LOCAL_MODE_NONE, No support for thread local variables. Code using __thread may or may not compile/link or work correctly, type=bool, default=0, group=pico_thread_local
36
37// PICO_CONFIG: PICO_THREAD_LOCAL_SUPPORT_EMUTLS, Thread local support should work with compilers that use emutls, type=bool, default=1, advanced=true, group=pico_thread_local
38// PICO_CONFIG: PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER, Thread local support should work with compilers that use a per thread pointer and provide .tdata and .tbss, type=bool, default=1, advanced=true, group=pico_thread_local
39
40// PICO_CONFIG: PICO_THREAD_LOCAL_EMUTLS_CONFIRMED, Passed from build if the compiler is known to use Emutls and so other types of support are not needed, type=bool, default=0, advanced=true, group=pico_thread_local
41// PICO_CONFIG: PICO_THREAD_LOCAL_THREAD_POINTER_ARM_AEABI_CONFIRMED, Passed from build if the compiler is known to use a thread pointer accessed via __areabi_read_tp and so other types of support are not needed, type=bool, default=0, advanced=true, group=pico_thread_local
42// PICO_CONFIG: PICO_THREAD_LOCAL_THREAD_POINTER_RISCV_REG_CONFIRMED, Passed from build if the compiler is known to use a thread pointer stored in the TP register and so other types of support are not needed, type=bool, default=0, advanced=true, group=pico_thread_local
43
44// Default is PICO_THREAD_LOCAL_MODE_PER_THREAD if not specified
45#if !PICO_THREAD_LOCAL_MODE_PER_THREAD && !PICO_THREAD_LOCAL_MODE_GLOBAL && !PICO_THREAD_LOCAL_MODE_NONE
46#undef PICO_THREAD_LOCAL_MODE_PER_THREAD
47#define PICO_THREAD_LOCAL_MODE_PER_THREAD 1
48#endif
49
50// Rest of file is contingent on not being in PICO_THREAD_LOCAL_MODE_NONE...
51#if !PICO_THREAD_LOCAL_MODE_NONE
52#if !PICO_THREAD_LOCAL_SUPPORT_EMUTLS && !PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER
53// PICO_THREAD_LOCAL_EMUTLS_CONFIRMED, PICO_THREAD_LOCAL_THREAD_POINTER_ARM_AEABI_CONFIRMED PICO_THREAD_LOCAL_THREAD_POINTER_RISCV_REG_CONFIRMED are
54// optional defines provided by the build that allow us to improve code size slightly if only one is set
55
56#if PICO_THREAD_LOCAL_EMUTLS_CONFIRMED + PICO_THREAD_LOCAL_THREAD_POINTER_ARM_AEABI_CONFIRMED + PICO_THREAD_LOCAL_THREAD_POINTER_RISCV_REG_CONFIRMED > 1
57#error expected at most one of PICO_THREAD_LOCAL_EMUTLS_CONFIRMED, PICO_THREAD_LOCAL_THREAD_POINTER_ARM_AEABI_CONFIRMED and PICO_THREAD_LOCAL_THREAD_POINTER_RISCV_REG_CONFIRMED to be set
58#endif
59
60#if PICO_THREAD_LOCAL_EMUTLS_CONFIRMED
61#define PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER 0
62#define PICO_THREAD_LOCAL_SUPPORT_EMUTLS 1
63#elif PICO_THREAD_LOCAL_THREAD_POINTER_ARM_AEABI_CONFIRMED || PICO_THREAD_LOCAL_THREAD_POINTER_RISCV_REG_CONFIRMED || defined(PICOLIBC_TLS) || __riscv
64// we assume here and in thread_local.c that if PICOLIBC_TLS is set, or we're on RISC-V
65// then we're not using emutls - we may want to re-visit if in practice this is not always the case
66//
67// particularly, with respect to RISC-V the fact that we have to set TP on thread init
68// means that TLS code cannot be elided on RISC-V so we want it to be as small as possible
69#define PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER 1
70#define PICO_THREAD_LOCAL_SUPPORT_EMUTLS 0
71#else
72// we know nothing, so support both at potential extra runtime cost
73#define PICO_THREAD_LOCAL_SUPPORT_THREAD_POINTER 1
74#define PICO_THREAD_LOCAL_SUPPORT_EMUTLS 1
75#endif
76#endif
77
78#if PICO_THREAD_LOCAL_SUPPORT_EMUTLS || PICO_THREAD_LOCAL_MODE_GLOBAL || PICO_THREAD_LOCAL_MODE_NONE
79#define PICO_THREAD_LOCAL_REQUIRES_CUSTOM_TLS_SIZE 1
80#endif
81
82// we can't use the stock header if supporting emutls as the TLS size isn't known at link time
83#if !PICO_THREAD_LOCAL_REQUIRES_CUSTOM_TLS_SIZE && defined(__has_include_next) && __has_include_next(<picotls.h>)
84// just use the stock header
85#include_next <picotls.h>
86#else
87
88#include <stddef.h>
89#include <stdint.h>
90
91#ifdef __cplusplus
92extern "C" {
93#endif
94
95#if PICO_THREAD_LOCAL_MODE_GLOBAL || PICO_THREAD_LOCAL_MODE_NONE
96static inline size_t _tls_size(void) { return 0; }
97#elif PICO_THREAD_LOCAL_SUPPORT_EMUTLS
98extern size_t _runtime_tls_size(void);
99static inline size_t _tls_size(void) { return _runtime_tls_size(); }
100#else
101// standard definition for picolibc
102extern char __tls_size[];
103static inline size_t _tls_size(void) { return (size_t) (uintptr_t) __tls_size; }
104#endif
105
106/*
107 * Initialize a TLS block, copying the data segment from flash and
108 * zeroing the BSS segment.
109 */
110void _init_tls(void *tls);
111
112/* Set the TLS pointer to the specific block */
113void _set_tls(void *tls);
114
115#ifdef __cplusplus
116}
117#endif
118
119#endif
120
121#endif
122
123#endif