Understanding TLS
The most important take away of this document is to know the compiler/linker emitted symbols: constants __tls_size
and __tls_align
, mut variable __tls_base
, and the function __wasm_init_tls
.
General TLS supports of the compiler and linker without the presence of a threading library
Compiler:
- recognizes the variables declared with TLS qualifier (
__thread
or_Thread_local
, different qualifiers depends on the compiler) - put TLS variables into special segments of the object file,
tdata
for initialized variables, andtbss
for uninitialized ones - generate code for accessing each TLS variable with the address calculated by adding an offset to the
TLS_base
. Note that thisTLS_base
is a mutable, latter I'll mention how to set this value.TLS_base
is a thread-specific pointer points to the starting address of the TLS block for that thread. The actual place storing thisTLS_base
pointer varries depends on the compiler and architecture (e.g., for x86_64, GCC put this pointer at thefs
register, and for WASM, this can be accessed byglobal.set
andglobal.get
).
Linker:
- consolidates the TLS segments from different objet files into a single one, which need to recalculate the offsets of each TLS variable
- the linker also create symbols
TLS_size
,TLS_align
, and a TLS init function. In the case of WASM these are__tls_size
,__tls_align
,__tls_base
, and the function__wasm_init_tls(mem)
, where themem
parameter is a pointer specifying the location to init the TLS block.
Threading library (wasm):
Note that the __wasm_init_tls
simply initialize the TLS block according to the TLS variables declared in the source file, it doesn't allocate the memory. So, when wasi-libc
implements the threading library, it uses the const symbols __tls_size
and __tls_align
to pre-allocate the TLS memory before invoking __wasm_init_tls
. And of course, like we anticipated, the pthread_create
calls __wasm_init_tls
to set up the new thread's TLS block. Eventually the pthread_create
also set the __tls_base
variable, so that later the user's code will access the TLS variables starting from this base address.
For more detailed description of __tls_size
and __tls_align
, see this LLVM doc https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md#thread-local-storage.