1# Thread Local Storage in Picolibc
2Copyright © 2019 Keith Packard
3
4The standard C library API includes many functions that use persistent
5state held by the library not the application. One obvious example is
6'errno', a global variable originall designed to hold error status
7from the Unix kernel, but which was co-opted by libc to provide
8additional error status values from the library itself. There are
9numerous other examples of this kind of state.
10
11To permit multiple threads sharing a single address space to use the
12library without conflicting over this data, each thread needs a
13private copy of data that it uses. Newlib did this by creating a
14global structure holding all thread-specific values and then defining
15an API for the library to get the global structure for the current
16thread.
17
18Picolibc does this by using the built-in thread-local-storage
19mechanisms in the toolchain. This has several benefits:
20
21 1) Source code is simpler as thread-local variables are
22    accessed directly by name.
23
24 2) Thread local storage contains only values used by the
25    application.
26
27 3) Generated code is smaller and faster.
28
29## TLS model used by Picolibc
30
31Picolibc is normally compiled with -ftls-model=local-exec. The selected
32model is included in the .specs file so applications should not
33include -ftls-model in their compile commands.
34
35Local-exec defines a single block of storage for all TLS
36variables. Each TLS variable is assigned an offset within this block
37and those values are placed in the binary during relocation.
38
39## Initial TLS block
40
41The sample Picolibc linker script (picolibc.ld) allocates RAM for an
42initial TLS block and arranges for it to be initialized as a part of
43the normal data/bss initialization process for the application.
44
45| flash | symbol |
46| ----- | ------ |
47| code  |        |
48| rodata |       |
49| data initializers | __data_source |
50| TLS data initializers | __tdata_source |
51
52| RAM  | symbol |
53| ---- | ------ |
54| data | __data_start |
55| TLS data | __tls_base |
56|          | __data_end |
57|          | __tdata_size = . - __tls_base |
58| TLS bss | __bss_start |
59|         | __tbss_size = . - __bss_start |
60|         | __tls_size = . - __tls_base  |
61| bss | |
62|     | __bss_end
63
64The crt0 code copies __data_end - __data_start bytes from _data_source
65to _data_start. This initializes the regular data segment *and* the
66initial TLS data segment. Then, it clears memory from __bss_start to
67__bss_end, initializing the TLS bss segment *and* the regular bss
68segment. Finally, it sets the architecture-specific TLS data pointer
69to __tls_base. Once that is set, access to TLS variables will
70reference this initial TLS block.
71
72## Creating more TLS blocks
73
74If the application is multi-threaded and wants to allow these threads
75to have separate TLS data, it may allocate memory for additional TLS
76blocks:
77
78 1) Allocate a block of size  __tls_size
79 2) Copy __tdata_size bytes from __tdata_source to the new block to
80    set the initial TLS values.
81 3) Clear __tbss_size bytes starting _tdata_size bytes into the new
82    block
83 4) Set the TLS pointer as necessary
84
85## Picolibc APIs related to TLS
86
87Picolib provides a couple of helper APIs for TLS:
88
89* _set_tls
90```
91void
92_set_tls(void *tls);
93```
94This is an architecture-specific function which sets the TLS
95block pointer for the processor to `tls`.
96
97* _init_tls
98```
99void
100_init_tls(void *tls);
101```
102This function initializes the specified TLS block, copying values
103into the initialized data portion and clearing values in the
104uninitialized data portion.
105
106Picolib also provides architecture-specific internal GCC APIs as
107necessary, for example, __aeabi_read_tp for ARM processors.
108