TLS for Android

David Nadlinger code at klickverbot.at
Sun Mar 9 09:11:51 PDT 2014


On 9 Mar 2014, at 8:36, Joakim wrote:
> You mention "replacing the part that Glibc does (but Bionic doesn't) 
> with a piece of code in druntime."  Just to be clear, you're referring 
> to accessing TLS variables using an offset into the initialization 
> image, which is what ___tls_get_addr from druntime does in Walter's 
> packed TLS approach, right?  If not, I'm not sure exactly what you're 
> referring to.  With all this TLS stuff split up between the compiler, 
> linker, and runtime linker, often undocumented or poorly documenented 
> in the latter two cases, it's been confusing to follow the TLS code 
> path to see what's happening.

There are several possible ABIs for thread-local storage. For the sake 
of this argument, let's assume that our particular system works like the 
Linux/x86 implementation or Walter's OS X approach in that the TLS 
storage area is simply a flat block of memory where the individual 
variables reside at some offset. Then, there is still the question of 
how the application knows a) the base address of the block and b) the 
offset of the variable of interest.

In Walter's OS X implementation, both is taken care of by 
__tls_get_addr, which expects a pointer into the section where the TLS 
initialization data is stored. On e.g. Linux/x86_64, however, the base 
address is stored in %fs, and the offset is provided by special linker 
relocations (which essentially evaluate to the offset of a given symbol 
from the beginning of the initialization image). No extra function calls 
are inserted by the compiler here to access TLS data, and the (C) 
runtime is not directly involved for the accesses.

For an overview of the different models, see 
http://www.akkadia.org/drepper/tls.pdf (which is the most comprehensive 
document I could find, in spite of what you might think about the 
author).

But regardless of what model is chosen, there is still the issue of 
actually setting up a copy of the data for each thread during 
initialization. This is what I was referring to when I mentioned 
"replacing the part that Glibc does (but Bionic doesn't) with a piece of 
code in druntime".

So, if %gs works as expected on Android and the linker supports the 
necessary relocations, then it might be an option to simply use the 
existing TLS implementation in LLVM and simply provide the missing bits 
in druntime. On the other hand, if you choose to go with an entirely 
different TLS scheme (such as the DMD OS X implementation), you need to 
figure out how to change the codegen to emit the extra function calls to 
your __tls_get_addr analog, etc. Looking at 
llvm/lib/Target/ARM/ARMISelLowering.cpp, there might actually be a 
working implementation for this in LLVM already (which I didn't realize 
before), so this route would not necessarily be more complex than going 
with a different scheme. You'd probably just need to provide the 
__tls_get_addr implementation in druntime and figure out how LLVM emits 
the TLS image resp. how to get its base address.

Hope this helps,
David


More information about the digitalmars-d-ldc mailing list