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 (
__threador_Thread_local, different qualifiers depends on the compiler) - put TLS variables into special segments of the object file,
tdatafor initialized variables, andtbssfor uninitialized ones - generate code for accessing each TLS variable with the address calculated by adding an offset to the
TLS_base. Note that thisTLS_baseis a mutable, latter I'll mention how to set this value.TLS_baseis a thread-specific pointer points to the starting address of the TLS block for that thread. The actual place storing thisTLS_basepointer varries depends on the compiler and architecture (e.g., for x86_64, GCC put this pointer at thefsregister, and for WASM, this can be accessed byglobal.setandglobal.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 thememparameter 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.