TLS for Android (and iOS)

Joakim joakim at airpost.net
Sun Mar 30 02:37:31 PDT 2014


On Sunday, 30 March 2014 at 08:22:15 UTC, Dan Olson wrote:
> "Joakim" <joakim at airpost.net> writes:
>
>> On Thursday, 27 March 2014 at 16:01:31 UTC, Dan Olson wrote:
>>
>>> If nobody is working on the emulated TLS for LDC, I will give 
>>> it a
>>> try.
>>> Nothing to lose.
>>
>> Whatever I do to implement packed TLS in the dmd backend is 
>> not going
>> to work for ldc anyway, so nothing stopping you from making 
>> your own
>> effort.  You will have to patch llvm also, if the weak symbols 
>> bug
>> David pointed out is still around in llvm 3.5.  Let us know 
>> what
>> approach you take.
>
> The approach I started with was to make LLVM do the work.  I 
> read
> through all of the comments in this thread and decided this 
> might be the
> most fun.
>
> ARMISelLowering.cpp has TLS disabled for all but ELF targets.  I
> commented out an assertion blocking other targets to see what 
> would
> happen for iOS (Mach-O).  To my suprise, found that Mach-O tls 
> sections
> are generated (__thread_vars, __thread_data, .tbss) and 
> populated with
> the D thread local vars.
Nice find, I guess it helps that they have a desktop OS that does 
it differently.

> The load/store instructions were treating TLS vars like global 
> data
> though.  So I looked at the Mach-O X86 version and saw what it 
> is trying
> to do.  LLVM coding is still a mystery to me, but managed after 
> many
> hours today to hack together something that would turn this D 
> code
>
> module tlsd;
> int a;
>
> void test()
> {
>   a += 4;   // access a
> }
>
> into this:
>
> 	movw	r0, :lower16:(__D4tlsd1ai-(LPC4_0+4))
> 	movt	r0, :upper16:(__D4tlsd1ai-(LPC4_0+4))
> LPC4_0:
> 	add	r0, pc
> 	blx	___tls_get_addr
> 	ldr	r1, [r0]
> 	adds	r1, #4
> 	str	r1, [r0]
>
> ...
>
>
> .tbss __D4tlsd1ai$tlv$init, 4, 2
>
> 	.section	__DATA,__thread_vars,thread_local_variables
> 	.globl	__D4tlsd1ai
> __D4tlsd1ai:
> 	.long	__tlv_bootstrap
> 	.long	0
> 	.long	__D4tlsd1ai$tlv$init
>
>
> The following link helped explain what is going on with the
> __thread_vars data layout.
>
> http://www.opensource.apple.com/source/dyld/dyld-210.2.3/src/threadLocalVariables.c
>
> Mach-O dyln replaces tlv_bootstrap (thunk) with tlv_get_addr in 
> the
> TLVDescriptor (__thread_vars).  My LLVM hack for now is just 
> doing a
> direct call to __tls_get_addr instead of indirect to 
> tlv_get_addr.  For
> proof of concept (one thread only), I have __tls_get_addr hard 
> wired as
> follows:
>
> extern (C)
> {
>     struct TLVDescriptor
>     {
> 	void*  function(TLVDescriptor*) thunk;
> 	uint	key;
> 	uint	offset;
>     }
>
>     //void* tlv_get_addr(TLVDescriptor* d)
>     //void* __tls_get_addr(void* ptr)
>     void* __tls_get_addr(TLVDescriptor* tlvd)
>     {
>         __gshared static ubyte data[512];
>
>         printf("__tls_get_addr %p \n", tlvd);
>         printf("thunk %p, key %u, offset %u\n",
>                tlvd.thunk, tlvd.key, tlvd.offset);
>         return data.ptr + tlvd.offset;
>     }
>
>     void _tlv_bootstrap()
>     {
>         assert(false, "Should not get here");
>     }
> }
>
> It looks promising.  Next step is to add in some realistic 
> runtime
> support.  Not sure if I will base it on dmd's sections-osx or 
> the Apple
> dyld.  Probably a hybrid.

Have you experimented with seeing which of that TLV stuff from OS 
X that iOS actually supports?  The iOS dyld could be pretty 
different.  We don't know since they don't release the source for 
the iOS core like they do for OS X, ie is tlv_get_addr even 
available in the iOS dyld and does it execute other possible TLS 
relocations?  Only way to find out is to try it, or somehow 
inspect their iOS binaries. ;) Their source does show an ARM 
assembly implementation of tlv_get_address but it's commented out:

http://www.opensource.apple.com/source/dyld/dyld-210.2.3/src/threadLocalHelpers.s

I wonder if it'd be easier to pack your own Mach-O sections 
rather than figuring out how to access all their sections and 
reimplementing their TLV functions, assuming they're not 
available.  You might even be able to do it as an llvm patch 
since the relevant lib/MC/ files where llvm packs the TLS data 
into Mach-O sections seem pretty straightforward.

> Eventually will need some help getting the LLVM changes clean 
> instead of
> my hack job.
>
> Now that I've gone down this path a bit, I am beginning to 
> wonder if
> changing LLVM to support iOS thread locals will have issues.  
> Would LLVM
> want changes that affect Darwin/Mach-O (Apple's turf)?  I 
> suppose they
> could be optional.
I've never submitted anything to llvm, so not really based on 
anything than speculation, but I doubt they would accept such a 
patch, doesn't mean we can't use it though. ;)


More information about the digitalmars-d-ldc mailing list